diff options
Diffstat (limited to 'src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp')
-rw-r--r-- | src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp | 113 |
1 files changed, 85 insertions, 28 deletions
diff --git a/src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp b/src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp index 551b174ed..519f2e176 100644 --- a/src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp +++ b/src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -55,7 +56,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace FBX { - +//enum Flag +//{ +// e_unknown_0 = 1 << 0, +// e_unknown_1 = 1 << 1, +// e_unknown_2 = 1 << 2, +// e_unknown_3 = 1 << 3, +// e_unknown_4 = 1 << 4, +// e_unknown_5 = 1 << 5, +// e_unknown_6 = 1 << 6, +// e_unknown_7 = 1 << 7, +// e_unknown_8 = 1 << 8, +// e_unknown_9 = 1 << 9, +// e_unknown_10 = 1 << 10, +// e_unknown_11 = 1 << 11, +// e_unknown_12 = 1 << 12, +// e_unknown_13 = 1 << 13, +// e_unknown_14 = 1 << 14, +// e_unknown_15 = 1 << 15, +// e_unknown_16 = 1 << 16, +// e_unknown_17 = 1 << 17, +// e_unknown_18 = 1 << 18, +// e_unknown_19 = 1 << 19, +// e_unknown_20 = 1 << 20, +// e_unknown_21 = 1 << 21, +// e_unknown_22 = 1 << 22, +// e_unknown_23 = 1 << 23, +// e_flag_field_size_64_bit = 1 << 24, // Not sure what is +// e_unknown_25 = 1 << 25, +// e_unknown_26 = 1 << 26, +// e_unknown_27 = 1 << 27, +// e_unknown_28 = 1 << 28, +// e_unknown_29 = 1 << 29, +// e_unknown_30 = 1 << 30, +// e_unknown_31 = 1 << 31 +//}; +// +//bool check_flag(uint32_t flags, Flag to_check) +//{ +// return (flags & to_check) != 0; +//} // ------------------------------------------------------------------------------------------------ Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset) : @@ -106,23 +146,39 @@ void TokenizeError(const std::string& message, const char* begin, const char* cu // ------------------------------------------------------------------------------------------------ uint32_t ReadWord(const char* input, const char*& cursor, const char* end) { - if(Offset(cursor, end) < 4) { + const size_t k_to_read = sizeof( uint32_t ); + if(Offset(cursor, end) < k_to_read ) { TokenizeError("cannot ReadWord, out of bounds",input, cursor); } - uint32_t word = *reinterpret_cast<const uint32_t*>(cursor); + uint32_t word; + memcpy(&word, cursor, 4); AI_SWAP4(word); - cursor += 4; + cursor += k_to_read; return word; } +// ------------------------------------------------------------------------------------------------ +uint64_t ReadDoubleWord(const char* input, const char*& cursor, const char* end) { + const size_t k_to_read = sizeof(uint64_t); + if(Offset(cursor, end) < k_to_read) { + TokenizeError("cannot ReadDoubleWord, out of bounds",input, cursor); + } + + uint64_t dword = *reinterpret_cast<const uint64_t*>(cursor); + AI_SWAP8(dword); + + cursor += k_to_read; + + return dword; +} // ------------------------------------------------------------------------------------------------ uint8_t ReadByte(const char* input, const char*& cursor, const char* end) { - if(Offset(cursor, end) < 1) { + if(Offset(cursor, end) < sizeof( uint8_t ) ) { TokenizeError("cannot ReadByte, out of bounds",input, cursor); } @@ -165,8 +221,6 @@ unsigned int ReadString(const char*& sbegin_out, const char*& send_out, const ch return length; } - - // ------------------------------------------------------------------------------------------------ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, const char*& cursor, const char* end) { @@ -287,10 +341,10 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, // ------------------------------------------------------------------------------------------------ -bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end) +bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end, bool const is64bits) { // the first word contains the offset at which this block ends - const uint32_t end_offset = ReadWord(input, cursor, end); + const uint64_t end_offset = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end); // we may get 0 if reading reached the end of the file - // fbx files have a mysterious extra footer which I don't know @@ -308,10 +362,10 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, } // the second data word contains the number of properties in the scope - const uint32_t prop_count = ReadWord(input, cursor, end); + const uint64_t prop_count = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end); // the third data word contains the length of the property list - const uint32_t prop_length = ReadWord(input, cursor, end); + const uint64_t prop_length = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end); // now comes the name of the scope/key const char* sbeg, *send; @@ -337,29 +391,28 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, // at the end of each nested block, there is a NUL record to indicate // that the sub-scope exists (i.e. to distinguish between P: and P : {}) - // this NUL record is 13 bytes long. -#define BLOCK_SENTINEL_LENGTH 13 + // this NUL record is 13 bytes long on 32 bit version and 25 bytes long on 64 bit. + const size_t sentinel_block_length = is64bits ? (sizeof(uint64_t)* 3 + 1) : (sizeof(uint32_t)* 3 + 1); if (Offset(input, cursor) < end_offset) { - - if (end_offset - Offset(input, cursor) < BLOCK_SENTINEL_LENGTH) { + if (end_offset - Offset(input, cursor) < sentinel_block_length) { TokenizeError("insufficient padding bytes at block end",input, cursor); } output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_OPEN_BRACKET, Offset(input, cursor) )); // XXX this is vulnerable to stack overflowing .. - while(Offset(input, cursor) < end_offset - BLOCK_SENTINEL_LENGTH) { - ReadScope(output_tokens, input, cursor, input + end_offset - BLOCK_SENTINEL_LENGTH); + while(Offset(input, cursor) < end_offset - sentinel_block_length) { + ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, is64bits); } output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) )); - for (unsigned int i = 0; i < BLOCK_SENTINEL_LENGTH; ++i) { + for (unsigned int i = 0; i < sentinel_block_length; ++i) { if(cursor[i] != '\0') { TokenizeError("failed to read nested block sentinel, expected all bytes to be 0",input, cursor); } } - cursor += BLOCK_SENTINEL_LENGTH; + cursor += sentinel_block_length; } if (Offset(input, cursor) != end_offset) { @@ -369,10 +422,10 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, return true; } - } // ------------------------------------------------------------------------------------------------ +// TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length) { ai_assert(input); @@ -385,13 +438,17 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le TokenizeError("magic bytes not found",0); } - - //uint32_t offset = 0x1b; - - const char* cursor = input + 0x1b; - - while (cursor < input + length) { - if(!ReadScope(output_tokens, input, cursor, input + length)) { + const char* cursor = input + 18; + /*Result ignored*/ ReadByte(input, cursor, input + length); + /*Result ignored*/ ReadByte(input, cursor, input + length); + /*Result ignored*/ ReadByte(input, cursor, input + length); + /*Result ignored*/ ReadByte(input, cursor, input + length); + /*Result ignored*/ ReadByte(input, cursor, input + length); + const uint32_t version = ReadWord(input, cursor, input + length); + const bool is64bits = version >= 7500; + while (cursor < input + length) + { + if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) { break; } } |