Loading...
Searching...
No Matches
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-2025 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 "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
38static constexpr const unsigned errLen = 80;
39
40
41// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
42
43namespace
44{
45
46// Convert a single character to a word with length 1
47inline Foam::word charToWord(char c)
48{
49 return Foam::word(std::string(1, c), false);
50}
51
52
53// Permit slash-scoping of entries
54inline bool validVariableChar(char c)
55{
56 return (Foam::word::valid(c) || c == '/');
57}
58
59
60inline 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
79bool Foam::ISstream::readCompoundToken
80(
81 token& tok,
82 const word& compoundType
83)
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
123char 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
177namespace 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.
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
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...'
276 }
277 else if (lookahead == token::END_BLOCK)
278 {
279 // Looks like '${}'
281 << "Ignoring empty ${}" << endl;
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
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
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, '}')
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;
518
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
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
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
660 }
661 }
662 else
663 {
664 // '#' followed by non-word. Just ignore leading '#'?
665 putback(nextC);
666
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 bool isIntegral = (c != '.'); // possible integral value?
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 std::isdigit(c)
729 || c == '+'
730 || c == '-'
731 || c == '.'
732 || c == 'E'
733 || c == 'e'
734 )
735 )
736 {
737 // Silently skip "'" digit separators in numeric literals?
738
739 // Still possible as integral?
740 isIntegral = isIntegral && std::isdigit(c);
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)
770 {
771 // Special single char handling
772 switch (buf[0])
773 {
774 case '-' : // A single '-' is punctuation
775 {
777 break;
778 }
779 case '.' : // A single '.' is currently bad
780 {
781 t.setBad();
782 break;
783 }
784 default :
785 {
786 if (isIntegral)
787 {
788 // Single digit : conversion is trivial
789 t.int32Token(buf[0] - '0');
790 }
791 else
792 {
793 // At the moment nothing to handle here
794 t.setBad();
795 }
796 break;
797 }
798 }
799 return *this;
800 }
801
802 if (isIntegral)
803 {
804 // Parse as an integral?
805 // - read with largest resolution and narrow when possible.
806 // - retain (signed|unsigned) int32/int64 ...
807
808 if (int64_t val; Foam::readInt64(buf, val))
809 {
810 // Use smaller representations when possible
811 if (val >= INT32_MIN && val <= INT32_MAX)
812 {
813 t.int32Token(static_cast<int32_t>(val));
814 }
815 else if (val >= 0 && val <= int64_t(UINT32_MAX))
816 {
817 t.uint32Token(static_cast<uint32_t>(val));
818 }
819 else
820 {
821 t.int64Token(val);
822 }
823 }
824 else if (uint64_t val; Foam::readUint64(buf, val))
825 {
826 // Use smaller representations when possible
827 if (val <= UINT32_MAX)
828 {
829 t.uint32Token(static_cast<uint32_t>(val));
830 }
831 else
832 {
833 t.uint64Token(val);
834 }
835 }
836 else
837 {
838 // Fallthrough to scalar parsing
839 isIntegral = false;
840 }
841 }
842
843 // Floating point format or a series of digits that are too
844 // big to fit an integral representation
845 //
846 // - read as 'scalar' (float|double) since this is what the
847 // rest of the code expects to handle anyhow
848
849 if (!isIntegral)
850 {
851 if (scalar val; Foam::readScalar(buf, val))
852 {
853 t = val;
854 }
855 else
856 {
857 t.setBad();
858 }
859 }
860 }
861
862 return *this;
863 }
864
865 // Should be a word (which can also be a single character)
866 default:
867 {
868 putback(c);
869
870 word val;
871 if (read(val).bad())
872 {
873 t.setBad();
874 }
875 else if
876 (
878 || !readCompoundToken(t, val)
879 )
880 {
881 t = std::move(val); // Move contents to token
882 }
884 return *this;
885 }
886 }
887}
888
889
891{
892 c = nextValid();
893 return *this;
894}
895
896
898{
899 constexpr const unsigned bufLen = 1024;
900 static char buf[bufLen];
901
902 unsigned nChar = 0;
903 unsigned depth = 0; // Depth of (..) nesting
904 char c;
905
906 str.clear();
907 while (get(c))
908 {
909 if (!word::valid(c))
910 {
911 putback(c);
912 break;
913 }
914
915 if (c == token::BEGIN_LIST)
916 {
917 ++depth;
918 }
919 else if (c == token::END_LIST)
920 {
921 if (!depth)
922 {
923 // Closed ')' without opening '(':
924 // - don't consider it part of our input
925 putback(c);
926 break;
927 }
928 --depth;
929 }
930
931 buf[nChar++] = c;
932 if (nChar == bufLen) // Flush full buffer
933 {
934 str.append(buf, nChar);
935 nChar = 0;
936 }
937 }
938
939 str.append(buf, nChar); // Finalize pending content
940
941 if (bad())
942 {
943 // Could probably skip this check
944
945 strncpy(buf, str.c_str(), errLen);
946 buf[errLen] = '\0';
947
949 << "Problem while reading word '" << buf
950 << "...' [after " << str.length() << " chars]\n"
951 << exit(FatalIOError);
952
953 return *this;
954 }
955
956 if (str.empty())
957 {
959 << "Invalid first character found : " << c
960 << exit(FatalIOError);
961 }
962 else if (depth)
963 {
964 strncpy(buf, str.c_str(), errLen);
965 buf[errLen] = '\0';
966
968 << "Missing " << depth
969 << " closing ')' while parsing" << nl << nl
970 << buf << nl << endl;
971 }
972
973 return *this;
974}
975
976
978{
979 constexpr const unsigned bufLen = 1024;
980 static char buf[bufLen];
981
982 unsigned nChar = 0;
983 char c;
984
985 if (!get(c))
986 {
988 << "cannot read start of string"
989 << exit(FatalIOError);
990
991 return *this;
992 }
993
994 // Note, we could also handle single-quoted strings here (if desired)
995 if (c != token::DQUOTE)
996 {
998 << "Incorrect start of string character found : " << c
999 << exit(FatalIOError);
1000
1001 return *this;
1002 }
1003
1004 str.clear();
1005 bool escaped = false;
1006 while (get(c))
1007 {
1008 if (c == '\\')
1009 {
1010 escaped = !escaped; // Toggle state (retains backslashes)
1011 }
1012 else if (c == token::DQUOTE)
1013 {
1014 if (escaped)
1015 {
1016 escaped = false;
1017 --nChar; // Overwrite backslash
1018 }
1019 else
1020 {
1021 // Done reading
1022 str.append(buf, nChar);
1023 return *this;
1024 }
1025 }
1026 else if (c == token::NL)
1027 {
1028 if (escaped)
1029 {
1030 escaped = false;
1031 --nChar; // Overwrite backslash
1032 }
1033 else
1034 {
1035 str.append(buf, nChar); // Finalize pending content
1036 strncpy(buf, str.c_str(), errLen);
1037 buf[errLen] = '\0';
1038
1040 << "Unescaped '\\n' while reading string \"" << buf
1041 << "...\" [after " << str.length() << " chars]\n"
1042 << exit(FatalIOError);
1043
1044 return *this;
1045 }
1046 }
1047 else
1048 {
1049 escaped = false;
1050 }
1051
1052 buf[nChar++] = c;
1053 if (nChar == bufLen) // Flush full buffer
1054 {
1055 // Keep lookback character (eg, for backslash escaping)
1056 str.append(buf, nChar-1);
1057 nChar = 1;
1058 buf[0] = c;
1059 }
1060 }
1061
1062
1063 // Abnormal exit of the loop
1064 // Don't worry about a dangling backslash if string terminated prematurely
1065
1066 str.append(buf, nChar); // Finalize pending content
1067 strncpy(buf, str.c_str(), errLen);
1068 buf[errLen] = '\0';
1069
1071 << "Problem while reading string \"" << buf << "...\""
1072 << exit(FatalIOError);
1073
1074 return *this;
1075}
1076
1077
1080 is_ >> val;
1081 syncState();
1082 return *this;
1083}
1084
1085
1088 is_ >> val;
1089 syncState();
1090 return *this;
1091}
1092
1093
1094Foam::Istream& Foam::ISstream::read(uint32_t& val)
1096 is_ >> val;
1097 syncState();
1098 return *this;
1099}
1100
1101
1102Foam::Istream& Foam::ISstream::read(uint64_t& val)
1104 is_ >> val;
1105 syncState();
1106 return *this;
1107}
1108
1109
1112 is_ >> val;
1113 syncState();
1114 return *this;
1115}
1116
1117
1120 is_ >> val;
1121 syncState();
1122 return *this;
1123}
1124
1125
1126Foam::Istream& Foam::ISstream::read(char* data, std::streamsize count)
1127{
1128 beginRawRead();
1129 readRaw(data, count);
1130 endRawRead();
1131
1132 return *this;
1133}
1134
1135
1136Foam::Istream& Foam::ISstream::readRaw(char* data, std::streamsize count)
1137{
1138 if (count)
1139 {
1140 if (data)
1141 {
1142 is_.read(data, count);
1143 }
1144 else
1145 {
1146 is_.ignore(count);
1148 }
1149 syncState();
1150 return *this;
1151}
1152
1153
1155{
1157 {
1159 << "stream format not binary"
1160 << exit(FatalIOError);
1161 }
1163 readBegin("binaryBlock");
1164 syncState();
1165 return is_.good();
1166}
1167
1168
1171 readEnd("binaryBlock");
1172 syncState();
1173 return is_.good();
1174}
1175
1176
1178{
1179 Istream::rewind(); // Drop any putback
1180 lineNumber_ = 1; // Reset line number
1181
1182 stdStream().clear(); // Clear the iostate error state flags
1183 setGood(); // Sync local copy of iostate
1184
1185 stdStream().rdbuf()->pubseekpos(0, std::ios_base::in);
1186
1187 // NOTE: this form of rewind does not work with igzstream.
1188 // However, igzstream is usually wrapped as IFstream which has its
1189 // own dedicated rewind treatment for igzstream.
1190}
1191
1192
1193// ************************************************************************* //
static constexpr const unsigned errLen
Definition ISstream.C:31
label lineNumber() const noexcept
Const access to the current stream line number.
Definition IOstream.H:409
bool bad() const noexcept
True if stream is corrupted.
Definition IOstream.H:305
label lineNumber_
The file line.
Definition IOstream.H:140
void setGood() noexcept
Set stream state to be good.
Definition IOstream.H:174
Generic input stream using a standard (STL) stream.
Definition ISstream.H:54
ISstream & get(char &c)
Raw, low-level get character function.
Definition ISstreamI.H:49
virtual void rewind() override
Rewind the stream so that it may be read again.
Definition ISstream.C:1170
ISstream & putback(const char c)
Raw, low-level putback character function.
Definition ISstreamI.H:99
virtual bool endRawRead() override
End of low-level raw binary read.
Definition ISstream.C:1162
int peek()
Raw, low-level peek function.
Definition ISstreamI.H:63
ISstream & getLine(std::string &str, char delim='\n')
Raw, low-level getline (until delimiter) into a string.
Definition ISstreamI.H:69
void syncState()
Set stream state to match that of the std::istream.
Definition ISstream.H:195
virtual bool beginRawRead() override
Start of low-level raw binary read.
Definition ISstream.C:1147
**return False if stream exhausted before finding the comment end *bool seekCommentEnd_Cstyle()
Discard until end of C-style comment '.
Definition ISstream.C:84
virtual Istream & read(token &t) override
Return next token from stream.
Definition ISstream.C:535
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
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:1129
virtual const std::istream & stdStream() const
Const access to underlying std::istream.
Definition ISstream.H:163
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition Istream.H:60
bool getBack(token &tok)
Retrieve the put-back token if there is one.
Definition Istream.C:115
virtual void rewind()=0
Rewind the stream so that it may be read again.
Definition Istream.C:214
bool readEnd(const char *funcName)
End read of data chunk, ends with ')'.
Definition Istream.C:152
bool readBegin(const char *funcName)
Begin read of data chunk, starts with '('.
Definition Istream.C:134
static std::string::size_type length(const char *s)
Length of the character sequence (with nullptr protection).
Definition string.H:259
static bool isCompound(const word &compoundType)
True if a known (registered) compound type.
Definition token.C:104
A token holds an item read from Istream.
Definition token.H:70
tokenType
Enumeration defining the types of token.
Definition token.H:81
@ ERROR
Token error encountered.
Definition token.H:83
@ EXPRESSION
Definition token.H:104
@ DIRECTIVE
Definition token.H:101
label lineNumber() const noexcept
The line number for the token.
Definition tokenI.H:570
punctuationToken
Standard punctuation tokens (a character).
Definition token.H:140
@ DIVIDE
Divide [isseparator].
Definition token.H:160
@ BEGIN_BLOCK
Begin block [isseparator].
Definition token.H:178
@ BEGIN_SQR
Begin dimensions [isseparator].
Definition token.H:176
@ COLON
Colon [isseparator].
Definition token.H:146
@ END_BLOCK
End block [isseparator].
Definition token.H:179
@ HASH
Hash - directive or start verbatim string.
Definition token.H:149
@ ASSIGN
Assignment/equals [isseparator].
Definition token.H:156
@ END_STATEMENT
End entry [isseparator].
Definition token.H:173
@ BEGIN_LIST
Begin list [isseparator].
Definition token.H:174
@ PLUS
Addition [isseparator].
Definition token.H:157
@ DOLLAR
Dollar - start variable or expression.
Definition token.H:150
@ DQUOTE
Double quote.
Definition token.H:154
@ END_LIST
End list [isseparator].
Definition token.H:175
@ END_SQR
End dimensions [isseparator].
Definition token.H:177
@ MULTIPLY
Multiply [isseparator].
Definition token.H:159
@ NL
Newline [isspace].
Definition token.H:143
@ MINUS
Subtract or start of negative number.
Definition token.H:158
@ COMMA
Comma [isseparator].
Definition token.H:148
punctuationToken pToken() const
Return punctuation character.
Definition tokenI.H:676
void setBad()
Clear token and set to be ERROR.
Definition tokenI.H:456
uint32_t uint32Token() const
Return int32 value, convert from other integer type or Error.
Definition tokenI.H:798
bool setType(const tokenType tokType) noexcept
Change the token type, for similar types.
Definition tokenI.H:488
int64_t int64Token() const
Return int64 value, convert from other integer type or Error.
Definition tokenI.H:767
void reset()
Reset token to UNDEFINED and clear any allocated storage.
Definition tokenI.H:412
int32_t int32Token() const
Return int32 value, convert from other integer type or Error.
Definition tokenI.H:739
uint64_t uint64Token() const
Return int64 value, convert from other integer type or Error.
Definition tokenI.H:829
A class for handling words, derived from Foam::string.
Definition word.H:66
static bool valid(char c)
Is this character valid for a word?
Definition wordI.H:52
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
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))
System signed integer.
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
const dimensionedScalar c
Speed of light in a vacuum.
void inplaceTrimRight(std::string &s)
Trim trailing whitespace inplace.
Namespace for OpenFOAM.
static Foam::word charToWord(char c)
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition int32.H:127
constexpr bool isspace(char c) noexcept
Test for whitespace (C-locale only).
Definition char.H:77
static ISstream & readVerbatim(ISstream &is, std::string &str)
Definition ISstream.C:178
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
static token::tokenType readVariable(ISstream &is, std::string &str, char c)
Definition ISstream.C:240
static bool readUntilBalancedDelimiter(ISstream &is, std::string &str, const bool stripComments, const char delimOpen, const char delimClose)
Definition ISstream.C:419
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
static bool readCompoundToken(token &tok, const word &compoundType, Istream &is)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
int64_t readInt64(Istream &is)
Read int64_t from stream.
Definition int64IO.C:74
uint64_t readUint64(Istream &is)
Read uint64_t from stream.
Definition uint64IO.C:73
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
word format(conversionProperties.get< word >("format"))