mergeDictionaries.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2025-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "mergeDictionaries.H"
27 #include "HashSet.H"
28 #include "ListOps.H"
29 #include "stringListOps.H"
30 
31 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
32 
33 namespace Foam
34 {
35 
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
37 
39 (
40  dictionary& tgtDict,
41  entry& tgtEntry,
42  const entry& srcEntry,
43  const bool wildcards,
44  const HashTable<wordList, word>& shortcuts
45 )
46 {
47  bool changed = false;
48 
49  // Recursively merge sub-dictionaries
50  // TODO: merge without copying
51  if (tgtEntry.isDict() && srcEntry.isDict())
52  {
53  if
54  (
56  (
57  const_cast<dictionary&>(tgtEntry.dict()),
58  srcEntry.dict(),
59  wildcards,
60  shortcuts
61  )
62  )
63  {
64  changed = true;
65  }
66  }
67  else
68  {
69  // Should use in-place modification instead of adding
70  tgtDict.add(srcEntry.clone(tgtDict).ptr(), true);
71  changed = true;
72  }
73 
74  return changed;
75 }
76 
77 
79 (
80  const bool wildcards,
81  const HashTable<wordList, word>& shortcuts,
82  const wordList& shortcutNames,
83  const wordList& tgtKeys,
84  const keyType& srcKey
85 )
86 {
87  labelList matches;
88 
89  if (wildcards && srcKey.isPattern())
90  {
91  // Wildcard match
92  matches = findStrings(srcKey, tgtKeys);
93  }
94  else if (shortcuts.size())
95  {
96  // See if shortcuts expand to valid tgtKeys
97  labelList indices = findStrings(srcKey, shortcutNames);
98  forAll(indices, i)
99  {
100  const word& name = shortcutNames[indices[i]];
101  const wordList& keys = shortcuts[name];
102  forAll(keys, j)
103  {
104  const label index = findIndex(tgtKeys, keys[j]);
105  if (index != -1)
106  {
107  matches.append(index);
108  }
109  }
110  }
111  }
112 
113  return matches;
114 }
115 
116 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
117 
118 } // End namespace Foam
119 
120 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
121 
123 (
124  dictionary& tgtDict,
125  const dictionary& srcDict,
126  const bool wildcards,
127  const HashTable<wordList, word>& shortcuts
128 )
129 {
130  const wordList shortcutNames(shortcuts.toc());
131 
132  bool changed = false;
133 
134  // Save current (non-wildcard) keys before adding items.
135  HashSet<word> tgtKeysSet;
136  {
137  List<keyType> keys = tgtDict.keys(false);
138  forAll(keys, i)
139  {
140  tgtKeysSet.insert(keys[i]);
141  }
142  }
143 
144  // Pass 1. All literal matches
145  forAllConstIter(IDLList<entry>, srcDict, srcIter)
146  {
147  const keyType& srcKey = srcIter().keyword();
148 
149  if (srcKey[0] == '~')
150  {
151  word eraseKey = srcKey(1, srcKey.size()-1);
152 
153  if (tgtDict.remove(eraseKey))
154  {
155  // Mark tgtDict entry as having been match for wildcard
156  // handling later on.
157  tgtKeysSet.erase(eraseKey);
158  }
159 
160  changed = true;
161  }
162  else if (srcKey[0] == '#')
163  {
164  // function entry - just add
165  tgtDict.add(srcIter().clone(tgtDict).ptr());
166  changed = true;
167  }
168  else if (!wildcards || !(srcKey.isPattern() || shortcuts.found(srcKey)))
169  {
170  entry* entryPtr = tgtDict.lookupEntryPtr
171  (
172  srcKey,
173  false, // recursive
174  false // patternMatch
175  );
176 
177  if (entryPtr)
178  {
179  // Mark tgtDict entry as having been match for wildcard
180  // handling later on.
181  tgtKeysSet.erase(entryPtr->keyword());
182 
183  if
184  (
185  addEntry
186  (
187  tgtDict,
188  *entryPtr,
189  srcIter(),
190  wildcards,
191  shortcuts
192  )
193  )
194  {
195  changed = true;
196  }
197  }
198  else
199  {
200  // not found - just add
201  tgtDict.add(srcIter().clone(tgtDict).ptr());
202  changed = true;
203  }
204  }
205  }
206 
207  // Pass 2. Wildcard or shortcut matches (if any) on any non-match keys.
208  if (tgtKeysSet.size() > 0)
209  {
210  // Pick up remaining dictionary entries
211  wordList tgtKeys(tgtKeysSet.toc());
212 
213  forAllConstIter(IDLList<entry>, srcDict, srcIter)
214  {
215  const keyType& srcKey = srcIter().keyword();
216 
217  if (srcKey[0] == '~')
218  {
219  word eraseKey = srcKey(1, srcKey.size()-1);
220 
221  // List of indices into tgtKeys
222  labelList matches
223  (
225  (
226  wildcards,
227  shortcuts,
228  shortcutNames,
229  tgtKeys,
230  eraseKey
231  )
232  );
233 
234  // Remove all matches
235  forAll(matches, i)
236  {
237  tgtKeysSet.erase(tgtKeys[matches[i]]);
238  }
239 
240  changed = true;
241  }
242  else
243  {
244  // List of indices into tgtKeys
245  labelList matches
246  (
248  (
249  wildcards,
250  shortcuts,
251  shortcutNames,
252  tgtKeys,
253  srcKey
254  )
255  );
256 
257  // Add all matches
258  forAll(matches, i)
259  {
260  const word& tgtKey = tgtKeys[matches[i]];
261 
262  entry& tgtEntry = const_cast<entry&>
263  (
264  tgtDict.lookupEntry(tgtKey, false, false)
265  );
266 
267  if
268  (
269  addEntry
270  (
271  tgtDict,
272  tgtEntry,
273  srcIter(),
274  wildcards,
276  )
277  )
278  {
279  changed = true;
280  }
281  }
282  }
283  }
284  }
285 
286  return changed;
287 }
288 
289 
290 // ************************************************************************* //
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:492
A HashTable with keys but without contents.
Definition: HashSet.H:62
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:109
An STL-conforming hash table.
Definition: HashTable.H:127
bool erase(const iterator &)
Erase a hashedEntry specified by given iterator.
Definition: HashTable.C:445
List< Key > toc() const
Return the table of contents.
Definition: HashTable.C:227
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:138
Template class for intrusive linked lists.
Definition: ILList.H:67
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
const entry * lookupEntryPtr(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream pointer if present.
Definition: dictionary.C:507
const entry & lookupEntry(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream if present otherwise error.
Definition: dictionary.C:626
List< keyType > keys(bool patterns=false) const
Return the list of available keys or patterns.
Definition: dictionary.C:1001
bool remove(const word &)
Remove an entry specified by keyword.
Definition: dictionary.C:1182
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:1019
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:68
virtual bool isDict() const
Return true if this entry is a dictionary.
Definition: entry.H:178
const keyType & keyword() const
Return keyword.
Definition: entry.H:136
virtual const dictionary & dict() const =0
Return dictionary if this entry is a dictionary.
virtual autoPtr< entry > clone(const dictionary &parentDict) const =0
Construct on freestore as copy with reference to the.
A class for handling keywords in dictionaries.
Definition: keyType.H:69
bool isPattern() const
Should be treated as a match rather than a literal string.
Definition: keyTypeI.H:97
A class for handling words, derived from string.
Definition: word.H:63
Function with which to merge one dictionary into another. Intended for user-facing dictionary merging...
Namespace for OpenFOAM.
labelList findMatches(const bool wildcards, const HashTable< wordList, word > &shortcuts, const wordList &shortcutNames, const wordList &tgtKeys, const keyType &srcKey)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
bool findStrings(const wordReListMatcher &matcher, const std::string &str)
Return true if string matches one of the regular expressions.
Definition: stringListOps.H:52
T clone(const T &t)
Definition: List.H:55
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
bool mergeDictionaries(dictionary &tgtDict, const dictionary &srcDict, const bool wildcards=true, const HashTable< wordList, word > &shortcuts=HashTable< wordList, word >(0))
bool addEntry(dictionary &tgtDict, entry &tgtEntry, const entry &srcEntry, const bool wildcards, const HashTable< wordList, word > &shortcuts)
Operations on lists of strings.