ITstream.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-2015 OpenFOAM Foundation
9  Copyright (C) 2017-2024 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 "error.H"
30 #include "ITstream.H"
31 #include "SpanStream.H"
32 #include <algorithm>
33 #include <memory>
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 static std::unique_ptr<Foam::ITstream> emptyStreamPtr_;
38 
39 
40 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
41 
42 namespace Foam
43 {
44 
45 // Convert input sequence into a list of tokens.
46 // Return the number of tokens in the resulting list.
47 static label parseStream(ISstream& is, tokenList& tokens)
48 {
49  tokens.clear();
50 
51  label count = 0;
52  token tok;
53  while (!is.read(tok).bad() && tok.good())
54  {
55  if (count >= tokens.size())
56  {
57  // Increase capacity (doubling) with min-size [64]
58  tokens.resize(Foam::max(label(64), label(2*tokens.size())));
59  }
60 
61  tokens[count] = std::move(tok);
62  ++count;
63  }
64 
65  tokens.resize(count);
66 
67  return count;
68 }
69 
70 } // End namespace Foam
71 
72 
73 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
74 
76 {
77  if (emptyStreamPtr_)
78  {
79  emptyStreamPtr_->ITstream::clear(); // Ensure it really is empty
80  emptyStreamPtr_->ITstream::seek(0); // rewind() bypassing virtual
81  }
82  else
83  {
84  emptyStreamPtr_.reset(new ITstream(Foam::zero{}, "empty-stream"));
85  }
86 
87  // Set stream as bad to indicate that this is an invald stream
88  emptyStreamPtr_->setBad();
89 
90  return *emptyStreamPtr_;
91 }
92 
93 
94 Foam::tokenList Foam::ITstream::parse_chars
95 (
96  const char* s,
97  size_t nbytes,
98  IOstreamOption streamOpt
99 )
100 {
101  ISpanStream is(s, nbytes, streamOpt);
102 
103  tokenList tokens;
104  parseStream(is, tokens);
105  return tokens;
106 }
107 
108 
109 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
110 
111 void Foam::ITstream::reset(const char* input, size_t nbytes)
112 {
113  ISpanStream is(input, nbytes, static_cast<IOstreamOption>(*this));
114 
115  parseStream(is, static_cast<tokenList&>(*this));
116  ITstream::seek(0); // rewind() bypassing virtual
117 }
118 
119 
120 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
121 
122 void Foam::ITstream::reserveCapacity(const label newCapacity)
123 {
124  // Reserve - leave excess capacity for further appends
125 
126  label len = tokenList::size();
127 
128  if (len < newCapacity)
129  {
130  // Min-size (16) when starting from zero
131  if (!len) len = 8;
132 
133  // Increase capacity. Strict doubling
134  do
135  {
136  len *= 2;
137  }
138  while (len < newCapacity);
139 
141  }
142 }
143 
144 
145 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
146 
147 Foam::ITstream::ITstream(const ITstream& is)
148 :
149  Istream(static_cast<IOstreamOption>(is)),
150  tokenList(is),
151  name_(is.name_),
152  tokenIndex_(0)
153 {
154  setOpened();
155  setGood();
156 }
157 
158 
160 :
161  Istream(static_cast<IOstreamOption>(is)),
162  tokenList(std::move(static_cast<tokenList&>(is))),
163  name_(std::move(is.name_)),
164  tokenIndex_(0)
165 {
166  setOpened();
167  setGood();
168 }
169 
170 
172 (
173  IOstreamOption streamOpt,
174  const string& name
175 )
176 :
177  Istream(IOstreamOption(streamOpt.format(), streamOpt.version())),
178  tokenList(),
179  name_(name),
180  tokenIndex_(0)
181 {
182  setOpened();
183  setGood();
184 }
185 
186 
188 (
189  const Foam::zero,
190  const string& name,
191  IOstreamOption streamOpt
192 )
193 :
194  ITstream(streamOpt, name)
195 {}
196 
197 
199 (
200  const UList<token>& tokens,
201  IOstreamOption streamOpt,
202  const string& name
203 )
204 :
205  Istream(IOstreamOption(streamOpt.format(), streamOpt.version())),
206  tokenList(tokens),
207  name_(name),
208  tokenIndex_(0)
209 {
210  setOpened();
211  setGood();
212 }
213 
214 
216 (
217  List<token>&& tokens,
218  IOstreamOption streamOpt,
219  const string& name
220 )
221 :
222  Istream(IOstreamOption(streamOpt.format(), streamOpt.version())),
223  tokenList(std::move(tokens)),
224  name_(name),
225  tokenIndex_(0)
226 {
227  setOpened();
228  setGood();
229 }
230 
231 
233 (
234  const UList<char>& input,
235  IOstreamOption streamOpt,
236  const string& name
237 )
238 :
239  ITstream(streamOpt, name)
240 {
241  reset(input.cdata(), input.size_bytes());
242 }
243 
244 
246 (
247  const std::string& input,
248  IOstreamOption streamOpt,
249  const string& name
250 )
251 :
252  ITstream(streamOpt, name)
253 {
254  reset(input.data(), input.size());
255 }
256 
257 
259 (
260  const char* input,
261  IOstreamOption streamOpt,
262  const string& name
263 )
264 :
265  ITstream(streamOpt, name)
266 {
267  reset(input, strlen(input));
268 }
269 
270 
271 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
272 
273 void Foam::ITstream::print(Ostream& os) const
274 {
275  os << "ITstream : " << name_.c_str() << ", line ";
276 
277  if (tokenList::empty())
278  {
279  os << lineNumber();
280  }
281  else
282  {
283  const tokenList& toks = *this;
284 
285  os << toks.front().lineNumber();
286 
287  if (toks.front().lineNumber() < toks.back().lineNumber())
288  {
289  os << '-' << toks.back().lineNumber();
290  }
291  }
292  os << ", ";
293 
295 }
296 
297 
298 std::string Foam::ITstream::toString() const
299 {
300  if (tokenList::empty())
301  {
302  return std::string();
303  }
304  else if (tokenList::size() == 1 && tokenList::front().isStringType())
305  {
306  // Already a string-type (WORD, STRING, ...). Just copy.
307  return tokenList::front().stringToken();
308  }
309 
310  // Stringify
311  OCharStream buf;
312  buf.precision(16); // Some reasonably high precision
313 
314  auto iter = tokenList::cbegin();
315  const auto last = tokenList::cend();
316 
317  // Note: could also just use the buffer token-wise
318 
319  // Contents - space separated
320  if (iter != last)
321  {
322  buf << *iter;
323 
324  for (++iter; (iter != last); (void)++iter)
325  {
326  buf << token::SPACE << *iter;
327  }
328  }
330  const auto view = buf.view();
331 
332  return std::string(view.data(), view.size());
333 }
334 
335 
337 {
338  // Use putback token if it exists
339  if (Istream::hasPutback())
340  {
342  }
343 
344  return peekNoFail(tokenIndex_);
345 }
346 
347 
349 {
350  if (tokenIndex_ < 0 || tokenIndex_ >= tokenList::size())
351  {
353  << "Token index " << tokenIndex_ << " out of range [0,"
354  << tokenList::size() << "]\n"
356  }
357 
358  return tokenList::operator[](tokenIndex_);
359 }
360 
361 
363 {
364  lineNumber_ = 0;
365 
366  if (pos < 0 || pos >= tokenList::size())
367  {
368  // Seek end (-1) or seek is out of range
369  tokenIndex_ = tokenList::size();
370 
371  if (!tokenList::empty())
372  {
373  // The closest reference lineNumber
374  lineNumber_ = tokenList::cdata()[tokenIndex_-1].lineNumber();
375  }
376 
377  setEof();
378  }
379  else
380  {
381  tokenIndex_ = pos;
382 
383  if (tokenIndex_ < tokenList::size())
384  {
385  lineNumber_ = tokenList::cdata()[tokenIndex_].lineNumber();
386  }
388  setOpened();
389  setGood();
390  }
391 }
392 
393 
394 bool Foam::ITstream::skip(label n) noexcept
395 {
396  if (!n)
397  {
398  // No movement - just check the current range
399  return (tokenIndex_ >= 0 && tokenIndex_ < tokenList::size());
400  }
401 
402  tokenIndex_ += n; // Move forward (+ve) or backwards (-ve)
403 
404  bool noError = true;
405 
406  if (tokenIndex_ < 0)
407  {
408  // Underflow range
409  noError = false;
410  tokenIndex_ = 0;
411  }
412  else if (tokenIndex_ >= tokenList::size())
413  {
414  // Overflow range
415  noError = false;
416  tokenIndex_ = tokenList::size();
417 
418  if (!tokenList::empty())
419  {
420  // The closest reference lineNumber
421  lineNumber_ = tokenList::cdata()[tokenIndex_-1].lineNumber();
422  }
423  }
424 
425  // Update stream information
426  if (tokenIndex_ < tokenList::size())
427  {
428  lineNumber_ = tokenList::cdata()[tokenIndex_].lineNumber();
429  setOpened();
430  setGood();
431  }
432  else
433  {
434  setEof();
435  }
436 
437  return noError;
438 }
439 
440 
442 {
443  // Use putback token if it exists
444  if (Istream::getBack(tok))
445  {
446  lineNumber_ = tok.lineNumber();
447  return *this;
448  }
449 
450  tokenList& toks = *this;
451  const label nToks = toks.size();
452 
453  if (tokenIndex_ < nToks)
454  {
455  tok = toks[tokenIndex_++];
456  lineNumber_ = tok.lineNumber();
457 
458  if (tokenIndex_ == nToks)
459  {
460  setEof();
461  }
462  }
463  else
464  {
465  if (eof())
466  {
468  << "attempt to read beyond EOF"
469  << exit(FatalIOError);
470  setBad();
471  }
472  else
473  {
474  setEof();
475  }
476 
477  tok.reset();
478 
479  if (nToks)
480  {
481  tok.lineNumber(toks.back().lineNumber());
482  }
483  else
484  {
485  tok.lineNumber(this->lineNumber());
486  }
487  }
488 
489  return *this;
490 }
491 
492 
494 (
495  const token::punctuationToken delimOpen,
496  const token::punctuationToken delimClose,
497  label pos
498 ) const
499 {
500  if (pos < 0)
501  {
502  pos = tokenIndex_;
503  }
504 
505  labelRange slice;
506 
507  for (label depth = 0; pos < tokenList::size(); ++pos)
508  {
509  const token& tok = tokenList::operator[](pos);
510 
511  if (tok.isPunctuation())
512  {
513  if (tok.isPunctuation(delimOpen))
514  {
515  if (!depth)
516  {
517  // Initial open delimiter
518  slice.start() = pos;
519  }
520 
521  ++depth;
522  }
523  else if (tok.isPunctuation(delimClose))
524  {
525  --depth;
526 
527  if (depth < 0)
528  {
529  // A closing delimiter without an open!
530  // Raise error?
531  break;
532  }
533  if (!depth)
534  {
535  // The end - include delimiter into the count
536  slice.size() = (pos - slice.start()) + 1;
537  break;
538  }
539  }
540  }
541  }
542 
543  return slice;
544 }
545 
546 
548 {
549  ITstream result
550  (
551  static_cast<IOstreamOption>(*this),
552  this->name()
553  );
554  result.setLabelByteSize(this->labelByteSize());
555  result.setScalarByteSize(this->scalarByteSize());
556 
557  // Validate the slice range of list
558  const labelRange slice(range.subset0(tokenList::size()));
559 
560  if (!slice.good())
561  {
562  // No-op
563  return result;
564  }
565 
566  auto first = tokenList::begin(slice.begin_value());
567  auto last = tokenList::begin(slice.end_value());
568 
569  result.resize(label(last - first));
570 
571  // Move tokens into result list
572  std::move(first, last, result.begin());
573  result.seek(0); // rewind() bypassing virtual
574 
576  (void) remove(slice); // Adjust the original list
577 
578  return result;
579 }
580 
581 
582 Foam::label Foam::ITstream::remove(const labelRange& range)
583 {
584  // Validate the slice range of list
585  const labelRange slice(range.subset0(tokenList::size()));
586 
587  if (!slice.good())
588  {
589  // No-op
590  return 0;
591  }
592 
593  if (slice.end_value() >= tokenList::size())
594  {
595  // Remove entire tail
596  tokenList::resize(slice.begin_value());
597  }
598  else
599  {
600  // Attempt to adjust the current token index to something sensible...
601  if (slice.contains(tokenIndex_))
602  {
603  // Within the removed slice - reposition tokenIndex before it
604  seek(slice.begin_value());
605  skip(-1);
606  }
607  else if (tokenIndex_ >= slice.end_value())
608  {
609  // After the removed slice - reposition tokenIndex relatively
610  skip(-slice.size());
611  }
612 
613  // Move tokens down in the list
614  std::move
615  (
616  tokenList::begin(slice.end_value()),
617  tokenList::end(),
618  tokenList::begin(slice.begin_value())
619  );
620 
621  // Truncate
622  tokenList::resize(tokenList::size() - slice.size());
623  }
624 
625  if (tokenIndex_ >= tokenList::size())
626  {
627  tokenIndex_ = tokenList::size();
628  setEof();
629  }
630  else if (tokenIndex_ >= 0 && tokenIndex_ < tokenList::size())
631  {
632  lineNumber_ = tokenList::operator[](tokenIndex_).lineNumber();
633  }
635  return slice.size();
636 }
637 
638 
639 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
640 
642 {
644  return *this;
645 }
646 
647 
649 {
651  return *this;
652 }
653 
654 
656 {
658  return *this;
659 }
660 
661 
663 {
665  return *this;
666 }
667 
668 
670 {
672  return *this;
673 }
674 
675 
677 {
679  return *this;
680 }
681 
682 
683 Foam::Istream& Foam::ITstream::readRaw(char*, std::streamsize)
684 {
686  return *this;
687 }
688 
689 
690 Foam::Istream& Foam::ITstream::read(char*, std::streamsize)
691 {
693  return *this;
694 }
695 
696 
697 void Foam::ITstream::add_tokens(const token& tok)
698 {
699  reserveCapacity(tokenIndex_ + 1);
700 
701  tokenList::operator[](tokenIndex_) = tok;
702  ++tokenIndex_;
703 }
704 
705 
707 {
708  reserveCapacity(tokenIndex_ + 1);
709 
710  tokenList::operator[](tokenIndex_) = std::move(tok);
711  ++tokenIndex_;
712 }
713 
714 
716 {
717  const label len = toks.size();
718  reserveCapacity(tokenIndex_ + len);
719 
720  std::copy_n(toks.begin(), len, tokenList::begin(tokenIndex_));
721  tokenIndex_ += len;
722 }
723 
724 
726 {
727  const label len = toks.size();
728  reserveCapacity(tokenIndex_ + len);
729 
730  std::move(toks.begin(), toks.end(), tokenList::begin(tokenIndex_));
731  tokenIndex_ += len;
732  toks.clear();
733 }
734 
735 
736 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
737 
738 void Foam::ITstream::operator=(const ITstream& is)
739 {
740  // Self-assignment is a no-op
741  if (this != &is)
742  {
743  Istream::operator=(is);
745  name_ = is.name_;
746  ITstream::seek(0); // rewind() bypassing virtual
747  }
748 }
749 
750 
752 {
753  tokenList::operator=(toks);
754  ITstream::seek(0); // rewind() bypassing virtual
755 }
756 
757 
759 {
760  tokenList::operator=(std::move(toks));
761  ITstream::seek(0); // rewind() bypassing virtual
762 }
763 
764 
765 // ************************************************************************* //
void add_tokens(const token &tok)
Copy append a token at the current tokenIndex, incrementing the index.
Definition: ITstream.C:690
bool good() const noexcept
True if token is not UNDEFINED or ERROR.
Definition: tokenI.H:507
const_iterator cend() const noexcept
Return const_iterator to end traversing the constant UList.
Definition: UListI.H:450
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
const token & peekBack() const noexcept
Examine putback token without removing it.
Definition: Istream.C:42
bool getBack(token &tok)
Retrieve the put-back token if there is one.
Definition: Istream.C:115
Input/output streams with (internal or external) character storage.
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
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:153
static std::unique_ptr< Foam::ITstream > emptyStreamPtr_
Definition: ITstream.C:30
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:52
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:675
A token holds an item read from Istream.
Definition: token.H:65
T & front()
Access first element of the list, position [0].
Definition: UListI.H:230
label remove(const labelRange &range)
Remove a (start,size) subset from the list and move remaining elements down.
Definition: ITstream.C:575
A simple container for options an IOstream can normally have.
std::string toString() const
Concatenate tokens into a space-separated std::string. The resulting string may contain quote charact...
Definition: ITstream.C:291
List< token > tokenList
List of token, used for dictionary primitive entry (for example)
Definition: tokenList.H:32
scalar range
T & operator[](const label i)
Return element of UList.
Definition: UListI.H:362
dimensionedScalar pos(const dimensionedScalar &ds)
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
virtual Istream & read(token &tok) override
Return next token from stream.
Definition: ITstream.C:434
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
void operator=(const UList< T > &list)
Assignment to UList operator. Takes linear time.
Definition: List.C:360
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:130
virtual Istream & readRaw(char *data, std::streamsize count) override
Low-level raw binary read : triggers not implemented error.
Definition: ITstream.C:676
A class for handling words, derived from Foam::string.
Definition: word.H:63
static Istream & input(Istream &is, IntRange< T > &range)
Definition: IntRanges.C:33
Space [isspace].
Definition: token.H:131
punctuationToken
Standard punctuation tokens (a character)
Definition: token.H:126
const token & currentToken() const noexcept
Read access to the token at the current tokenIndex.
Definition: ITstream.H:466
errorManip< error > abort(error &err)
Definition: errorManip.H:139
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition: UListI.H:392
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:105
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
const direction noexcept
Definition: Scalar.H:258
label size() const noexcept
The number of elements in the container.
Definition: UList.H:680
OBJstream os(runTime.globalPath()/outputName)
virtual void print(Ostream &os) const
Print stream description to Ostream.
Definition: IOstream.C:67
virtual Istream & read(token &t) override
Return next token from stream.
Definition: ISstream.C:535
unsigned scalarByteSize(const std::string &str)
Extract scalar size (in bytes) from "scalar=" tag in string.
label lineNumber() const noexcept
Const access to the current stream line number.
Definition: IOstream.H:390
word format(conversionProperties.get< word >("format"))
const std::string version
OpenFOAM version (name or stringified number) as a std::string.
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:637
const token & peek() const noexcept
Failsafe peek at what the next read would return, including handling of any putback.
Definition: ITstream.C:329
bool hasPutback() const noexcept
True if putback token is in use.
Definition: Istream.H:81
labelRange find(const token::punctuationToken delimOpen, const token::punctuationToken delimClose, label pos=0) const
Find range containing matching delimiter pair, starting at the specified position. The position -1 indicates to continue from the present tokenIndex() position.
Definition: ITstream.C:487
unsigned labelByteSize(const std::string &str)
Extract label size (in bytes) from "label=" tag in string.
static ITstream & empty_stream()
Return reference to an empty ITstream, for functions needing to return an ITstream reference but whic...
Definition: ITstream.C:68
static label parseStream(ISstream &is, tokenList &tokens)
Definition: ITstream.C:40
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
const_iterator cbegin() const noexcept
Return const_iterator to begin traversing the constant UList.
Definition: UListI.H:406
label n
const T * cdata() const noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:258
void print(Ostream &os) const override
Print stream description to Ostream.
Definition: ITstream.C:266
bool skip(label n=1) noexcept
Move tokenIndex relative to the current position.
Definition: ITstream.C:387
iterator end() noexcept
Return an iterator to end traversing the UList.
Definition: UListI.H:436
ITstream(const ITstream &is)
Copy construct.
Definition: ITstream.C:140
void operator=(const ITstream &is)
Copy assignment, with rewind()
Definition: ITstream.C:731
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))
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
Definition: error.H:696
void seek(label pos) noexcept
Move tokenIndex to the specified position and adjust the stream status (open/good/eof ...
Definition: ITstream.C:355
An input stream of tokens.
Definition: ITstream.H:52
Namespace for OpenFOAM.
ITstream extract(const labelRange &range)
Remove a (start,size) subset from the list and move remaining elements down.
Definition: ITstream.C:540
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...