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