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 -------------------------------------------------------------------------------
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 "expressionEntry.H"
30 #include "stringOps.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38 namespace 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 
84 namespace Foam
85 {
86 inline 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
98  << exit(FatalIOError);
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 - 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
264 
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 // ************************************************************************* //
dictionary dict
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
defineTypeName(expressionEntry)
static void inplaceExpand(std::string &s, const dictionary &dict)
Inplace expand expression with dictionary variables/entries.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
void inplaceTrim(std::string &s)
Trim leading and trailing whitespace inplace.
Definition: stringOps.C:1054
#define FatalErrorInLookup(lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalError.
Definition: error.H:605
std::string toString() const
Concatenate tokens into a space-separated std::string. The resulting string may contain quote charact...
Definition: ITstream.C:316
Macros for easy insertion into run-time selection tables.
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:114
Convert dictionary entry to a stringified expression.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
static autoPtr< expressionEntry > New(const word &name)
Return an entry to expression converter.
static expressions::exprString expand(const std::string &str, const dictionary &dict)
Expand expression with dictionary entries.
A class for handling words, derived from Foam::string.
Definition: word.H:63
A variant of Foam::string with expansion of dictionary variables into a comma-separated form...
Definition: exprString.H:55
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:68
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...
Definition: stringOps.C:718
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:627
virtual bool isDict() const noexcept
Return true if this entry is a dictionary.
Definition: entry.H:287
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
Macros to ease declaration of run-time selection tables.
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))
virtual ITstream & stream() const =0
Return token stream, if entry is a primitive entry.
addNamedToRunTimeSelectionTable(expressionEntry, expressionEntry, empty, direct)
static const entry * getVariableOrDie(const word &name, const dictionary &dict)
defineRunTimeSelectionTable(expressionEntry, empty)
An input stream of tokens.
Definition: ITstream.H:52
Namespace for OpenFOAM.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...