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-2023 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 "includeEntry.H"
29 #include "inputModeEntry.H"
30 #include "stringOps.H"
31 
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 
34 bool Foam::entry::getKeyword(keyType& keyword, token& keywordToken, Istream& is)
35 {
36  // Read the next valid token discarding spurious ';'s
37  do
38  {
39  if
40  (
41  is.read(keywordToken).bad()
42  || is.eof()
43  || !keywordToken.good()
44  )
45  {
46  return false;
47  }
48  }
49  while (keywordToken == token::END_STATEMENT);
50 
51  keyword = keywordToken;
52 
53  return !keyword.isUndefined();
54 }
55 
56 
57 bool Foam::entry::getKeyword(keyType& keyword, Istream& is)
58 {
59  token keywordToken;
60  bool ok = getKeyword(keyword, keywordToken, is);
61 
62  if (ok)
63  {
64  return true;
65  }
66  else
67  {
68  // Do some more checking
69  if (keywordToken == token::END_BLOCK || is.eof())
70  {
71  return false;
72  }
73  else
74  {
75  // Otherwise the token is invalid
76  cerr<< "--> FOAM Warning : " << std::endl
77  << " From function "
78  << "entry::getKeyword(keyType&, Istream&)" << std::endl
79  << " in file " << __FILE__
80  << " at line " << __LINE__ << std::endl
81  << " Reading " << is.name().c_str() << std::endl
82  << " found " << keywordToken << std::endl
83  << " expected either " << token::END_BLOCK << " or EOF"
84  << std::endl;
85  return false;
86  }
87  }
88 }
89 
90 
91 bool Foam::entry::New(dictionary& parentDict, Istream& is)
92 {
93  is.fatalCheck("entry::New(const dictionary& parentDict, Istream&)");
94 
95  keyType keyword;
96  token keyToken;
97 
98  // Get the next keyword and if a valid keyword return true
99  bool valid = getKeyword(keyword, keyToken, is);
100 
101  if (!valid)
102  {
103  // Do some more checking
104  if (keyToken == token::END_BLOCK || is.eof())
105  {
106  return false;
107  }
108  else if
109  (
110  keyToken.isLabel()
111  || (keyToken.isPunctuation() && keyToken.pToken() == token::BEGIN_LIST)
112  )
113  {
114  is.putBack(keyToken);
115  return parentDict.add
116  (
117  new dictionaryListEntry(parentDict, is),
118  false
119  );
120  }
121  else
122  {
123  // Otherwise the token is invalid
124  cerr<< "--> FOAM Warning : " << std::endl
125  << " From function "
126  << "entry::New(dictionary&, Istream&)" << std::endl
127  << " in file " << __FILE__
128  << " at line " << __LINE__ << std::endl
129  << " Reading " << is.name().c_str() << std::endl
130  << " found " << keyToken << std::endl
131  << " expected either " << token::END_BLOCK << " or EOF"
132  << std::endl;
133  return false;
134  }
135  }
136  else // Keyword starts entry ...
137  {
138  if (keyword.isFunctionName()) // ... Function entry
139  {
140  const word functionName = keyword(1, keyword.size() - 1);
141 
142  if (disableFunctionEntries)
143  {
144  bool success = parentDict.add
145  (
146  new functionEntry
147  (
148  keyword,
149  parentDict,
150  is
151  ),
152  false
153  );
154 
155  return success;
156  }
157  else
158  {
159  return functionEntry::execute(functionName, parentDict, is);
160  }
161  }
162  else if
163  (
164  !disableFunctionEntries
165  && keyword.isVariable()
166  ) // ... Substitution entry
167  {
168  token nextToken(is);
169  is.putBack(nextToken);
170 
171  if (keyword.size() > 2 && keyword[1] == token::BEGIN_BLOCK)
172  {
173  // Recursive substitution mode. Replace between {} with
174  // expansion and then let standard variable expansion deal
175  // with rest.
176  string s(keyword(2, keyword.size() - 3));
177 
178  // Substitute dictionary and environment variables. Do not allow
179  // empty substitutions.
180  stringOps::inplaceExpandEntry(s, parentDict, true, false);
181  keyword.std::string::replace(1, keyword.size() - 1, s);
182  }
183 
184  if (nextToken == token::BEGIN_BLOCK)
185  {
186  word varName = keyword(1, keyword.size() - 1);
187 
188  // Lookup the variable name in the given dictionary
189  const entry* ePtr = parentDict.lookupScopedEntryPtr
190  (
191  varName,
192  true,
193  true
194  );
195 
196  if (ePtr)
197  {
198  // Read as primitiveEntry
199  const keyType newKeyword(ePtr->stream());
200 
201  return parentDict.add
202  (
203  new dictionaryEntry(newKeyword, parentDict, is),
204  false
205  );
206  }
207  else
208  {
210  << "Attempt to use undefined variable " << varName
211  << " as keyword"
212  << exit(FatalIOError);
213  return false;
214  }
215  }
216  else
217  {
218  parentDict.substituteScopedKeyword(keyword);
219  }
220 
221  return true;
222  }
223  else // ... Data entries
224  {
225  token nextToken(is);
226  is.putBack(nextToken);
227 
228  // Deal with duplicate entries
229  bool mergeEntry = false;
230 
231  // If function entries are disabled allow duplicate entries
232  if (disableFunctionEntries)
233  {
234  mergeEntry = false;
235  }
236  else
237  {
238  // See (using exact match) if entry already present
239  entry* existingPtr = parentDict.lookupEntryPtr
240  (
241  keyword,
242  false,
243  false
244  );
245 
246  if (existingPtr)
247  {
249  {
250  mergeEntry = true;
251  }
253  {
254  // Clear dictionary so merge acts like overwrite
255  if (existingPtr->isDict())
256  {
257  existingPtr->dict().clear();
258  }
259  mergeEntry = true;
260  }
262  {
263  // Read and discard the entry
264  if (nextToken == token::BEGIN_BLOCK)
265  {
266  dictionaryEntry dummy(keyword, parentDict, is);
267  }
268  else
269  {
270  primitiveEntry dummy(keyword, parentDict, is);
271  }
272  return true;
273  }
275  {
277  << "ERROR! duplicate entry: " << keyword
278  << exit(FatalIOError);
279  return false;
280  }
281  }
282  }
283 
284  if (nextToken == token::BEGIN_BLOCK)
285  {
286  return parentDict.add
287  (
288  new dictionaryEntry(keyword, parentDict, is),
289  mergeEntry
290  );
291  }
292  else
293  {
294  return parentDict.add
295  (
296  new primitiveEntry(keyword, parentDict, is),
297  mergeEntry
298  );
299  }
300  }
301  }
302 }
303 
304 
306 {
307  is.fatalCheck("entry::New(Istream&)");
308 
309  keyType keyword;
310 
311  // Get the next keyword and if invalid return false
312  if (!getKeyword(keyword, is))
313  {
314  return autoPtr<entry>(nullptr);
315  }
316  else // Keyword starts entry ...
317  {
318  token nextToken(is);
319  is.putBack(nextToken);
320 
321  if (nextToken == token::BEGIN_BLOCK)
322  {
323  return autoPtr<entry>
324  (
325  new dictionaryEntry(keyword, dictionary::null, is)
326  );
327  }
328  else
329  {
330  return autoPtr<entry>
331  (
332  new primitiveEntry(keyword, is)
333  );
334  }
335  }
336 }
337 
338 
339 // * * * * * * * * * * * * * Ostream operator * * * * * * * * * * * * * * * //
340 
342 {
343  e.write(os);
344  return os;
345 }
346 
347 
348 // ************************************************************************* //
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:162
bool substituteScopedKeyword(const word &keyword)
Substitute the given scoped keyword prepended by '$' with the.
Definition: dictionary.C:773
const entry * lookupEntryPtr(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream pointer if present.
Definition: dictionary.C:548
const entry * lookupScopedEntryPtr(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream pointer if present,.
Definition: dictionary.C:737
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:1014
void clear()
Clear the dictionary.
Definition: dictionary.C:1344
static const dictionary null
Null dictionary.
Definition: dictionary.H:258
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:91
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:571
bool isPunctuation() const
Definition: tokenI.H:280
@ BEGIN_BLOCK
Definition: token.H:113
@ END_BLOCK
Definition: token.H:114
@ END_STATEMENT
Definition: token.H:108
@ BEGIN_LIST
Definition: token.H:109
punctuationToken pToken() const
Definition: tokenI.H:285
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:346
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 & inplaceExpandEntry(string &s, const dictionary &dict, const bool allowEnvVars, const bool allowEmpty, const char sigil='$')
Inplace expand occurrences of variables according to the dictionary.
Definition: stringOps.C:760
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
const doubleScalar e
Definition: doubleScalar.H:106
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:257
IOerror FatalIOError
Ostream & operator<<(Ostream &os, const fvConstraints &constraints)