UIPstream.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-2015 OpenFOAM Foundation
9  Copyright (C) 2017-2021 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 "error.H"
30 #include "UIPstream.H"
31 #include "int.H"
32 #include "token.H"
33 #include <cctype>
34 
35 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39 
40 // Convert a single character to a word with length 1
41 inline static Foam::word charToWord(char c)
42 {
43  return Foam::word(std::string(1, c), false);
44 }
45 
46 
47 // Adjust stream format based on the flagMask
48 inline static void processFlags(Istream& is, int flagMask)
49 {
50  if ((flagMask & token::ASCII))
51  {
52  is.format(IOstream::ASCII);
53  }
54  else if ((flagMask & token::BINARY))
55  {
56  is.format(IOstream::BINARY);
57  }
58 }
59 
60 
61 // Return the position with word boundary alignment
62 inline static label byteAlign(const label pos, const size_t align)
63 {
64  return
65  (
66  (align > 1)
67  ? (align + ((pos - 1) & ~(align - 1)))
68  : pos
69  );
70 }
71 
72 } // End namespace Foam
73 
74 
75 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
76 
77 inline void Foam::UIPstream::checkEof()
78 {
79  if (recvBufPos_ == messageSize_)
80  {
81  setEof();
82  }
83 }
84 
85 
86 inline void Foam::UIPstream::prepareBuffer(const size_t align)
87 {
88  recvBufPos_ = byteAlign(recvBufPos_, align);
89 }
90 
91 
92 template<class T>
93 inline void Foam::UIPstream::readFromBuffer(T& val)
94 {
95  prepareBuffer(sizeof(T));
96 
97  val = reinterpret_cast<T&>(recvBuf_[recvBufPos_]);
98  recvBufPos_ += sizeof(T);
99  checkEof();
100 }
101 
102 
103 inline void Foam::UIPstream::readFromBuffer
104 (
105  void* data,
106  const size_t count
107 )
108 {
109  const char* const __restrict__ buf = &recvBuf_[recvBufPos_];
110  char* const __restrict__ output = reinterpret_cast<char*>(data);
111 
112  for (size_t i = 0; i < count; ++i)
113  {
114  output[i] = buf[i];
115  }
116 
117  recvBufPos_ += count;
118  checkEof();
119 }
120 
121 
122 inline Foam::Istream& Foam::UIPstream::readString(std::string& str)
123 {
124  // Use std::string::assign() to copy content, including '\0'.
125  // Stripping (when desired) is the responsibility of the sending side.
126 
127  size_t len;
128  readFromBuffer(len);
129 
130  if (len)
131  {
132  str.assign(&recvBuf_[recvBufPos_], len);
133  recvBufPos_ += len;
134  checkEof();
135  }
136  else
137  {
138  str.clear();
139  }
140 
141  return *this;
142 }
143 
144 
145 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
146 
148 {
149  if (clearAtEnd_ && eof())
150  {
151  if (debug)
152  {
153  Pout<< "UIPstream::~UIPstream() : tag:" << tag_
154  << " fromProcNo:" << fromProcNo_
155  << " clearing receive buffer of size "
156  << recvBuf_.size()
157  << " messageSize_:" << messageSize_ << endl;
158  }
159  recvBuf_.clearStorage();
160  }
161 }
162 
163 
164 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
165 
167 {
168  // Return the put back token if it exists
169  // - with additional handling for special stream flags
170  if (Istream::getBack(t))
171  {
172  if (t.isFlag())
173  {
174  processFlags(*this, t.flagToken());
175  }
176  else
177  {
178  return *this;
179  }
180  }
181 
182  // Read character, return on error
183  // - with additional handling for special stream flags
184 
185  char c;
186  do
187  {
188  if (!read(c))
189  {
190  t.setBad(); // Error
191  return *this;
192  }
193 
194  if (c == token::FLAG)
195  {
196  char flagVal;
197 
198  if (read(flagVal))
199  {
200  processFlags(*this, flagVal);
201  }
202  else
203  {
204  t.setBad(); // Error
205  return *this;
206  }
207  }
208  }
209  while (c == token::FLAG);
210 
211 
212  // Set the line number of this token to the current stream line number
213  t.lineNumber(this->lineNumber());
214 
215  // Analyse input starting with this character.
216  switch (c)
217  {
218  // Punctuation
219  case token::END_STATEMENT :
220  case token::BEGIN_LIST :
221  case token::END_LIST :
222  case token::BEGIN_SQR :
223  case token::END_SQR :
224  case token::BEGIN_BLOCK :
225  case token::END_BLOCK :
226  case token::COLON :
227  case token::COMMA :
228  case token::ASSIGN :
229  case token::PLUS :
230  case token::MINUS :
231  case token::MULTIPLY :
232  case token::DIVIDE :
233  {
235  return *this;
236  }
237 
238  // The word-variants
239  case token::tokenType::WORD :
240  case token::tokenType::DIRECTIVE :
241  {
242  word val;
243  if (readString(val))
244  {
246  {
247  t = token::compound::New(val, *this).ptr();
248  }
249  else
250  {
251  t = std::move(val);
252  t.setType(token::tokenType(c));
253  }
254  }
255  else
256  {
257  t.setBad();
258  }
259  return *this;
260  }
261 
262  // The string-variants
263  case token::tokenType::STRING :
264  case token::tokenType::EXPRESSION :
265  case token::tokenType::VARIABLE :
266  case token::tokenType::VERBATIM :
267  {
268  string val;
269  if (readString(val))
270  {
271  t = std::move(val);
272  t.setType(token::tokenType(c));
273  }
274  else
275  {
276  t.setBad();
277  }
278  return *this;
279  }
280 
281  // Label
282  case token::tokenType::LABEL :
283  {
284  label val;
285  if (read(val))
286  {
287  t = val;
288  }
289  else
290  {
291  t.setBad();
292  }
293  return *this;
294  }
295 
296  // Float
297  case token::tokenType::FLOAT :
298  {
299  floatScalar val;
300  if (read(val))
301  {
302  t = val;
303  }
304  else
305  {
306  t.setBad();
307  }
308  return *this;
309  }
310 
311  // Double
312  case token::tokenType::DOUBLE :
313  {
314  doubleScalar val;
315  if (read(val))
316  {
317  t = val;
318  }
319  else
320  {
321  t.setBad();
322  }
323  return *this;
324  }
325 
326  // Character (returned as a single character word) or error
327  default:
328  {
329  if (isalpha(c))
330  {
331  t = charToWord(c);
332  return *this;
333  }
334 
335  setBad();
336  t.setBad();
337 
338  return *this;
339  }
340  }
341 }
342 
343 
345 {
346  c = recvBuf_[recvBufPos_];
347  ++recvBufPos_;
348  checkEof();
349  return *this;
350 }
351 
352 
354 {
355  return readString(str);
356 }
357 
358 
360 {
361  return readString(str);
362 }
363 
364 
366 {
367  readFromBuffer(val);
368  return *this;
369 }
370 
371 
373 {
374  readFromBuffer(val);
375  return *this;
376 }
377 
378 
380 {
381  readFromBuffer(val);
382  return *this;
383 }
384 
385 
386 Foam::Istream& Foam::UIPstream::read(char* data, std::streamsize count)
387 {
388  if (count)
389  {
390  // For count == 0, a no-op
391  // - see UOPstream::write(const char*, streamsize)
392  beginRawRead();
393  readRaw(data, count);
394  endRawRead();
395  }
396 
397  return *this;
398 }
399 
400 
401 Foam::Istream& Foam::UIPstream::readRaw(char* data, std::streamsize count)
402 {
403  // No check for format() == BINARY since this is either done in the
404  // beginRawRead() method, or the caller knows what they are doing.
405 
406  // Any alignment must have been done prior to this call
407  readFromBuffer(data, count);
408  return *this;
409 }
410 
411 
413 {
414  if (format() != BINARY)
415  {
417  << "stream format not binary"
419  }
420 
421  // Align on word boundary (64-bit)
422  // - as per read(const char*, streamsize)
423  // The check for zero-size will have been done by the caller
424  prepareBuffer(8);
425 
426  return true;
427 }
428 
429 
431 {
432  recvBufPos_ = 0;
433 }
434 
435 
436 void Foam::UIPstream::print(Ostream& os) const
437 {
438  os << "Reading from processor " << fromProcNo_
439  << " using communicator " << comm_
440  << " and tag " << tag_
441  << Foam::endl;
442 }
443 
444 
445 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Foam::token::ASSIGN
@ ASSIGN
Assignment/equals [isseparator].
Definition: token.H:133
token.H
Foam::doubleScalar
double doubleScalar
Floating-point double precision scalar type.
Definition: scalarFwd.H:48
Foam::token::COMMA
@ COMMA
Comma [isseparator].
Definition: token.H:125
int.H
System signed integer.
Foam::output
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:59
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:63
Foam::token::lineNumber
label lineNumber() const noexcept
Definition: tokenI.H:384
Foam::token::PLUS
@ PLUS
Addition [isseparator].
Definition: token.H:134
Foam::floatScalar
float floatScalar
Floating-point single precision scalar type.
Definition: scalarFwd.H:43
Foam::read
bool read(const char *buf, int32_t &val)
Definition: int32.H:125
Foam::UIPstream::rewind
void rewind()
Definition: UIPstream.C:423
Foam::IOstreamOption::format
streamFormat format() const noexcept
Definition: IOstreamOption.H:282
Foam::charToWord
static Foam::word charToWord(char c)
Definition: UIPstream.C:34
Foam::endl
Ostream & endl(Ostream &os)
Definition: Ostream.H:381
Foam::token
A token holds an item read from Istream.
Definition: token.H:64
Foam::Pout
prefixOSstream Pout
Foam::UIPstream::read
static label read(const commsTypes commsType, const int fromProcNo, char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label communicator=UPstream::worldComm)
Definition: UIPread.C:75
Foam::token::DIVIDE
@ DIVIDE
Divide [isseparator].
Definition: token.H:137
Foam::token::MINUS
@ MINUS
Subtract or start of negative number.
Definition: token.H:135
Foam::IOstream::setEof
void setEof() noexcept
Definition: IOstream.H:353
format
word format(conversionProperties.get< word >("format"))
Foam::byteAlign
static label byteAlign(const label pos, const size_t align)
Definition: UIPstream.C:55
Foam::token::BINARY
@ BINARY
BINARY-mode stream.
Definition: token.H:111
error.H
Foam::token::BEGIN_SQR
@ BEGIN_SQR
Begin dimensions [isseparator].
Definition: token.H:153
Foam::Istream
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:57
Foam::token::ASCII
@ ASCII
ASCII-mode stream.
Definition: token.H:110
Foam::T
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
Definition: FieldFieldFunctions.C:51
Foam::processFlags
static void processFlags(Istream &is, int flagMask)
Definition: UIPstream.C:41
Foam::token::isFlag
bool isFlag() const noexcept
Definition: tokenI.H:434
Foam::UIPstream::~UIPstream
~UIPstream()
Definition: UIPstream.C:140
Foam::token::END_STATEMENT
@ END_STATEMENT
End entry [isseparator].
Definition: token.H:150
Foam::token::compound::isCompound
static bool isCompound(const word &name)
Definition: token.C:73
Foam::UIPstream::print
void print(Ostream &os) const
Definition: UIPstream.C:429
Foam::token::END_BLOCK
@ END_BLOCK
End block [isseparator].
Definition: token.H:156
Foam::FatalError
error FatalError
Foam::token::END_SQR
@ END_SQR
End dimensions [isseparator].
Definition: token.H:154
os
OBJstream os(runTime.globalPath()/outputName)
Foam::token::MULTIPLY
@ MULTIPLY
Multiply [isseparator].
Definition: token.H:136
Foam
Definition: atmBoundaryLayer.C:26
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:139
Foam::token::BEGIN_BLOCK
@ BEGIN_BLOCK
Begin block [isseparator].
Definition: token.H:155
Foam::UIPstream::readRaw
Istream & readRaw(char *data, std::streamsize count)
Definition: UIPstream.C:394
Foam::Istream::getBack
bool getBack(token &tok)
Definition: Istream.C:85
Foam::IOstreamOption::BINARY
@ BINARY
"binary"
Definition: IOstreamOption.H:69
Foam::IOstreamOption::ASCII
@ ASCII
"ascii" (normal default)
Definition: IOstreamOption.H:68
FatalErrorInFunction
#define FatalErrorInFunction
Definition: error.H:465
Foam::token::COLON
@ COLON
Colon [isseparator].
Definition: token.H:123
Foam::BitOps::count
unsigned int count(const UList< bool > &bools, const bool val=true)
Definition: BitOps.H:75
Foam::token::tokenType
tokenType
Definition: token.H:72
Foam::token::FLAG
@ FLAG
stream flag (1-byte bitmask)
Definition: token.H:78
Foam::token::END_LIST
@ END_LIST
End list [isseparator].
Definition: token.H:152
Foam::constant::universal::c
const dimensionedScalar c
Foam::token::flagToken
int flagToken() const
Definition: tokenI.H:440
Foam::token::compound::New
static autoPtr< compound > New(const word &type, Istream &is)
Definition: token.C:49
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:52
Foam::token::BEGIN_LIST
@ BEGIN_LIST
Begin list [isseparator].
Definition: token.H:151
Foam::UIPstream::beginRawRead
bool beginRawRead()
Definition: UIPstream.C:405
Foam::token::setType
bool setType(const tokenType tokType) noexcept
Definition: tokenI.H:310
UIPstream.H
Foam::data
Database for solution data, solver performance and other reduced data.
Definition: data.H:51
Foam::token::punctuationToken
punctuationToken
Definition: token.H:116
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:170
Foam::token::setBad
void setBad()
Definition: tokenI.H:727