// ------------------------------------------------------------------------------------------------ int64_t ParseTokenAsInt64(const Token& t, const char*& err_out) { err_out = NULL; if (t.Type() != TokenType_DATA) { err_out = "expected TOK_DATA token"; return 0L; } if (t.IsBinary()) { const char* data = t.begin(); if (data[0] != 'L') { err_out = "failed to parse Int64, unexpected data type"; return 0L; } BE_NCONST int64_t id = SafeParse<int64_t>(data + 1, t.end()); AI_SWAP8(id); return id; } // XXX: should use size_t here unsigned int length = static_cast<unsigned int>(t.end() - t.begin()); ai_assert(length > 0); const char* out; const int64_t id = strtol10_64(t.begin(), &out, &length); if (out > t.end()) { err_out = "failed to parse Int64 (text)"; return 0L; } return id; }
// ------------------------------------------------------------------------------------------------ int ParseTokenAsInt(const Token& t, const char*& err_out) { err_out = NULL; if (t.Type() != TokenType_DATA) { err_out = "expected TOK_DATA token"; return 0; } if(t.IsBinary()) { const char* data = t.begin(); if (data[0] != 'I') { err_out = "failed to parse I(nt), unexpected data type (binary)"; return 0; } BE_NCONST int32_t ival = SafeParse<int32_t>(data+1, t.end()); AI_SWAP4(ival); return static_cast<int>(ival); } ai_assert(static_cast<size_t>(t.end() - t.begin()) > 0); const char* out; const int intval = strtol10(t.begin(),&out); if (out != t.end()) { err_out = "failed to parse ID"; return 0; } return intval; }
// ------------------------------------------------------------------------------------------------ size_t ParseTokenAsDim(const Token& t, const char*& err_out) { // same as ID parsing, except there is a trailing asterisk err_out = NULL; if (t.Type() != TokenType_DATA) { err_out = "expected TOK_DATA token"; return 0; } if(t.IsBinary()) { const char* data = t.begin(); if (data[0] != 'L') { err_out = "failed to parse ID, unexpected data type, expected L(ong) (binary)"; return 0; } BE_NCONST uint64_t id = SafeParse<uint64_t>(data+1, t.end()); AI_SWAP8(id); return static_cast<size_t>(id); } if(*t.begin() != '*') { err_out = "expected asterisk before array dimension"; return 0; } // XXX: should use size_t here unsigned int length = static_cast<unsigned int>(t.end() - t.begin()); if(length == 0) { err_out = "expected valid integer number after asterisk"; return 0; } const char* out; const size_t id = static_cast<size_t>(strtoul10_64(t.begin() + 1,&out,&length)); if (out > t.end()) { err_out = "failed to parse ID"; return 0; } return id; }
// ------------------------------------------------------------------------------------------------ std::string ParseTokenAsString(const Token& t, const char*& err_out) { err_out = NULL; if (t.Type() != TokenType_DATA) { err_out = "expected TOK_DATA token"; return ""; } if(t.IsBinary()) { const char* data = t.begin(); if (data[0] != 'S') { err_out = "failed to parse S(tring), unexpected data type (binary)"; return ""; } ai_assert(t.end() - data >= 5); // read string length BE_NCONST int32_t len = *reinterpret_cast<const int32_t*>(data+1); AI_SWAP4(len); ai_assert(t.end() - data == 5 + len); return std::string(data + 5, len); } const size_t length = static_cast<size_t>(t.end() - t.begin()); if(length < 2) { err_out = "token is too short to hold a string"; return ""; } const char* s = t.begin(), *e = t.end() - 1; if (*s != '\"' || *e != '\"') { err_out = "expected double quoted string"; return ""; } return std::string(s+1,length-2); }
// ------------------------------------------------------------------------------------------------ float ParseTokenAsFloat(const Token& t, const char*& err_out) { err_out = NULL; if (t.Type() != TokenType_DATA) { err_out = "expected TOK_DATA token"; return 0.0f; } if(t.IsBinary()) { const char* data = t.begin(); if (data[0] != 'F' && data[0] != 'D') { err_out = "failed to parse F(loat) or D(ouble), unexpected data type (binary)"; return 0.0f; } if (data[0] == 'F') { ai_assert(t.end() - data == 5); // no byte swapping needed for ieee floats return *reinterpret_cast<const float*>(data+1); } else { ai_assert(t.end() - data == 9); // no byte swapping needed for ieee floats return static_cast<float>(*reinterpret_cast<const double*>(data+1)); } } // need to copy the input string to a temporary buffer // first - next in the fbx token stream comes ',', // which fast_atof could interpret as decimal point. #define MAX_FLOAT_LENGTH 31 char temp[MAX_FLOAT_LENGTH + 1]; const size_t length = static_cast<size_t>(t.end()-t.begin()); std::copy(t.begin(),t.end(),temp); temp[std::min(static_cast<size_t>(MAX_FLOAT_LENGTH),length)] = '\0'; return fast_atof(temp); }