Loading...
Searching...
No Matches
expressionEntry.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) 2014-2018 Bernhard Gschaider
9 Copyright (C) 2019-2023 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 "expressionEntry.H"
30#include "stringOps.H"
33
34// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36namespace Foam
37{
38namespace exprTools
40
43
44// Various types can be used directly without any changes
45
50 empty,
51 direct
52);
53
58 empty,
59 label
60);
61
66 empty,
67 scalar
68);
69
71(
74 empty,
75 word
76);
77
78} // End namespace exprTools
79} // End namespace Foam
80
81
82// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
83
84namespace Foam
85{
86inline static const entry* getVariableOrDie
87(
88 const word& name,
89 const dictionary& dict
90)
91{
92 const entry* eptr = dict.findScoped(name, keyType::LITERAL_RECURSIVE);
93
94 if (!eptr)
95 {
97 << "No dictionary entry " << name << nl
99 }
100
101 if (eptr->isDict())
102 {
104 << "Found dictionary " << name << " instead of entry" << nl
105 << exit(FatalIOError);
106 }
107
108 return eptr;
109}
111} // End namespace Foam
112
113
114// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
115
118(
119 const word& name
120)
121{
122 auto* ctorPtr = emptyConstructorTable(name);
123
124 if (!ctorPtr)
125 {
127 (
128 "expressionEntry",
129 name,
130 *emptyConstructorTablePtr_
131 ) << exit(FatalError);
132 }
134 return autoPtr<expressionEntry>(ctorPtr());
135}
136
137
138// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
139
141(
142 std::string& s,
143 const dictionary& dict
144)
145{
146 // This is much like stringOps::inplaceExpand
147 constexpr const char sigil = '$';
148
149 // Step 1:
150 // Handle $[] special expansions first
151
152 std::string::size_type varBeg = 0;
153
154 while
155 (
156 (varBeg = s.find(sigil, varBeg)) != std::string::npos
157 && varBeg < s.size()-1
158 )
159 {
160 if (varBeg && s[varBeg-1] == '\\')
161 {
162 // Escaped character - pass through
163 ++varBeg;
164 continue;
165 }
166
167 if (s[varBeg+1] == '[')
168 {
169 // An expression pattern with $[...]
170
171 std::string::size_type varEnd = s.find(']', varBeg);
172 std::string::size_type delim = 1;
173
174 if (varEnd == std::string::npos)
175 {
176 // Parsed '$[...' without closing ']' - error
178 << "No correct terminating ']' found in " << s << nl
179 << exit(FatalError);
180 break;
181 }
182
183 // Look for embedded (type) cast
184 word castTo, varName;
185
186 const auto lparen = varBeg+2;
187 if (lparen < s.size() && s[lparen] == '(')
188 {
189 const auto rparen = s.find(')', lparen);
190
191 if (rparen > varEnd)
192 {
193 // Handles both "$[( ...]" and "$[( ...])" cases
194
195 auto& err = FatalErrorInFunction;
196
197 if (rparen == std::string::npos)
198 {
199 err << "No closing ')' found in ";
200 }
201 else
202 {
203 err << "Closing ')' found outside of";
204 }
205
206 err << " substring "
207 << s.substr(varBeg, varEnd-varBeg) << nl
208 << exit(FatalError);
209 }
210
211 castTo.assign(s.substr(lparen+1, rparen - lparen - 1));
212 varName.assign(s.substr(rparen+1, varEnd - rparen - 1));
213 }
214 else
215 {
216 varName.assign
217 (
218 s.substr(varBeg + 1 + delim, varEnd - varBeg - 2*delim)
219 );
220 }
221
222 // Likely no spaces there, but for extra safety...
223 stringOps::inplaceTrim(varName);
224
225 // Allow recursive plain expansion for the *variable* name.
226 // This means "$[(vector) var${index} ]" should work
227
228 // Expand with env=true, empty=true, subDict=false
229 stringOps::inplaceExpand(varName, dict, true, true, false);
230
231 // Length of original text to replace (incl. decorators)
232 const auto replaceLen = (varEnd - varBeg + 1);
233
234 // Get primitiveEntry with env=false, subDict=false
235 const entry* eptr = getVariableOrDie(varName, dict);
236
237 std::string varValue;
238
239 if (castTo.empty())
240 {
241 // Serialized with spaces - fails for non-primitiveEntry
242 ITstream& its = eptr->stream();
243 varValue = its.toString();
244 }
245 else
246 {
247 varValue = expressionEntry::New(castTo)->toExpr(*eptr);
248 }
249
250 s.std::string::replace(varBeg, replaceLen, varValue);
251 varBeg += varValue.size();
252 }
253 else
254 {
255 ++varBeg;
256 }
257 }
258
259
260 // Step 2:
261 // Handle all ${}, $var and ${{ ... }} expansions.
262 // - this is done second such that $[(vector) xyz] entries will have
263 // been properly expanded by this stage
265 // Expand with env=true, empty=true, subDict=false
266 stringOps::inplaceExpand(s, dict, true, true, false);
267}
268
269
272(
273 const std::string& orig,
274 const dictionary& dict
275)
276{
277 // Copy without validation (use assign)
279 s.assign(orig);
280
281 inplaceExpand(s, dict);
282
283 return s;
284}
285
286
287// ************************************************************************* //
Macros for easy insertion into run-time selection tables.
#define addNamedToRunTimeSelectionTable(baseType, thisType, argNames, lookupName)
Add to construction table with 'lookupName' as the key.
An input stream of tokens.
Definition ITstream.H:56
std::string toString() const
Concatenate tokens into a space-separated std::string. The resulting string may contain quote charact...
Definition ITstream.C:289
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
A keyword and a list of tokens is an 'entry'.
Definition entry.H:66
virtual ITstream & stream() const =0
Return token stream, if entry is a primitive entry.
virtual bool isDict() const noexcept
True if this entry is a dictionary.
Definition entry.H:284
Convert dictionary entry to a stringified expression.
static expressions::exprString expand(const std::string &str, const dictionary &dict)
Expand expression with dictionary entries.
static void inplaceExpand(std::string &s, const dictionary &dict)
Inplace expand expression with dictionary variables/entries.
static autoPtr< expressionEntry > New(const word &name)
Return an entry to expression converter.
A variant of Foam::string with expansion of dictionary variables into a comma-separated form.
Definition exprString.H:58
@ LITERAL_RECURSIVE
Definition keyType.H:87
A class for handling words, derived from Foam::string.
Definition word.H:66
#define defineTypeName(Type)
Define the typeName.
Definition className.H:113
#define FatalErrorInLookup(lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalError.
Definition error.H:607
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
auto & name
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Helper methods for creating expressions.
void inplaceExpand(std::string &s, const HashTable< string > &mapping, const char sigil='$')
Inplace expand occurrences of variables according to the mapping. Does not use environment values.
void inplaceTrim(std::string &s)
Trim leading and trailing whitespace inplace.
Namespace for OpenFOAM.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition exprTraits.C:127
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
static const entry * getVariableOrDie(const word &name, const dictionary &dict)
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
Macros to ease declaration of run-time selection tables.
#define defineRunTimeSelectionTable(baseType, argNames)
Define run-time selection table.
dictionary dict