ENH: improve robustness of raw reading, file size checks

- use ignore instead of seekg/tellg to swallow input (robuster)

- check for bad gcount() values

- wrap Foam::fileSize() compressed/uncompressed handling into IFstream.

- improve handling of compressed files in masterUncollatedFileOperation.
  Previously read into a string via stream iterators.
  Now read chunk-wise into a List of char for fewer reallocations.
This commit is contained in:
Mark Olesen
2023-08-29 12:27:36 +02:00
committed by Andrew Heather
parent a341d09afc
commit 459aaad0f9
16 changed files with 318 additions and 144 deletions

View File

@ -50,12 +50,10 @@ Foam::ensightReadFile::detectBinaryHeader(const fileName& pathname)
// Binary string is *exactly* 80 characters
string buf(size_t(80), '\0');
iss.read(&buf[0], 80);
const std::streamsize gcount = iss.gcount();
buf.erase(gcount <= 0 ? 0 : gcount); // Truncated?
if (!iss)
{
// Truncated?
buf.erase(iss.gcount());
}
// Could exit on truncated input, but no real advantage
// Truncate at the first embedded '\0'
const auto endp = buf.find('\0');
@ -119,15 +117,13 @@ Foam::Istream& Foam::ensightReadFile::read(string& value)
// Binary string is *exactly* 80 characters
value.resize(80, '\0');
iss.read(&value[0], 80);
const std::streamsize gcount = iss.gcount();
value.erase(gcount <= 0 ? 0 : gcount); // Truncated?
// Could exit on truncated input, but no real advantage
syncState();
if (!iss)
{
// Truncated - could also exit here, but no real advantage
value.erase(iss.gcount());
}
// Truncate at the first embedded '\0'
auto endp = value.find('\0');

View File

@ -112,8 +112,8 @@ public:
// Constructors
//- From input stream and the approximate number of vertices in the STL
inline STLAsciiParse(const label approxNpoints);
//- Construct with the estimated number of triangles in the STL
inline STLAsciiParse(const label nTrisEstimated);
// Member Functions

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2018 OpenCFD Ltd.
Copyright (C) 2016-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -89,10 +89,10 @@ public:
// Constructors
//- From input stream and the approximate number of vertices in the STL
STLAsciiParseFlex(istream* is, const label approxNpoints)
//- From input stream, with the estimated number of triangles in the STL
STLAsciiParseFlex(istream* is, const label nTrisEstimated)
:
Detail::STLAsciiParse(approxNpoints),
Detail::STLAsciiParse(nTrisEstimated),
yySTLFlexLexer(is)
{}
@ -306,9 +306,8 @@ endsolid {space}("endsolid"|"ENDSOLID")({some_space}{word})*
%%
//
// Member Function
//
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::fileFormats::STLReader::readAsciiFlex
(
const fileName& filename
@ -322,8 +321,20 @@ bool Foam::fileFormats::STLReader::readAsciiFlex
<< exit(FatalError);
}
// Create with approx number of vertices in the STL (from file size)
STLAsciiParseFlex lexer(&(is.stdStream()), Foam::fileSize(filename)/400);
// Create with estimated number of triangles in the STL.
// 180 bytes / triangle. For simplicity, ignore compression
const auto fileLen = is.fileSize();
const label nTrisEstimated =
(
(fileLen > 0)
? max(label(100), label(fileLen/180))
: label(100)
);
STLAsciiParseFlex lexer(&(is.stdStream()), nTrisEstimated);
lexer.execute();
transfer(lexer);
@ -331,6 +342,5 @@ bool Foam::fileFormats::STLReader::readAsciiFlex
return true;
}
/* ------------------------------------------------------------------------ *\
------ End of STLReaderASCII.L
\* ------------------------------------------------------------------------ */
// ************************************************************************* //

View File

