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-2020 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 "SLList.H"
33 #include "contiguous.H"
34 
35 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
36 
37 template<class T>
39 {
40  const word tag("List<" + word(pTraits<T>::typeName) + '>');
41  if (token::compound::isCompound(tag))
42  {
43  os << tag << token::SPACE;
44  }
45 
46  if (size())
47  {
48  os << *this;
49  }
50  else if (os.format() == IOstream::ASCII)
51  {
52  // Zero-sized ASCII - Write size and delimiters
53  os << 0 << token::BEGIN_LIST << token::END_LIST;
54  }
55  else
56  {
57  // Zero-sized binary - Write size only
58  os << 0;
59  }
60 }
61 
62 
63 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
64 
65 template<class T>
66 void Foam::UList<T>::writeEntry(const word& keyword, Ostream& os) const
67 {
68  if (keyword.size())
69  {
70  os.writeKeyword(keyword);
71  }
72  writeEntry(os);
73  os << token::END_STATEMENT << endl;
74 }
75 
76 
77 template<class T>
79 (
80  Ostream& os,
81  const label shortLen
82 ) const
83 {
84  const UList<T>& list = *this;
85 
86  const label len = list.size();
87 
88  // Write list contents depending on data format
89  if (os.format() == IOstream::ASCII || !is_contiguous<T>::value)
90  {
91  if (len > 1 && is_contiguous<T>::value && list.uniform())
92  {
93  // Two or more entries, and all entries have identical values.
94  os << len << token::BEGIN_BLOCK << list[0] << token::END_BLOCK;
95  }
96  else if
97  (
98  (len <= 1 || !shortLen)
99  ||
100  (
101  (len <= shortLen)
102  &&
103  (
106  )
107  )
108  )
109  {
110  // Size and start delimiter
111  os << len << token::BEGIN_LIST;
112 
113  // Contents
114  for (label i=0; i < len; ++i)
115  {
116  if (i) os << token::SPACE;
117  os << list[i];
118  }
119 
120  // End delimiter
121  os << token::END_LIST;
122  }
123  else
124  {
125  // Size and start delimiter
126  os << nl << len << nl << token::BEGIN_LIST << nl;
127 
128  // Contents
129  for (label i=0; i < len; ++i)
130  {
131  os << list[i] << nl;
132  }
133 
134  // End delimiter
135  os << token::END_LIST << nl;
136  }
137  }
138  else
139  {
140  // Contents are binary and contiguous
141  os << nl << len << nl;
142 
143  if (len)
144  {
145  // write(...) includes surrounding start/end delimiters
146  os.write
147  (
148  reinterpret_cast<const char*>(list.cdata()),
149  list.byteSize()
150  );
151  }
152  }
153 
154  os.check(FUNCTION_NAME);
155  return os;
156 }
157 
158 
159 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
160 
161 template<class T>
163 {
164  // The target list length - must match with sizes read
165  const label len = list.size();
166 
168 
169  token firstToken(is);
170 
171  is.fatalCheck("operator>>(Istream&, UList<T>&) : reading first token");
172 
173  // Compound: simply transfer contents
174  if (firstToken.isCompound())
175  {
176  List<T> elems;
177  elems.transfer
178  (
180  (
181  firstToken.transferCompoundToken(is)
182  )
183  );
184 
185  const label inputLen = elems.size();
186 
187  // List lengths must match
188  if (inputLen != len)
189  {
191  << "incorrect length for UList. Read "
192  << inputLen << " expected " << len
193  << exit(FatalIOError);
194  }
195 
196  for (label i = 0; i < len; ++i)
197  {
198  list[i] = std::move(elems[i]);
199  }
200 
201  return is;
202  }
203 
204 
205  // Label: could be int(..), int{...} or just a plain '0'
206  if (firstToken.isLabel())
207  {
208  const label inputLen = firstToken.labelToken();
209 
210  // List lengths must match
211  if (inputLen != len)
212  {
214  << "incorrect length for UList. Read "
215  << inputLen << " expected " << len
216  << exit(FatalIOError);
217  }
218 
219  // Read list contents depending on data format
220 
221  if (is.format() == IOstream::ASCII || !is_contiguous<T>::value)
222  {
223  // Read beginning of contents
224  const char delimiter = is.readBeginList("List");
225 
226  if (len)
227  {
228  if (delimiter == token::BEGIN_LIST)
229  {
230  for (label i=0; i<len; ++i)
231  {
232  is >> list[i];
233 
234  is.fatalCheck
235  (
236  "operator>>(Istream&, UList<T>&) : reading entry"
237  );
238  }
239  }
240  else
241  {
242  // Uniform content (delimiter == token::BEGIN_BLOCK)
243 
244  T element;
245  is >> element;
246 
247  is.fatalCheck
248  (
249  "operator>>(Istream&, UList<T>&) : "
250  "reading the single entry"
251  );
252 
253  for (label i=0; i<len; ++i)
254  {
255  list[i] = element; // Copy the value
256  }
257  }
258  }
259 
260  // Read end of contents
261  is.readEndList("List");
262  }
263  else if (len)
264  {
265  // Non-empty, binary, contiguous
266 
267  Detail::readContiguous<T>
268  (
269  is,
270  reinterpret_cast<char*>(list.data()),
271  len*sizeof(T)
272  );
273 
274  is.fatalCheck
275  (
276  "operator>>(Istream&, UList<T>&) : reading the binary block"
277  );
278  }
279 
280  return is;
281  }
282 
283 
284  // "(...)" : read as SLList and transfer contents
285  if (firstToken.isPunctuation())
286  {
287  if (firstToken.pToken() != token::BEGIN_LIST)
288  {
290  << "incorrect first token, expected '(', found "
291  << firstToken.info()
292  << exit(FatalIOError);
293  }
294 
295  is.putBack(firstToken); // Putback the opening bracket
296 
297  SLList<T> sll(is); // Read as singly-linked list
298 
299  // List lengths must match
300  if (sll.size() != len)
301  {
303  << "incorrect length for UList. Read "
304  << sll.size() << " expected " << len
305  << exit(FatalIOError);
306  }
307 
308  // Move assign each list element
309  for (label i = 0; i < len; ++i)
310  {
311  list[i] = std::move(sll.removeHead());
312  }
313 
314  return is;
315  }
316 
317 
319  << "incorrect first token, expected <int> or '(', found "
320  << firstToken.info()
321  << exit(FatalIOError);
322 
323  return is;
324 }
325 
326 
327 // ************************************************************************* //
Foam::UList::writeList
Ostream & writeList(Ostream &os, const label shortLen=0) const
Write List, with line-breaks in ASCII when length exceeds shortLen.
Definition: UListIO.C:79
token.H
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::token::Compound
A templated class for holding compound tokens.
Definition: token.H:225
Foam::Istream::readBeginList
char readBeginList(const char *funcName)
Begin read of list data, starts with '(' or '{'.
Definition: Istream.C:146
Foam::UList::data
T * data()
Return a pointer to the first data element.
Definition: UListI.H:205
Foam::IOstream::fatalCheck
bool fatalCheck(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:57
Foam::IOstreamOption::format
streamFormat format() const noexcept
Get the current stream format.
Definition: IOstreamOption.H:289
Foam::Istream::readEndList
char readEndList(const char *funcName)
End read of list data, ends with ')' or '}'.
Definition: Istream.C:167
Foam::FatalIOError
IOerror FatalIOError
Foam::operator>>
Istream & operator>>(Istream &, directionInfo &)
Definition: directionInfo.C:230
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
Foam::token
A token holds an item read from Istream.
Definition: token.H:68
Foam::UList::uniform
bool uniform() const
True if all entries have identical values, and list is non-empty.
Definition: UListI.H:146
Foam::Istream
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:61
Foam::List::transfer
void transfer(List< T > &list)
Definition: List.C:459
Foam::IOstream::check
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:51
Foam::Ostream::write
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
Foam::Ostream::writeKeyword
virtual Ostream & writeKeyword(const keyType &kw)
Write the keyword followed by an appropriate indentation.
Definition: Ostream.C:57
T
const volScalarField & T
Definition: createFieldRefs.H:2
Foam::UList::writeEntry
void writeEntry(Ostream &os) const
Write the UList with its compound type.
Definition: UListIO.C:38
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Ostream.H
UList.H
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::Detail::ListPolicy::no_linebreak
Definition: ListPolicy.H:76
SLList.H
Non-intrusive singly-linked list.
contiguous.H
Foam::dynamicCast
To & dynamicCast(From &r)
Definition: typeInfo.H:88
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:63
Foam::pTraits
Traits class for primitives.
Definition: pTraits.H:54
Foam::Istream::putBack
void putBack(const token &tok)
Put back token.
Definition: Istream.C:53
Foam::UList
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:103
Foam::UList::byteSize
std::streamsize byteSize() const
Definition: UList.C:191
Foam::UList::cdata
const T * cdata() const
Return a const pointer to the first data element.
Definition: UListI.H:198
FUNCTION_NAME
#define FUNCTION_NAME
Definition: messageStream.H:270
Foam::UList::size
void size(const label n) noexcept
Override size to be inconsistent with allocated storage.
Definition: UListI.H:360
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:401
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::is_contiguous
A template class to specify that a data type can be considered as being contiguous in memory.
Definition: contiguous.H:75