BUG: STL ASCII being incorrectly detected as BINARY (fixes #422)

- now explicitly check for "SOLID" or "solid" in the header

- does not affect triSurface in the master branch, since that used a
  different parser.
This commit is contained in:
Mark Olesen
2017-03-08 13:30:43 +01:00
parent 8060792b92
commit 37e7fca9dc
2 changed files with 39 additions and 21 deletions

View File

@ -35,6 +35,27 @@ License
// The number of bytes in the STL binary header // The number of bytes in the STL binary header
static const unsigned STLHeaderSize = 80; static const unsigned STLHeaderSize = 80;
// Check if "SOLID" or "solid" appears as the first non-space content.
// Assume that any leading space is less than 75 chars or so, otherwise
// it is really bad input.
static bool startsWithSolid(const char header[STLHeaderSize])
{
unsigned pos = 0;
while (std::isspace(header[pos]) && pos < STLHeaderSize)
{
++pos;
}
return
(
pos < (STLHeaderSize-5) // At least 5 chars remaining
&& std::toupper(header[pos+0]) == 'S'
&& std::toupper(header[pos+1]) == 'O'
&& std::toupper(header[pos+2]) == 'L'
&& std::toupper(header[pos+3]) == 'I'
&& std::toupper(header[pos+4]) == 'D'
);
}
//! \endcond //! \endcond
@ -58,10 +79,10 @@ bool Foam::fileFormats::STLCore::isBinaryName
// Check binary by getting the header and number of facets // Check binary by getting the header and number of facets
// this seems to work better than the old token-based method // this seems to work better than the old token-based method
// - some programs (eg, pro-STAR) have 'solid' as the first word in
// the binary header.
// - using wordToken can cause an abort if non-word (binary) content // - using wordToken can cause an abort if non-word (binary) content
// is detected ... this is not exactly what we want. // is detected ... this is not exactly what we want.
// - some programs (eg, pro-STAR) have 'solid' as the first word in
// the binary header. This is just wrong and not our fault.
int Foam::fileFormats::STLCore::detectBinaryHeader int Foam::fileFormats::STLCore::detectBinaryHeader
( (
const fileName& filename const fileName& filename
@ -93,27 +114,24 @@ int Foam::fileFormats::STLCore::detectBinaryHeader
char header[STLHeaderSize]; char header[STLHeaderSize];
is.read(header, STLHeaderSize); is.read(header, STLHeaderSize);
// Check that stream is OK, if not this may be an ASCII file // If the stream is bad, it can't be a binary STL
if (!is.good()) if (!is.good() || startsWithSolid(header))
{ {
return 0; return 0;
} }
// Read the number of triangles in the STL file // Read the number of triangles in the STL file
// (note: read as int so we can check whether >2^31) // (note: read as signed so we can check whether >2^31)
int nTris; int32_t nTris;
is.read(reinterpret_cast<char*>(&nTris), sizeof(unsigned int)); is.read(reinterpret_cast<char*>(&nTris), sizeof(int32_t));
// Check that stream is OK and number of triangles is positive, // Check that stream is OK and number of triangles is positive,
// if not this may be an ASCII file // if not this may be an ASCII file
// //
// Also compare the file size with that expected from the number of tris // Also compare the file size with that expected from the number of tris
// If the comparison is not sensible then it may be an ASCII file // If the comparison is still not sensible then it may be an ASCII file
if if (!is || nTris < 0)
(
!is
|| nTris < 0
)
{ {
return 0; return 0;
} }
@ -176,7 +194,7 @@ Foam::fileFormats::STLCore::readBinaryHeader
is.read(header, STLHeaderSize); is.read(header, STLHeaderSize);
// Check that stream is OK, if not this may be an ASCII file // Check that stream is OK, if not this may be an ASCII file
if (!is.good()) if (!is.good()) // could check again: startsWithSolid(header)
{ {
streamPtr.clear(); streamPtr.clear();
@ -187,8 +205,8 @@ Foam::fileFormats::STLCore::readBinaryHeader
// Read the number of triangles in the STl file // Read the number of triangles in the STl file
// (note: read as int so we can check whether >2^31) // (note: read as int so we can check whether >2^31)
int nTris; int32_t nTris;
is.read(reinterpret_cast<char*>(&nTris), sizeof(unsigned int)); is.read(reinterpret_cast<char*>(&nTris), sizeof(int32_t));
// Check that stream is OK and number of triangles is positive, // Check that stream is OK and number of triangles is positive,
// if not this maybe an ASCII file // if not this maybe an ASCII file
@ -230,7 +248,7 @@ Foam::fileFormats::STLCore::readBinaryHeader
void Foam::fileFormats::STLCore::writeBinaryHeader void Foam::fileFormats::STLCore::writeBinaryHeader
( (
ostream& os, ostream& os,
unsigned int nTris uint32_t nTris
) )
{ {
// STL header with extra information about nTris // STL header with extra information about nTris
@ -244,7 +262,7 @@ void Foam::fileFormats::STLCore::writeBinaryHeader
} }
os.write(header, STLHeaderSize); os.write(header, STLHeaderSize);
os.write(reinterpret_cast<char*>(&nTris), sizeof(unsigned int)); os.write(reinterpret_cast<char*>(&nTris), sizeof(uint32_t));
} }

View File

@ -79,7 +79,7 @@ protected:
//- Check contents to detect if the file is a binary STL. //- Check contents to detect if the file is a binary STL.
// Return the estimated number of triangles or 0 on error. // Return the estimated number of triangles or 0 on error.
static int detectBinaryHeader(const fileName&); static int detectBinaryHeader(const fileName& filename);
//- Read STL binary file header. //- Read STL binary file header.
@ -92,7 +92,7 @@ protected:
); );
//- Write STL binary file and number of triangles to stream //- Write STL binary file and number of triangles to stream
static void writeBinaryHeader(ostream&, unsigned int); static void writeBinaryHeader(ostream& os, uint32_t nTris);
// Constructors // Constructors