@ -131,15 +131,15 @@ inline void Foam::Detail::STLAsciiParse::endFacet()
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
inline Foam::Detail::STLAsciiParse::STLAsciiParse(const label approxNpoints)
inline Foam::Detail::STLAsciiParse::STLAsciiParse(const label nTrisEstimated)
:
sorted_(true),
groupId_(-1),
lineNum_(1),
nFacetPoints_(0),
nVertexCmpt_(0),
points_(approxNpoints),
facets_(approxNpoints/2)
points_(3*nTrisEstimated),
facets_(nTrisEstimated)
{}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -30,7 +30,6 @@ Description
#include "STLAsciiParse.H"
#include "STLReader.H"
#include "OSspecific.H"
#include "stringOps.H"
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
@ -127,10 +126,10 @@ class STLAsciiParseManual
public:
//- From input stream and the approximate number of vertices in the STL
STLAsciiParseManual(const label approxNpoints)
//- Construct with the estimated number of triangles in the STL
STLAsciiParseManual(const label nTrisEstimated)
:
Detail::STLAsciiParse(approxNpoints)
Detail::STLAsciiParse(nTrisEstimated)
{}
//- Execute parser
@ -179,7 +178,7 @@ void Foam::Detail::STLAsciiParseManual::execute(std::istream& is)
is.read(data, buflen);
const std::streamsize gcount = is.gcount();
if (!gcount)
if (gcount <= 0)
{
// EOF
// If scanning for next "solid" this is a valid way to exit, but
@ -398,11 +397,8 @@ void Foam::Detail::STLAsciiParseManual::execute(std::istream& is)
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
//
// Member Function
//
bool Foam::fileFormats::STLReader::readAsciiManual
(
const fileName& filename
@ -416,8 +412,20 @@ bool Foam::fileFormats::STLReader::readAsciiManual
<< exit(FatalError);
}
// Create with the approximate number of vertices in the STL from file size
Detail::STLAsciiParseManual lexer(Foam::fileSize(filename)/400);
// Create with estimated number of triangles in the STL.
// 180 bytes / triangle. For simplicity, ignore compression
const auto fileLen = is.fileSize();
const label nTrisEstimated =
(
(fileLen > 0)
? max(label(100), label(fileLen/180))
: label(100)
);
Detail::STLAsciiParseManual lexer(nTrisEstimated);
lexer.execute(is.stdStream());
transfer(lexer);

View File

@ -7,7 +7,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -35,7 +35,6 @@ Description
#include "STLAsciiParse.H"
#include "STLReader.H"
#include "OSspecific.H"
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#pragma GCC diagnostic ignored "-Wunused-const-variable"
@ -69,6 +68,7 @@ Description
// - Only look for initial 'facet '. Ignore 'normal ...'
// - Ignore name for 'endsolid'
//
// ------------------------------------------------------------------------- //
// Ragel machine definition
// Ragel variables (p, pe, eof, cs, top, stack, ts, te, act) defined later...
@ -121,10 +121,10 @@ class STLAsciiParseRagel
public:
//- From input stream and the approximate number of vertices in the STL
STLAsciiParseRagel(const label approxNpoints)
//- From input stream, with the estimated number of triangles in the STL
STLAsciiParseRagel(const label nTrisEstimated)
:
Detail::STLAsciiParse(approxNpoints)
Detail::STLAsciiParse(nTrisEstimated)
{}
//- Execute lexer
@ -184,7 +184,7 @@ void Foam::Detail::STLAsciiParseRagel::execute(std::istream& is)
is.read(data, buflen);
const std::streamsize gcount = is.gcount();
if (!gcount)
if (gcount <= 0)
{
break;
}
@ -2970,9 +2970,7 @@ void Foam::Detail::STLAsciiParseRagel::die
const char *pe
) const
{
auto error = FatalErrorInFunction;
error
FatalErrorInFunction
<< nl
<< "Parsing error at or near line " << lineNum_
<<", while parsing for " << what << nl
@ -2984,22 +2982,19 @@ void Foam::Detail::STLAsciiParseRagel::die
for (unsigned i=0; i < 80; ++i)
{
if (*parsing == '\n' || parsing == pe) break;
error << *parsing;
FatalError << *parsing;
++parsing;
}
}
error
FatalError
<< "'\n"
<< exit(FatalError);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
//
// Member Function
//
bool Foam::fileFormats::STLReader::readAsciiRagel
(
const fileName& filename
@ -3013,8 +3008,20 @@ bool Foam::fileFormats::STLReader::readAsciiRagel
<< exit(FatalError);
}
// Create with approx number of vertices in the STL (from file size)
Detail::STLAsciiParseRagel lexer(Foam::fileSize(filename)/400);
// Create with estimated number of triangles in the STL.
// 180 bytes / triangle. For simplicity, ignore compression
const auto fileLen = is.fileSize();
const label nTrisEstimated =
(
(fileLen > 0)
? max(label(100), label(fileLen/180))
: label(100)
);
Detail::STLAsciiParseRagel lexer(nTrisEstimated);
lexer.execute(is.stdStream());
transfer(lexer);

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -33,7 +33,6 @@ Description
#include "STLAsciiParse.H"
#include "STLReader.H"
#include "OSspecific.H"
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#pragma GCC diagnostic ignored "-Wunused-const-variable"
@ -67,6 +66,7 @@ Description
// - Only look for initial 'facet '. Ignore 'normal ...'
// - Ignore name for 'endsolid'
//
// ------------------------------------------------------------------------- //
// Ragel machine definition
// Ragel variables (p, pe, eof, cs, top, stack, ts, te, act) defined later...
@ -176,10 +176,10 @@ class STLAsciiParseRagel
public:
//- From input stream and the approximate number of vertices in the STL
STLAsciiParseRagel(const label approxNpoints)
//- From input stream, with the estimated number of triangles in the STL
STLAsciiParseRagel(const label nTrisEstimated)
:
Detail::STLAsciiParse(approxNpoints)
Detail::STLAsciiParse(nTrisEstimated)
{}
//- Execute lexer
@ -232,7 +232,7 @@ void Foam::Detail::STLAsciiParseRagel::execute(std::istream& is)
is.read(data, buflen);
const std::streamsize gcount = is.gcount();
if (!gcount)
if (gcount <= 0)
{
break;
}
@ -303,9 +303,7 @@ void Foam::Detail::STLAsciiParseRagel::die
const char *pe
) const
{
auto error = FatalErrorInFunction;
error
FatalErrorInFunction
<< nl
<< "Parsing error at or near line " << lineNum_
<<", while parsing for " << what << nl
@ -317,22 +315,19 @@ void Foam::Detail::STLAsciiParseRagel::die
for (unsigned i=0; i < 80; ++i)
{
if (*parsing == '\n' || parsing == pe) break;
error << *parsing;
FatalError << *parsing;
++parsing;
}
}
error
FatalError
<< "'\n"
<< exit(FatalError);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
//
// Member Function
//
bool Foam::fileFormats::STLReader::readAsciiRagel
(
const fileName& filename
@ -346,8 +341,20 @@ bool Foam::fileFormats::STLReader::readAsciiRagel
<< exit(FatalError);
}
// Create with approx number of vertices in the STL (from file size)
Detail::STLAsciiParseRagel lexer(Foam::fileSize(filename)/400);
// Create with estimated number of triangles in the STL.
// 180 bytes / triangle. For simplicity, ignore compression
const auto fileLen = is.fileSize();
const label nTrisEstimated =
(
(fileLen > 0)
? max(label(100), label(fileLen/180))
: label(100)
);
Detail::STLAsciiParseRagel lexer(nTrisEstimated);
lexer.execute(is.stdStream());
transfer(lexer);

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2022 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -645,7 +645,8 @@ Foam::label Foam::vtk::seriesWriter::scan
header.resize(1024);
is.read(&(header.front()), header.size());
header.resize(is.gcount());
const std::streamsize gcount = is.gcount();
header.erase(gcount <= 0 ? 0 : gcount);
// DebugInfo
// << "got header:\n=====\n" << header << "\n=====\n" << nl;