primitiveEntryIO.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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2015 OpenFOAM Foundation
9  Copyright (C) 2017-2019 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "primitiveEntry.H"
30 #include "functionEntry.H"
31 
32 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
33 
34 namespace
35 {
36  // This is akin to a SafeIOWarning, which does not yet exist
37  inline void safeIOWarning
38  (
39  const Foam::IOstream& is,
40  const std::string& msg
41  )
42  {
43  std::cerr
44  << "--> FOAM Warning :\n"
45  << " Reading \"" << is.name() << "\" at line "
46  << is.lineNumber() << '\n'
47  << " " << msg << std::endl;
48  }
49 
50 } // End anonymous namespace
51 
52 
53 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
54 
55 bool Foam::primitiveEntry::acceptToken
56 (
57  const token& tok,
58  const dictionary& dict,
59  Istream& is
60 )
61 {
62  bool accept = tok.good();
63 
64  if (tok.isWord())
65  {
66  const word& key = tok.wordToken();
67 
68  accept =
69  (
71  || key.size() == 1
72  || (
73  !(key[0] == '$' && expandVariable(key.substr(1), dict))
74  && !(key[0] == '#' && expandFunction(key.substr(1), dict, is))
75  )
76  );
77  }
78  else if (tok.isVariable())
79  {
80  const string& key = tok.stringToken();
81 
82  accept =
83  (
85  || key.size() == 1
86  || !(key[0] == '$' && expandVariable(key.substr(1), dict))
87  );
88  }
89 
90  return accept;
91 }
92 
93 
94 bool Foam::primitiveEntry::expandFunction
95 (
96  const word& functionName,
97  const dictionary& dict,
98  Istream& is
99 )
100 {
101  return functionEntry::execute(functionName, dict, *this, is);
102 }
103 
104 
106 {
108 
109  // Track balanced bracket/brace pairs, with max stack depth of 60.
110  // Use a bitmask to track the opening char: 0 = '()', 1 = '{}'
111  //
112  // Notes
113  // - the bitmask is set *before* increasing the depth since the left
114  // shift implicitly carries a 1-offset with it.
115  // Eg, (1u << 0) already corresponds to depth=1 (the first bit)
116  //
117  // - similarly, the bitmask is tested *after* decreasing depth
118 
119  uint64_t balanced = 0u;
120  label depth = 0;
121  token tok;
122 
123  while
124  (
125  !is.read(tok).bad() && tok.good()
126  && !(tok == token::END_STATEMENT && depth == 0)
127  )
128  {
129  if (tok.isPunctuation())
130  {
131  const char c = tok.pToken();
132  switch (c)
133  {
134  case token::BEGIN_LIST:
135  {
136  if (depth >= 0 && depth < 61)
137  {
138  balanced &= ~(1u << depth); // clear bit
139  }
140  ++depth;
141  }
142  break;
143 
144  case token::BEGIN_BLOCK:
145  {
146  if (depth >= 0 && depth < 61)
147  {
148  balanced |= (1u << depth); // set bit
149  }
150  ++depth;
151  }
152  break;
153 
154  case token::END_LIST:
155  {
156  --depth;
157  if (depth < 0)
158  {
159  safeIOWarning
160  (
161  is,
162  "Too many closing ')' ... was a ';' forgotten?"
163  );
164  }
165  else if (depth < 61 && ((balanced >> depth) & 1u))
166  {
167  // Bit was set, but expected it to be unset.
168  safeIOWarning(is, "Imbalanced '{' with ')'");
169  }
170  }
171  break;
172 
173  case token::END_BLOCK:
174  {
175  --depth;
176  if (depth < 0)
177  {
178  safeIOWarning
179  (
180  is,
181  "Too many closing '}' ... was a ';' forgotten?"
182  );
183  }
184  else if (depth < 61 && !((balanced >> depth) & 1u))
185  {
186  // Bit was unset, but expected it to be set.
187  safeIOWarning(is, "Imbalanced '(' with '}'");
188  }
189  }
190  break;
191  }
192  }
193 
194  if (acceptToken(tok, dict, is))
195  {
196  newElmt(tokenIndex()++) = std::move(tok);
197  }
198 
199  // With/without move: clear any old content and force to have a
200  // known good token so that we can rely on it for the return value.
201 
202  tok = token::punctuationToken::NULL_TOKEN;
203  }
204 
205  if (depth)
206  {
207  safeIOWarning(is, "Imbalanced brackets");
208  }
209 
211  return tok.good();
212 }
213 
214 
215 void Foam::primitiveEntry::readEntry(const dictionary& dict, Istream& is)
216 {
217  const label keywordLineNumber = is.lineNumber();
218  tokenIndex() = 0;
219 
220  if (read(dict, is))
221  {
222  setSize(tokenIndex());
223  tokenIndex() = 0;
224  }
225  else
226  {
227  std::ostringstream os;
228  os << "ill defined primitiveEntry starting at keyword '"
229  << keyword() << '\''
230  << " on line " << keywordLineNumber
231  << " and ending at line " << is.lineNumber();
232 
234  (
235  is,
236  os.str()
237  );
238  }
239 }
240 
241 
242 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
243 
245 (
246  const keyType& key,
247  const dictionary& dict,
248  Istream& is
249 )
250 :
251  entry(key),
252  ITstream
253  (
254  is.name() + '.' + key,
255  tokenList(10),
256  is.format(),
257  is.version()
258  )
259 {
260  readEntry(dict, is);
261 }
262 
263 
265 :
266  primitiveEntry(key, dictionary::null, is)
267 {}
268 
269 
270 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
271 
272 void Foam::primitiveEntry::write(Ostream& os, const bool contentsOnly) const
273 {
274  if (!contentsOnly)
275  {
276  os.writeKeyword(keyword());
277  }
278 
279  bool addSpace = false; // Separate from previous tokens with a space
280  for (const token& tok : *this)
281  {
282  if (addSpace) os << token::SPACE;
283 
284  // Try to output token directly, with special handling in Ostreams.
285 
286  if (!os.write(tok))
287  {
288  os << tok; // Revert to normal '<<' output operator
289  }
290 
291  addSpace = true; // Separate from following tokens
292  }
293 
294  if (!contentsOnly)
295  {
296  os << token::END_STATEMENT << endl;
297  }
298 }
299 
300 
302 {
303  this->write(os, false);
304 }
305 
306 
307 // * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * * * //
308 
309 template<>
310 Foam::Ostream& Foam::operator<<
311 (
312  Ostream& os,
313  const InfoProxy<primitiveEntry>& ip
314 )
315 {
316  const primitiveEntry& e = ip.t_;
317 
318  e.print(os);
319 
320  const label nPrintTokens = 10;
321 
322  os << " primitiveEntry '" << e.keyword() << "' comprises ";
323 
324  for (label i=0; i<min(e.size(), nPrintTokens); ++i)
325  {
326  os << nl << " " << e[i].info();
327  }
328 
329  if (e.size() > nPrintTokens)
330  {
331  os << " ...";
332  }
333 
334  os << endl;
335 
336  return os;
337 }
338 
339 
340 // ************************************************************************* //
Foam::entry
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:67
setSize
points setSize(newPointi)
Foam::IOstream::fatalCheck
void fatalCheck(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:64
Foam::primitiveEntry
A keyword and a list of tokens comprise a primitiveEntry. A primitiveEntry can be read,...
Definition: primitiveEntry.H:62
primitiveEntry.H
Foam::InfoProxy
A helper class for outputting values to Ostream.
Definition: InfoProxy.H:47
Foam::read
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:108
Foam::primitiveEntry::primitiveEntry
primitiveEntry(const keyType &key, Istream &is)
Construct from keyword and a Istream.
Definition: primitiveEntryIO.C:264
Foam::IOstream
An IOstream is an abstract base class for all input/output systems; be they streams,...
Definition: IOstream.H:75
Foam::IOstreamOption::format
streamFormat format() const noexcept
Get the current stream format.
Definition: IOstreamOption.H:273
Foam::primitiveEntry::read
virtual bool read(const dictionary &dict, Istream &is)
Read tokens from the given stream.
Definition: primitiveEntryIO.C:105
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::token
A token holds an item read from Istream.
Definition: token.H:69
Foam::primitiveEntry::write
virtual void write(Ostream &os) const
Write.
Definition: primitiveEntryIO.C:301
functionEntry.H
Foam::token::good
bool good() const
True if token is not UNDEFINED or ERROR.
Definition: tokenI.H:368
Foam::primitiveEntry::dict
virtual const dictionary & dict() const
This entry is not a dictionary,.
Definition: primitiveEntry.C:182
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::token::pToken
punctuationToken pToken() const
Return punctuation character.
Definition: tokenI.H:428
Foam::keyType
A class for handling keywords in dictionaries.
Definition: keyType.H:60
Foam::label
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:62
Foam::ITstream
An input stream of tokens.
Definition: ITstream.H:55
Foam::Istream
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:61
Foam::IOstream::name
virtual const fileName & name() const
Return the name of the stream.
Definition: IOstream.C:39
Foam::token::END_STATEMENT
End entry [isseparator].
Definition: token.H:116
Foam::token::END_BLOCK
End block [isseparator].
Definition: token.H:122
Foam::IOstreamOption::version
versionNumber version() const noexcept
Get the stream version.
Definition: IOstreamOption.H:321
dict
dictionary dict
Definition: searchingEngine.H:14
SafeFatalIOErrorInFunction
#define SafeFatalIOErrorInFunction(ios, msg)
Report an error message using Foam::FatalIOError.
Definition: error.H:399
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
Foam::IOstream::bad
bool bad() const
Return true if stream is corrupted.
Definition: IOstream.H:234
Foam::Ostream::write
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
Foam::Ostream::writeKeyword
virtual Ostream & writeKeyword(const keyType &kw)
Write the keyword followed by an appropriate indentation.
Definition: Ostream.C:57
Foam::entry::disableFunctionEntries
static int disableFunctionEntries
Enable or disable use of function entries and variable expansions.
Definition: entry.H:119
Foam::token::BEGIN_BLOCK
Begin block [isseparator].
Definition: token.H:121
Foam::tokenList
List< token > tokenList
List of tokens, used for a IOdictionary entry.
Definition: tokenList.H:44
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::token::SPACE
Space [isspace].
Definition: token.H:112
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
FUNCTION_NAME
#define FUNCTION_NAME
Definition: messageStream.H:261
Foam::vtk::write
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
Definition: foamVtkOutputTemplates.C:35
Foam::token::END_LIST
End list [isseparator].
Definition: token.H:118
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::IOstream::lineNumber
label lineNumber() const
Const access to the current stream line number.
Definition: IOstream.H:301
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::token::isPunctuation
bool isPunctuation() const
Token is PUNCTUATION.
Definition: tokenI.H:422
Foam::token::BEGIN_LIST
Begin list [isseparator].
Definition: token.H:117
Foam::functionEntry::execute
static bool execute(const word &functionName, dictionary &parentDict, Istream &is)
Execute the functionEntry in a sub-dict context.
Definition: functionEntry.C:83
Foam::Istream::read
virtual Istream & read(token &)=0
Return next token from stream.