functionEntry.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-2026 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 "functionEntry.H"
27 #include "OTstream.H"
28 
29 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
30 
31 namespace Foam
32 {
35 
37  (
39  execute,
40  primitiveEntryIstream
41  );
42 }
43 
44 
45 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
46 
47 void Foam::functionEntry::readRestOfArgs(string& fNameArgs, Istream& is) const
48 {
49  int listDepth = 1
50  + fNameArgs.count(token::BEGIN_LIST) - fNameArgs.count(token::END_LIST);
51 
52  if (dynamic_cast<ISstream*>(&is))
53  {
54  if (listDepth != 0)
55  {
56  ISstream& iss = dynamic_cast<ISstream&>(is);
57 
58  char c;
59 
60  while (iss.get(c))
61  {
62  if (c == token::BEGIN_LIST)
63  {
64  listDepth++;
65  }
66  else if (c == token::END_LIST)
67  {
68  listDepth--;
69 
70  if (listDepth == 0)
71  {
72  break;
73  }
74  }
75 
76  fNameArgs += c;
77  }
78  }
79  else
80  {
81  // Remove trailing token::END_LIST
82  fNameArgs.resize(fNameArgs.size() - 1);
83  }
84  }
85  else
86  {
87  OStringStream argStream;
88 
89  token currToken;
90 
91  while
92  (
93  !is.read(currToken).bad()
94  && currToken.good()
95  && !(currToken == token::END_STATEMENT && listDepth == 1)
96  )
97  {
98  if (currToken == token::BEGIN_LIST)
99  {
100  listDepth++;
101  }
102  else if (currToken == token::END_LIST)
103  {
104  listDepth--;
105 
106  if (listDepth == 0)
107  {
108  break;
109  }
110  }
111 
112  argStream << currToken;
113  }
114 
115  fNameArgs.append(argStream.str());
116  }
117 }
118 
119 
120 // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
121 
123 (
124  const functionName& functionType,
125  Istream& is,
126  const bool optional
127 ) const
128 {
130 
131  // Read the next token to check for '('
132  // in case the optional arguments start on the next line
133  const token nextToken(is);
134 
135  if
136  (
137  nextToken.isPunctuation()
138  && nextToken.pToken() == token::BEGIN_LIST
139  )
140  {
141  argList.append(nextToken);
142 
143  const token nextToken(is);
144 
145  // Check if the argument list has been parsed previously
146  // and converted into a single string token
147  if (nextToken.isString())
148  {
149  argList.append(nextToken);
150 
151  const token endListToken(is);
152  if
153  (
154  endListToken.isPunctuation()
155  && endListToken.pToken() == token::END_LIST
156  )
157  {
158  argList.append(endListToken);
159  }
160  else
161  {
163  << "Unclosed argument list " << nextToken
164  << " in functionEntry " << argList
165  << exit(FatalIOError);
166  }
167  }
168  else
169  {
170  string fArgs(nextToken.anyStringToken());
171  readRestOfArgs(fArgs, is);
172  argList.append(token(fArgs, nextToken.lineNumber()));
173  argList.append(token(token::END_LIST, is.lineNumber()));
174  }
175  }
176  else
177  {
178  if (!optional)
179  {
181  << "Expected " << char(token::BEGIN_LIST)
182  << " to open argument list, but found " << nextToken
183  << " in functionEntry " << functionType
184  << exit(FatalIOError);
185  }
186 
187  is.putBack(nextToken);
188  }
189 
190  return argList;
191 }
192 
193 
195 (
196  const functionName& functionType,
197  Istream& is
198 ) const
199 {
200  tokenList funcNameArgList;
201  string::size_type argsStart = string::npos;
202 
203  // Read the function name with arguments if on the same line
204  const token fName(is);
205  const label fNameLineNumber = is.lineNumber();
206 
207  if (fName.isWord() || fName.isString())
208  {
209  if (fName.isString())
210  {
211  funcNameArgList.append(fName);
212  }
213  else
214  {
215  word fNameArgs = fName.wordToken();
216 
217  argsStart = fNameArgs.find(token::BEGIN_LIST);
218 
219  // If the function name includes a '(' read the rest of the list
220  if (argsStart != string::npos)
221  {
222  const word fName(fNameArgs(0, argsStart));
223  funcNameArgList.append(token(fName, fNameLineNumber));
224  funcNameArgList.append
225  (
226  token(token::BEGIN_LIST, fNameLineNumber)
227  );
228 
229  string fArgs
230  (
231  fNameArgs(argsStart + 1, fNameArgs.size() - argsStart)
232  );
233  readRestOfArgs(fArgs, is);
234 
235  funcNameArgList.append(token(fArgs, fNameLineNumber));
236  funcNameArgList.append(token(token::END_LIST, fNameLineNumber));
237  }
238  else
239  {
240  funcNameArgList.append(token(fNameArgs, fNameLineNumber));
241  }
242  }
243 
244  if (argsStart == string::npos)
245  {
246  funcNameArgList.append(readArgList(functionType, is, true));
247  }
248  }
249  else
250  {
251  // For any other kind of string return for error reporting
252  funcNameArgList.append(fName);
253  }
254 
255  return funcNameArgList;
256 }
257 
258 
260 (
261  const functionName& functionType,
262  Istream& is
263 ) const
264 {
265  tokenList fileNameArgList;
266 
267  // Read the file name
268  const token fName(is);
269 
270  // Check the file name is a string
271  if (fName.isString())
272  {
273  // Append the file name
274  fileNameArgList.append(fName);
275 
276  // Append the optional argument list
277  fileNameArgList.append(readArgList(functionType, is, true));
278  }
279  else
280  {
281  // For any other kind of string return for error reporting
282  fileNameArgList.append(fName);
283  }
284 
285  return fileNameArgList;
286 }
287 
288 
290 (
291  const functionName& functionType,
292  Istream& is
293 ) const
294 {
296 
297  // Read the next token to check for '('
298  // in case the optional arguments start on the next line
299  token currToken(is);
300 
301  if
302  (
303  currToken.isPunctuation()
304  && currToken.pToken() == token::BEGIN_LIST
305  )
306  {
307  do
308  {
309  argList.append(currToken);
310  }
311  while
312  (
313  !(currToken == token::END_LIST)
314  && !is.read(currToken).bad()
315  && currToken.good()
316  );
317 
318  if
319  (
320  !currToken.isPunctuation()
321  || currToken.pToken() != token::END_LIST
322  )
323  {
325  << "Unclosed argument list " << currToken
326  << " in functionEntry " << functionType
327  << exit(FatalIOError);
328  }
329  }
330  else
331  {
332  argList.append(currToken);
333  }
334 
335  return argList;
336 }
337 
338 
340 (
341  const dictionary& parentDict,
342  dictionary& contextDict,
343  const token& t,
344  Istream& is
345 )
346 {
347  is.putBack(t);
348  return entry::New(contextDict, is);
349 }
350 
351 
353 (
354  const dictionary& parentDict,
355  primitiveEntry& contextEntry,
356  const token& t,
357  Istream& is
358 )
359 {
360  contextEntry.append(t, parentDict, is);
361  return true;
362 }
363 
364 
366 (
367  dictionary& contextDict,
368  const OTstream& ots
369 )
370 {
371  contextDict.read(ITstream(ots.name(), ots)());
372  return true;
373 }
374 
375 
377 (
378  const dictionary& parentDict,
379  primitiveEntry& contextEntry,
380  const OTstream& ots
381 )
382 {
383  contextEntry.read(parentDict, ITstream(ots.name(), ots)());
384  return true;
385 }
386 
387 
389 (
390  dictionary& contextDict,
391  const string& str
392 )
393 {
394  contextDict.read(IStringStream(str)());
395  return true;
396 }
397 
398 
400 (
401  const dictionary& parentDict,
402  primitiveEntry& contextEntry,
403  const string& str
404 )
405 {
406  contextEntry.read(parentDict, IStringStream(str)());
407  return true;
408 }
409 
410 
411 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
412 
414 (
415  const functionName& functionType,
416  const label lineNumber,
417  const dictionary& dict
418 )
419 :
420  primitiveEntry(lineNumber, keyType(functionType))
421 {}
422 
423 
425 (
426  const functionName& functionType,
427  const label lineNumber,
428  const dictionary& dict,
429  const Istream& is,
430  const token& token
431 )
432 :
434  (
435  lineNumber,
436  keyType(functionType),
437  ITstream(is.name(), token)
438  )
439 {}
440 
441 
443 (
444  const functionName& functionType,
445  const label lineNumber,
446  const dictionary& dict,
447  const Istream& is,
448  const tokenList& tokens
449 )
450 :
452  (
453  lineNumber,
454  keyType(functionType),
455  ITstream(is.name(), tokens)
456  )
457 {}
458 
459 
460 // * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
461 
463 (
464  const keyType& functionType,
465  const dictionary& parentDict,
466  Istream& is
467 )
468 {
469  // If the functionEntry constructor table has not yet been constructed
470  // assume the dictionary is a configuration dictionary for which
471  // functionEntries are not supported
472  if (!dictionaryConstructorTablePtr_)
473  {
474  cerr<< "--> FOAM Error: Found " << functionType
475  << " while reading configuration dictionary " << is.name()
476  << std::endl
477  << " Function entries cannot be used in "
478  "configuration dictionaries."
479  << std::endl;
480  std::exit(1);
481 
482  return autoPtr<functionEntry>(nullptr);
483  }
484 
485  dictionaryConstructorTable::iterator cstrIter =
486  dictionaryConstructorTablePtr_->find(functionType);
487 
488  if (cstrIter == dictionaryConstructorTablePtr_->end())
489  {
491  << "Unknown functionEntry "
492  << functionType << nl << nl
493  << "Valid functions are : " << nl
494  << dictionaryConstructorTablePtr_->sortedToc()
495  << exit(FatalError);
496 
497  return autoPtr<functionEntry>(nullptr);
498  }
499 
500  return autoPtr<functionEntry>(cstrIter()(is.lineNumber(), parentDict, is));
501 }
502 
503 
504 // * * * * * * * * * * * * Member Function Selectors * * * * * * * * * * * * //
505 
507 (
508  const word& functionName,
509  const dictionary& contextDict,
510  primitiveEntry& contextEntry,
511  Istream& is
512 )
513 {
514  is.fatalCheck
515  (
516  "functionEntry::execute"
517  "(const word&, const dictionary&, primitiveEntry&, Istream&)"
518  );
519 
520  if (!executeprimitiveEntryIstreamMemberFunctionTablePtr_)
521  {
522  cerr<< "functionEntry::execute"
523  << "(const word&, const dictionary&, primitiveEntry&, Istream&)"
524  << " not yet initialised, function = "
525  << functionName.c_str() << std::endl;
526 
527  // Return true to keep reading
528  return true;
529  }
530 
531  executeprimitiveEntryIstreamMemberFunctionTable::iterator mfIter =
532  executeprimitiveEntryIstreamMemberFunctionTablePtr_->find(functionName);
533 
534  if (mfIter == executeprimitiveEntryIstreamMemberFunctionTablePtr_->end())
535  {
537  << "Unknown functionEntry '" << functionName
538  << "' in " << is.name() << " at line " << is.lineNumber()
539  << nl << nl
540  << "Valid functionEntries are :" << endl
541  << executeprimitiveEntryIstreamMemberFunctionTablePtr_->toc()
542  << exit(FatalError);
543  }
544 
545  return mfIter()(contextDict, contextEntry, is);
546 }
547 
548 
550 {
551  writeKeyword(os, keyword());
552 
553  if (size())
554  {
555  primitiveEntry::write(os, true);
556  }
557 }
558 
559 
560 // ************************************************************************* //
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:73
label lineNumber() const
Return current stream line number.
Definition: IOstream.H:450
virtual const fileName & name() const
Return the name of the stream.
Definition: IOstream.H:297
void fatalCheck(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:121
bool bad() const
Return true if stream is corrupted.
Definition: IOstream.H:351
Input from memory buffer stream.
Definition: IStringStream.H:52
Input token stream.
Definition: ITstream.H:56
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:60
virtual Istream & read(token &)=0
Return next token from stream.
void putBack(const token &)
Put back token.
Definition: Istream.C:30
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:91
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
Output token stream.
Definition: OTstream.H:56
virtual const fileName & name() const
Return the name of the stream.
Definition: OTstream.H:86
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
Extract command arguments and options from the supplied argc and argv parameters.
Definition: argList.H:103
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 list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
bool read(Istream &, const bool keepHeader=false)
Read dictionary from Istream, optionally keeping the header.
Definition: dictionaryIO.C:105
static bool New(dictionary &parentDict, Istream &)
Construct from Istream and insert into dictionary.
Definition: entryIO.C:105
A functionEntry causes entries to be added/manipulated on the specified dictionary given an input str...
Definition: functionEntry.H:66
tokenList readArgOrList(const functionName &functionType, Istream &is) const
Read a single argument or list.
virtual void write(Ostream &) const
Write.
virtual bool execute(dictionary &contextDict, Istream &is)=0
Expand the functionEntry into the contextDict.
static bool insert(const dictionary &parentDict, dictionary &contextDict, const token &t, Istream &is)
Read entry starting from token t and insert into contextDict.
tokenList readFuncNameArgList(const functionName &functionType, Istream &is) const
Read the function name and optional argument list.
tokenList readArgList(const functionName &functionType, Istream &is, const bool optional=false) const
tokenList readFileNameArgList(const functionName &functionType, Istream &is) const
Read the filen name and optional argument list.
static autoPtr< functionEntry > New(const keyType &functionName, const dictionary &parentDict, Istream &is)
Construct from Istream and insert into dictionary.
A functionName is a word starting with '#'.
Definition: functionName.H:60
A class for handling keywords in dictionaries.
Definition: keyType.H:69
A keyword and a list of tokens is a 'primitiveEntry'. An primitiveEntry can be read,...
void write(Ostream &) const
Write.
friend class functionEntry
virtual bool read(const dictionary &, Istream &)
Read tokens from the given stream.
A token holds items read from Istream.
Definition: token.H:74
bool isPunctuation() const
Definition: tokenI.H:324
@ END_STATEMENT
Definition: token.H:109
@ BEGIN_LIST
Definition: token.H:110
@ END_LIST
Definition: token.H:111
punctuationToken pToken() const
Definition: tokenI.H:329
const string & anyStringToken() const
Definition: tokenI.H:444
bool isString() const
Definition: tokenI.H:396
bool good() const
Definition: tokenI.H:309
bool isWord() const
Definition: tokenI.H:342
const word & wordToken() const
Definition: tokenI.H:347
label lineNumber() const
Definition: tokenI.H:847
A class for handling words, derived from string.
Definition: word.H:63
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
const dimensionedScalar c
Speed of light in a vacuum.
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
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
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
defineFunctionTypeName(functionEntry)
defineRunTimeSelectionTable(fvConstraint, dictionary)
IOerror FatalIOError
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
error FatalError
Ostream & writeKeyword(Foam::Ostream &os, const keyType &kw)
Write the keyword to the Ostream with the current level of indentation.
Definition: keyType.C:155
defineMemberFunctionSelectionTable(edgeMesh, write, fileExtension)
static const char nl
Definition: Ostream.H:297
dictionary dict