entryIO.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) 2011-2018 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 "entry.H"
27 #include "primitiveEntry.H"
28 #include "dictionaryEntry.H"
29 #include "functionEntry.H"
30 #include "includeEntry.H"
31 #include "inputModeEntry.H"
32 #include "stringOps.H"
33 #include "dictionaryListEntry.H"
34 
35 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
36 
37 bool Foam::entry::getKeyword(keyType& keyword, token& keywordToken, Istream& is)
38 {
39  // Read the next valid token discarding spurious ';'s
40  do
41  {
42  if
43  (
44  is.read(keywordToken).bad()
45  || is.eof()
46  || !keywordToken.good()
47  )
48  {
49  return false;
50  }
51  }
52  while (keywordToken == token::END_STATEMENT);
53 
54  // If the token is a valid keyword set 'keyword' return true...
55  if (keywordToken.isWord())
56  {
57  keyword = keywordToken.wordToken();
58  return true;
59  }
60  else if (keywordToken.isString())
61  {
62  // Enable wildcards
63  keyword = keywordToken.stringToken();
64  return true;
65  }
66  else
67  {
68  return false;
69  }
70 }
71 
72 
73 bool Foam::entry::getKeyword(keyType& keyword, Istream& is)
74 {
75  token keywordToken;
76  bool ok = getKeyword(keyword, keywordToken, is);
77 
78  if (ok)
79  {
80  return true;
81  }
82  else
83  {
84  // Do some more checking
85  if (keywordToken == token::END_BLOCK || is.eof())
86  {
87  return false;
88  }
89  else
90  {
91  // Otherwise the token is invalid
92  cerr<< "--> FOAM Warning : " << std::endl
93  << " From function "
94  << "entry::getKeyword(keyType&, Istream&)" << std::endl
95  << " in file " << __FILE__
96  << " at line " << __LINE__ << std::endl
97  << " Reading " << is.name().c_str() << std::endl
98  << " found " << keywordToken << std::endl
99  << " expected either " << token::END_BLOCK << " or EOF"
100  << std::endl;
101  return false;
102  }
103  }
104 }
105 
106 
107 bool Foam::entry::New(dictionary& parentDict, Istream& is)
108 {
109  is.fatalCheck("entry::New(const dictionary& parentDict, Istream&)");
110 
112  token keyToken;
113 
114  // Get the next keyword and if a valid keyword return true
115  bool valid = getKeyword(keyword, keyToken, is);
116 
117  if (!valid)
118  {
119  // Do some more checking
120  if (keyToken == token::END_BLOCK || is.eof())
121  {
122  return false;
123  }
124  else if
125  (
126  keyToken.isLabel()
127  || (keyToken.isPunctuation() && keyToken.pToken() == token::BEGIN_LIST)
128  )
129  {
130  is.putBack(keyToken);
131  return parentDict.add
132  (
133  new dictionaryListEntry(parentDict, is),
134  false
135  );
136  }
137  else
138  {
139  // Otherwise the token is invalid
140  cerr<< "--> FOAM Warning : " << std::endl
141  << " From function "
142  << "entry::New(dictionary&, Istream&)" << std::endl
143  << " in file " << __FILE__
144  << " at line " << __LINE__ << std::endl
145  << " Reading " << is.name().c_str() << std::endl
146  << " found " << keyToken << std::endl
147  << " expected either " << token::END_BLOCK << " or EOF"
148  << std::endl;
149  return false;
150  }
151  }
152  else // Keyword starts entry ...
153  {
154  if (keyword[0] == '#') // ... Function entry
155  {
156  word functionName = keyword(1, keyword.size()-1);
158  {
159  return parentDict.add
160  (
161  new functionEntry
162  (
163  keyword,
164  parentDict,
165  is
166  ),
167  false
168  );
169  }
170  else
171  {
172  return functionEntry::execute(functionName, parentDict, is);
173  }
174  }
175  else if
176  (
178  && keyword[0] == '$'
179  ) // ... Substitution entry
180  {
181  token nextToken(is);
182  is.putBack(nextToken);
183 
184  if (keyword.size() > 2 && keyword[1] == token::BEGIN_BLOCK)
185  {
186  // Recursive substitution mode. Replace between {} with
187  // expansion and then let standard variable expansion deal
188  // with rest.
189  string s(keyword(2, keyword.size()-3));
190  // Substitute dictionary and environment variables. Do not allow
191  // empty substitutions.
192  stringOps::inplaceExpand(s, parentDict, true, false);
193  keyword.std::string::replace(1, keyword.size()-1, s);
194  }
195 
196  if (nextToken == token::BEGIN_BLOCK)
197  {
198  word varName = keyword(1, keyword.size()-1);
199 
200  // lookup the variable name in the given dictionary
201  const entry* ePtr = parentDict.lookupScopedEntryPtr
202  (
203  varName,
204  true,
205  true
206  );
207 
208  if (ePtr)
209  {
210  // Read as primitiveEntry
211  const keyType newKeyword(ePtr->stream());
212 
213  return parentDict.add
214  (
215  new dictionaryEntry(newKeyword, parentDict, is),
216  false
217  );
218  }
219  else
220  {
222  << "Attempt to use undefined variable " << varName
223  << " as keyword"
224  << exit(FatalIOError);
225  return false;
226  }
227  }
228  else
229  {
230  parentDict.substituteScopedKeyword(keyword);
231  }
232 
233  return true;
234  }
235  else if
236  (
238  && keyword == "include"
239  ) // ... For backward compatibility
240  {
241  return functionEntries::includeEntry::execute(parentDict, is);
242  }
243  else // ... Data entries
244  {
245  token nextToken(is);
246  is.putBack(nextToken);
247 
248  // Deal with duplicate entries
249  bool mergeEntry = false;
250 
251  // See (using exact match) if entry already present
252  entry* existingPtr = parentDict.lookupEntryPtr
253  (
254  keyword,
255  false,
256  false
257  );
258 
259  if (existingPtr)
260  {
262  {
263  mergeEntry = true;
264  }
266  {
267  // clear dictionary so merge acts like overwrite
268  if (existingPtr->isDict())
269  {
270  existingPtr->dict().clear();
271  }
272  mergeEntry = true;
273  }
275  {
276  // read and discard the entry
277  if (nextToken == token::BEGIN_BLOCK)
278  {
279  dictionaryEntry dummy(keyword, parentDict, is);
280  }
281  else
282  {
283  primitiveEntry dummy(keyword, parentDict, is);
284  }
285  return true;
286  }
288  {
290  << "ERROR! duplicate entry: " << keyword
291  << exit(FatalIOError);
292 
293  return false;
294  }
295  }
296 
297  if (nextToken == token::BEGIN_BLOCK)
298  {
299  return parentDict.add
300  (
301  new dictionaryEntry(keyword, parentDict, is),
302  mergeEntry
303  );
304  }
305  else
306  {
307  return parentDict.add
308  (
309  new primitiveEntry(keyword, parentDict, is),
310  mergeEntry
311  );
312  }
313  }
314  }
315 }
316 
317 
319 {
320  is.fatalCheck("entry::New(Istream&)");
321 
323 
324  // Get the next keyword and if invalid return false
325  if (!getKeyword(keyword, is))
326  {
327  return autoPtr<entry>(nullptr);
328  }
329  else // Keyword starts entry ...
330  {
331  token nextToken(is);
332  is.putBack(nextToken);
333 
334  if (nextToken == token::BEGIN_BLOCK)
335  {
336  return autoPtr<entry>
337  (
338  new dictionaryEntry(keyword, dictionary::null, is)
339  );
340  }
341  else
342  {
343  return autoPtr<entry>
344  (
345  new primitiveEntry(keyword, is)
346  );
347  }
348  }
349 }
350 
351 
352 // * * * * * * * * * * * * * Ostream operator * * * * * * * * * * * * * * * //
353 
355 {
356  e.write(os);
357  return os;
358 }
359 
360 
361 // ************************************************************************* //
bool isLabel() const
Definition: tokenI.H:271
A class for handling keywords in dictionaries.
Definition: keyType.H:64
punctuationToken pToken() const
Definition: tokenI.H:217
const entry * lookupEntryPtr(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream pointer if present.
Definition: dictionary.C:470
const keyType & keyword() const
Return keyword.
Definition: entry.H:123
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
virtual void write(Ostream &) const =0
Write.
static const dictionary null
Null dictionary.
Definition: dictionary.H:202
A token holds items read from Istream.
Definition: token.H:69
static bool New(dictionary &parentDict, Istream &)
Construct from Istream and insert into dictionary.
Definition: entryIO.C:107
void putBack(const token &)
Put back token.
Definition: Istream.C:30
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
virtual const dictionary & dict() const =0
Return dictionary if this entry is a dictionary.
static bool execute(dictionary &parentDict, Istream &)
Execute the functionEntry in a sub-dict context.
Definition: includeEntry.C:122
A keyword and a list of tokens is a &#39;dictionaryEntry&#39;.
const entry * lookupScopedEntryPtr(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream pointer if present.
Definition: dictionary.C:587
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:814
A keyword and a list of tokens is a &#39;primitiveEntry&#39;. An primitiveEntry can be read, written and printed, and the types and values of its tokens analysed.
static bool protect()
Return true if the inputMode is protect.
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
static int disableFunctionEntries
Definition: entry.H:86
A class for handling words, derived from string.
Definition: word.H:59
virtual const fileName & name() const
Return the name of the stream.
Definition: IOstream.H:297
A functionEntry causes entries to be added/manipulated on the specified dictionary given an input str...
Definition: functionEntry.H:63
static bool execute(const word &functionName, dictionary &parentDict, Istream &)
Execute the functionEntry in a sub-dict context.
Definition: functionEntry.C:81
void fatalCheck(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:105
bool eof() const
Return true if end of input seen.
Definition: IOstream.H:339
Read/write List of dictionaries.
virtual bool isDict() const
Return true if this entry is a dictionary.
Definition: entry.H:156
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
static bool merge()
Return true if the inputMode is merge.
string & inplaceExpand(string &, const HashTable< string, word, string::hash > &mapping, const char sigil='$')
Inplace expand occurrences of variables according to the mapping.
Definition: stringOps.C:87
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:331
Ostream & operator<<(Ostream &, const ensightPart &)
bool substituteScopedKeyword(const word &keyword)
Substitute the given scoped keyword prepended by &#39;$&#39; with the.
Definition: dictionary.C:622
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:52
const doubleScalar e
Elementary charge.
Definition: doubleScalar.H:98
static bool overwrite()
Return true if the inputMode is overwrite.
void clear()
Clear the dictionary.
Definition: dictionary.C:1135
static bool error()
Return true if the inputMode is error.
bool isPunctuation() const
Definition: tokenI.H:212
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:65
IOerror FatalIOError