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