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