int VelocyPackHelper::compareNumberValues(VPackValueType lhsType, VPackSlice lhs, VPackSlice rhs) { if (lhsType == rhs.type()) { // both types are equal if (lhsType == VPackValueType::Int || lhsType == VPackValueType::SmallInt) { // use exact comparisons. no need to cast to double int64_t l = lhs.getInt(); int64_t r = rhs.getInt(); if (l == r) { return 0; } return (l < r ? -1 : 1); } if (lhsType == VPackValueType::UInt) { // use exact comparisons. no need to cast to double uint64_t l = lhs.getUInt(); uint64_t r = rhs.getUInt(); if (l == r) { return 0; } return (l < r ? -1 : 1); } // fallthrough to double comparison } double left = lhs.getNumericValue<double>(); double right = rhs.getNumericValue<double>(); if (left == right) { return 0; } return (left < right ? -1 : 1); }
v8::Handle<v8::Value> TRI_VPackToV8(v8::Isolate* isolate, VPackSlice const& slice, VPackOptions const* options, VPackSlice const* base) { switch (slice.type()) { case VPackValueType::Null: { return v8::Null(isolate); } case VPackValueType::Bool: { return v8::Boolean::New(isolate, slice.getBool()); } case VPackValueType::Double: { // convert NaN, +inf & -inf to null double value = slice.getDouble(); if (std::isnan(value) || !std::isfinite(value) || value == HUGE_VAL || value == -HUGE_VAL) { return v8::Null(isolate); } return v8::Number::New(isolate, slice.getDouble()); } case VPackValueType::Int: { int64_t value = slice.getInt(); if (value >= -2147483648LL && value <= 2147483647LL) { // value is within bounds of an int32_t return v8::Integer::New(isolate, static_cast<int32_t>(value)); } if (value >= 0 && value <= 4294967295LL) { // value is within bounds of a uint32_t return v8::Integer::NewFromUnsigned(isolate, static_cast<uint32_t>(value)); } // must use double to avoid truncation return v8::Number::New(isolate, static_cast<double>(slice.getInt())); } case VPackValueType::UInt: { uint64_t value = slice.getUInt(); if (value <= 4294967295ULL) { // value is within bounds of a uint32_t return v8::Integer::NewFromUnsigned(isolate, static_cast<uint32_t>(value)); } // must use double to avoid truncation return v8::Number::New(isolate, static_cast<double>(slice.getUInt())); } case VPackValueType::SmallInt: { return v8::Integer::New(isolate, slice.getNumericValue<int32_t>()); } case VPackValueType::String: { return ObjectVPackString(isolate, slice); } case VPackValueType::Array: { return ObjectVPackArray(isolate, slice, options, base); } case VPackValueType::Object: { return ObjectVPackObject(isolate, slice, options, base); } case VPackValueType::External: { // resolve external return TRI_VPackToV8(isolate, VPackSlice(slice.getExternal()), options, base); } case VPackValueType::Custom: { if (options == nullptr || options->customTypeHandler == nullptr || base == nullptr) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "Could not extract custom attribute."); } std::string id = options->customTypeHandler->toString(slice, options, *base); return TRI_V8_STD_STRING(id); } case VPackValueType::None: default: { return v8::Undefined(isolate); } } }