closes https://github.com/assimp/assimp/issues/1729: check for bit flip when unsigned int overflow happens in x-file parsing.
parent
48d41b4bf9
commit
3685791e0d
|
@ -87,59 +87,60 @@ static void dummy_free (void* /*opaque*/, void* address) {
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Constructor. Creates a data structure out of the XFile given in the memory block.
|
// Constructor. Creates a data structure out of the XFile given in the memory block.
|
||||||
XFileParser::XFileParser( const std::vector<char>& pBuffer)
|
XFileParser::XFileParser( const std::vector<char>& pBuffer)
|
||||||
{
|
: mMajorVersion( 0 )
|
||||||
mMajorVersion = mMinorVersion = 0;
|
, mMinorVersion( 0 )
|
||||||
mIsBinaryFormat = false;
|
, mIsBinaryFormat( false )
|
||||||
mBinaryNumCount = 0;
|
, mBinaryNumCount( 0 )
|
||||||
P = End = NULL;
|
, mP( nullptr )
|
||||||
mLineNumber = 0;
|
, mEnd( nullptr )
|
||||||
mScene = NULL;
|
, mLineNumber( 0 )
|
||||||
|
, mScene( nullptr ) {
|
||||||
// vector to store uncompressed file for INFLATE'd X files
|
// vector to store uncompressed file for INFLATE'd X files
|
||||||
std::vector<char> uncompressed;
|
std::vector<char> uncompressed;
|
||||||
|
|
||||||
// set up memory pointers
|
// set up memory pointers
|
||||||
P = &pBuffer.front();
|
mP = &pBuffer.front();
|
||||||
End = P + pBuffer.size() - 1;
|
mEnd = mP + pBuffer.size() - 1;
|
||||||
|
|
||||||
// check header
|
// check header
|
||||||
if( strncmp( P, "xof ", 4) != 0)
|
if ( 0 != strncmp( mP, "xof ", 4 ) ) {
|
||||||
throw DeadlyImportError( "Header mismatch, file is not an XFile.");
|
throw DeadlyImportError( "Header mismatch, file is not an XFile." );
|
||||||
|
}
|
||||||
|
|
||||||
// read version. It comes in a four byte format such as "0302"
|
// read version. It comes in a four byte format such as "0302"
|
||||||
mMajorVersion = (unsigned int)(P[4] - 48) * 10 + (unsigned int)(P[5] - 48);
|
mMajorVersion = (unsigned int)(mP[4] - 48) * 10 + (unsigned int)(mP[5] - 48);
|
||||||
mMinorVersion = (unsigned int)(P[6] - 48) * 10 + (unsigned int)(P[7] - 48);
|
mMinorVersion = (unsigned int)(mP[6] - 48) * 10 + (unsigned int)(mP[7] - 48);
|
||||||
|
|
||||||
bool compressed = false;
|
bool compressed = false;
|
||||||
|
|
||||||
// txt - pure ASCII text format
|
// txt - pure ASCII text format
|
||||||
if( strncmp( P + 8, "txt ", 4) == 0)
|
if( strncmp( mP + 8, "txt ", 4) == 0)
|
||||||
mIsBinaryFormat = false;
|
mIsBinaryFormat = false;
|
||||||
|
|
||||||
// bin - Binary format
|
// bin - Binary format
|
||||||
else if( strncmp( P + 8, "bin ", 4) == 0)
|
else if( strncmp( mP + 8, "bin ", 4) == 0)
|
||||||
mIsBinaryFormat = true;
|
mIsBinaryFormat = true;
|
||||||
|
|
||||||
// tzip - Inflate compressed text format
|
// tzip - Inflate compressed text format
|
||||||
else if( strncmp( P + 8, "tzip", 4) == 0)
|
else if( strncmp( mP + 8, "tzip", 4) == 0)
|
||||||
{
|
{
|
||||||
mIsBinaryFormat = false;
|
mIsBinaryFormat = false;
|
||||||
compressed = true;
|
compressed = true;
|
||||||
}
|
}
|
||||||
// bzip - Inflate compressed binary format
|
// bzip - Inflate compressed binary format
|
||||||
else if( strncmp( P + 8, "bzip", 4) == 0)
|
else if( strncmp( mP + 8, "bzip", 4) == 0)
|
||||||
{
|
{
|
||||||
mIsBinaryFormat = true;
|
mIsBinaryFormat = true;
|
||||||
compressed = true;
|
compressed = true;
|
||||||
}
|
}
|
||||||
else ThrowException( format() << "Unsupported xfile format '" <<
|
else ThrowException( format() << "Unsupported xfile format '" <<
|
||||||
P[8] << P[9] << P[10] << P[11] << "'");
|
mP[8] << mP[9] << mP[10] << mP[11] << "'");
|
||||||
|
|
||||||
// float size
|
// float size
|
||||||
mBinaryFloatSize = (unsigned int)(P[12] - 48) * 1000
|
mBinaryFloatSize = (unsigned int)(mP[12] - 48) * 1000
|
||||||
+ (unsigned int)(P[13] - 48) * 100
|
+ (unsigned int)(mP[13] - 48) * 100
|
||||||
+ (unsigned int)(P[14] - 48) * 10
|
+ (unsigned int)(mP[14] - 48) * 10
|
||||||
+ (unsigned int)(P[15] - 48);
|
+ (unsigned int)(mP[15] - 48);
|
||||||
|
|
||||||
if( mBinaryFloatSize != 32 && mBinaryFloatSize != 64)
|
if( mBinaryFloatSize != 32 && mBinaryFloatSize != 64)
|
||||||
ThrowException( format() << "Unknown float size " << mBinaryFloatSize << " specified in xfile header." );
|
ThrowException( format() << "Unknown float size " << mBinaryFloatSize << " specified in xfile header." );
|
||||||
|
@ -147,7 +148,7 @@ XFileParser::XFileParser( const std::vector<char>& pBuffer)
|
||||||
// The x format specifies size in bits, but we work in bytes
|
// The x format specifies size in bits, but we work in bytes
|
||||||
mBinaryFloatSize /= 8;
|
mBinaryFloatSize /= 8;
|
||||||
|
|
||||||
P += 16;
|
mP += 16;
|
||||||
|
|
||||||
// If this is a compressed X file, apply the inflate algorithm to it
|
// If this is a compressed X file, apply the inflate algorithm to it
|
||||||
if (compressed)
|
if (compressed)
|
||||||
|
@ -186,13 +187,13 @@ XFileParser::XFileParser( const std::vector<char>& pBuffer)
|
||||||
::inflateInit2(&stream, -MAX_WBITS);
|
::inflateInit2(&stream, -MAX_WBITS);
|
||||||
|
|
||||||
// skip unknown data (checksum, flags?)
|
// skip unknown data (checksum, flags?)
|
||||||
P += 6;
|
mP += 6;
|
||||||
|
|
||||||
// First find out how much storage we'll need. Count sections.
|
// First find out how much storage we'll need. Count sections.
|
||||||
const char* P1 = P;
|
const char* P1 = mP;
|
||||||
unsigned int est_out = 0;
|
unsigned int est_out = 0;
|
||||||
|
|
||||||
while (P1 + 3 < End)
|
while (P1 + 3 < mEnd)
|
||||||
{
|
{
|
||||||
// read next offset
|
// read next offset
|
||||||
uint16_t ofs = *((uint16_t*)P1);
|
uint16_t ofs = *((uint16_t*)P1);
|
||||||
|
@ -216,18 +217,18 @@ XFileParser::XFileParser( const std::vector<char>& pBuffer)
|
||||||
// Allocate storage and terminating zero and do the actual uncompressing
|
// Allocate storage and terminating zero and do the actual uncompressing
|
||||||
uncompressed.resize(est_out + 1);
|
uncompressed.resize(est_out + 1);
|
||||||
char* out = &uncompressed.front();
|
char* out = &uncompressed.front();
|
||||||
while (P + 3 < End)
|
while (mP + 3 < mEnd)
|
||||||
{
|
{
|
||||||
uint16_t ofs = *((uint16_t*)P);
|
uint16_t ofs = *((uint16_t*)mP);
|
||||||
AI_SWAP2(ofs);
|
AI_SWAP2(ofs);
|
||||||
P += 4;
|
mP += 4;
|
||||||
|
|
||||||
if (P + ofs > End + 2) {
|
if (mP + ofs > mEnd + 2) {
|
||||||
throw DeadlyImportError("X: Unexpected EOF in compressed chunk");
|
throw DeadlyImportError("X: Unexpected EOF in compressed chunk");
|
||||||
}
|
}
|
||||||
|
|
||||||
// push data to the stream
|
// push data to the stream
|
||||||
stream.next_in = (Bytef*)P;
|
stream.next_in = (Bytef*)mP;
|
||||||
stream.avail_in = ofs;
|
stream.avail_in = ofs;
|
||||||
stream.next_out = (Bytef*)out;
|
stream.next_out = (Bytef*)out;
|
||||||
stream.avail_out = MSZIP_BLOCK;
|
stream.avail_out = MSZIP_BLOCK;
|
||||||
|
@ -242,15 +243,15 @@ XFileParser::XFileParser( const std::vector<char>& pBuffer)
|
||||||
|
|
||||||
// and advance to the next offset
|
// and advance to the next offset
|
||||||
out += MSZIP_BLOCK - stream.avail_out;
|
out += MSZIP_BLOCK - stream.avail_out;
|
||||||
P += ofs;
|
mP += ofs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// terminate zlib
|
// terminate zlib
|
||||||
::inflateEnd(&stream);
|
::inflateEnd(&stream);
|
||||||
|
|
||||||
// ok, update pointers to point to the uncompressed file data
|
// ok, update pointers to point to the uncompressed file data
|
||||||
P = &uncompressed[0];
|
mP = &uncompressed[0];
|
||||||
End = out;
|
mEnd = out;
|
||||||
|
|
||||||
// FIXME: we don't need the compressed data anymore, could release
|
// FIXME: we don't need the compressed data anymore, could release
|
||||||
// it already for better memory usage. Consider breaking const-co.
|
// it already for better memory usage. Consider breaking const-co.
|
||||||
|
@ -647,8 +648,8 @@ void XFileParser::ParseDataObjectMeshVertexColors( Mesh* pMesh)
|
||||||
if( !mIsBinaryFormat)
|
if( !mIsBinaryFormat)
|
||||||
{
|
{
|
||||||
FindNextNoneWhiteSpace();
|
FindNextNoneWhiteSpace();
|
||||||
if( *P == ';' || *P == ',')
|
if( *mP == ';' || *mP == ',')
|
||||||
P++;
|
mP++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,8 +679,8 @@ void XFileParser::ParseDataObjectMeshMaterialList( Mesh* pMesh)
|
||||||
// commented out version check, as version 03.03 exported from blender also has 2 semicolons
|
// commented out version check, as version 03.03 exported from blender also has 2 semicolons
|
||||||
if( !mIsBinaryFormat) // && MajorVersion == 3 && MinorVersion <= 2)
|
if( !mIsBinaryFormat) // && MajorVersion == 3 && MinorVersion <= 2)
|
||||||
{
|
{
|
||||||
if(P < End && *P == ';')
|
if(mP < mEnd && *mP == ';')
|
||||||
++P;
|
++mP;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there was only a single material index, replicate it on all faces
|
// if there was only a single material index, replicate it on all faces
|
||||||
|
@ -1029,12 +1030,12 @@ void XFileParser::TestForSeparator()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
FindNextNoneWhiteSpace();
|
FindNextNoneWhiteSpace();
|
||||||
if( P >= End)
|
if( mP >= mEnd)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// test and skip
|
// test and skip
|
||||||
if( *P == ';' || *P == ',')
|
if( *mP == ';' || *mP == ',')
|
||||||
P++;
|
mP++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -1062,46 +1063,54 @@ std::string XFileParser::GetNextToken()
|
||||||
// in binary mode it will only return NAME and STRING token
|
// in binary mode it will only return NAME and STRING token
|
||||||
// and (correctly) skip over other tokens.
|
// and (correctly) skip over other tokens.
|
||||||
|
|
||||||
if( End - P < 2) return s;
|
if( mEnd - mP < 2) return s;
|
||||||
unsigned int tok = ReadBinWord();
|
unsigned int tok = ReadBinWord();
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
|
|
||||||
// standalone tokens
|
// standalone tokens
|
||||||
switch( tok)
|
switch( tok)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1: {
|
||||||
// name token
|
// name token
|
||||||
if( End - P < 4) return s;
|
if ( mEnd - mP < 4 ) return s;
|
||||||
len = ReadBinDWord();
|
len = ReadBinDWord();
|
||||||
if( End - P < int(len)) return s;
|
const int bounds( mEnd - mP );
|
||||||
s = std::string(P, len);
|
const int iLen( len );
|
||||||
P += len;
|
if ( iLen < 0 ) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
if ( bounds < iLen ) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
s = std::string( mP, len );
|
||||||
|
mP += len;
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
case 2:
|
case 2:
|
||||||
// string token
|
// string token
|
||||||
if( End - P < 4) return s;
|
if( mEnd - mP < 4) return s;
|
||||||
len = ReadBinDWord();
|
len = ReadBinDWord();
|
||||||
if( End - P < int(len)) return s;
|
if( mEnd - mP < int(len)) return s;
|
||||||
s = std::string(P, len);
|
s = std::string(mP, len);
|
||||||
P += (len + 2);
|
mP += (len + 2);
|
||||||
return s;
|
return s;
|
||||||
case 3:
|
case 3:
|
||||||
// integer token
|
// integer token
|
||||||
P += 4;
|
mP += 4;
|
||||||
return "<integer>";
|
return "<integer>";
|
||||||
case 5:
|
case 5:
|
||||||
// GUID token
|
// GUID token
|
||||||
P += 16;
|
mP += 16;
|
||||||
return "<guid>";
|
return "<guid>";
|
||||||
case 6:
|
case 6:
|
||||||
if( End - P < 4) return s;
|
if( mEnd - mP < 4) return s;
|
||||||
len = ReadBinDWord();
|
len = ReadBinDWord();
|
||||||
P += (len * 4);
|
mP += (len * 4);
|
||||||
return "<int_list>";
|
return "<int_list>";
|
||||||
case 7:
|
case 7:
|
||||||
if( End - P < 4) return s;
|
if( mEnd - mP < 4) return s;
|
||||||
len = ReadBinDWord();
|
len = ReadBinDWord();
|
||||||
P += (len * mBinaryFloatSize);
|
mP += (len * mBinaryFloatSize);
|
||||||
return "<flt_list>";
|
return "<flt_list>";
|
||||||
case 0x0a:
|
case 0x0a:
|
||||||
return "{";
|
return "{";
|
||||||
|
@ -1159,19 +1168,19 @@ std::string XFileParser::GetNextToken()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FindNextNoneWhiteSpace();
|
FindNextNoneWhiteSpace();
|
||||||
if( P >= End)
|
if( mP >= mEnd)
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
while( (P < End) && !isspace( (unsigned char) *P))
|
while( (mP < mEnd) && !isspace( (unsigned char) *mP))
|
||||||
{
|
{
|
||||||
// either keep token delimiters when already holding a token, or return if first valid char
|
// either keep token delimiters when already holding a token, or return if first valid char
|
||||||
if( *P == ';' || *P == '}' || *P == '{' || *P == ',')
|
if( *mP == ';' || *mP == '}' || *mP == '{' || *mP == ',')
|
||||||
{
|
{
|
||||||
if( !s.size())
|
if( !s.size())
|
||||||
s.append( P++, 1);
|
s.append( mP++, 1);
|
||||||
break; // stop for delimiter
|
break; // stop for delimiter
|
||||||
}
|
}
|
||||||
s.append( P++, 1);
|
s.append( mP++, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
@ -1186,18 +1195,18 @@ void XFileParser::FindNextNoneWhiteSpace()
|
||||||
bool running = true;
|
bool running = true;
|
||||||
while( running )
|
while( running )
|
||||||
{
|
{
|
||||||
while( P < End && isspace( (unsigned char) *P))
|
while( mP < mEnd && isspace( (unsigned char) *mP))
|
||||||
{
|
{
|
||||||
if( *P == '\n')
|
if( *mP == '\n')
|
||||||
mLineNumber++;
|
mLineNumber++;
|
||||||
++P;
|
++mP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( P >= End)
|
if( mP >= mEnd)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// check if this is a comment
|
// check if this is a comment
|
||||||
if( (P[0] == '/' && P[1] == '/') || P[0] == '#')
|
if( (mP[0] == '/' && mP[1] == '/') || mP[0] == '#')
|
||||||
ReadUntilEndOfLine();
|
ReadUntilEndOfLine();
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
@ -1214,22 +1223,22 @@ void XFileParser::GetNextTokenAsString( std::string& poString)
|
||||||
}
|
}
|
||||||
|
|
||||||
FindNextNoneWhiteSpace();
|
FindNextNoneWhiteSpace();
|
||||||
if( P >= End)
|
if( mP >= mEnd)
|
||||||
ThrowException( "Unexpected end of file while parsing string");
|
ThrowException( "Unexpected end of file while parsing string");
|
||||||
|
|
||||||
if( *P != '"')
|
if( *mP != '"')
|
||||||
ThrowException( "Expected quotation mark.");
|
ThrowException( "Expected quotation mark.");
|
||||||
++P;
|
++mP;
|
||||||
|
|
||||||
while( P < End && *P != '"')
|
while( mP < mEnd && *mP != '"')
|
||||||
poString.append( P++, 1);
|
poString.append( mP++, 1);
|
||||||
|
|
||||||
if( P >= End-1)
|
if( mP >= mEnd-1)
|
||||||
ThrowException( "Unexpected end of file while parsing string");
|
ThrowException( "Unexpected end of file while parsing string");
|
||||||
|
|
||||||
if( P[1] != ';' || P[0] != '"')
|
if( mP[1] != ';' || mP[0] != '"')
|
||||||
ThrowException( "Expected quotation mark and semicolon at the end of a string.");
|
ThrowException( "Expected quotation mark and semicolon at the end of a string.");
|
||||||
P+=2;
|
mP+=2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -1238,35 +1247,35 @@ void XFileParser::ReadUntilEndOfLine()
|
||||||
if( mIsBinaryFormat)
|
if( mIsBinaryFormat)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while( P < End)
|
while( mP < mEnd)
|
||||||
{
|
{
|
||||||
if( *P == '\n' || *P == '\r')
|
if( *mP == '\n' || *mP == '\r')
|
||||||
{
|
{
|
||||||
++P; mLineNumber++;
|
++mP; mLineNumber++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
++P;
|
++mP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
unsigned short XFileParser::ReadBinWord()
|
unsigned short XFileParser::ReadBinWord()
|
||||||
{
|
{
|
||||||
ai_assert(End - P >= 2);
|
ai_assert(mEnd - mP >= 2);
|
||||||
const unsigned char* q = (const unsigned char*) P;
|
const unsigned char* q = (const unsigned char*) mP;
|
||||||
unsigned short tmp = q[0] | (q[1] << 8);
|
unsigned short tmp = q[0] | (q[1] << 8);
|
||||||
P += 2;
|
mP += 2;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
unsigned int XFileParser::ReadBinDWord()
|
unsigned int XFileParser::ReadBinDWord() {
|
||||||
{
|
ai_assert(mEnd - mP >= 4);
|
||||||
ai_assert(End - P >= 4);
|
|
||||||
const unsigned char* q = (const unsigned char*) P;
|
const unsigned char* q = (const unsigned char*) mP;
|
||||||
unsigned int tmp = q[0] | (q[1] << 8) | (q[2] << 16) | (q[3] << 24);
|
unsigned int tmp = q[0] | (q[1] << 8) | (q[2] << 16) | (q[3] << 24);
|
||||||
P += 4;
|
mP += 4;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1275,20 +1284,20 @@ unsigned int XFileParser::ReadInt()
|
||||||
{
|
{
|
||||||
if( mIsBinaryFormat)
|
if( mIsBinaryFormat)
|
||||||
{
|
{
|
||||||
if( mBinaryNumCount == 0 && End - P >= 2)
|
if( mBinaryNumCount == 0 && mEnd - mP >= 2)
|
||||||
{
|
{
|
||||||
unsigned short tmp = ReadBinWord(); // 0x06 or 0x03
|
unsigned short tmp = ReadBinWord(); // 0x06 or 0x03
|
||||||
if( tmp == 0x06 && End - P >= 4) // array of ints follows
|
if( tmp == 0x06 && mEnd - mP >= 4) // array of ints follows
|
||||||
mBinaryNumCount = ReadBinDWord();
|
mBinaryNumCount = ReadBinDWord();
|
||||||
else // single int follows
|
else // single int follows
|
||||||
mBinaryNumCount = 1;
|
mBinaryNumCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
--mBinaryNumCount;
|
--mBinaryNumCount;
|
||||||
if ( End - P >= 4) {
|
if ( mEnd - mP >= 4) {
|
||||||
return ReadBinDWord();
|
return ReadBinDWord();
|
||||||
} else {
|
} else {
|
||||||
P = End;
|
mP = mEnd;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -1299,24 +1308,24 @@ unsigned int XFileParser::ReadInt()
|
||||||
|
|
||||||
// check preceding minus sign
|
// check preceding minus sign
|
||||||
bool isNegative = false;
|
bool isNegative = false;
|
||||||
if( *P == '-')
|
if( *mP == '-')
|
||||||
{
|
{
|
||||||
isNegative = true;
|
isNegative = true;
|
||||||
P++;
|
mP++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// at least one digit expected
|
// at least one digit expected
|
||||||
if( !isdigit( *P))
|
if( !isdigit( *mP))
|
||||||
ThrowException( "Number expected.");
|
ThrowException( "Number expected.");
|
||||||
|
|
||||||
// read digits
|
// read digits
|
||||||
unsigned int number = 0;
|
unsigned int number = 0;
|
||||||
while( P < End)
|
while( mP < mEnd)
|
||||||
{
|
{
|
||||||
if( !isdigit( *P))
|
if( !isdigit( *mP))
|
||||||
break;
|
break;
|
||||||
number = number * 10 + (*P - 48);
|
number = number * 10 + (*mP - 48);
|
||||||
P++;
|
mP++;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckForSeparator();
|
CheckForSeparator();
|
||||||
|
@ -1329,10 +1338,10 @@ ai_real XFileParser::ReadFloat()
|
||||||
{
|
{
|
||||||
if( mIsBinaryFormat)
|
if( mIsBinaryFormat)
|
||||||
{
|
{
|
||||||
if( mBinaryNumCount == 0 && End - P >= 2)
|
if( mBinaryNumCount == 0 && mEnd - mP >= 2)
|
||||||
{
|
{
|
||||||
unsigned short tmp = ReadBinWord(); // 0x07 or 0x42
|
unsigned short tmp = ReadBinWord(); // 0x07 or 0x42
|
||||||
if( tmp == 0x07 && End - P >= 4) // array of floats following
|
if( tmp == 0x07 && mEnd - mP >= 4) // array of floats following
|
||||||
mBinaryNumCount = ReadBinDWord();
|
mBinaryNumCount = ReadBinDWord();
|
||||||
else // single float following
|
else // single float following
|
||||||
mBinaryNumCount = 1;
|
mBinaryNumCount = 1;
|
||||||
|
@ -1341,22 +1350,22 @@ ai_real XFileParser::ReadFloat()
|
||||||
--mBinaryNumCount;
|
--mBinaryNumCount;
|
||||||
if( mBinaryFloatSize == 8)
|
if( mBinaryFloatSize == 8)
|
||||||
{
|
{
|
||||||
if( End - P >= 8) {
|
if( mEnd - mP >= 8) {
|
||||||
ai_real result = (ai_real) (*(double*) P);
|
ai_real result = (ai_real) (*(double*) mP);
|
||||||
P += 8;
|
mP += 8;
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
P = End;
|
mP = mEnd;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
if( End - P >= 4) {
|
if( mEnd - mP >= 4) {
|
||||||
ai_real result = *(ai_real*) P;
|
ai_real result = *(ai_real*) mP;
|
||||||
P += 4;
|
mP += 4;
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
P = End;
|
mP = mEnd;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1367,21 +1376,21 @@ ai_real XFileParser::ReadFloat()
|
||||||
// check for various special strings to allow reading files from faulty exporters
|
// check for various special strings to allow reading files from faulty exporters
|
||||||
// I mean you, Blender!
|
// I mean you, Blender!
|
||||||
// Reading is safe because of the terminating zero
|
// Reading is safe because of the terminating zero
|
||||||
if( strncmp( P, "-1.#IND00", 9) == 0 || strncmp( P, "1.#IND00", 8) == 0)
|
if( strncmp( mP, "-1.#IND00", 9) == 0 || strncmp( mP, "1.#IND00", 8) == 0)
|
||||||
{
|
{
|
||||||
P += 9;
|
mP += 9;
|
||||||
CheckForSeparator();
|
CheckForSeparator();
|
||||||
return 0.0;
|
return 0.0;
|
||||||
} else
|
} else
|
||||||
if( strncmp( P, "1.#QNAN0", 8) == 0)
|
if( strncmp( mP, "1.#QNAN0", 8) == 0)
|
||||||
{
|
{
|
||||||
P += 8;
|
mP += 8;
|
||||||
CheckForSeparator();
|
CheckForSeparator();
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ai_real result = 0.0;
|
ai_real result = 0.0;
|
||||||
P = fast_atoreal_move<ai_real>( P, result);
|
mP = fast_atoreal_move<ai_real>( mP, result);
|
||||||
|
|
||||||
CheckForSeparator();
|
CheckForSeparator();
|
||||||
|
|
||||||
|
|
|
@ -49,10 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <assimp/types.h>
|
#include <assimp/types.h>
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp {
|
||||||
{
|
namespace XFile {
|
||||||
namespace XFile
|
|
||||||
{
|
|
||||||
struct Node;
|
struct Node;
|
||||||
struct Mesh;
|
struct Mesh;
|
||||||
struct Scene;
|
struct Scene;
|
||||||
|
@ -61,21 +59,20 @@ namespace Assimp
|
||||||
struct AnimBone;
|
struct AnimBone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The XFileParser reads a XFile either in text or binary form and builds a temporary
|
/**
|
||||||
* data structure out of it.
|
* @brief The XFileParser reads a XFile either in text or binary form and builds a temporary
|
||||||
*/
|
* data structure out of it.
|
||||||
class XFileParser
|
*/
|
||||||
{
|
class XFileParser {
|
||||||
public:
|
public:
|
||||||
/** Constructor. Creates a data structure out of the XFile given in the memory block.
|
/// Constructor. Creates a data structure out of the XFile given in the memory block.
|
||||||
* @param pBuffer Null-terminated memory buffer containing the XFile
|
/// @param pBuffer Null-terminated memory buffer containing the XFile
|
||||||
*/
|
|
||||||
explicit XFileParser( const std::vector<char>& pBuffer);
|
explicit XFileParser( const std::vector<char>& pBuffer);
|
||||||
|
|
||||||
/** Destructor. Destroys all imported data along with it */
|
/// Destructor. Destroys all imported data along with it
|
||||||
~XFileParser();
|
~XFileParser();
|
||||||
|
|
||||||
/** Returns the temporary representation of the imported data */
|
/// Returns the temporary representation of the imported data.
|
||||||
XFile::Scene* GetImportedData() const { return mScene; }
|
XFile::Scene* GetImportedData() const { return mScene; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -101,10 +98,10 @@ protected:
|
||||||
//! places pointer to next begin of a token, and ignores comments
|
//! places pointer to next begin of a token, and ignores comments
|
||||||
void FindNextNoneWhiteSpace();
|
void FindNextNoneWhiteSpace();
|
||||||
|
|
||||||
//! returns next parseable token. Returns empty string if no token there
|
//! returns next valid token. Returns empty string if no token there
|
||||||
std::string GetNextToken();
|
std::string GetNextToken();
|
||||||
|
|
||||||
//! reads header of dataobject including the opening brace.
|
//! reads header of data object including the opening brace.
|
||||||
//! returns false if error happened, and writes name of object
|
//! returns false if error happened, and writes name of object
|
||||||
//! if there is one
|
//! if there is one
|
||||||
void readHeadOfDataObject( std::string* poName = NULL);
|
void readHeadOfDataObject( std::string* poName = NULL);
|
||||||
|
@ -118,8 +115,8 @@ protected:
|
||||||
//! checks for a separator char, either a ',' or a ';'
|
//! checks for a separator char, either a ',' or a ';'
|
||||||
void CheckForSeparator();
|
void CheckForSeparator();
|
||||||
|
|
||||||
/// tests and possibly consumes a separator char, but does nothing if there was no separator
|
/// tests and possibly consumes a separator char, but does nothing if there was no separator
|
||||||
void TestForSeparator();
|
void TestForSeparator();
|
||||||
|
|
||||||
//! reads a x file style string
|
//! reads a x file style string
|
||||||
void GetNextTokenAsString( std::string& poString);
|
void GetNextTokenAsString( std::string& poString);
|
||||||
|
@ -138,27 +135,23 @@ protected:
|
||||||
/** Throws an exception with a line number and the given text. */
|
/** Throws an exception with a line number and the given text. */
|
||||||
AI_WONT_RETURN void ThrowException( const std::string& pText) AI_WONT_RETURN_SUFFIX;
|
AI_WONT_RETURN void ThrowException( const std::string& pText) AI_WONT_RETURN_SUFFIX;
|
||||||
|
|
||||||
/** Filters the imported hierarchy for some degenerated cases that some exporters produce.
|
/**
|
||||||
* @param pData The sub-hierarchy to filter
|
* @brief Filters the imported hierarchy for some degenerated cases that some exporters produce.
|
||||||
*/
|
* @param pData The sub-hierarchy to filter
|
||||||
|
*/
|
||||||
void FilterHierarchy( XFile::Node* pNode);
|
void FilterHierarchy( XFile::Node* pNode);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned int mMajorVersion, mMinorVersion; ///< version numbers
|
unsigned int mMajorVersion, mMinorVersion; ///< version numbers
|
||||||
bool mIsBinaryFormat; ///< true if the file is in binary, false if it's in text form
|
bool mIsBinaryFormat; ///< true if the file is in binary, false if it's in text form
|
||||||
unsigned int mBinaryFloatSize; ///< float size in bytes, either 4 or 8
|
unsigned int mBinaryFloatSize; ///< float size in bytes, either 4 or 8
|
||||||
// counter for number arrays in binary format
|
unsigned int mBinaryNumCount; /// < counter for number arrays in binary format
|
||||||
unsigned int mBinaryNumCount;
|
const char* mP;
|
||||||
|
const char* mEnd;
|
||||||
const char* P;
|
unsigned int mLineNumber; ///< Line number when reading in text format
|
||||||
const char* End;
|
XFile::Scene* mScene; ///< Imported data
|
||||||
|
|
||||||
/// Line number when reading in text format
|
|
||||||
unsigned int mLineNumber;
|
|
||||||
|
|
||||||
/// Imported data
|
|
||||||
XFile::Scene* mScene;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} //! ns Assimp
|
||||||
|
|
||||||
#endif // AI_XFILEPARSER_H_INC
|
#endif // AI_XFILEPARSER_H_INC
|
||||||
|
|
Loading…
Reference in New Issue