UListIO.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) 2016-2025 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 "UList.H"
30 #include "Ostream.H"
31 #include "token.H"
32 
33 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
34 
35 template<class T>
37 {
38  const word tag("List<" + word(pTraits<T>::typeName) + '>');
39  if (token::compound::isCompound(tag))
40  {
41  os << tag << token::SPACE;
42  }
43 
44  if (size())
45  {
46  os << *this;
47  }
48  else if
49  (
50  os.format() == IOstreamOption::BINARY
51  || std::is_same_v<char, std::remove_cv_t<T>>
52  )
53  {
54  // Zero-sized binary - Write size only
55  // NB: special treatment for char data (binary I/O only)
56  os << label(0);
57  }
58  else
59  {
60  // Zero-sized ASCII - Write size and delimiters
61  os << label(0) << token::BEGIN_LIST << token::END_LIST;
62  }
63 }
64 
65 
66 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
67 
68 template<class T>
69 void Foam::UList<T>::writeEntry(const word& keyword, Ostream& os) const
70 {
71  if (keyword.size())
72  {
73  os.writeKeyword(keyword);
74  }
75  writeEntry(os);
76  os.endEntry();
77 }
78 
79 
80 template<class T>
82 (
83  Ostream& os,
84  const label shortLen
85 ) const
86 {
87  const UList<T>& list = *this;
88 
89  const label len = list.size();
90 
91  if (os.format() == IOstreamOption::BINARY && is_contiguous_v<T>)
92  {
93  // Binary and contiguous
94 
95  os << nl << len << nl;
96 
97  if (len)
98  {
99  // write(...) includes surrounding start/end delimiters
100  os.write(list.cdata_bytes(), list.size_bytes());
101  }
102  }
103  else if constexpr (std::is_same_v<char, std::remove_cv_t<T>>)
104  {
105  // Special treatment for char data (binary I/O only)
106 
107  const auto oldFmt = os.format(IOstreamOption::BINARY);
108  os << nl << len << nl;
109 
110  if (len)
111  {
112  // write(...) includes surrounding start/end delimiters
113  os.write(list.cdata_bytes(), list.size_bytes());
114  }
115 
116  os.format(oldFmt);
117  }
118  else if (is_contiguous_v<T> && len > 1 && list.uniform())
119  {
120  // Two or more entries, and all entries have identical values.
121  os << len << token::BEGIN_BLOCK << list[0] << token::END_BLOCK;
122  }
123  else if
124  (
125  (len <= 1 || !shortLen)
126  ||
127  (
128  (len <= shortLen)
129  && (is_contiguous_v<T> || Foam::ListPolicy::no_linebreak<T>::value)
130  )
131  )
132  {
133  // Single-line output
134 
135  // Size and start delimiter
136  os << len << token::BEGIN_LIST;
137 
138  auto iter = list.cbegin();
139  const auto last = list.cend();
140 
141  // Contents
142  if (iter != last)
143  {
144  os << *iter;
145 
146  for (++iter; (iter != last); (void)++iter)
147  {
148  os << token::SPACE << *iter;
149  }
150  }
151 
152  // End delimiter
153  os << token::END_LIST;
154  }
155  else
156  {
157  // Multi-line output
158 
159  // Size and start delimiter
160  os << nl << len << nl << token::BEGIN_LIST;
161 
162  auto iter = list.cbegin();
163  const auto last = list.cend();
164 
165  // Contents
166  for (/*nil*/; (iter != last); (void)++iter)
167  {
168  os << nl << *iter;
169  }
170 
171  // End delimiter
172  os << nl << token::END_LIST << nl;
173  }
175  os.check(FUNCTION_NAME);
176  return os;
177 }
178 
179 
180 template<class T>
182 {
183  UList<T>& list = *this;
184 
185  // The target list length - must match with sizes read
186  const label len = list.size();
187 
189 
190  token tok(is);
191 
192  is.fatalCheck("UList<T>::readList(Istream&) : reading first token");
193 
194  if (tok.isCompound())
195  {
196  // Compound: simply transfer contents
197 
198  List<T> elems;
199  elems.transfer
200  (
202  );
203 
204  const label inputLen = elems.size();
205 
206  // List lengths must match
207  if (inputLen != len)
208  {
210  << "incorrect length for UList. Read "
211  << inputLen << " expected " << len
212  << exit(FatalIOError);
213  }
214 
215  std::move(elems.begin(), elems.end(), list.begin());
216  }
217  else if (tok.isLabel())
218  {
219  // Label: could be int(..), int{...} or just a plain '0'
220 
221  const label inputLen = tok.labelToken();
222 
223  // List lengths must match
224  if (inputLen != len)
225  {
227  << "incorrect length for UList. Read "
228  << inputLen << " expected " << len
229  << exit(FatalIOError);
230  }
231 
232  if (is.format() == IOstreamOption::BINARY && is_contiguous_v<T>)
233  {
234  // Binary and contiguous
235 
236  if (len)
237  {
238  Detail::readContiguous<T>
239  (
240  is,
241  list.data_bytes(),
242  list.size_bytes()
243  );
244 
245  is.fatalCheck
246  (
247  "UList<T>::readList(Istream&) : "
248  "reading binary block"
249  );
250  }
251  }
252  else if constexpr (std::is_same_v<char, std::remove_cv_t<T>>)
253  {
254  // Special treatment for char data (binary I/O only)
255  const auto oldFmt = is.format(IOstreamOption::BINARY);
256 
257  if (len)
258  {
259  // read(...) includes surrounding start/end delimiters
260  is.read(list.data_bytes(), list.size_bytes());
261 
262  is.fatalCheck
263  (
264  "UList<char>::readList(Istream&) : "
265  "reading binary block"
266  );
267  }
268 
269  is.format(oldFmt);
270  }
271  else
272  {
273  // Begin of contents marker
274  const char delimiter = is.readBeginList("List");
275 
276  if (len)
277  {
278  if (delimiter == token::BEGIN_LIST)
279  {
280  for (label i=0; i<len; ++i)
281  {
282  is >> list[i];
283 
284  is.fatalCheck
285  (
286  "UList<T>::readList(Istream&) : "
287  "reading entry"
288  );
289  }
290  }
291  else
292  {
293  // Uniform content (delimiter == token::BEGIN_BLOCK)
294 
295  T elem;
296  is >> elem;
297 
298  is.fatalCheck
299  (
300  "UList<T>::readList(Istream&) : "
301  "reading the single entry"
302  );
303 
304  // Fill with the value
305  this->fill_uniform(elem);
306  }
307  }
308 
309  // End of contents marker
310  is.readEndList("List");
311  }
312  }
313  else if (tok.isPunctuation(token::BEGIN_LIST))
314  {
315  // "(...)" : read into list, handling size-mismatch after
316 
317  is >> tok;
318  is.fatalCheck(FUNCTION_NAME);
319 
320  label inputLen = 0;
321 
322  while (!tok.isPunctuation(token::END_LIST))
323  {
324  is.putBack(tok);
325  if (inputLen < len)
326  {
327  is >> list[inputLen];
328  }
329  else
330  {
331  // Read and discard
332  T dummy;
333  is >> dummy;
334  }
335  ++inputLen;
336 
337  is.fatalCheck
338  (
339  "UList<T>::readList(Istream&) : "
340  "reading entry"
341  );
342 
343  is >> tok;
344  is.fatalCheck(FUNCTION_NAME);
345  }
346 
347  // List lengths must match
348  if (inputLen != len)
349  {
351  << "incorrect length for UList. Read "
352  << inputLen << " expected " << len
353  << exit(FatalIOError);
354  }
355  }
356  else
357  {
359  << "incorrect first token, expected <int> or '(', found "
360  << tok.info() << nl
361  << exit(FatalIOError);
362  }
363 
364  return is;
365 }
366 
367 
368 // ************************************************************************* //
bool isPunctuation() const noexcept
Token is PUNCTUATION.
Definition: tokenI.H:561
const_iterator cend() const noexcept
Return const_iterator to end traversing the constant UList.
Definition: UListI.H:443
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
void transfer(List< T > &list)
Transfer the contents of the argument List into this list and annul the argument list.
Definition: List.C:337
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:821
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
A traits class, which is primarily used for primitives and vector-space.
Definition: pTraits.H:61
bool uniform() const
True if all entries have identical values, and list is non-empty.
Definition: UListI.H:208
char * data_bytes() noexcept
Return pointer to the underlying array serving as data storage,.
Definition: UListI.H:279
Istream & readList(Istream &is)
Read List contents from Istream.
Definition: UListIO.C:174
const char * cdata_bytes() const noexcept
Return pointer to the underlying array serving as data storage,.
Definition: UListI.H:272
Ostream & writeList(Ostream &os, const label shortLen=0) const
Write List, with line-breaks in ASCII when length exceeds shortLen.
Definition: UListIO.C:75
compound & transferCompoundToken(const Istream *is=nullptr)
Return reference to compound and mark internally as released.
Definition: token.C:157
A class for handling words, derived from Foam::string.
Definition: word.H:63
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition: UListI.H:385
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
OBJstream os(runTime.globalPath()/outputName)
#define FUNCTION_NAME
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:629
label labelToken() const
Return label value.
Definition: tokenI.H:633
bool isLabel() const noexcept
Token is LABEL.
Definition: tokenI.H:599
const_iterator cbegin() const noexcept
Return const_iterator to begin traversing the constant UList.
Definition: UListI.H:399
void writeEntry(Ostream &os) const
Write the UList with its compound type.
Definition: UListIO.C:29
iterator end() noexcept
Return an iterator to end traversing the UList.
Definition: UListI.H:429
streamFormat format() const noexcept
Get the current stream format.
std::streamsize size_bytes() const noexcept
Number of contiguous bytes for the List data.
Definition: UListI.H:286
Can suppress additional line breaks separate ASCII data content when the data elements are primitives...
Definition: ListPolicy.H:73
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...