bitSetIO.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) 2018-2025 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 "bitSet.H"
29 #include "Switch.H"
30 #include "IOstreams.H"
31 
32 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
33 
34 // Format is either of these:
35 //
36 // <int1> <int2> ( ... )
37 // <int1> <int2> { <bool> }
38 // where int1 = size, int2 = number of 'on' entries
39 // - within the brackets : the locations of the 'on' entries.
40 // - within the braces : a uniform set where true = all, false = none
41 //
43 (
44  Ostream& os,
45  label shortLen
46 ) const
47 {
48  const bitSet& bitset = *this;
49  if (shortLen < 0) shortLen = 1; // <- sanity
50 
51  // Size and number of 'ON' entries:
52  const label len = bitset.size();
53  const label tocLen = (bitset.any() ? bitset.count() : 0);
54 
56  (
57  (tocLen == 0) ? Switch::FALSE // None on
58  : (tocLen == len) ? Switch::TRUE // All on
59  : Switch::INVALID // Mixed
60  );
61 
62 
63  // Not yet:
64  // if (os.format() == IOstreamOption::BINARY) {}
65 
66  if (len > 1 && uniformity.good())
67  {
68  // Two or more entries, and all entries have identical values
69 
70  // Count/size and delimiter
71  os << len << token::SPACE << tocLen << token::BEGIN_BLOCK;
72 
73  if (uniformity)
74  {
75  os << word("true");
76  }
77  else
78  {
79  os << word("false");
80  }
81  os << token::END_BLOCK;
82 
83  }
84  else if (len <= 1 || !shortLen || (len <= shortLen))
85  {
86  // Single-line output
87 
88  // Count/size and delimiter
89  os << len << token::SPACE << tocLen << token::BEGIN_LIST;
90 
91  label iter = bitset.find_first();
92 
93  if (iter >= 0)
94  {
95  os << iter;
96  iter = bitset.find_next(iter);
97  }
98 
99  // Contents
100  for (/*nil*/; iter >= 0; iter = bitset.find_next(iter))
101  {
102  os << token::SPACE << iter;
103  }
104 
105  // End delimiter
106  os << token::END_LIST;
107  }
108  else
109  {
110  // Multi-line output, but with linebreaks according to shortLen
111 
112  // Count/size and delimiter
113  os << len << token::SPACE << tocLen << token::BEGIN_LIST;
114 
115  label column = 0; // The current output position
116 
117  // Contents
118  for
119  (
120  label iter = bitset.find_first();
121  iter >= 0;
122  iter = bitset.find_next(iter)
123  )
124  {
125  if (column >= shortLen) { os << nl; }
126  else if (column) { os << token::SPACE; }
127  ++column;
128  os << iter;
129  }
130 
131  // End delimiter
132  os << nl << token::END_LIST;
133  }
134 
135  return os;
136 }
137 
138 
140 {
141  bitSet& bitset = *this;
142 
143  // Input errors that may be encountered:
144  enum errorType
145  {
146  ErrorNone = 0, // OK
147  ErrorToken1, // Bad first token
148  ErrorToken2, // Bad second token
149  ErrorSizing, // Bad size (len < tocLen)
150  ErrorBounds, // Bad toc entry
151  };
152  int errorCode(errorType::ErrorNone);
153 
154  label len(0);
155  label tocLen(0);
156  label tocEntry(-1); // The toc entry while reading
157 
158 
159  is.fatalCheck(FUNCTION_NAME);
160 
161  token tok(is);
162  is.fatalCheck("bitSet::readTocList() : reading first token");
163 
164  if (tok.isLabel())
165  {
166  len = tok.labelToken();
167  tok.read(is);
168 
169  if (tok.isLabel())
170  {
171  tocLen = tok.labelToken();
172  if (len < tocLen) { errorCode = errorType::ErrorSizing; }
173  }
174  else
175  {
176  errorCode = errorType::ErrorToken2;
177  }
178  }
179  else
180  {
181  errorCode = errorType::ErrorToken1;
182  }
183 
184  if (errorCode == errorType::ErrorNone) do
185  {
186  bitset.clear(); // Clear old contents
187  bitset.resize(len);
188 
189  // Not yet:
190  // if (is.format() == IOstreamOption::BINARY) {} else
191  {
192  // Begin of contents marker
193  const char delimiter = is.readBeginList("bitSet");
194 
195  if (delimiter == token::BEGIN_LIST)
196  {
197  // Read entries
198  for (label i = 0; i < tocLen; ++i)
199  {
200  is >> tocEntry;
201  is.fatalCheck
202  (
203  "bitSet::readCompact(Istream&) : "
204  "reading entry"
205  );
206 
207  if (tocEntry < 0 || tocEntry >= len)
208  {
209  errorCode = errorType::ErrorBounds;
210  break;
211  }
212  else
213  {
214  bitset.set(tocEntry);
215  }
216  }
217  }
218  else
219  {
220  // Uniform content (delimiter == token::BEGIN_BLOCK)
221  Switch uniformity(is);
222 
223  is.fatalCheck
224  (
225  "bitSet::readTocList() : "
226  "reading the single entry"
227  );
228 
229  // Fill with the value
231  }
232 
233  // End of contents marker
234 
235  if (errorCode == errorType::ErrorNone)
236  {
237  is.readEndList("bitSet");
238  }
239  }
240  }
241  while (false);
242 
243  if (errorCode != errorType::ErrorNone)
244  {
245  auto& err = FatalIOErrorInFunction(is);
246 
247  if (errorType::ErrorToken1 == errorCode)
248  {
249  err << "Incorrect first token [size], expected <int>, found "
250  << tok.info() << nl;
251  }
252  else if (errorType::ErrorToken2 == errorCode)
253  {
254  err << "Incorrect second token [toc size], expected <int>, found "
255  << tok.info() << nl;
256  }
257  else if (errorType::ErrorSizing == errorCode)
258  {
259  err << "Bad sizing: has " << tocLen
260  << " entries for a bitSet with size " << len << nl;
261  }
262  else if (errorType::ErrorBounds == errorCode)
263  {
264  err << "Entry " << tocEntry
265  << " not within the expected bounds [0," << len << "]" << nl;
266  }
267  else
268  {
269  err << "Unspecified error" << nl;
270  }
271 
272  err << exit(FatalIOError);
273  }
275  return is;
276 }
277 
278 
279 // * * * * * * * * * * * * * * Ostream Operators * * * * * * * * * * * * * * //
280 
282 {
283  return bitset.writeList(os, 40);
284 }
285 
286 
287 Foam::Ostream& Foam::operator<<
288 (
289  Ostream& os,
290  const InfoProxy<bitSet>& iproxy
291 )
292 {
293  const auto& bitset = *iproxy;
294 
295  os << "bitSet<" << bitSet::elem_per_block
296  << "> size=" << bitset.size() << '/' << bitset.capacity()
297  << " count=" << bitset.count()
298  << nl;
299 
300  return os;
301 }
302 
303 
304 // ************************************************************************* //
Begin block [isseparator].
Definition: token.H:178
unsigned int count(const bool on=true) const
Count number of bits set.
Definition: bitSetI.H:420
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:502
void fill(const bool val)
Assign all entries to the given value.
Definition: bitSetI.H:474
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
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
label find_first() const
Locate the first bit that is set.
Definition: bitSetI.H:260
A simple wrapper around bool so that it can be read as a word: true/false, on/off, yes/no, any/none. Also accepts 0/1 as a string and shortcuts t/f, y/n.
Definition: Switch.H:80
Begin list [isseparator].
Definition: token.H:174
label find_next(label pos) const
Locate the next bit set, starting one beyond the specified position.
Definition: bitSetI.H:347
Ostream & writeListToc(Ostream &os, label shortLen=0) const
Write contents in "compact" format, which is the listing of the &#39;on&#39; bits (toc), with line-breaks in ...
Definition: bitSetIO.C:36
bool any() const
True if any bits in this bitset are set.
Definition: bitSetI.H:408
void resize(const label numElem, const unsigned int val=0u)
Reset addressable list size, does not shrink the allocated size.
Definition: PackedListI.H:455
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
Ostream & writeList(Ostream &os, label shortLen=0) const
Write List, with line-breaks in ASCII when length exceeds shortLen.
Definition: PackedListIO.C:172
A class for handling words, derived from Foam::string.
Definition: word.H:63
Space [isspace].
Definition: token.H:144
errorType
Enumeration for possible parsing error.
Definition: parsing.H:55
End list [isseparator].
Definition: token.H:175
void clear()
Clear the list, i.e. set addressable size to zero.
Definition: PackedListI.H:577
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
#define FUNCTION_NAME
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:77
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:58
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:681
static constexpr unsigned elem_per_block
The number of elements stored per data block.
Definition: PackedList.H:174
label capacity() const noexcept
Number of elements that can be stored without reallocating.
Definition: PackedListI.H:437
End block [isseparator].
Definition: token.H:179
uniformity
Classification of list/container uniformity. The values can be used with bit-wise or reduction...
Definition: ListPolicy.H:360
bitSet bitset(const labelHashSet &locations)
Transform the on locations to a bitSet.
Definition: HashOps.C:63
label size() const noexcept
Number of entries.
Definition: PackedList.H:392
Istream & readListToc(Istream &is)
Read contents in "compact" format, which is the listing of the &#39;on&#39; bits (toc)
Definition: bitSetIO.C:132
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...