// ------------------------------------------------------------------------------------------------ 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; }
// ------------------------------------------------------------------------------------------------ // read an array of int64_ts void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el) { out.resize( 0 ); const TokenList& tok = el.Tokens(); if (tok.empty()) { ParseError("unexpected empty element", &el); } if (tok[0]->IsBinary()) { const char* data = tok[0]->begin(), *end = tok[0]->end(); char type; uint32_t count; ReadBinaryDataArrayHead(data, end, type, count, el); if (!count) { return; } if (type != 'l') { ParseError("expected long array (binary)", &el); } std::vector<char> buff; ReadBinaryDataArray(type, count, data, end, buff, el); ai_assert(data == end); ai_assert(buff.size() == count * 8); out.reserve(count); const int64_t* ip = reinterpret_cast<const int64_t*>(&buff[0]); for (unsigned int i = 0; i < count; ++i, ++ip) { BE_NCONST int64_t val = *ip; AI_SWAP8(val); out.push_back(val); } return; } const size_t dim = ParseTokenAsDim(*tok[0]); // see notes in ParseVectorDataArray() out.reserve(dim); const Scope& scope = GetRequiredScope(el); const Element& a = GetRequiredElement(scope, "a", &el); for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end;) { const int64_t ival = ParseTokenAsInt64(**it++); out.push_back(ival); } }
// ------------------------------------------------------------------------------------------------ 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; }
// ------------------------------------------------------------------------------------------------ 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; }