ISstream.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-2016 OpenFOAM Foundation
9  Copyright (C) 2017-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 "ISstream.H"
30 #include "int.H"
31 #include "token.H"
32 #include <cctype>
33 #include <cstring>
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 // Truncate error message for readability
38 static constexpr const unsigned errLen = 80;
39 
40 
41 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
42 
43 namespace
44 {
45 
46 // Convert a single character to a word with length 1
47 inline Foam::word charToWord(char c)
48 {
49  return Foam::word(std::string(1, c), false);
50 }
51 
52 
53 // Permit slash-scoping of entries
54 inline bool validVariableChar(char c)
55 {
56  return (Foam::word::valid(c) || c == '/');
57 }
58 
59 
60 inline void inplaceTrimRight(std::string& s)
61 {
62  auto end = s.length();
63  if (end)
64  {
65  while (end && Foam::isspace(s[end-1]))
66  {
67  --end;
68  }
69 
70  s.erase(end);
71  }
72 }
73 
74 } // End anonymous namespace
75 
76 
77 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
78 
79 bool Foam::ISstream::readCompoundToken
80 (
81  token& tok,
82  const word& compoundType
83 )
84 {
85  return tok.readCompoundToken(compoundType, *this);
86 }
87 
88 
89 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
90 
92 {
93  // Search for end of C-style comment - "*/"
94 
95  // Can use getLine(nullptr, '*') in the logic,
96  // but written out looks less obscure
97 
98  char c = 0;
99  bool star = false;
100 
101  while (get(c))
102  {
103  if (c == '*')
104  {
105  star = true;
106  }
107  else if (star)
108  {
109  star = false;
110  if (c == '/')
111  {
112  // Matched "*/"
113  return true;
114  }
115  }
116  }
117 
118  // Exhausted stream without finding "*/" sequence
119  return false;
120 }
121 
122 
123 char Foam::ISstream::nextValid()
124 {
125  char c = 0;
126 
127  // Get next non-whitespace character
128  while (get(c))
129  {
130  if (isspace(c))
131  {
132  continue;
133  }
134 
135  // Check if this starts a C/C++ comment
136  if (c == '/')
137  {
138  if (!get(c))
139  {
140  // Cannot get another character - return this one
141  return '/';
142  }
143 
144  if (c == '/')
145  {
146  // C++ comment: discard through newline
147  (void) getLine(nullptr, '\n');
148  }
149  else if (c == '*')
150  {
151  // C-style comment: discard through to "*/" ending
152  if (!seekCommentEnd_Cstyle())
153  {
154  return 0; // Premature end of stream
155  }
156  }
157  else
158  {
159  // The '/' did not start a C/C++ comment - return it
160  putback(c);
161  return '/';
162  }
163  }
164  else
165  {
166  // A valid character - return it
167  return c;
168  }
169  }
170 
171  return 0;
172 }
173 
174 
175 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
176 
177 namespace Foam
178 {
179 
180 // Read a verbatim string (excluding block delimiters),
181 // continuing until a closing "#}" has been found.
182 //
183 // The leading "#{" removed from stream prior to calling.
184 static ISstream& readVerbatim
185 (
186  ISstream& is,
187  std::string& str
188 )
189 {
190  constexpr const unsigned bufLen = 8000;
191  static char buf[bufLen];
192 
193  unsigned nChar = 0;
194  char c;
195 
196  str.clear();
197  while (is.get(c))
198  {
199  if (c == token::HASH)
200  {
201  char nextC;
202  is.get(nextC);
203  if (nextC == token::END_BLOCK)
204  {
205  // Found closing "#}" sequence
206  str.append(buf, nChar);
207  return is;
208  }
209  else
210  {
211  // Re-analyze the character
212  is.putback(nextC);
213  }
214  }
215 
216  buf[nChar++] = c;
217  if (nChar == bufLen) // Flush full buffer
218  {
219  str.append(buf, nChar);
220  nChar = 0;
221  }
222  }
223 
224 
225  // Abnormal exit of the loop
226  str.append(buf, nChar); // Finalize pending content
227  strncpy(buf, str.c_str(), errLen);
228  buf[errLen] = '\0';
229 
231  << "Problem while reading verbatim \"" << buf
232  << "...\" [after " << str.length() << " chars]\n"
233  << exit(FatalIOError);
234 
235  return is;
236 }
237 
238 
239 // Read a variable or expression.
240 // Handles "$var" and "${var}" forms, permits '/' scoping character.
241 // Also handles "${{expr}}".
242 //
243 // Return the token type or ERROR
244 //
245 // The leading "${" or "$c" removed from stream prior to calling.
247 (
248  ISstream& is,
249  std::string& str,
250  char c // Next character after '$'
251 )
252 {
253  constexpr const unsigned bufLen = 1024;
254  static char buf[bufLen];
255 
256  token::tokenType tokType(token::tokenType::VARIABLE);
257 
258  // The first two characters are known:
259  buf[0] = token::DOLLAR;
260  buf[1] = c;
261 
262  unsigned nChar = 2; // Starts with two characters
263  unsigned depth = 0; // Depth of {..} nesting
264 
265  str.clear();
266  if (c == token::BEGIN_BLOCK)
267  {
268  // Processing '${variable}' or '${{expr}}'
269  ++depth;
270 
271  int lookahead = is.peek();
272  if (lookahead == token::BEGIN_BLOCK)
273  {
274  // Looks like '${{expr...'
275  tokType = token::tokenType::EXPRESSION;
276  }
277  else if (lookahead == token::END_BLOCK)
278  {
279  // Looks like '${}'
281  << "Ignoring empty ${}" << endl;
282  return token::tokenType::ERROR;
283  }
284 
285  while (is.get(c))
286  {
287  buf[nChar++] = c;
288 
289  if (c == token::BEGIN_BLOCK)
290  {
291  ++depth;
292  }
293  else if (c == token::END_BLOCK)
294  {
295  --depth;
296  if (!depth)
297  {
298  // Found closing '}' character
299  str.append(buf, nChar);
300  return tokType;
301  }
302  }
303  else if (c == '/' && tokType == token::tokenType::EXPRESSION)
304  {
305  // Strip C/C++ comments from expressions
306  // Note: could also peek instead of get/putback
307 
308  if (!is.get(c))
309  {
310  break; // Premature end of stream
311  }
312  else if (c == '/')
313  {
314  --nChar; // Remove initial '/' from buffer
315 
316  // C++ comment: discard through newline
317  (void) is.getLine(nullptr, '\n');
318  }
319  else if (c == '*')
320  {
321  --nChar; // Remove initial '/' from buffer
322 
323  // C-style comment: seek "*/" ending
324  if (!is.seekCommentEnd_Cstyle())
325  {
326  break; // Premature end of stream
327  }
328  }
329  else
330  {
331  // Re-analyze the character
332  is.putback(c);
333  }
334  }
335 
336  if (nChar == bufLen) // Flush full buffer
337  {
338  str.append(buf, nChar);
339  nChar = 0;
340  }
341  }
342 
343 
344  // Abnormal exit of the loop
345 
346  str.append(buf, nChar); // Finalize pending content
347  strncpy(buf, str.c_str(), errLen);
348  buf[errLen] = '\0';
349 
351  << "stream terminated while reading variable '" << buf
352  << "...' [after " << str.length() << " chars]\n"
353  << exit(FatalIOError);
354 
355  return token::tokenType::ERROR;
356  }
357  else if (validVariableChar(c))
358  {
359  // Processing '$variable'
360 
361  while (is.get(c))
362  {
363  if (!validVariableChar(c))
364  {
365  is.putback(c);
366  break;
367  }
368 
369  if (c == token::BEGIN_LIST)
370  {
371  ++depth;
372  }
373  else if (c == token::END_LIST)
374  {
375  if (!depth)
376  {
377  // Closed ')' without opening '(':
378  // - don't consider it part of our input
379  is.putback(c);
380  break;
381  }
382  --depth;
383  }
384 
385  buf[nChar++] = c;
386  if (nChar == bufLen) // Flush full buffer
387  {
388  str.append(buf, nChar);
389  nChar = 0;
390  }
391  }
392 
393  str.append(buf, nChar); // Finalize pending content
394 
395  if (depth)
396  {
397  strncpy(buf, str.c_str(), errLen);
398  buf[errLen] = '\0';
399 
401  << "Missing " << depth
402  << " closing ')' while parsing" << nl << nl
403  << buf << endl;
404  }
405 
406  return tokType;
407  }
408  else
409  {
410  // Invalid character. Terminate string (for message)
411 
412  buf[nChar--] = '\0';
413 
415  << "Ignoring bad variable name: " << buf << nl << endl;
416  }
417 
418  return token::tokenType::ERROR;
419 }
420 
421 
422 // Raw, low-level get into a string.
423 // Continues reading after an initial opening delimiter (eg, '{')
424 // until it finds the matching closing delimiter (eg, '}')
425 static bool readUntilBalancedDelimiter
426 (
427  ISstream& is,
428  std::string& str,
429  const bool stripComments,
430  const char delimOpen,
431  const char delimClose
432 )
433 {
434  constexpr const unsigned bufLen = 1024;
435  static char buf[bufLen];
436 
437  unsigned nChar = 0;
438  unsigned depth = 1; // Initial '{' already seen by caller
439  char c = 0;
440 
441  str.clear();
442  while (is.get(c))
443  {
444  if ((str.empty() && !nChar) && isspace(c))
445  {
446  continue; // Ignore leading whitespace
447  }
448 
449  buf[nChar++] = c;
450 
451  // Note: no '\' escape handling needed at the moment
452 
453  if (c == delimOpen)
454  {
455  ++depth;
456  }
457  else if (c == delimClose)
458  {
459  --depth;
460  if (!depth)
461  {
462  // Closing character - do not include in output
463  --nChar;
464  str.append(buf, nChar);
465  inplaceTrimRight(str); // Remove trailing whitespace
466  return true;
467  }
468  }
469  else if (stripComments && c == '/')
470  {
471  // Strip C/C++ comments from expressions
472  // Note: could also peek instead of get/putback
473 
474  if (!is.get(c))
475  {
476  break; // Premature end of stream
477  }
478  else if (c == '/')
479  {
480  --nChar; // Remove initial '/' from buffer
481 
482  // C++ comment: discard through newline
483  (void) is.getLine(nullptr, '\n');
484  }
485  else if (c == '*')
486  {
487  --nChar; // Remove initial '/' from buffer
488 
489  // C-style comment: discard through to "*/" ending
490  if (!is.seekCommentEnd_Cstyle())
491  {
492  break; // Premature end of stream
493  }
494  }
495  else
496  {
497  // Reanalyze the char
498  is.putback(c);
499  }
500  }
501 
502  if (nChar == bufLen)
503  {
504  str.append(buf, nChar); // Flush full buffer
505  nChar = 0;
506  }
507  }
508 
509 
510  // Abnormal exit of the loop
511 
512  str.append(buf, nChar); // Finalize pending content
513  inplaceTrimRight(str); // Remove trailing whitespace
514 
515  // Exhausted stream without finding closing sequence
516  return false;
517 }
519 } // End namespace Foam
520 
521 
522 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
523 
525 (
526  std::string& str,
527  const bool stripComments
528 )
529 {
530  return
532  (
533  *this,
534  str,
535  stripComments,
538  );
539 }
540 
541 
543 {
544  constexpr const unsigned bufLen = 128; // Max length for labels/scalars
545  static char buf[bufLen];
546 
547  // Return the putback token if it exists
548  if (Istream::getBack(t))
549  {
550  return *this;
551  }
552 
553  // Reset token, adjust its line number according to the stream
554  t.reset();
555  t.lineNumber(this->lineNumber());
556 
557  // Assume that the streams supplied are in working order.
558  // Lines are counted by '\n'
559 
560  // Get next 'valid character': i.e. proceed through any whitespace
561  // and/or comments until a semantically valid character is found
562 
563  char c = nextValid();
564 
565  // Return on error
566  if (!c)
567  {
568  t.setBad();
569  return *this;
570  }
571 
572  // Analyse input starting with this character.
573  switch (c)
574  {
575  // Check for punctuation first - same as token::isseparator()
576 
577  case token::END_STATEMENT :
578  case token::BEGIN_LIST :
579  case token::END_LIST :
580  case token::BEGIN_SQR :
581  case token::END_SQR :
582  case token::BEGIN_BLOCK :
583  case token::END_BLOCK :
584  case token::COLON :
585  case token::COMMA :
586  case token::ASSIGN :
587  case token::PLUS :
588  // NB: token::MINUS handled later as the possible start of a Number
589  case token::MULTIPLY :
590  case token::DIVIDE :
591  {
593  return *this;
594  }
595 
596  // String: enclosed by double quotes.
597  case token::DQUOTE :
598  {
599  putback(c);
600 
601  string val;
602  if (read(val).bad())
603  {
604  t.setBad();
605  }
606  else
607  {
608  t = std::move(val); // Move contents to token
609  }
610 
611  return *this;
612  }
613 
614  // Verbatim string '#{ .. #}' or dictionary '#directive'
615  case token::HASH :
616  {
617  char nextC;
618  int lookahead = peek();
619 
620  if (lookahead == token::BEGIN_BLOCK)
621  {
622  // Verbatim string: #{ ... #}
623  // Token stored without the surrounding delimiters
624 
625  (void) get(nextC); // Discard '{' lookahead
626 
627  string val;
628  if (readVerbatim(*this, val).bad())
629  {
630  t.setBad();
631  }
632  else
633  {
634  t = std::move(val); // Move contents to token
635  t.setType(token::tokenType::VERBATIM);
636  }
637  }
638  else if (read(nextC).bad())
639  {
640  // Return lone '#' as word
641  t = charToWord(c);
642  }
643  else if (word::valid(nextC))
644  {
645  // Directive (wordToken) beginning with '#'. Eg, "#include"
646  // Put back both so that '#...' is included in the directive
647 
648  putback(nextC);
649  putback(c);
650 
651  word val;
652  if (read(val).bad())
653  {
654  t.setBad();
655  }
656  else
657  {
658  t = std::move(val); // Move contents to token
659  t.setType(token::tokenType::DIRECTIVE);
660  }
661  }
662  else
663  {
664  // '#' followed by non-word. Just ignore leading '#'?
665  putback(nextC);
666 
667  IOWarningInFunction(*this)
668  << "Invalid sequence #" << char(nextC)
669  << " ... ignoring the leading '#'" << nl << endl;
670  }
671 
672  return *this;
673  }
674 
675  // Dictionary variable or ${{ expression }}
676  case token::DOLLAR :
677  {
678  char nextC;
679  if (read(nextC).bad())
680  {
681  // Return lone '$' as word. Could also ignore
682  t = charToWord(c);
683  }
684  else
685  {
686  // NB: the parser is slightly generous here.
687  // It will also accept '$ {' as input.
688  // - to be revisited (2021-05-17)
689 
690  string val;
691  token::tokenType tokType = readVariable(*this, val, nextC);
692  if (tokType == token::tokenType::ERROR)
693  {
694  t.setBad();
695  }
696  else
697  {
698  t = std::move(val); // Move contents to token
699  t.setType(tokType);
700  }
701  }
702 
703  return *this;
704  }
705 
706  // Number: integer or floating point
707  //
708  // ideally match the equivalent of this regular expression
709  //
710  // /[-+]?([0-9]+\.?[0-9]*|\.[0-9]+)([Ee][-+]?[0-9]+)?/
711  //
712  case '-' :
713  case '.' :
714  case '0' : case '1' : case '2' : case '3' : case '4' :
715  case '5' : case '6' : case '7' : case '8' : case '9' :
716  {
717  label labelVal = (c != '.'); // used as bool here
718 
719  unsigned nChar = 0;
720  buf[nChar++] = c;
721 
722  // get everything that could resemble a number and let
723  // readScalar determine the validity
724  while
725  (
726  is_.get(c)
727  && (
728  isdigit(c)
729  || c == '+'
730  || c == '-'
731  || c == '.'
732  || c == 'E'
733  || c == 'e'
734  )
735  )
736  {
737  if (labelVal)
738  {
739  labelVal = isdigit(c);
740  }
741 
742  buf[nChar++] = c;
743  if (nChar == bufLen)
744  {
745  // Runaway argument - avoid buffer overflow
746  buf[bufLen-1] = '\0';
747 
749  << "Number '" << buf << "...'\n"
750  << " is too long (max. " << bufLen << " characters)"
751  << exit(FatalIOError);
752 
753  t.setBad();
754  return *this;
755  }
756  }
757  buf[nChar] = '\0'; // Terminate string
758 
759  syncState();
760 
761  if (is_.bad())
762  {
763  t.setBad();
764  }
765  else
766  {
767  is_.putback(c);
768 
769  if (nChar == 1 && buf[0] == '-')
770  {
771  // A single '-' is punctuation
773  }
774  else if (labelVal && Foam::read(buf, labelVal))
775  {
776  t = labelVal;
777  }
778  else
779  {
780  scalar scalarVal;
781 
782  if (readScalar(buf, scalarVal))
783  {
784  // A scalar or too big to fit as a label
785  t = scalarVal;
786  }
787  else
788  {
789  t.setBad();
790  }
791  }
792  }
793 
794  return *this;
795  }
796 
797  // Should be a word (which can also be a single character)
798  default:
799  {
800  putback(c);
801 
802  word val;
803  if (read(val).bad())
804  {
805  t.setBad();
806  }
807  else if
808  (
810  || !readCompoundToken(t, val)
811  )
812  {
813  t = std::move(val); // Move contents to token
814  }
816  return *this;
817  }
818  }
819 }
820 
821 
823 {
824  c = nextValid();
825  return *this;
826 }
827 
828 
830 {
831  constexpr const unsigned bufLen = 1024;
832  static char buf[bufLen];
833 
834  unsigned nChar = 0;
835  unsigned depth = 0; // Depth of (..) nesting
836  char c;
837 
838  str.clear();
839  while (get(c))
840  {
841  if (!word::valid(c))
842  {
843  putback(c);
844  break;
845  }
846 
847  if (c == token::BEGIN_LIST)
848  {
849  ++depth;
850  }
851  else if (c == token::END_LIST)
852  {
853  if (!depth)
854  {
855  // Closed ')' without opening '(':
856  // - don't consider it part of our input
857  putback(c);
858  break;
859  }
860  --depth;
861  }
862 
863  buf[nChar++] = c;
864  if (nChar == bufLen) // Flush full buffer
865  {
866  str.append(buf, nChar);
867  nChar = 0;
868  }
869  }
870 
871  str.append(buf, nChar); // Finalize pending content
872 
873  if (bad())
874  {
875  // Could probably skip this check
876 
877  strncpy(buf, str.c_str(), errLen);
878  buf[errLen] = '\0';
879 
881  << "Problem while reading word '" << buf
882  << "...' [after " << str.length() << " chars]\n"
883  << exit(FatalIOError);
884 
885  return *this;
886  }
887 
888  if (str.empty())
889  {
891  << "Invalid first character found : " << c
892  << exit(FatalIOError);
893  }
894  else if (depth)
895  {
896  strncpy(buf, str.c_str(), errLen);
897  buf[errLen] = '\0';
898 
899  IOWarningInFunction(*this)
900  << "Missing " << depth
901  << " closing ')' while parsing" << nl << nl
902  << buf << nl << endl;
903  }
904 
905  return *this;
906 }
907 
908 
910 {
911  constexpr const unsigned bufLen = 1024;
912  static char buf[bufLen];
913 
914  unsigned nChar = 0;
915  char c;
916 
917  if (!get(c))
918  {
920  << "cannot read start of string"
921  << exit(FatalIOError);
922 
923  return *this;
924  }
925 
926  // Note, we could also handle single-quoted strings here (if desired)
927  if (c != token::DQUOTE)
928  {
930  << "Incorrect start of string character found : " << c
931  << exit(FatalIOError);
932 
933  return *this;
934  }
935 
936  str.clear();
937  bool escaped = false;
938  while (get(c))
939  {
940  if (c == '\\')
941  {
942  escaped = !escaped; // Toggle state (retains backslashes)
943  }
944  else if (c == token::DQUOTE)
945  {
946  if (escaped)
947  {
948  escaped = false;
949  --nChar; // Overwrite backslash
950  }
951  else
952  {
953  // Done reading
954  str.append(buf, nChar);
955  return *this;
956  }
957  }
958  else if (c == token::NL)
959  {
960  if (escaped)
961  {
962  escaped = false;
963  --nChar; // Overwrite backslash
964  }
965  else
966  {
967  str.append(buf, nChar); // Finalize pending content
968  strncpy(buf, str.c_str(), errLen);
969  buf[errLen] = '\0';
970 
972  << "Unescaped '\\n' while reading string \"" << buf
973  << "...\" [after " << str.length() << " chars]\n"
974  << exit(FatalIOError);
975 
976  return *this;
977  }
978  }
979  else
980  {
981  escaped = false;
982  }
983 
984  buf[nChar++] = c;
985  if (nChar == bufLen) // Flush full buffer
986  {
987  // Keep lookback character (eg, for backslash escaping)
988  str.append(buf, nChar-1);
989  nChar = 1;
990  buf[0] = c;
991  }
992  }
993 
994 
995  // Abnormal exit of the loop
996  // Don't worry about a dangling backslash if string terminated prematurely
997 
998  str.append(buf, nChar); // Finalize pending content
999  strncpy(buf, str.c_str(), errLen);
1000  buf[errLen] = '\0';
1001 
1002  FatalIOErrorInFunction(*this)
1003  << "Problem while reading string \"" << buf << "...\""
1004  << exit(FatalIOError);
1005 
1006  return *this;
1007 }
1008 
1009 
1012  is_ >> val;
1013  syncState();
1014  return *this;
1015 }
1016 
1017 
1020  is_ >> val;
1021  syncState();
1022  return *this;
1023 }
1024 
1025 
1026 Foam::Istream& Foam::ISstream::read(double& val)
1028  is_ >> val;
1029  syncState();
1030  return *this;
1031 }
1032 
1033 
1034 Foam::Istream& Foam::ISstream::read(char* data, std::streamsize count)
1035 {
1036  beginRawRead();
1037  readRaw(data, count);
1038  endRawRead();
1039 
1040  return *this;
1041 }
1042 
1043 
1044 Foam::Istream& Foam::ISstream::readRaw(char* data, std::streamsize count)
1045 {
1046  if (count)
1047  {
1048  if (data)
1049  {
1050  is_.read(data, count);
1051  }
1052  else
1053  {
1054  is_.ignore(count);
1055  }
1056  }
1057  syncState();
1058  return *this;
1059 }
1060 
1061 
1063 {
1064  if (format() != IOstreamOption::BINARY)
1065  {
1066  FatalIOErrorInFunction(*this)
1067  << "stream format not binary"
1068  << exit(FatalIOError);
1069  }
1071  readBegin("binaryBlock");
1072  syncState();
1073  return is_.good();
1074 }
1075 
1076 
1079  readEnd("binaryBlock");
1080  syncState();
1081  return is_.good();
1082 }
1083 
1084 
1086 {
1087  lineNumber_ = 1; // Reset line number
1088 
1089  stdStream().clear(); // Clear the iostate error state flags
1090  setGood(); // Sync local copy of iostate
1091 
1092  stdStream().rdbuf()->pubseekpos(0, std::ios_base::in);
1093 
1094  // NOTE: this form of rewind does not work with igzstream.
1095  // However, igzstream is usually wrapped as IFstream which has its
1096  // own dedicated rewind treatment for igzstream.
1097 }
1098 
1099 
1100 // ************************************************************************* //
Subtract or start of negative number.
Definition: token.H:145
static bool isCompound(const word &compoundType)
True if a known (registered) compound type.
Definition: token.C:104
Begin block [isseparator].
Definition: token.H:165
static Foam::word charToWord(char c)
Definition: UIPstreamBase.C:34
**return False if stream exhausted before finding the comment end *bool seekCommentEnd_Cstyle()
Discard until end of C-style comment &#39;.
Definition: ISstream.C:84
bool getBack(token &tok)
Retrieve the put-back token if there is one.
Definition: Istream.C:115
virtual Istream & readRaw(char *data, std::streamsize count) override
Low-level raw binary read (without possible block delimiters). Reading into a null pointer behaves li...
Definition: ISstream.C:1037
static std::string::size_type length(const char *s)
Length of the character sequence (with nullptr protection)
Definition: string.H:258
static bool readUntilBalancedDelimiter(ISstream &is, std::string &str, const bool stripComments, const char delimOpen, const char delimClose)
Definition: ISstream.C:419
System signed integer.
bool bad() const noexcept
True if stream is corrupted.
Definition: IOstream.H:305
virtual void rewind() override
Rewind the stream so that it may be read again.
Definition: ISstream.C:1078
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
ISstream & putback(const char c)
Raw, low-level putback character function.
Definition: ISstreamI.H:99
Double quote.
Definition: token.H:141
Begin dimensions [isseparator].
Definition: token.H:163
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
A token holds an item read from Istream.
Definition: token.H:65
tokenType
Enumeration defining the types of token.
Definition: token.H:76
Newline [isspace].
Definition: token.H:130
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
bool continueReadUntilRightBrace(std::string &str, const bool stripComments=true)
Raw, low-level get into a string. Continues reading after an initial left-brace until it finds the ma...
Definition: ISstream.C:518
Begin list [isseparator].
Definition: token.H:161
static constexpr const unsigned errLen
Definition: ISstream.C:31
Assignment/equals [isseparator].
Definition: token.H:143
End entry [isseparator].
Definition: token.H:160
static token::tokenType readVariable(ISstream &is, std::string &str, char c)
Definition: ISstream.C:240
Dollar - start variable or expression.
Definition: token.H:137
End dimensions [isseparator].
Definition: token.H:164
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:127
static ISstream & readVerbatim(ISstream &is, std::string &str)
Definition: ISstream.C:178
virtual bool endRawRead() override
End of low-level raw binary read.
Definition: ISstream.C:1070
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
Addition [isseparator].
Definition: token.H:144
Comma [isseparator].
Definition: token.H:135
void inplaceTrimRight(std::string &s)
Trim trailing whitespace inplace.
Definition: stringOps.C:979
label lineNumber() const noexcept
The line number for the token.
Definition: tokenI.H:493
virtual Istream & read(token &)=0
Return next token from stream.
A class for handling words, derived from Foam::string.
Definition: word.H:63
int peek()
Raw, low-level peek function.
Definition: ISstreamI.H:63
void setBad()
Clear token and set to be ERROR.
Definition: tokenI.H:379
punctuationToken
Standard punctuation tokens (a character)
Definition: token.H:126
static bool readCompoundToken(token &tok, const word &compoundType, Istream &is)
Definition: UIPstreamBase.C:68
End list [isseparator].
Definition: token.H:162
virtual bool beginRawRead() override
Start of low-level raw binary read.
Definition: ISstream.C:1055
static bool valid(char c)
Is this character valid for a word?
Definition: wordI.H:52
Divide [isseparator].
Definition: token.H:147
ISstream & getLine(std::string &str, char delim='\n')
Raw, low-level getline (until delimiter) into a string.
Definition: ISstreamI.H:69
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:201
bool setType(const tokenType tokType) noexcept
Change the token type, for similar types.
Definition: tokenI.H:411
virtual Istream & read(token &t) override
Return next token from stream.
Definition: ISstream.C:535
word format(conversionProperties.get< word >("format"))
void reset()
Reset token to UNDEFINED and clear any allocated storage.
Definition: tokenI.H:335
Generic input stream using a standard (STL) stream.
Definition: ISstream.H:51
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:627
const dimensionedScalar c
Speed of light in a vacuum.
bool isspace(char c) noexcept
Test for whitespace (C-locale)
Definition: char.H:69
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
ISstream & get(char &c)
Raw, low-level get character function.
Definition: ISstreamI.H:49
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))
End block [isseparator].
Definition: token.H:166
Multiply [isseparator].
Definition: token.H:146
Namespace for OpenFOAM.
Hash - directive or start verbatim string.
Definition: token.H:136
Colon [isseparator].
Definition: token.H:133
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...