Loading...
Searching...
No Matches
CompactIOList.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-2017 OpenFOAM Foundation
9 Copyright (C) 2015-2025 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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 "CompactIOList.H"
30
31// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32
33template<class T>
34bool Foam::CompactIOList<T>::readIOcontents()
35{
36 typedef IOList<T> plain_type;
37
38 if (isReadRequired() || (isReadOptional() && headerOk()))
39 {
40 Istream& is = readStream(word::null);
41
42 if (isHeaderClass(typeName))
43 {
44 // Compact form
45 is >> *this; // or: this->readCompact(is);
46 }
47 else if (isHeaderClass<plain_type>())
48 {
49 // Non-compact form
50 is >> static_cast<content_type&>(*this);
51 }
52 else
53 {
55 << "Unexpected class name " << headerClassName()
56 << " expected " << typeName
57 << " or " << plain_type::typeName << endl
58 << " while reading object " << name()
59 << exit(FatalIOError);
60 }
61
62 close();
63 return true;
64 }
65
66 return false;
67}
68
69
70template<class T>
71Foam::label Foam::CompactIOList<T>::readIOsize()
72{
73 typedef IOList<T> plain_type;
74
75 label count(-1);
76
77 if (isReadRequired() || (isReadOptional() && headerOk()))
78 {
79 Istream& is = readStream(word::null);
80
81 token tok(is);
82
83 if (tok.isLabel())
84 {
85 // The majority of files will have lists with sizing prefix
86 count = tok.labelToken();
87
88 if (isHeaderClass(typeName))
89 {
90 // Compact form: read offsets, not content
91 if (--count < 0)
92 {
93 count = 0;
94 }
95 }
96 }
97 else
98 {
99 is.putBack(tok);
100
101 if (isHeaderClass(typeName))
102 {
103 // Compact form: can just read the offsets
104 labelList offsets(is);
105 count = Foam::max(0, (offsets.size()-1));
106 }
107 else if (isHeaderClass<plain_type>())
108 {
109 // Non-compact form: need to read everything
110 List<T> list(is);
111 count = list.size();
112 }
113 else
114 {
116 << "Unexpected class name " << headerClassName()
117 << " expected " << typeName
118 << " or " << plain_type::typeName << endl
119 << " while reading object " << name()
120 << exit(FatalIOError);
121 }
122 }
123 close();
124 }
125
126 return count;
127}
128
129
130template<class T>
131bool Foam::CompactIOList<T>::overflows() const
132{
133 // Can safely assume that int64 will not overflow
134 if constexpr (sizeof(label) < sizeof(int64_t))
135 {
136 const UList<T>& lists = *this;
137
138 label total = 0;
139 for (const auto& list : lists)
140 {
141 const label prev = total;
142 total += list.size();
143 if (total < prev)
144 {
145 return true;
146 }
147 }
148 }
149 return false;
150}
151
152
153// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
154
155template<class T>
157:
159{
160 readIOcontents();
161}
162
163
164template<class T>
166(
167 const IOobject& io,
169)
170:
172{
173 readIOcontents();
174}
175
176
177template<class T>
179(
180 const IOobject& io,
181 const label len
182)
183:
185{
186 if (!readIOcontents())
188 List<T>::resize(len);
189 }
190}
191
192
193template<class T>
195(
196 const IOobject& io,
197 const UList<T>& content
198)
199:
200 regIOobject(io)
201{
202 if (!readIOcontents())
204 List<T>::operator=(content);
205 }
206}
207
208
209template<class T>
211(
212 const IOobject& io,
213 List<T>&& content
214)
215:
216 regIOobject(io)
217{
218 List<T>::transfer(content);
219
220 readIOcontents();
221}
222
223
224// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
225
226template<class T>
228{
230 if (rio.readOpt() == IOobjectOption::READ_MODIFIED)
231 {
232 rio.readOpt(IOobjectOption::MUST_READ);
233 }
234 rio.resetHeader();
235
236 // Construct NO_READ, changing after construction
237 const auto rOpt = rio.readOpt(IOobjectOption::NO_READ);
238
239 CompactIOList<T> reader(rio);
240 reader.readOpt(rOpt);
241
242 return reader.readIOsize();
243}
244
245
246template<class T>
248{
251 {
253 }
254 rio.resetHeader();
255
256 CompactIOList<T> reader(rio);
257
258 return List<T>(std::move(static_cast<List<T>&>(reader)));
259}
260
261
262// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
263
264template<class T>
266(
267 IOstreamOption streamOpt,
268 const bool writeOnProc
269) const
270{
271 if
272 (
273 streamOpt.format() == IOstreamOption::BINARY
274 && overflows()
275 )
276 {
277 streamOpt.format(IOstreamOption::ASCII);
278
280 << "Overall number of elements of CompactIOList (size:"
281 << this->size() << ") overflows a label (int"
282 << (8*sizeof(label)) << ')' << nl
283 << " Switching to ascii writing" << endl;
284 }
285
286 if (streamOpt.format() != IOstreamOption::BINARY)
287 {
288 // Change type to be non-compact format type
289 const word oldTypeName(typeName);
290
291 const_cast<word&>(typeName) = IOList<T>::typeName;
292
293 bool good = regIOobject::writeObject(streamOpt, writeOnProc);
294
295 // Change type back
296 const_cast<word&>(typeName) = oldTypeName;
297
298 return good;
300
301 return regIOobject::writeObject(streamOpt, writeOnProc);
302}
303
304
305template<class T>
306bool Foam::CompactIOList<T>::writeData(Ostream& os) const
307{
308 return (os << *this).good();
309}
310
311
312// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
313
314template<class T>
316{
317 List<T>& lists = *this;
318
319 // The base type for packed values
320 typedef typename T::value_type base_type;
321
322 // Read compact: offsets + packed values
323 const labelList offsets(is);
324 List<base_type> values(is);
325
326 // Transcribe
327 const label len = Foam::max(0, (offsets.size()-1));
328 lists.resize_nocopy(len);
329
330 auto iter = values.begin();
331
332 for (label i = 0; i < len; ++i)
333 {
334 auto& list = lists[i];
335 const label count = (offsets[i+1] - offsets[i]);
336
337 list.resize_nocopy(count);
338
339 std::move(iter, iter + count, list.begin());
340
341 iter += count;
343
344 return is;
345}
346
347
348template<class T>
350{
351 const List<T>& lists = *this;
352
353 // The base type for packed values
354 typedef typename T::value_type base_type;
355
356 // Convert to compact format
357 label total = 0;
358 const label len = lists.size();
359
360 // offsets
361 {
362 labelList offsets(len+1);
363
364 for (label i = 0; i < len; ++i)
365 {
366 offsets[i] = total;
367 total += lists[i].size();
368
369 if (total < offsets[i])
370 {
372 << "Overall number of elements of CompactIOList (size:"
373 << len
374 << ") overflows the representation of a label" << nl
375 << "Please recompile with a larger representation"
376 << " for label" << exit(FatalIOError);
377 }
378 }
379 offsets[len] = total;
380 os << offsets;
381 }
382
383 // packed values: make deepCopy for writing
384 {
385 List<base_type> values(total);
386
387 auto iter = values.begin();
388
389 for (const auto& list : lists)
390 {
391 iter = std::copy_n(list.begin(), list.size(), iter);
392
393 // With IndirectList? [unlikely]
394 // const label count = list.size();
395 // for (label i = 0; i < count; (void)++i, (void)++iter)
396 // {
397 // *iter = list[i];
398 // }
399 }
400 os << values;
401 }
402
403 return os;
404}
405
406
407// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
408
409template<class T>
410Foam::Istream& Foam::operator>>
411(
412 Foam::Istream& is,
413 Foam::CompactIOList<T>& lists
414)
415{
416 return lists.readCompact(is);
417}
418
419
420template<class T>
421Foam::Ostream& Foam::operator<<
422(
423 Foam::Ostream& os,
424 const Foam::CompactIOList<T>& lists
425)
426{
427 // Keep ASCII writing same
429 {
431 }
432 else
433 {
434 lists.writeCompact(os);
435 }
436
437 return os;
438}
439
440
441// ************************************************************************* //
A List of objects of type <T> with automated input and output using a compact storage....
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc) const
Write using stream options. Checks for overflow in binary.
Ostream & writeCompact(Ostream &os) const
Write as offsets/packed-values.
virtual bool writeData(Ostream &os) const
Write as plain or compact content (depends on stream format).
static List< T > readContents(const IOobject &io)
Read and return contents. The IOobject will not be registered.
Istream & readCompact(Istream &is)
Read as offsets/packed-values and transcribe into *this.
CompactIOList(const CompactIOList &)=default
Default copy construct.
static label readContentsSize(const IOobject &io)
Read and return content size, -1 if not read.
A List of objects of type <T> with automated input and output.
Definition IOList.H:53
@ NO_REGISTER
Do not request registration (bool: false).
readOption readOpt() const noexcept
Get the read option.
@ NO_READ
Nothing to be read.
@ MUST_READ
Reading required.
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
bool good() const noexcept
Did last readHeader() succeed?
Definition IOobjectI.H:354
void resetHeader(const word &newName=word::null)
Clear various bits (headerClassName, note, sizeof...) that would be obtained when reading from a file...
Definition IOobject.C:644
A simple container for options an IOstream can normally have.
streamFormat format() const noexcept
Get the current stream format.
@ ASCII
"ascii" (normal default)
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition Istream.H:60
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void transfer(List< T > &list)
Transfer the contents of the argument List into this list and annul the argument list.
Definition List.C:347
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition ListI.H:171
void operator=(const UList< T > &list)
Assignment to UList operator. Takes linear time.
Definition List.C:381
void resize(const label len)
Adjust allocated size of list.
Definition ListI.H:153
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition Ostream.H:59
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition regIOobject.H:71
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc) const
Write using stream options.
regIOobject(const IOobject &io, const bool isTimeObject=false)
Construct from IOobject. The optional flag adds special handling if the object is the top-level regIO...
Definition regIOobject.C:43
A class for handling words, derived from Foam::string.
Definition word.H:66
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition zero.H:58
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
OBJstream os(runTime.globalPath()/outputName)
const auto & io
auto & name
#define WarningInFunction
Report a warning using Foam::Warning.
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
Definition BitOps.H:73
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition HashOps.H:164
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
List< label > labelList
A List of labels.
Definition List.H:62
const word GlobalIOList< Tuple2< scalar, vector > >::typeName("scalarVectorTable")
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50