foamDictionary.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2016 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 Application
25  foamDictionary
26 
27 Description
28  Interrogates and manipulates dictionaries.
29 
30 Usage
31  \b foamDictionary [OPTION] dictionary
32 
33  - \par -entry <name>
34  Selects an entry
35 
36  - \par -keywords <name>
37  Prints the keywords (of the selected entry or of the top level if
38  no entry was selected
39 
40  - \par -add <value>
41  Adds the entry (should not exist yet)
42 
43  - \par -set <value>
44  Adds or replaces the entry
45 
46  - \par -expand
47  Read the specified dictionary file, expand the macros etc. and write
48  the resulting dictionary to standard output.
49 
50  - \par -includes
51  List the \c #include and \c #includeIfPresent files to standard output.
52 
53  Typical usage:
54  - Change simulation to run for one timestep only:
55  \verbatim
56  foamDictionary system/controlDict -entry stopAt -set writeNow
57  \endverbatim
58 
59  - Change solver:
60  \verbatim
61  foamDictionary system/fvSolution -entry solvers.p.solver -set PCG
62  \endverbatim
63 
64  - Print bc type:
65  \verbatim
66  foamDictionary 0/U -entry boundaryField.movingWall.type
67  \endverbatim
68 
69  - Change bc parameter:
70  \verbatim
71  foamDictionary 0/U -entry boundaryField.movingWall.value \
72  -set "uniform (2 0 0)"
73  \endverbatim
74 
75  - Change whole bc type:
76  \verbatim
77  foamDictionary 0/U -entry boundaryField.movingWall \
78  -set "{type uniformFixedValue; uniformValue (2 0 0);}"
79  \endverbatim
80 
81 \*---------------------------------------------------------------------------*/
82 
83 #include "argList.H"
84 #include "Time.H"
85 #include "IFstream.H"
86 #include "OFstream.H"
87 #include "includeEntry.H"
88 
89 using namespace Foam;
90 
91 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
92 
93 //- Converts old scope syntax to new syntax
94 word scope(const fileName& entryName)
95 {
96  if (entryName.find(':') != string::npos)
97  {
98  wordList entryNames(entryName.components(':'));
99 
100  word entry(entryNames[0]);
101  for (label i = 1; i < entryNames.size(); i++)
102  {
103  entry += word('.') + entryNames[i];
104  }
105  return entry;
106  }
107  else
108  {
109  return entryName;
110  }
111 }
112 
113 
114 //- Extract keyword (last bit of scoped name
115 word keyword(const word& scopedName)
116 {
117  word key(scopedName);
118  string::size_type i = scopedName.find_last_of(".");
119  if (i != string::npos)
120  {
121  key = scopedName.substr(i+1, string::npos);
122  }
123  return key;
124 }
125 
126 
127 void setScoped
128 (
129  dictionary& dict,
130  const word& keyword,
131  const bool overwrite,
132  entry* d
133 )
134 {
135  if (keyword[0] == ':')
136  {
137  // Go up to top level and recurse to find entries
138  setScoped
139  (
140  const_cast<dictionary&>(dict.topDict()),
141  keyword.substr(1, keyword.size()-1),
142  overwrite,
143  d
144  );
145  return;
146  }
147  else
148  {
149  string::size_type dotPos = keyword.find('.');
150 
151  if (dotPos == string::npos)
152  {
153  // Non-scoped lookup
154  if (overwrite)
155  {
156  dict.set(d);
157  }
158  else
159  {
160  dict.add(d, false);
161  }
162  return;
163  }
164  else
165  {
166  if (dotPos == 0)
167  {
168  // Starting with a '.'. Go up for every 2nd '.' found
169 
170  const dictionary* dictPtr = &dict;
171 
172  string::size_type begVar = dotPos + 1;
173  string::const_iterator iter =
174  keyword.begin() + begVar;
175  string::size_type endVar = begVar;
176  while
177  (
178  iter != keyword.end()
179  && *iter == '.'
180  )
181  {
182  ++iter;
183  ++endVar;
184 
185  // Go to parent
186  if (&dictPtr->parent() == &dictionary::null)
187  {
189  << "No parent of current dictionary"
190  << " when searching for "
191  << keyword.substr
192  (
193  begVar,
194  keyword.size() - begVar
195  )
196  << exit(FatalIOError);
197  }
198  dictPtr = &dictPtr->parent();
199  }
200 
201  setScoped
202  (
203  const_cast<dictionary&>(*dictPtr),
204  keyword.substr(endVar),
205  overwrite,
206  d
207  );
208  return;
209  }
210  else
211  {
212  // Extract the first word
213  word firstWord = keyword.substr(0, dotPos);
214 
215  const entry* entPtr = dict.lookupScopedEntryPtr
216  (
217  firstWord,
218  false, // Recursive
219  false
220  );
221 
222  if (!entPtr || !entPtr->isDict())
223  {
225  << "keyword " << firstWord
226  << " is undefined in dictionary "
227  << dict.name() << " or is not a dictionary"
228  << endl
229  << "Valid keywords are " << dict.keys()
230  << exit(FatalIOError);
231  }
232 
233  const dictionary& firstDict = entPtr->dict();
234 
235  setScoped
236  (
237  const_cast<dictionary&>(firstDict),
238  keyword.substr(dotPos, keyword.size()-dotPos),
239  overwrite,
240  d
241  );
242  return;
243  }
244  }
245  }
246 }
247 
248 
249 int main(int argc, char *argv[])
250 {
251  argList::addNote("manipulates dictionaries");
252 
254  argList::validArgs.append("dictionary");
255  argList::addBoolOption("keywords", "list keywords");
256  argList::addOption("entry", "name", "report/select the named entry");
258  (
259  "value",
260  "print entry value"
261  );
263  (
264  "set",
265  "value",
266  "set entry value or add new entry"
267  );
269  (
270  "add",
271  "value",
272  "add a new entry"
273  );
275  (
276  "includes",
277  "List the #include/#includeIfPresent files to standard output."
278  );
280  (
281  "expand",
282  "Read the specified dictionary file, expand the macros etc. and write "
283  "the resulting dictionary to standard output."
284  );
285 
286  argList args(argc, argv);
287 
288  const bool listIncludes = args.optionFound("includes");
289 
290  if (listIncludes)
291  {
293  }
294 
295  fileName dictFileName(args[1]);
296 
297  autoPtr<IFstream> dictFile(new IFstream(dictFileName));
298 
299  if (dictFile().good())
300  {
301  bool changed = false;
302 
303  // Read but preserve headers
305  dict.read(dictFile(), true);
306 
307  if (listIncludes)
308  {
309  return 0;
310  }
311  else if (args.optionFound("expand"))
312  {
314  <<"//\n// " << dictFileName << "\n//\n";
315  dict.write(Info, false);
317 
318  return 0;
319  }
320 
321  word entryName;
322  if (args.optionReadIfPresent("entry", entryName))
323  {
324  word scopedName(scope(entryName));
325 
326  string newValue;
327  if
328  (
329  args.optionReadIfPresent("set", newValue)
330  || args.optionReadIfPresent("add", newValue)
331  )
332  {
333  bool overwrite = args.optionFound("set");
334 
335  word key(keyword(scopedName));
336 
337  IStringStream str(string(key) + ' ' + newValue + ';');
338  setScoped(dict, scopedName, overwrite, entry::New(str).ptr());
339  changed = true;
340 
341  // Print the changed entry
342  const entry* entPtr = dict.lookupScopedEntryPtr
343  (
344  scopedName,
345  false,
346  true // Support wildcards
347  );
348  if (entPtr)
349  {
350  Info<< *entPtr << endl;
351  }
352  }
353  else
354  {
355  const entry* entPtr = dict.lookupScopedEntryPtr
356  (
357  scopedName,
358  false,
359  true // Support wildcards
360  );
361 
362  if (entPtr)
363  {
364  if (args.optionFound("keywords"))
365  {
366  const dictionary& dict = entPtr->dict();
367  forAllConstIter(dictionary, dict, iter)
368  {
369  Info<< iter().keyword() << endl;
370  }
371  }
372  else
373  {
374  if (args.optionFound("value"))
375  {
376  if (entPtr->isStream())
377  {
378  const tokenList& tokens = entPtr->stream();
379  forAll(tokens, i)
380  {
381  Info<< tokens[i] << token::SPACE;
382  }
383  Info<< endl;
384  }
385  else if (entPtr->isDict())
386  {
387  Info<< entPtr->dict();
388  }
389  }
390  else
391  {
392  Info<< *entPtr << endl;
393  }
394  }
395  }
396  else
397  {
398  FatalIOErrorInFunction(dictFile)
399  << "Cannot find entry " << entryName
400  << exit(FatalError, 2);
401  }
402  }
403  }
404  else if (args.optionFound("keywords"))
405  {
406  forAllConstIter(dictionary, dict, iter)
407  {
408  Info<< iter().keyword() << endl;
409  }
410  }
411  else
412  {
413  Info<< dict;
414  }
415 
416  if (changed)
417  {
418  dictFile.clear();
419  OFstream os(dictFileName);
421  dict.write(os, false);
423  }
424  }
425  else
426  {
428  << "Cannot open file " << dictFileName
429  << exit(FatalError, 1);
430  }
431 
432  return 0;
433 }
434 
435 
436 // ************************************************************************* //
bool read(Istream &)
Read dictionary from Istream.
Definition: dictionaryIO.C:126
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
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
A class for handling file names.
Definition: fileName.H:69
static Stream & writeBanner(Stream &os, bool noHint=false)
Write the standard OpenFOAM file/dictionary banner.
Definition: IOobjectI.H:45
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
List< keyType > keys(bool patterns=false) const
Return the list of available keys or patterns.
Definition: dictionary.C:719
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
Output to file stream.
Definition: OFstream.H:81
static Stream & writeDivider(Stream &os)
Write the standard file section divider.
Definition: IOobjectI.H:98
bool optionReadIfPresent(const word &opt, T &) const
Read a value from the named option if present.
Definition: argListI.H:198
static const dictionary null
Null dictionary.
Definition: dictionary.H:193
static bool New(dictionary &parentDict, Istream &)
Construct from Istream and insert into dictionary.
Definition: entryIO.C:91
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
virtual const dictionary & dict() const =0
Return dictionary if this entry is a dictionary.
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition: argList.H:154
const fileName & name() const
Return the dictionary name.
Definition: dictionary.H:103
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:737
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:108
const entry * lookupScopedEntryPtr(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream pointer if present.
Definition: dictionary.C:462
A class for handling words, derived from string.
Definition: word.H:59
Extract command arguments and options from the supplied argc and argv parameters. ...
Definition: argList.H:102
wordList components(const char delimiter='/') const
Return path components as wordList.
Definition: fileName.C:298
static void addOption(const word &opt, const string &param="", const string &usage="")
Add to an option to validOptions with usage information.
Definition: argList.C:93
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:73
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
Input from file stream.
Definition: IFstream.H:81
static Stream & writeEndDivider(Stream &os)
Write the standard end file divider.
Definition: IOobjectI.H:108
void write(Ostream &, const bool subDict=true) const
Write dictionary, normally with sub-dictionary formatting.
Definition: dictionaryIO.C:173
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:331
Input from memory buffer stream.
Definition: IStringStream.H:49
void set(entry *)
Assign a new entry, overwrite any existing entry.
Definition: dictionary.C:864
messageStream Info
static void noBanner()
Disable emitting the banner information.
Definition: argList.C:140
const dictionary & parent() const
Return the parent dictionary.
Definition: dictionary.H:251
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:53
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
Definition: argList.C:83
static void addNote(const string &)
Add extra notes for the usage information.
Definition: argList.C:124
static bool log
Report which file is included to stdout.
Definition: includeEntry.H:94
void clear()
Clear the dictionary.
Definition: dictionary.C:1058
virtual ITstream & stream() const =0
Return token stream if this entry is a primitive entry.
Foam::argList args(argc, argv)
const dictionary & topDict() const
Return the top of the tree.
Definition: dictionary.C:231
virtual bool isStream() const
Return true if this entry is a stream.
Definition: entry.H:144
virtual bool isDict() const
Return true if this entry is a dictionary.
Definition: entry.H:153
Namespace for OpenFOAM.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:65
IOerror FatalIOError