Commit bdc1c9bf authored by Mark Olesen's avatar Mark Olesen Committed by Andrew Heather
Browse files

ENH: support low-level reading of raw binary blocks (#1378)

- symmetric with writeRaw() etc for the output stream. These are
  methods that are not required by normal users, but which provide
  a finer granularity for reading.

- additional information about the current stream position when
  endList fails. This may help when tracing errors.

STYLE: change return type of beginRaw()/endRaw() to bool

- was of type Ostream& for output, but return value was unused.
  Having bool may be better for encapsulating logic

STYLE: remove unused Istream::readEndBegin() function
parent 78ce269a
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2016 OpenFOAM Foundation
......@@ -26,6 +26,26 @@ License
\*---------------------------------------------------------------------------*/
#include "Istream.H"
#include "ISstream.H"
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
// Return the current get position for std input stream
static inline std::streampos tellg(Istream* isptr)
{
ISstream* sptr = dynamic_cast<ISstream*>(isptr);
if (sptr)
{
return sptr->stdStream().tellg();
}
return 0;
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
......@@ -85,26 +105,28 @@ bool Foam::Istream::peekBack(token& tok)
}
Foam::Istream& Foam::Istream::readBegin(const char* funcName)
bool Foam::Istream::readBegin(const char* funcName)
{
token delimiter(*this);
const token delimiter(*this);
if (delimiter != token::BEGIN_LIST)
{
setBad();
FatalIOErrorInFunction(*this)
<< "Expected a '" << token::BEGIN_LIST
<< "' while reading " << funcName
<< ", found " << delimiter.info()
<< ", found " << delimiter.info() << nl
<< exit(FatalIOError);
}
return *this;
return true;
}
Foam::Istream& Foam::Istream::readEnd(const char* funcName)
bool Foam::Istream::readEnd(const char* funcName)
{
token delimiter(*this);
const token delimiter(*this);
if (delimiter != token::END_LIST)
{
setBad();
......@@ -112,23 +134,17 @@ Foam::Istream& Foam::Istream::readEnd(const char* funcName)
<< "Expected a '" << token::END_LIST
<< "' while reading " << funcName
<< ", found " << delimiter.info()
<< " at stream position " << tellg(this) << nl
<< exit(FatalIOError);
}
return *this;
}
Foam::Istream& Foam::Istream::readEndBegin(const char* funcName)
{
readEnd(funcName);
return readBegin(funcName);
return true;
}
char Foam::Istream::readBeginList(const char* funcName)
{
token delimiter(*this);
const token delimiter(*this);
if (delimiter != token::BEGIN_LIST && delimiter != token::BEGIN_BLOCK)
{
......@@ -149,7 +165,7 @@ char Foam::Istream::readBeginList(const char* funcName)
char Foam::Istream::readEndList(const char* funcName)
{
token delimiter(*this);
const token delimiter(*this);
if (delimiter != token::END_LIST && delimiter != token::END_BLOCK)
{
......@@ -159,6 +175,7 @@ char Foam::Istream::readEndList(const char* funcName)
<< "' or a '" << token::END_BLOCK
<< "' while reading " << funcName
<< ", found " << delimiter.info()
<< " at stream position " << tellg(this) << nl
<< exit(FatalIOError);
return '\0';
......
......@@ -167,21 +167,39 @@ public:
//- Read binary block
virtual Istream& read(char*, std::streamsize) = 0;
//- Start of low-level raw binary read
virtual bool beginRaw() = 0;
//- End of low-level raw binary read
virtual bool endRaw() = 0;
//- Low-level raw binary read
virtual Istream& readRaw(char*, std::streamsize) = 0;
//- Rewind the stream so that it may be read again
virtual void rewind() = 0;
// Read List punctuation tokens
Istream& readBegin(const char* funcName);
Istream& readEnd(const char* funcName);
Istream& readEndBegin(const char* funcName);
//- Begin read of data chunk, starts with '('.
// \return true or FatalIOError
bool readBegin(const char* funcName);
//- End read of data chunk, ends with ')'
// \return true or FatalIOError
bool readEnd(const char* funcName);
//- Begin read of list data, starts with '(' or '{'
// \return starting delimiter or FatalIOError
char readBeginList(const char* funcName);
//- End read of list data, ends with ')' or '}'
// \return closing delimiter or FatalIOError
char readEndList(const char* funcName);
// Member operators
// Member Operators
//- Return a non-const reference to const Istream
// Needed for read-constructors where the stream argument is temporary:
......
......@@ -141,11 +141,6 @@ public:
//- Write binary block.
virtual Ostream& write(const char* data, std::streamsize count) = 0;
//- Emit begin marker for low-level raw binary output.
// The count should indicate the number of bytes for subsequent
// writeRaw calls.
virtual Ostream& beginRaw(std::streamsize count) = 0;
//- Low-level raw binary output.
virtual Ostream& writeRaw
(
......@@ -153,8 +148,13 @@ public:
std::streamsize count
) = 0;
//- Emit begin marker for low-level raw binary output.
// The count indicates the number of bytes for subsequent
// writeRaw calls.
virtual bool beginRaw(std::streamsize count) = 0;
//- Emit end marker for low-level raw binary output.
virtual Ostream& endRaw() = 0;
virtual bool endRaw() = 0;
//- Add indentation characters
virtual void indent() = 0;
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2015 OpenFOAM Foundation
......@@ -70,11 +70,20 @@ inline void Foam::UIPstream::checkEof()
}
inline void Foam::UIPstream::prepareBuffer(const size_t align)
{
if (align > 1)
{
externalBufPosition_ =
align + ((externalBufPosition_ - 1) & ~(align - 1));
}
}
template<class T>
inline void Foam::UIPstream::readFromBuffer(T& val)
{
const size_t align = sizeof(T);
externalBufPosition_ = align + ((externalBufPosition_ - 1) & ~(align - 1));
prepareBuffer(sizeof(T));
val = reinterpret_cast<T&>(externalBuf_[externalBufPosition_]);
externalBufPosition_ += sizeof(T);
......@@ -85,17 +94,9 @@ inline void Foam::UIPstream::readFromBuffer(T& val)
inline void Foam::UIPstream::readFromBuffer
(
void* data,
const size_t count,
const size_t align
const size_t count
)
{
if (align > 1)
{
externalBufPosition_ =
align
+ ((externalBufPosition_ - 1) & ~(align - 1));
}
const char* const __restrict__ buf = &externalBuf_[externalBufPosition_];
char* const __restrict__ output = reinterpret_cast<char*>(data);
......@@ -382,6 +383,27 @@ Foam::Istream& Foam::UIPstream::read(doubleScalar& val)
Foam::Istream& Foam::UIPstream::read(char* data, std::streamsize count)
{
beginRaw();
readRaw(data, count);
endRaw();
return *this;
}
Foam::Istream& Foam::UIPstream::readRaw(char* data, std::streamsize count)
{
// No check for format() == BINARY since this is either done in the
// beginRaw() method, or the caller knows what they are doing.
// Any alignment must have been done prior to this call
readFromBuffer(data, count);
return *this;
}
bool Foam::UIPstream::beginRaw()
{
if (format() != BINARY)
{
......@@ -390,8 +412,10 @@ Foam::Istream& Foam::UIPstream::read(char* data, std::streamsize count)
<< Foam::abort(FatalError);
}
readFromBuffer(data, count, 8);
return *this;
// Alignment = 8, as per read(const char*, streamsize)
prepareBuffer(8);
return true;
}
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd |
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2013 OpenFOAM Foundation
......@@ -80,18 +80,16 @@ class UIPstream
//- Check the bufferPosition against messageSize_ for EOF
inline void checkEof();
//- Prepare transfer buffer by adjusting alignment
inline void prepareBuffer(const size_t align);
//- Read a T from the transfer buffer
template<class T>
inline void readFromBuffer(T& val);
//- Read count bytes of data from the transfer buffer
// using align byte alignment
inline void readFromBuffer
(
void* data,
const size_t count,
const size_t align
);
//- Read count bytes of data from the transfer buffer.
// Prior data alignment is done by prepareBuffer
inline void readFromBuffer(void* data, const size_t count);
//- Read string length and its content.
inline Istream& readStringFromBuffer(std::string& str);
......@@ -124,7 +122,7 @@ public:
~UIPstream();
// Member functions
// Member Functions
// Inquiry
......@@ -171,7 +169,19 @@ public:
Istream& read(doubleScalar& val);
//- Read binary block with 8-byte alignment.
Istream& read(char* data, const std::streamsize count);
Istream& read(char* data, std::streamsize count);
//- Low-level raw binary read
Istream& readRaw(char* data, std::streamsize count);
//- Start of low-level raw binary read
bool beginRaw();
//- End of low-level raw binary read
bool endRaw()
{
return true;
}
//- Rewind the stream so that it may be read again
void rewind();
......
......@@ -342,10 +342,23 @@ Foam::Ostream& Foam::UOPstream::write
}
Foam::Ostream& Foam::UOPstream::beginRaw
Foam::Ostream& Foam::UOPstream::writeRaw
(
const char* data,
const std::streamsize count
)
{
// No check for format() == BINARY since this is either done in the
// beginRaw() method, or the caller knows what they are doing.
// Previously aligned and sizes reserved via beginRaw()
writeToBuffer(data, count, 1);
return *this;
}
bool Foam::UOPstream::beginRaw(const std::streamsize count)
{
if (format() != BINARY)
{
......@@ -357,23 +370,7 @@ Foam::Ostream& Foam::UOPstream::beginRaw
// Alignment = 8, as per write(const char*, streamsize)
prepareBuffer(count, 8);
return *this;
}
Foam::Ostream& Foam::UOPstream::writeRaw
(
const char* data,
const std::streamsize count
)
{
// No check for format() == BINARY since this is either done in the
// beginRaw() method, or the caller knows what they are doing.
// Previously aligned and sizes reserved via beginRaw()
writeToBuffer(data, count, 1);
return *this;
return true;
}
......
......@@ -192,11 +192,6 @@ public:
const std::streamsize count
);
//- Begin marker for low-level raw binary output.
// The count should indicate the number of bytes for subsequent
// writeRaw calls.
virtual Ostream& beginRaw(const std::streamsize count);
//- Low-level raw binary output.
virtual Ostream& writeRaw
(
......@@ -204,10 +199,15 @@ public:
const std::streamsize count
);
//- Begin marker for low-level raw binary output.
// The count indicates the number of bytes for subsequent
// writeRaw calls.
virtual bool beginRaw(const std::streamsize count);
//- End marker for low-level raw binary output.
virtual Ostream& endRaw()
virtual bool endRaw()
{
return *this;
return true;
}
//- Add indentation characters
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2016 OpenFOAM Foundation
......@@ -776,8 +776,26 @@ Foam::Istream& Foam::ISstream::read(doubleScalar& val)
}
// read binary block
Foam::Istream& Foam::ISstream::read(char* buf, std::streamsize count)
{
beginRaw();
readRaw(buf, count);
endRaw();
return *this;
}
Foam::Istream& Foam::ISstream::readRaw(char* buf, std::streamsize count)
{
is_.read(buf, count);
setState(is_.rdstate());
return *this;
}
bool Foam::ISstream::beginRaw()
{
if (format() != BINARY)
{
......@@ -787,12 +805,18 @@ Foam::Istream& Foam::ISstream::read(char* buf, std::streamsize count)
}
readBegin("binaryBlock");
is_.read(buf, count);
readEnd("binaryBlock");
setState(is_.rdstate());
return is_.good();
}
bool Foam::ISstream::endRaw()
{
readEnd("binaryBlock");
setState(is_.rdstate());
return *this;
return is_.good();
}
......@@ -810,7 +834,6 @@ void Foam::ISstream::rewind()
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
std::ios_base::fmtflags Foam::ISstream::flags() const
{
return is_.flags();
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2012 OpenFOAM Foundation
......@@ -27,7 +27,7 @@ Class
Foam::ISstream
Description
Generic input stream.
Generic input stream using standard (STL) streams.
SourceFiles
ISstreamI.H
......@@ -102,7 +102,7 @@ public:
virtual ~ISstream() = default;
// Member functions
// Member Functions
// Inquiry
......@@ -167,6 +167,15 @@ public:
//- Read binary block
virtual Istream& read(char* buf, std::streamsize count);
//- Low-level raw binary read
virtual Istream& readRaw(char* data, std::streamsize count);
//- Start of low-level raw binary read
virtual bool beginRaw();
//- End of low-level raw binary read
virtual bool endRaw();
//- Rewind the stream so that it may be read again
virtual void rewind();
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd |
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2014 OpenFOAM Foundation
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2016 OpenFOAM Foundation
......@@ -210,10 +210,7 @@ Foam::Ostream& Foam::OSstream::write
}
Foam::Ostream& Foam::OSstream::beginRaw
(
const std::streamsize count
)
bool Foam::OSstream::beginRaw(const std::streamsize count)
{
if (format() != BINARY)
{
......@@ -223,10 +220,18 @@ Foam::Ostream& Foam::OSstream::beginRaw
}
os_ << token::BEGIN_LIST;
setState(os_.rdstate());
return os_.good();
}
bool Foam::OSstream::endRaw()
{
os_ << token::END_LIST;
setState(os_.rdstate());
return *this;
return os_.good();
}
......@@ -246,15 +251,6 @@ Foam::Ostream& Foam::OSstream::writeRaw
}
Foam::Ostream& Foam::OSstream::endRaw()
{
os_ << token::END_LIST;
setState(os_.rdstate());
return *this;
}
void Foam::OSstream::indent()
{
for (unsigned short i = 0; i < indentLevel_*indentSize_; ++i)
......
......@@ -152,11 +152,6 @@ public:
const std::streamsize count
);
//- Begin marker for low-level raw binary output.
// The count should indicate the number of bytes for subsequent
// writeRaw calls.
virtual Ostream& beginRaw(const std::streamsize count);
//- Low-level raw binary output.
virtual Ostream& writeRaw
(
......@@ -164,8 +159,13 @@ public:
const std::streamsize count
);
//- Begin marker for low-level raw binary output.
// The count indicates the number of bytes for subsequent
// writeRaw calls.
virtual bool beginRaw(const std::streamsize count);
//- End marker for low-level raw binary output.
virtual Ostream& endRaw();
virtual bool endRaw();
//- Add indentation characters
virtual void indent();