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 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 (!wildcards || !(srcKey.isPattern() || shortcuts.found(srcKey)))
163  {
164  entry* entryPtr = tgtDict.lookupEntryPtr
165  (
166  srcKey,
167  false, // recursive
168  false // patternMatch
169  );
170 
171  if (entryPtr)
172  {
173  // Mark tgtDict entry as having been match for wildcard
174  // handling later on.
175  tgtKeysSet.erase(entryPtr->keyword());
176 
177  if
178  (
179  addEntry
180  (
181  tgtDict,
182  *entryPtr,
183  srcIter(),
184  wildcards,
185  shortcuts
186  )
187  )
188  {
189  changed = true;
190  }
191  }
192  else
193  {
194  // not found - just add
195  tgtDict.add(srcIter().clone(tgtDict).ptr());
196  changed = true;
197  }
198  }
199  }
200 
201  // Pass 2. Wildcard or shortcut matches (if any) on any non-match keys.
202  if (tgtKeysSet.size() > 0)
203  {
204  // Pick up remaining dictionary entries
205  wordList tgtKeys(tgtKeysSet.toc());
206 
207  forAllConstIter(IDLList<entry>, srcDict, srcIter)
208  {
209  const keyType& srcKey = srcIter().keyword();
210 
211  if (srcKey[0] == '~')
212  {
213  word eraseKey = srcKey(1, srcKey.size()-1);
214 
215  // List of indices into tgtKeys
216  labelList matches
217  (
219  (
220  wildcards,
221  shortcuts,
222  shortcutNames,
223  tgtKeys,
224  eraseKey
225  )
226  );
227 
228  // Remove all matches
229  forAll(matches, i)
230  {
231  tgtKeysSet.erase(tgtKeys[matches[i]]);
232  }
233 
234  changed = true;
235  }
236  else
237  {
238  // List of indices into tgtKeys
239  labelList matches
240  (
242  (
243  wildcards,
244  shortcuts,
245  shortcutNames,
246  tgtKeys,
247  srcKey
248  )
249  );
250 
251  // Add all matches
252  forAll(matches, i)
253  {
254  const word& tgtKey = tgtKeys[matches[i]];
255 
256  entry& tgtEntry = const_cast<entry&>
257  (
258  tgtDict.lookupEntry(tgtKey, false, false)
259  );
260 
261  if
262  (
263  addEntry
264  (
265  tgtDict,
266  tgtEntry,
267  srcIter(),
268  wildcards,
270  )
271  )
272  {
273  changed = true;
274  }
275  }
276  }
277  }
278  }
279 
280  return changed;
281 }
282 
283 
284 // ************************************************************************* //
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:476
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:578
const entry & lookupEntry(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream if present otherwise error.
Definition: dictionary.C:697
List< keyType > keys(bool patterns=false) const
Return the list of available keys or patterns.
Definition: dictionary.C:1002
bool remove(const word &)
Remove an entry specified by keyword.
Definition: dictionary.C:1183
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:1020
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:62
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.