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-2020 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.isDirective())
65  {
66  // Directive: wordToken starts with '#'
67  const word& key = tok.wordToken();
68 
69  accept =
70  (
72  || key.size() == 1
73  || !expandFunction(key.substr(1), dict, is)
74  );
75  }
76  else if (tok.isVariable())
77  {
78  // Variable: stringToken starts with '$'
79  const string& key = tok.stringToken();
80 
81  accept =
82  (
84  || key.size() == 1
85  || !expandVariable(key.substr(1), dict)
86  );
87  }
88 
89  return accept;
90 }
91 
92 
93 bool Foam::primitiveEntry::expandFunction
94 (
95  const word& functionName,
96  const dictionary& dict,
97  Istream& is
98 )
99 {
100  return functionEntry::execute(functionName, dict, *this, is);
101 }
102 
103 
105 {
107 
108  // Track balanced bracket/brace pairs, with max stack depth of 60.
109  // Use a bitmask to track the opening char: 0 = '()', 1 = '{}'
110  //
111  // Notes
112  // - the bitmask is set *before* increasing the depth since the left
113  // shift implicitly carries a 1-offset with it.
114  // Eg, (1u << 0) already corresponds to depth=1 (the first bit)
115  //
116  // - similarly, the bitmask is tested *after* decreasing depth
117 
118  uint64_t balanced = 0u;
119  label depth = 0;
120  token tok;
121 
122  while
123  (
124  !is.read(tok).bad() && tok.good()
125  && !(tok == token::END_STATEMENT && depth == 0)
126  )
127  {
128  if (tok.isPunctuation())
129  {
130  const char c = tok.pToken();
131  switch (c)
132  {
133  case token::BEGIN_LIST:
134  {
135  if (depth >= 0 && depth < 61)
136  {
137  balanced &= ~(1u << depth); // clear bit
138  }
139  ++depth;
140  }
141  break;
142 
143  case token::BEGIN_BLOCK:
144  {
145  if (depth >= 0 && depth < 61)
146  {
147  balanced |= (1u << depth); // set bit
148  }
149  ++depth;
150  }
151  break;
152 
153  case token::END_LIST:
154  {
155  --depth;
156  if (depth < 0)
157  {
158  safeIOWarning
159  (
160  is,
161  "Too many closing ')' ... was a ';' forgotten?"
162  );
163  }
164  else if (depth < 61 && ((balanced >> depth) & 1u))
165  {
166  // Bit was set, but expected it to be unset.
167  safeIOWarning(is, "Imbalanced '{' with ')'");
168  }
169  }
170  break;
171 
172  case token::END_BLOCK:
173  {
174  --depth;
175  if (depth < 0)
176  {
177  safeIOWarning
178  (
179  is,
180  "Too many closing '}' ... was a ';' forgotten?"
181  );
182  }
183  else if (depth < 61 && !((balanced >> depth) & 1u))
184  {
185  // Bit was unset, but expected it to be set.
186  safeIOWarning(is, "Imbalanced '(' with '}'");
187  }
188  }
189  break;
190  }
191  }
192 
193  if (acceptToken(tok, dict, is))
194  {
195  newElmt(tokenIndex()++) = std::move(tok);
196  }
197 
198  // With/without move: clear any old content and force to have a
199  // known good token so that we can rely on it for the return value.
200 
201  tok = token::punctuationToken::NULL_TOKEN;
202  }
203 
204  if (depth)
205  {
206  safeIOWarning(is, "Imbalanced brackets");
207  }
208 
210  return tok.good();
211 }
212 
213 
214 void Foam::primitiveEntry::readEntry(const dictionary& dict, Istream& is)
215 {
216  const label keywordLineNumber = is.lineNumber();
217  tokenIndex() = 0;
218 
219  if (read(dict, is))
220  {
221  setSize(tokenIndex());
222  tokenIndex() = 0;
223  }
224  else
225  {
226  std::ostringstream os;
227  os << "ill defined primitiveEntry starting at keyword '"
228  << keyword() << '\''
229  << " on line " << keywordLineNumber
230  << " and ending at line " << is.lineNumber();
231 
233  (
234  is,
235  os.str()
236  );
237  }
238 }
239 
240 
241 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
242 
244 (
245  const keyType& key,
246  const dictionary& dict,
247  Istream& is
248 )
249 :
250  entry(key),
251  ITstream
252  (
253  is.name() + '.' + key,
254  tokenList(10),
255  is.format(),
256  is.version()
257  )
258 {
259  readEntry(dict, is);
260 }
261 
262 
264 :
265  primitiveEntry(key, dictionary::null, is)
266 {}
267 
268 
269 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
270 
271 void Foam::primitiveEntry::write(Ostream& os, const bool contentsOnly) const
272 {
273  if (!contentsOnly)
274  {
275  os.writeKeyword(keyword());
276  }
277 
278  bool addSpace = false; // Separate from previous tokens with a space
279  for (const token& tok : *this)
280  {
281  if (addSpace) os << token::SPACE;
282 
283  // Try to output token directly, with special handling in Ostreams.
284 
285  if (!os.write(tok))
286  {
287  os << tok; // Revert to normal '<<' output operator
288  }
289 
290  addSpace = true; // Separate from following tokens
291  }
292 
293  if (!contentsOnly)
294  {
295  os << token::END_STATEMENT << endl;
296  }
297 }
298 
299 
301 {
302  this->write(os, false);
303 }
304 
305 
306 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
307 
308 template<>
309 Foam::Ostream& Foam::operator<<
310 (
311  Ostream& os,
312  const InfoProxy<primitiveEntry>& ip
313 )
314 {
315  const primitiveEntry& e = ip.t_;
316 
317  e.print(os);
318 
319  const label nPrintTokens = 10;
320 
321  os << " primitiveEntry '" << e.keyword() << "' comprises ";
322 
323  for (label i=0; i<min(e.size(), nPrintTokens); ++i)
324  {
325  os << nl << " " << e[i].info();
326  }
327 
328  if (e.size() > nPrintTokens)
329  {
330  os << " ...";
331  }
332 
333  os << endl;
334 
335  return os;
336 }
337 
338 
339 // ************************************************************************* //
Foam::entry
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:67
setSize
points setSize(newPointi)
Foam::primitiveEntry
A keyword and a list of tokens comprise a primitiveEntry. A primitiveEntry can be read,...
Definition: primitiveEntry.H:63
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)
Construct from keyword and no tokens.
Definition: primitiveEntry.C:216
Foam::IOstream::fatalCheck
bool fatalCheck(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:57
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:289
Foam::primitiveEntry::read
virtual bool read(const dictionary &dict, Istream &is)
Read tokens from the given stream.
Definition: primitiveEntryIO.C:104
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
Foam::token
A token holds an item read from Istream.
Definition: token.H:68
Foam::primitiveEntry::write
virtual void write(Ostream &os) const
Write.
Definition: primitiveEntryIO.C:300
functionEntry.H
Foam::primitiveEntry::dict
virtual const dictionary & dict() const
This entry is not a dictionary,.
Definition: primitiveEntry.C:297
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:459
Foam::keyType
A class for handling keywords in dictionaries.
Definition: keyType.H:60
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::token::isPunctuation
bool isPunctuation() const noexcept
Token is PUNCTUATION.
Definition: tokenI.H:453
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:121
Foam::token::END_BLOCK
End block [isseparator].
Definition: token.H:127
Foam::IOstreamOption::version
versionNumber version() const noexcept
Get the stream version.
Definition: IOstreamOption.H:341
dict
dictionary dict
Definition: searchingEngine.H:14
SafeFatalIOErrorInFunction
#define SafeFatalIOErrorInFunction(ios, msg)
Report an error message using Foam::FatalIOError.
Definition: error.H:425
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:242
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:126
Foam::tokenList
List< token > tokenList
List of tokens, used for a IOdictionary entry.
Definition: tokenList.H:44
Foam::token::good
bool good() const noexcept
True if token is not UNDEFINED or ERROR.
Definition: tokenI.H:399
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::token::SPACE
Space [isspace].
Definition: token.H:117
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
FUNCTION_NAME
#define FUNCTION_NAME
Definition: messageStream.H:270
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:123
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:309
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::token::BEGIN_LIST
Begin list [isseparator].
Definition: token.H:122
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.