bool StringData::isInteger() const { if (m_hash < 0) return false; int64_t lval; double dval; DataType ret = isNumericWithVal(lval, dval, 0); switch (ret) { case KindOfNull: case KindOfDouble: return false; case KindOfInt64: return true; case KindOfUninit: case KindOfBoolean: case KindOfPersistentString: case KindOfString: case KindOfPersistentArray: case KindOfArray: case KindOfObject: case KindOfResource: case KindOfRef: case KindOfClass: break; } not_reached(); }
int StringData::numericCompare(const StringData *v2) const { ASSERT(v2); int64 lval1, lval2; double dval1, dval2; DataType ret1, ret2; if ((ret1 = isNumericWithVal(lval1, dval1, 0)) == KindOfNull || (ret1 == KindOfDouble && !finite(dval1)) || (ret2 = v2->isNumericWithVal(lval2, dval2, 0)) == KindOfNull || (ret2 == KindOfDouble && !finite(dval2))) { return -2; } if (ret1 == KindOfInt64 && ret2 == KindOfInt64) { if (lval1 > lval2) return 1; if (lval1 == lval2) return 0; return -1; } if (ret1 == KindOfDouble && ret2 == KindOfDouble) { if (dval1 > dval2) return 1; if (dval1 == dval2) return 0; return -1; } if (ret1 == KindOfDouble) { ASSERT(ret2 == KindOfInt64); dval2 = (double)lval2; } else { ASSERT(ret1 == KindOfInt64); ASSERT(ret2 == KindOfDouble); dval1 = (double)lval1; } if (dval1 > dval2) return 1; if (dval1 == dval2) return 0; return -1; }
void StringData::setStatic() const { _count = (1 << 30); ASSERT(!isShared()); // because we are gonna reuse the space! m_hash = hash_string(data(), size()); ASSERT(m_hash >= 0); int64 lval; double dval; if (isNumericWithVal(lval, dval, 1) == KindOfNull) { m_hash |= (1ull << 63); } }
void StringData::preCompute() const { assert(!isShared()); // because we are gonna reuse the space! StringSlice s = slice(); m_hash = hash_string(s.ptr, s.len); assert(m_hash >= 0); int64_t lval; double dval; if (isNumericWithVal(lval, dval, 1) == KindOfNull) { m_hash |= STRHASH_MSB; } }
void StringData::preCompute() const { ASSERT(!isShared()); // because we are gonna reuse the space! // We don't want to collect taint for a hash StringSlice s = slice(); m_hash = hash_string(s.ptr, s.len); ASSERT(m_hash >= 0); int64 lval; double dval; if (isNumericWithVal(lval, dval, 1) == KindOfNull) { m_hash |= STRHASH_MSB; } }
bool StringData::isInteger() const { if (m_hash < 0) return false; int64 lval; double dval; DataType ret = isNumericWithVal(lval, dval, 0); switch (ret) { case KindOfNull: return false; case KindOfInt64: return true; case KindOfDouble: return false; default: ASSERT(false); break; } return false; }
int64 StringData::hashForIntSwitch(int64 firstNonZero, int64 noMatch) const { int64 lval; double dval; DataType ret = isNumericWithVal(lval, dval, 1); switch (ret) { case KindOfNull: // if the string is not a number, it matches 0 return 0; case KindOfInt64: return lval; case KindOfDouble: return Variant::DoubleHashForIntSwitch(dval, noMatch); default: break; } ASSERT(false); return 0; }
int StringData::numericCompare(const StringData *v2) const { assert(v2); int oflow1, oflow2; int64_t lval1, lval2; double dval1, dval2; DataType ret1, ret2; if ((ret1 = isNumericWithVal(lval1, dval1, 0, &oflow1)) == KindOfNull || (ret1 == KindOfDouble && !finite(dval1)) || (ret2 = v2->isNumericWithVal(lval2, dval2, 0, &oflow2)) == KindOfNull || (ret2 == KindOfDouble && !finite(dval2))) { return -2; } if (oflow1 && oflow1 == oflow2 && dval1 == dval2) { return -2; // overflow in same direction, comparison will be inaccurate } if (ret1 == KindOfInt64 && ret2 == KindOfInt64) { if (lval1 > lval2) return 1; if (lval1 == lval2) return 0; return -1; } if (ret1 == KindOfDouble && ret2 == KindOfDouble) { if (dval1 > dval2) return 1; if (dval1 == dval2) return 0; return -1; } if (ret1 == KindOfDouble) { assert(ret2 == KindOfInt64); if (oflow1) { return oflow1; } dval2 = (double)lval2; } else { assert(ret1 == KindOfInt64); assert(ret2 == KindOfDouble); if (oflow2) { return -oflow2; } dval1 = (double)lval1; } if (dval1 > dval2) return 1; if (dval1 == dval2) return 0; return -1; }
int64 StringData::hashForStringSwitch( int64 firstTrueCaseHash, int64 firstNullCaseHash, int64 firstFalseCaseHash, int64 firstZeroCaseHash, int64 firstHash, int64 noMatchHash, bool &needsOrder) const { int64 lval; double dval; DataType ret = isNumericWithVal(lval, dval, 1); needsOrder = false; switch (ret) { case KindOfNull: return empty() ? firstNullCaseHash : hash(); case KindOfInt64: return lval; case KindOfDouble: return (int64) dval; default: break; } ASSERT(false); return 0; }
DataType StringData::toNumeric(int64_t &lval, double &dval) const { if (m_hash < 0) return KindOfString; DataType ret = isNumericWithVal(lval, dval, 0); if (ret == KindOfInt64 || ret == KindOfDouble) return ret; return KindOfString; }