#include "Core.h" NAMESPACE_UPP #ifndef flagSO const Nuller Null; #endif #define LTIMING(x) // RTIMING(x) ValueTypeError::ValueTypeError(const String& text, const Value& src, int target) : Exc(text), src(src), target(target) {} unsigned Value::GetOtherHashValue() const { if(IsNull()) return 0; byte st = data.GetSt(); if(st == REF) return ptr()->GetHashValue(); return svo[st]->GetHashValue(&data); } void Value::RefRelease() { ASSERT(ptr()->GetType() >= 255 || !svo[ptr()->GetType()]); // Check that svo type is not registered as Ref ptr()->Release(); } void Value::RefRetain() { ptr()->Retain(); } Value& Value::operator=(const Value& v) { if(this == &v) return *this; Value h = v; // Make copy a 'v' can be reference to ValueMap/Array contained element FreeRef(); // e.g. json = json["foo"] data = h.data; if(IsRef()) ptr()->Retain(); return *this; } void Value::SetLarge(const Value& v) { if(v.IsRef()) { data.SetSmall(v.data); RefRetain(); } else data.LSet(v.data); } dword Value::GetType() const { if(IsString()) return STRING_V; byte st = data.GetSt(); return st == REF ? ptr()->GetType() : st == VOIDV ? VOID_V : st; } bool Value::IsNull() const { if(IsString()) return data.GetCount() == 0; int st = data.GetSt(); if(st == VOIDV) return true; if(st == REF) return ptr()->IsNull(); return svo[st]->IsNull(&data); } bool Value::IsPolyEqual(const Value& v) const { int st = data.GetSpecial(); if(st == REF) return ptr()->IsPolyEqual(v); if(svo[st] && svo[st]->IsPolyEqual(&data, v)) return true; return IsNull() && v.IsNull(); } bool Value::operator==(const Value& v) const { if(IsString() && v.IsString()) return data == v.data; if(GetType() != v.GetType()) return IsPolyEqual(v) || v.IsPolyEqual(*this); int st = data.GetSpecial(); if(st == REF) return ptr()->IsEqual(v.ptr()); if(st == VOIDV) return v.IsVoid(); return svo[st]->IsEqual(&data, &v.data); } int Value::PolyCompare(const Value& v) const { int st = data.GetSpecial(); if(st == REF) return ptr()->PolyCompare(v); if(st != VOIDV) return svo[st]->PolyCompare(&data, v); return 0; } int Value::Compare(const Value& v) const { if(IsString() && v.IsString()) return SgnCompare(data, v.data); bool a = IsNull(); bool b = v.IsNull(); if(a || b) return SgnCompare(b, a); int st = data.GetSpecial(); if(GetType() == v.GetType()) { if(st == REF) return ptr()->Compare(v.ptr()); if(st != VOIDV) return svo[st]->Compare(&data, &v.data); } if(st != VOIDV) { int q = PolyCompare(v); if(q) return q; // Perhaps optimize this return v.PolyCompare(*this); } return 0; } static bool sIsSame(const Value& a, const Value& b) { if(a.Is() && b.Is()) { ValueMap m = a; ValueMap n = b; for(int i = 0; i < m.GetCount(); i++) if(!sIsSame(n[m.GetKey(i)], m.GetValue(i))) return false; for(int i = 0; i < n.GetCount(); i++) if(!sIsSame(m[n.GetKey(i)], n.GetValue(i))) return false; return true; } else if(a.Is() && b.Is()) { if(a.GetCount() != b.GetCount()) return false; for(int i = 0; i < a.GetCount(); i++) if(!sIsSame(a[i], b[i])) return false; return true; } else return a == b; } bool Value::IsSame(const Value& v) const { return sIsSame(*this, v); } Value::Value(const WString& s) { InitRef(new RichValueRep(s)); Magic(); } Value::operator WString() const { if(IsNull()) return Null; return GetType() == WSTRING_V ? RichValue::Extract(*this) : ((String)(*this)).ToWString();//!!! } Date Value::GetOtherDate() const { if(IsNull()) return Null; return GetSmall