Exemple #1
0
inline const char* fast_atoreal_move(const char* c, Real& out)
{
	Real f;

	bool inv = (*c == '-');
	if (inv || *c == '+') {
		++c;
	}

	f = static_cast<Real>(strtoul10_64(c, &c));
	if (*c == '.' || (c[0] == ',' && c[1] >= '0' && c[1] <= '9')) // allow for commas, too
	{
		++c;

		// NOTE: The original implementation is highly inaccurate here. The precision of a single
		// IEEE 754 float is not high enough, everything behind the 6th digit tends to be more
		// inaccurate than it would need to be. Casting to double seems to solve the problem.
		// strtol_64 is used to prevent integer overflow.

		// Another fix: this tends to become 0 for long numbers if we don't limit the maximum
		// number of digits to be read. FAST_ATOF_RELAVANT_DECIMALS can be a value between
		// 1 and 15.
		unsigned int diff = FAST_ATOF_RELAVANT_DECIMALS;
		double pl = static_cast<double>(strtoul10_64(c, &c, &diff));

		pl *= fast_atof_table[diff];
		f += static_cast<Real>(pl);
	}

	// A major 'E' must be allowed. Necessary for proper reading of some DXF files.
	// Thanks to Zhao Lei to point out that this if() must be outside the if (*c == '.' ..)
	if (*c == 'e' || *c == 'E') {
		++c;
		const bool einv = (*c == '-');
		if (einv || *c == '+') {
			++c;
		}

		// The reason float constants are used here is that we've seen cases where compilers
		// would perform such casts on compile-time constants at runtime, which would be
		// bad considering how frequently fast_atoreal_move<float> is called in Assimp.
		Real exp = static_cast<Real>(strtoul10_64(c, &c));
		if (einv) {
			exp = -exp;
		}
		f *= pow(static_cast<Real>(10.0f), exp);
	}

	if (inv) {
		f = -f;
	}
	out = f;
	return c;
}
// ------------------------------------------------------------------------------------------------
uint64_t ParseTokenAsID(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 ID, unexpected data type, expected L(ong) (binary)";
            return 0L;
        }

        BE_NCONST uint64_t id = SafeParse<uint64_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 uint64_t id = strtoul10_64(t.begin(),&out,&length);
    if (out > t.end()) {
        err_out = "failed to parse ID (text)";
        return 0L;
    }

    return id;
}
// ------------------------------------------------------------------------------------------------
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;
}