CompactIOList.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "CompactIOList.H"
27 #include "IOList.H"
28 
29 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
30 
31 template
32 <
33  template<class> class Container,
34  template<class> class IOContainer,
35  template<class> class CompactIOContainer,
36  class Type
37 >
38 bool
40 overflows() const
41 {
42  label size = 0;
43 
44  forAll(*this, i)
45  {
46  label oldSize = size;
47 
48  size += this->operator[](i).size();
49 
50  if (size < oldSize)
51  {
52  return true;
53  }
54  }
55 
56  return false;
57 }
58 
59 
60 template
61 <
62  template<class> class Container,
63  template<class> class IOContainer,
64  template<class> class CompactIOContainer,
65  class Type
66 >
67 void
70 (
71  labelList& start,
72  List<typename Type::value_type>& elems
73 ) const
74 {
75  start.setSize(this->size() + 1);
76 
77  start[0] = 0;
78 
79  for (label i = 1; i < start.size(); i++)
80  {
81  const label prev = start[i-1];
82 
83  start[i] = prev + this->operator[](i-1).size();
84 
85  if (start[i] < prev)
86  {
88  << "Overall number of elements " << start[i]
89  << " of CompactIOListBase of size "
90  << this->size() << " overflows the representation of a label"
91  << endl << "Please recompile with a larger representation"
92  << " for label" << exit(FatalError);
93  }
94  }
95 
96  elems.setSize(start[start.size() - 1]);
97 
98  label elemi = 0;
99 
100  forAll(*this, i)
101  {
102  const Type& subList = this->operator[](i);
103 
104  forAll(subList, j)
105  {
106  elems[elemi++] = subList[j];
107  }
108  }
109 }
110 
111 
112 template
113 <
114  template<class> class Container,
115  template<class> class IOContainer,
116  template<class> class CompactIOContainer,
117  class Type
118 >
119 void
122 (
123  const labelList& start,
124  const List<typename Type::value_type>& elems
125 )
126 {
127  this->setSize(start.size() - 1);
128 
129  forAll(*this, i)
130  {
131  Type& subList = this->operator[](i);
132 
133  label index = start[i];
134 
135  subList.setSize(start[i+1] - index);
136 
137  forAll(subList, j)
138  {
139  subList[j] = elems[index++];
140  }
141  }
142 }
143 
144 
145 template
146 <
147  template<class> class Container,
148  template<class> class IOContainer,
149  template<class> class CompactIOContainer,
150  class Type
151 >
152 void
154 readFromStream(const bool read)
155 {
156  Istream& is = readStream(word::null, read);
157 
158  if (read)
159  {
160  if (headerClassName() == IOContainer<Type>::typeName)
161  {
162  is >> static_cast<Container<Type>&>(*this);
163  close();
164  }
165  else if (headerClassName() == CompactIOContainer<Type>::typeName)
166  {
167  is >> *this;
168  close();
169  }
170  else
171  {
173  << "unexpected class name " << headerClassName()
174  << " expected " << CompactIOContainer<Type>::typeName << " or "
175  << IOContainer<Type>::typeName << endl
176  << " while reading object " << name()
177  << exit(FatalIOError);
178  }
179  }
180 }
181 
182 
183 // * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
184 
185 template
186 <
187  template<class> class Container,
188  template<class> class IOContainer,
189  template<class> class CompactIOContainer,
190  class Type
191 >
193 CompactIOListBase(const IOobject& io)
194 :
195  regIOobject(io)
196 {
197  if
198  (
200  || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
201  )
202  {
203  readFromStream();
204  }
205 }
206 
207 
208 template
209 <
210  template<class> class Container,
211  template<class> class IOContainer,
212  template<class> class CompactIOContainer,
213  class Type
214 >
217 (
218  const IOobject& io,
219  const bool read
220 )
221 :
222  regIOobject(io)
223 {
224  if (io.readOpt() == IOobject::MUST_READ)
225  {
226  readFromStream(read);
227  }
228  else if (io.readOpt() == IOobject::READ_IF_PRESENT)
229  {
230  bool haveFile = headerOk();
231  readFromStream(read && haveFile);
232  }
233 }
234 
235 
236 template
237 <
238  template<class> class Container,
239  template<class> class IOContainer,
240  template<class> class CompactIOContainer,
241  class Type
242 >
245 (
246  const IOobject& io,
247  const label size
248 )
249 :
250  regIOobject(io)
251 {
252  if
253  (
255  || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
256  )
257  {
258  readFromStream();
259  }
260  else
261  {
262  this->setSize(size);
263  }
264 }
265 
266 
267 template
268 <
269  template<class> class Container,
270  template<class> class IOContainer,
271  template<class> class CompactIOContainer,
272  class Type
273 >
276 (
277  const IOobject& io,
278  const Container<Type>& l
279 )
280 :
281  regIOobject(io),
282  Container<Type>(l)
283 {
284  if
285  (
287  || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
288  )
289  {
290  readFromStream();
291  }
292 }
293 
294 
295 template
296 <
297  template<class> class Container,
298  template<class> class IOContainer,
299  template<class> class CompactIOContainer,
300  class Type
301 >
304 (
305  const IOobject& io,
306  Container<Type>&& l
307 )
308 :
309  regIOobject(io),
310  Container<Type>(move(l))
311 {
312  if
313  (
315  || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
316  )
317  {
318  readFromStream();
319  }
320 }
321 
322 
323 template
324 <
325  template<class> class Container,
326  template<class> class IOContainer,
327  template<class> class CompactIOContainer,
328  class Type
329 >
332 (
334 )
335 :
336  regIOobject(move(l)),
337  Container<Type>(move(l))
338 {}
339 
340 
341 // * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * //
342 
343 template
344 <
345  template<class> class Container,
346  template<class> class IOContainer,
347  template<class> class CompactIOContainer,
348  class Type
349 >
352 {}
353 
354 
355 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
356 
357 template
358 <
359  template<class> class Container,
360  template<class> class IOContainer,
361  template<class> class CompactIOContainer,
362  class Type
363 >
364 bool
367 (
371  const bool write
372 ) const
373 {
374  if (fmt == IOstream::ASCII)
375  {
376  // Change type to be non-compact format type
377  const word oldTypeName = CompactIOContainer<Type>::typeName;
378 
379  const_cast<word&>(CompactIOContainer<Type>::typeName) =
380  IOContainer<Type>::typeName;
381 
382  bool good = regIOobject::writeObject(fmt, ver, cmp, write);
383 
384  // Change type back
385  const_cast<word&>(CompactIOContainer<Type>::typeName) = oldTypeName;
386 
387  return good;
388  }
389  else if (this->overflows())
390  {
392  << "Overall number of elements of CompactIOListBase of size "
393  << this->size() << " overflows the representation of a label"
394  << endl << " Switching to ascii writing" << endl;
395 
396  // Change type to be non-compact format type
397  const word oldTypeName = CompactIOContainer<Type>::typeName;
398 
399  const_cast<word&>(CompactIOContainer<Type>::typeName) =
400  IOContainer<Type>::typeName;
401 
402  bool good = regIOobject::writeObject(IOstream::ASCII, ver, cmp, write);
403 
404  // Change type back
405  const_cast<word&>(CompactIOContainer<Type>::typeName) = oldTypeName;
406 
407  return good;
408  }
409  else
410  {
411  return regIOobject::writeObject(fmt, ver, cmp, write);
412  }
413 }
414 
415 
416 template
417 <
418  template<class> class Container,
419  template<class> class IOContainer,
420  template<class> class CompactIOContainer,
421  class Type
422 >
423 bool
425 writeData(Ostream& os) const
426 {
427  return (os << *this).good();
428 }
429 
430 
431 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
432 
433 template
434 <
435  template<class> class Container,
436  template<class> class IOContainer,
437  template<class> class CompactIOContainer,
438  class Type
439 >
440 void
442 operator=
443 (
445  rhs
446 )
447 {
448  Container<Type>::operator=(rhs);
449 }
450 
451 
452 template
453 <
454  template<class> class Container,
455  template<class> class IOContainer,
456  template<class> class CompactIOContainer,
457  class Type
458 >
459 void
461 operator=
462 (
464 )
465 {
466  Container<Type>::operator=(move(rhs));
467 }
468 
469 
470 // * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
471 
472 template
473 <
474  template<class> class Container,
475  template<class> class IOContainer,
476  template<class> class CompactIOContainer,
477  class Type
478 >
480 (
481  Ostream& os,
483 )
484 {
485  os << l;
486 }
487 
488 
489 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
490 
491 template
492 <
493  template<class> class Container,
494  template<class> class IOContainer,
495  template<class> class CompactIOContainer,
496  class Type
497 >
498 Foam::Istream& Foam::operator>>
499 (
500  Istream& is,
501  CompactIOListBase<Container, IOContainer, CompactIOContainer, Type>& l
502 )
503 {
504  // ASCII is not compacted
505  if (is.format() == IOstream::ASCII)
506  {
507  is >> static_cast<Container<Type>&>(l);
508  }
509  else
510  {
511  labelList start(is);
512  List<typename Type::value_type> elems(is);
513  l.convertFromCompact(start, elems);
514  }
515 
516  return is;
517 }
518 
519 
520 template
521 <
522  template<class> class Container,
523  template<class> class IOContainer,
524  template<class> class CompactIOContainer,
525  class Type
526 >
527 Foam::Ostream& Foam::operator<<
528 (
529  Ostream& os,
530  const CompactIOListBase<Container, IOContainer, CompactIOContainer, Type>& l
531 )
532 {
533  // ASCII is not compacted
534  if (os.format() == IOstream::ASCII)
535  {
536  os << static_cast<const Container<Type>&>(l);
537  }
538  else
539  {
540  labelList start;
541  List<typename Type::value_type> elems;
542  l.convertToCompact(start, elems);
543  os << start << elems;
544  }
545 
546  return os;
547 }
548 
549 
550 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
virtual bool writeData(Ostream &) const
WriteData function required for regIOobject write operation.
virtual ~CompactIOListBase()
Destructor.
virtual bool writeObject(IOstream::streamFormat, IOstream::versionNumber, IOstream::compressionType, const bool write) const
WriteObject function. Changes the write type depending on whether.
CompactIOListBase(const IOobject &)
Construct from IOobject.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
readOption readOpt() const
Definition: IOobject.H:360
Version number type.
Definition: IOstream.H:97
streamFormat
Enumeration for the format of data in the stream.
Definition: IOstream.H:87
compressionType
Enumeration for the format of data in the stream.
Definition: IOstream.H:194
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:60
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:55
virtual bool writeObject(IOstream::streamFormat, IOstream::versionNumber, IOstream::compressionType, const bool write) const
Write using given format, version and compression.
bool headerOk()
Read and check header info.
Definition: regIOobject.C:453
virtual bool read()
Read object.
A class for handling words, derived from string.
Definition: word.H:62
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
#define WarningInFunction
Report a warning using Foam::Warning.
void read(Istream &, label &, const dictionary &)
In-place read with dictionary lookup.
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
bool read(const char *, int32_t &)
Definition: int32IO.C:85
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:257
word name(const bool)
Return a word representation of a bool.
Definition: boolIO.C:39
void writeEntry(Ostream &os, const HashTable< T, Key, Hash > &ht)
Definition: HashTableIO.C:96
IOerror FatalIOError
error FatalError
points setSize(newPointi)