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-2021 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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#include "evalEntry.H"
32
33// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34
35bool Foam::primitiveEntry::acceptToken
36(
37 const token& tok,
38 const dictionary& dict,
39 Istream& is
40)
41{
42 bool accept = tok.good();
43
44 if (tok.isDirective())
45 {
46 // Directive (wordToken) begins with '#'. Eg, "#include"
47 // Remove leading '#' sigil before dispatching
48
49 const word& key = tok.wordToken();
50
51 // Min-size is 2: sigil '#' with any content
52 accept =
53 (
54 (disableFunctionEntries || key.size() < 2)
55 || !expandFunction(key.substr(1), dict, is)
56 );
57 }
58 else if (tok.isExpression())
59 {
60 // Expression (stringToken): ${{ expr }}
61 // Surrounding delimiters are stripped as required in evalEntry
62
63 const string& key = tok.stringToken();
64
65 // Min-size is 6: decorators '${{}}' with any content
66 accept =
67 (
68 (disableFunctionEntries || key.size() < 6)
70 (
71 dict,
72 *this,
73 key,
74 1, // Field width is 1
75 is // For error messages
76 )
77 );
78 }
79 else if (tok.isVariable())
80 {
81 // Variable (stringToken): starts with '$'
82 // Eg, "$varName" or "${varName}"
83 // Remove leading '$' sigil before dispatching
84
85 const string& key = tok.stringToken();
86
87 // Min-size is 2: sigil '$' with any content
88 accept =
89 (
90 (disableFunctionEntries || key.size() < 2)
91 || !expandVariable(key.substr(1), dict)
92 );
93 }
94
95 return accept;
96}
97
98
99bool Foam::primitiveEntry::expandFunction
100(
101 const word& functionName,
102 const dictionary& dict,
103 Istream& is
104)
105{
106 return functionEntry::execute(functionName, dict, *this, is);
107}
108
109
111{
113
114 // Track balanced bracket/brace pairs, with max stack depth of 60.
115 // Use a bitmask to track the opening char: 0 = '()', 1 = '{}'
116 //
117 // Notes
118 // - the bitmask is set *before* increasing the depth since the left
119 // shift implicitly carries a 1-offset with it.
120 // Eg, (1u << 0) already corresponds to depth=1 (the first bit)
121 //
122 // - similarly, the bitmask is tested *after* decreasing depth
123
124 uint64_t balanced = 0u;
125 int depth = 0;
126 token tok;
127
128 while
129 (
130 !is.read(tok).bad() && tok.good()
131 && !(tok == token::END_STATEMENT && depth == 0)
132 )
133 {
134 if (tok.isPunctuation())
135 {
136 const char c = tok.pToken();
137 switch (c)
138 {
140 {
141 if (depth >= 0 && depth < 61)
142 {
143 balanced &= ~(1u << depth); // clear bit
144 }
145 ++depth;
146 }
147 break;
148
150 {
151 if (depth >= 0 && depth < 61)
152 {
153 balanced |= (1u << depth); // set bit
154 }
155 ++depth;
156 }
157 break;
158
159 case token::END_LIST:
160 {
161 --depth;
162 if (depth < 0)
163 {
164 reportReadWarning
165 (
166 is,
167 "Too many closing ')' ... was a ';' forgotten?"
168 );
169 }
170 else if (depth < 61 && ((balanced >> depth) & 1u))
171 {
172 // Bit was set, but expected it to be unset.
173 reportReadWarning(is, "Imbalanced '{' with ')'");
174 }
175 }
176 break;
177
178 case token::END_BLOCK:
179 {
180 --depth;
181 if (depth < 0)
182 {
183 reportReadWarning
184 (
185 is,
186 "Too many closing '}' ... was a ';' forgotten?"
187 );
188 }
189 else if (depth < 61 && !((balanced >> depth) & 1u))
190 {
191 // Bit was unset, but expected it to be set.
192 reportReadWarning(is, "Imbalanced '(' with '}'");
193 }
194 }
195 break;
196 }
197 }
198
199 if (acceptToken(tok, dict, is))
200 {
201 newElmt(tokenIndex()++) = std::move(tok);
202 }
203
204 // With/without move: clear any old content and force to have a
205 // known good token so that we can rely on it for the return value.
206
208 }
209
210 if (depth)
211 {
212 reportReadWarning(is, "Imbalanced brackets");
213 }
214
216 return tok.good();
217}
218
219
220void Foam::primitiveEntry::readEntry(const dictionary& dict, Istream& is)
221{
222 const label keywordLineNumber = is.lineNumber();
223 tokenIndex() = 0;
224
225 if (read(dict, is))
226 {
227 setSize(tokenIndex());
228 tokenIndex() = 0;
229 }
230 else
231 {
232 std::ostringstream os;
233 os << "ill defined primitiveEntry starting at keyword '"
234 << keyword() << '\''
235 << " on line " << keywordLineNumber
236 << " and ending at line " << is.lineNumber();
237
239 (
240 is,
241 os.str()
242 );
243 }
244}
245
246
247// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
248
250(
251 const keyType& key,
252 const dictionary& dict,
253 Istream& is
254)
255:
256 entry(key),
258 (
259 is.name() + '.' + key,
260 tokenList(10),
261 static_cast<IOstreamOption>(is)
262 )
263{
264 readEntry(dict, is);
265}
266
267
269:
270 primitiveEntry(key, dictionary::null, is)
271{}
272
273
274// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
275
276void Foam::primitiveEntry::write(Ostream& os, const bool contentsOnly) const
277{
278 if (!contentsOnly)
279 {
280 os.writeKeyword(keyword());
281 }
282
283 bool addSpace = false; // Separate from previous token with a space
284 for (const token& tok : *this)
285 {
286 if (addSpace) os << token::SPACE;
287 addSpace = true;
288
289 // Output token with direct handling in Ostream(s),
290 // or use normal '<<' output operator
291 if (!os.write(tok))
292 {
293 os << tok;
294 }
295 }
296
297 if (!contentsOnly)
298 {
300 }
301}
302
303
305{
306 this->write(os, false);
307}
308
309
310// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
311
312template<>
313Foam::Ostream& Foam::operator<<
314(
315 Ostream& os,
317)
318{
319 const primitiveEntry& e = ip.t_;
320
321 e.print(os);
322
323 const label nPrintTokens = 10;
324
325 os << " primitiveEntry '" << e.keyword() << "' comprises ";
326
327 for (label i=0; i<min(e.size(), nPrintTokens); ++i)
328 {
329 os << nl << " " << e[i].info();
330 }
331
332 if (e.size() > nPrintTokens)
333 {
334 os << " ...";
335 }
336
337 os << endl;
338
339 return os;
340}
341
342
343// ************************************************************************* //
InfoProxy< IOobject > info() const
Return info proxy, for printing information to a stream.
Definition: IOobject.H:690
The IOstreamOption is a simple container for options an IOstream can normally have.
label lineNumber() const noexcept
Const access to the current stream line number.
Definition: IOstream.H:318
bool fatalCheck(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:64
bool bad() const noexcept
True if stream is corrupted.
Definition: IOstream.H:251
An input stream of tokens.
Definition: ITstream.H:56
A helper class for outputting values to Ostream.
Definition: InfoProxy.H:52
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:64
virtual Istream & read(token &)=0
Return next token from stream.
virtual Ostream & write(const char c)
Write character.
Definition: OBJstream.C:78
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:62
virtual Ostream & writeKeyword(const keyType &kw)
Write the keyword followed by an appropriate indentation.
Definition: Ostream.C:57
virtual bool read()
Re-read model coefficients if they have changed.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:70
static int disableFunctionEntries
Enable or disable use of function entries and variable expansions.
Definition: entry.H:127
virtual bool execute()
Calculate the output fields.
virtual bool write()
Write the output fields.
A class for handling keywords in dictionaries.
Definition: keyType.H:71
A keyword and a list of tokens comprise a primitiveEntry. A primitiveEntry can be read,...
virtual const dictionary & dict() const
This entry is not a dictionary,.
A token holds an item read from Istream.
Definition: token.H:69
bool isPunctuation() const noexcept
Token is PUNCTUATION.
Definition: tokenI.H:459
@ BEGIN_BLOCK
Begin block [isseparator].
Definition: token.H:159
@ END_BLOCK
End block [isseparator].
Definition: token.H:160
@ END_STATEMENT
End entry [isseparator].
Definition: token.H:154
@ NULL_TOKEN
Nul character.
Definition: token.H:122
@ BEGIN_LIST
Begin list [isseparator].
Definition: token.H:155
@ END_LIST
End list [isseparator].
Definition: token.H:156
@ SPACE
Space [isspace].
Definition: token.H:125
punctuationToken pToken() const
Return punctuation character.
Definition: tokenI.H:485
bool good() const noexcept
True if token is not UNDEFINED or ERROR.
Definition: tokenI.H:405
#define SafeFatalIOErrorInFunction(ios, msg)
Report an error message using Foam::FatalIOError.
Definition: error.H:497
OBJstream os(runTime.globalPath()/outputName)
#define FUNCTION_NAME
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:108
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:108
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
runTime write()
points setSize(newPointi)
dictionary dict
volScalarField & e
Definition: createFields.H:11