CircularBufferIO.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) 2022 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "List.H"
29 #include "Istream.H"
30 #include "contiguous.H"
31 
32 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
33 
34 template<class T>
36 {
37  this->readList(is);
38 }
39 
40 
41 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
42 
43 template<class T>
45 {
46  os << "size=" << size() << '/' << capacity()
47  << " begin=" << begin_
48  << " end=" << end_
51  << nl;
52 
53  return os;
54 }
55 
56 
57 template<class T>
59 {
60  // Clear list
61  storage_.clear();
62  begin_ = 0;
63  end_ = 0;
64 
65  // More work than it should be. We avoid completely filled buffers!
66 
68 
69  token tok(is);
70 
71  is.fatalCheck
72  (
73  "CircularBuffer<T>::readList(Istream&) : "
74  "reading first token"
75  );
76 
77  if (tok.isCompound())
78  {
79  // Compound: simply transfer contents
80 
81  storage_.transfer
82  (
84  (
85  tok.transferCompoundToken(is)
86  )
87  );
88 
89  end_ = storage_.size();
90  if (end_)
91  {
92  // Resize larger to avoid full buffer
93  storage_.resize(end_ + min_size());
94  }
95  }
96  else if (tok.isLabel())
97  {
98  // Label: could be int(..), int{...} or just a plain '0'
99 
100  const label len = tok.labelToken();
101 
102  end_ = len;
103  if (end_)
104  {
105  // Resize larger to avoid full buffer
106  storage_.resize(end_ + min_size());
107  }
108 
109  // Dispatch to UList reading...
110 
111  UList<T> list(storage_.data(), end_);
112 
113  is.putBack(tok);
114  list.readList(is);
115  }
116  else if (tok.isPunctuation(token::BEGIN_LIST))
117  {
118  // "(...)" : read as SLList and transfer contents
119 
120  is.putBack(tok); // Putback the opening bracket
121  SLList<T> sll(is); // Read as singly-linked list
122 
123  const label len = sll.size();
124 
125  end_ = len;
126  if (end_)
127  {
128  // Resize larger to avoid full buffer
129  storage_.resize(end_ + min_size());
130 
131  // Move assign each list element
132  for (label i = 0; i < len; ++i)
133  {
134  storage_[i] = std::move(sll.removeHead());
135  }
136  }
137  }
138  else
139  {
141  << "incorrect first token, expected <int> or '(', found "
142  << tok.info() << nl
143  << exit(FatalIOError);
144  }
146  return is;
147 }
148 
149 
150 template<class T>
152 (
153  Ostream& os,
154  const label shortLen
155 ) const
156 {
157  const label len = this->size();
158  const auto list1 = this->array_one();
159  const auto list2 = this->array_two();
160 
161  #ifdef FULLDEBUG
162  if (len != (list1.size() + list2.size()))
163  {
165  << "Size check failed"
166  << abort(FatalError);
167  }
168  #endif
169 
170  if (os.format() == IOstreamOption::BINARY && is_contiguous<T>::value)
171  {
172  // Binary and contiguous
173 
174  os << nl << len << nl;
175 
176  if (len)
177  {
178  // The TOTAL number of bytes to be written.
179  // - possibly add start delimiter
180  // This is much like IndirectListBase output
181 
182  os.beginRawWrite(len*sizeof(T));
183 
184  if (!list1.empty())
185  {
186  os.writeRaw(list1.cdata_bytes(), list1.size_bytes());
187  }
188  if (!list2.empty())
189  {
190  os.writeRaw(list2.cdata_bytes(), list2.size_bytes());
191  }
192 
193  // End delimiter and/or cleanup.
194  os.endRawWrite();
195  }
196  }
197  else if
198  (
199  (len <= 1 || !shortLen)
200  ||
201  (
202  (len <= shortLen)
203  &&
204  (
205  is_contiguous<T>::value
206  || Detail::ListPolicy::no_linebreak<T>::value
207  )
208  )
209  )
210  {
211  // Single-line output
212 
213  // Size and start delimiter
214  os << len << token::BEGIN_LIST;
215 
216  // Contents
217  label i = 0;
218  for (const T& val : list1)
219  {
220  if (i++) os << token::SPACE;
221  os << val;
222  }
223  for (const T& val : list2)
224  {
225  if (i++) os << token::SPACE;
226  os << val;
227  }
228 
229  // End delimiter
230  os << token::END_LIST;
231  }
232  else
233  {
234  // Multi-line output
235 
236  // Size and start delimiter
237  os << nl << len << nl << token::BEGIN_LIST << nl;
238 
239  // Contents
240  for (const T& val : list1)
241  {
242  os << val << nl;
243  }
244  for (const T& val : list2)
245  {
246  os << val << nl;
247  }
248 
249  // End delimiter
250  os << token::END_LIST << nl;
251  }
252 
253  os.check(FUNCTION_NAME);
254  return os;
255 }
256 
257 
258 // ************************************************************************* //
Ostream & writeList(Ostream &os, const label shortLen=0) const
Write buffer contents with line-breaks in ASCII when length exceeds shortLen.
bool isPunctuation() const noexcept
Token is PUNCTUATION.
Definition: tokenI.H:452
constexpr CircularBuffer() noexcept
Default construct, empty buffer without allocation.
compound & transferCompoundToken()
Return reference to compound and mark internally as released.
Definition: token.C:86
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
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
bool isCompound() const noexcept
Token is COMPOUND.
Definition: tokenI.H:709
InfoProxy< token > info() const
Return info proxy for printing token information to a stream.
Definition: token.H:788
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
A templated class for holding compound tokens.
Definition: token.H:281
Istream & readList(Istream &is)
Read buffer contents from Istream.
void putBack(const token &tok)
Put back a token. Only a single put back is permitted.
Definition: Istream.C:63
errorManip< error > abort(error &err)
Definition: errorManip.H:139
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:55
OBJstream os(runTime.globalPath()/outputName)
#define FUNCTION_NAME
Type & dynamicCast(U &obj)
A dynamic_cast (for references) that generates FatalError on failed casts.
Definition: typeInfo.H:108
const volScalarField & T
bool fatalCheck(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:51
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:607
label labelToken() const
Return label value.
Definition: tokenI.H:506
bool isLabel() const noexcept
Token is LABEL.
Definition: tokenI.H:490
Ostream & info(Ostream &os) const
Print information.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...