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 Original code Copyright (C) 2014-2018 Bernhard Gschaider
9 Copyright (C) 2019-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 "expressionEntry.H"
30#include "stringOps.H"
33
34// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35
36namespace Foam
37{
38namespace exprTools
39{
40
43
44// Various types can be used directly without any changes
45
47(
50 empty,
51 direct
52);
53
55(
58 empty,
59 label
60);
61
63(
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{
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}
110
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 }
133
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
242 ITstream& its = eptr->stream();
243
244 if (its.size() == 1 && its[0].isStringType())
245 {
246 // Already a string-type (WORD, STRING, ...). Just copy.
247 varValue = its[0].stringToken();
248 }
249 else
250 {
251 varValue = its.toString();
252 }
253 }
254 else
255 {
256 varValue = expressionEntry::New(castTo)->toExpr(*eptr);
257 }
258
259 s.std::string::replace(varBeg, replaceLen, varValue);
260 varBeg += varValue.size();
261 }
262 else
263 {
264 ++varBeg;
265 }
266 }
267
268
269 // Step 2:
270 // Handle all ${}, $var and ${{ ... }} expansions.
271 // - this is done second such that $[(vector) xyz] entries will have
272 // been properly expanded by this stage
273
274 // Expand with env=true, empty=true, subDict=false
275 stringOps::inplaceExpand(s, dict, true, true, false);
276}
277
278
281(
282 const std::string& orig,
283 const dictionary& dict
284)
285{
286 // Copy without validation (use assign)
288 s.assign(orig);
289
290 inplaceExpand(s, dict);
291
292 return s;
293}
294
295
296// ************************************************************************* //
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
Definition: ITstream.C:320
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
const entry * findScoped(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search for a scoped entry (const access) with the given keyword.
Definition: dictionaryI.H:117
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:70
virtual ITstream & stream() const =0
Return token stream, if entry is a primitive entry.
virtual bool isDict() const noexcept
Return true if this entry is a dictionary.
Definition: entry.H:233
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.
@ LITERAL_RECURSIVE
Definition: keyType.H:86
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define defineTypeName(Type)
Define the typeName.
Definition: className.H:96
#define FatalErrorInLookup(lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalError.
Definition: error.H:457
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
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))
A variant of Foam::string with expansion of dictionary variables into a comma-separated form.
void inplaceExpand(std::string &s, const HashTable< string > &mapping, const char sigil='$')
Definition: stringOps.C:731
void inplaceTrim(std::string &s)
Trim leading and trailing whitespace inplace.
Definition: stringOps.C:1067
Namespace for OpenFOAM.
IOerror FatalIOError
error FatalError
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
static const entry * getVariableOrDie(const word &name, const dictionary &dict)
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
Macros to ease declaration of run-time selection tables.
#define defineRunTimeSelectionTable(baseType, argNames)
Define run-time selection table.
dictionary dict