mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
385 lines
No EOL
14 KiB
C++
385 lines
No EOL
14 KiB
C++
class Id;
|
|
class Value;
|
|
class ValueArray;
|
|
class ValueMap;
|
|
class XmlIO;
|
|
class JsonIO;
|
|
|
|
class Ref;
|
|
struct ValueTypeRef;
|
|
|
|
template <class T>
|
|
void Jsonize(JsonIO& io, T& var);
|
|
|
|
template <class T>
|
|
void Xmlize(XmlIO& xml, T& var);
|
|
|
|
const dword VOID_V = 0;
|
|
|
|
const dword INT_V = 1;
|
|
const dword DOUBLE_V = 2;
|
|
const dword STRING_V = 3;
|
|
const dword DATE_V = 4;
|
|
const dword TIME_V = 5;
|
|
|
|
const dword ERROR_V = 6;
|
|
|
|
const dword VALUE_V = 7;
|
|
|
|
const dword WSTRING_V = 8;
|
|
|
|
const dword VALUEARRAY_V = 9;
|
|
|
|
const dword INT64_V = 10;
|
|
const dword BOOL_V = 11;
|
|
|
|
const dword VALUEMAP_V = 12;
|
|
const dword FLOAT_V = 13;
|
|
|
|
const dword UNKNOWN_V = (dword)0xffffffff;
|
|
|
|
template <class T>
|
|
inline dword ValueTypeNo(const T *) { return StaticTypeNo<T>() + 0x8000000; }
|
|
|
|
template<> inline dword ValueTypeNo(const int*) { return INT_V; }
|
|
template<> inline dword ValueTypeNo(const int64*) { return INT64_V; }
|
|
template<> inline dword ValueTypeNo(const double*) { return DOUBLE_V; }
|
|
template<> inline dword ValueTypeNo(const float*) { return FLOAT_V; }
|
|
template<> inline dword ValueTypeNo(const bool*) { return BOOL_V; }
|
|
template<> inline dword ValueTypeNo(const String*) { return STRING_V; }
|
|
template<> inline dword ValueTypeNo(const WString*) { return WSTRING_V; }
|
|
template<> inline dword ValueTypeNo(const Date*) { return DATE_V; }
|
|
template<> inline dword ValueTypeNo(const Time*) { return TIME_V; }
|
|
template<> inline dword ValueTypeNo(const Value*) { return VALUE_V; }
|
|
|
|
template <class T, dword type = UNKNOWN_V, class B = EmptyClass>
|
|
class ValueType : public B {
|
|
public:
|
|
static dword ValueTypeNo() { return type == UNKNOWN_V ? StaticTypeNo<T>() + 0x8000000 : type; }
|
|
friend dword ValueTypeNo(const T*) { return T::ValueTypeNo(); }
|
|
|
|
bool IsNullInstance() const { return false; }
|
|
void Serialize(Stream& s) { NEVER(); }
|
|
void Xmlize(XmlIO& xio) { NEVER(); }
|
|
void Jsonize(JsonIO& jio) { NEVER(); }
|
|
hash_t GetHashValue() const { return 0; }
|
|
bool operator==(const T&) const { NEVER(); return false; }
|
|
String ToString() const { return typeid(T).name(); }
|
|
int Compare(const T&) const { NEVER(); return 0; }
|
|
int PolyCompare(const Value&) const { NEVER(); return 0; }
|
|
|
|
operator ValueTypeRef();
|
|
};
|
|
|
|
template <class T, dword type, class B = EmptyClass> // Backward compatiblity
|
|
class AssignValueTypeNo : public ValueType<T, type, B> {};
|
|
|
|
template <class T>
|
|
dword GetValueTypeNo() { return ValueTypeNo((T*)NULL); }
|
|
|
|
class Value : Moveable<Value> {
|
|
public:
|
|
class Void {
|
|
protected:
|
|
Atomic refcount;
|
|
|
|
public:
|
|
void Retain() { AtomicInc(refcount); }
|
|
void Release() { if(AtomicDec(refcount) == 0) delete this; }
|
|
int GetRefCount() const { return refcount; }
|
|
|
|
virtual bool IsNull() const { return true; }
|
|
virtual void Serialize(Stream& s) {}
|
|
virtual void Xmlize(XmlIO& xio) {}
|
|
virtual void Jsonize(JsonIO& jio) {}
|
|
virtual hash_t GetHashValue() const { return 0; }
|
|
virtual bool IsEqual(const Void *p) { return false; }
|
|
virtual bool IsPolyEqual(const Value& v) { return false; }
|
|
virtual String AsString() const { return ""; }
|
|
virtual int Compare(const Void *p) { return 0; }
|
|
virtual int PolyCompare(const Value& p) { return 0; }
|
|
|
|
Void() { refcount = 1; }
|
|
virtual ~Void() {}
|
|
|
|
friend class Value;
|
|
};
|
|
|
|
struct Sval {
|
|
bool (*IsNull)(const void *p);
|
|
void (*Serialize)(void *p, Stream& s);
|
|
void (*Xmlize)(void *p, XmlIO& xio);
|
|
void (*Jsonize)(void *p, JsonIO& jio);
|
|
hash_t (*GetHashValue)(const void *p);
|
|
bool (*IsEqual)(const void *p1, const void *p2);
|
|
bool (*IsPolyEqual)(const void *p, const Value& v);
|
|
String (*AsString)(const void *p);
|
|
int (*Compare)(const void *p1, const void *p2);
|
|
int (*PolyCompare)(const void *p1, const Value& p2);
|
|
};
|
|
|
|
protected:
|
|
enum { STRING = 0, REF = 255, VOIDV = 3 };
|
|
|
|
static VectorMap<dword, Void* (*)()>& Typemap();
|
|
static Sval *svo[256];
|
|
static Index<String>& NameNdx();
|
|
static Index<dword>& TypeNdx();
|
|
|
|
static void AddName(dword type, const char *name);
|
|
static int GetType(const char *name);
|
|
static String GetName(dword type);
|
|
static void RegisterStd();
|
|
|
|
friend void ValueRegisterHelper();
|
|
|
|
String data;
|
|
Void *&ptr() { ASSERT(IsRef()); return *(Void **)&data; }
|
|
Void *ptr() const { ASSERT(IsRef()); return *(Void **)&data; }
|
|
|
|
void SetRefType(dword type) { ASSERT(IsRef()); ((int *)&data)[2] = type; }
|
|
dword GetRefType() const { ASSERT(IsRef()); return ((int *)&data)[2]; }
|
|
|
|
bool IsString() const { return !data.IsSpecial(); }
|
|
bool Is(byte v) const { return data.IsSpecial(v); }
|
|
bool IsRef() const { return Is(REF); }
|
|
void InitRef(Void *p, dword t) { data.SetSpecial(REF); ptr() = p; SetRefType(t); }
|
|
void RefRelease();
|
|
void RefRetain();
|
|
void FreeRef() { if(IsRef()) RefRelease(); }
|
|
void Free() { FreeRef(); data.Clear(); }
|
|
void SetLarge(const Value& v);
|
|
|
|
template <class T>
|
|
void InitSmall(const T& init);
|
|
template <class T>
|
|
T& GetSmallRaw() const;
|
|
template <class T>
|
|
T& GetSmall() const;
|
|
|
|
int GetOtherInt() const;
|
|
int64 GetOtherInt64() const;
|
|
double GetOtherDouble() const;
|
|
float GetOtherFloat() const;
|
|
bool GetOtherBool() const;
|
|
Date GetOtherDate() const;
|
|
Time GetOtherTime() const;
|
|
String GetOtherString() const;
|
|
hash_t GetOtherHashValue() const;
|
|
|
|
bool IsPolyEqual(const Value& v) const;
|
|
|
|
enum VSMALL { SMALL };
|
|
|
|
template <class T>
|
|
Value(const T& value, VSMALL);
|
|
|
|
template <class T> friend Value SvoToValue(const T& x);
|
|
|
|
String GetName() const;
|
|
|
|
int PolyCompare(const Value& v) const;
|
|
int Compare2(const Value& v) const;
|
|
|
|
Vector<Value>& UnShareArray();
|
|
|
|
const Vector<Value>& GetVA() const;
|
|
|
|
#if defined(_DEBUG) && defined(COMPILER_GCC)
|
|
uint32 magic[4];
|
|
void Magic() { magic[0] = 0xc436d851; magic[1] = 0x72f67c76; magic[2] = 0x3e5e10fd; magic[3] = 0xc90d370b; }
|
|
void ClearMagic() { magic[0] = magic[1] = magic[2] = magic[3] = 0; }
|
|
#else
|
|
void Magic() {}
|
|
void ClearMagic() {}
|
|
#endif
|
|
|
|
#ifndef DEPRECATED
|
|
static void Register(dword w, Void* (*c)(), const char *name = NULL);
|
|
#endif
|
|
|
|
Value(Void *p) = delete;
|
|
|
|
public:
|
|
template <class T>
|
|
static void Register(const char *name = NULL);
|
|
template <class T>
|
|
static void SvoRegister(const char *name = NULL);
|
|
|
|
dword GetType() const;
|
|
bool IsError() const { return GetType() == ERROR_V; }
|
|
bool IsVoid() const { return Is(VOIDV) || IsError(); }
|
|
bool IsNull() const;
|
|
|
|
template <class T>
|
|
bool Is() const;
|
|
template <class T>
|
|
const T& To() const;
|
|
template <class T>
|
|
const T& Get() const;
|
|
|
|
operator String() const { return IsString() ? data : GetOtherString(); }
|
|
operator WString() const;
|
|
operator Date() const { return Is(DATE_V) ? GetSmallRaw<Date>() : GetOtherDate(); }
|
|
operator Time() const { return Is(TIME_V) ? GetSmallRaw<Time>() : GetOtherTime(); }
|
|
operator double() const { return Is(DOUBLE_V) ? GetSmallRaw<double>() : GetOtherDouble(); }
|
|
operator float() const { return Is(FLOAT_V) ? GetSmallRaw<float>() : GetOtherFloat(); }
|
|
operator int() const { return Is(INT_V) ? GetSmallRaw<int>() : GetOtherInt(); }
|
|
operator int64() const { return Is(INT64_V) ? GetSmallRaw<int64>() : GetOtherInt64(); }
|
|
operator bool() const { return Is(BOOL_V) ? GetSmallRaw<bool>() : GetOtherBool(); }
|
|
std::string ToStd() const { return operator String().ToStd(); }
|
|
std::wstring ToWStd() const { return operator WString().ToStd(); }
|
|
|
|
Value(const String& s) : data(s) { Magic(); }
|
|
Value(const WString& s);
|
|
Value(const char *s) : data(s) { Magic(); }
|
|
Value(int i) : data(i, INT_V, String::SPECIAL) { Magic(); }
|
|
Value(int64 i) : data(i, INT64_V, String::SPECIAL) { Magic(); }
|
|
Value(double d) : data(d, DOUBLE_V, String::SPECIAL) { Magic(); }
|
|
Value(float d) : data(d, FLOAT_V, String::SPECIAL) { Magic(); }
|
|
Value(bool b) : data(b, BOOL_V, String::SPECIAL) { Magic(); }
|
|
Value(Date d) : data(d, DATE_V, String::SPECIAL) { Magic(); }
|
|
Value(Time t) : data(t, TIME_V, String::SPECIAL) { Magic(); }
|
|
Value(const Nuller&) : data((int)Null, INT_V, String::SPECIAL) { Magic(); }
|
|
Value(const std::string& s) : Value(String(s)) {}
|
|
Value(const std::wstring& s) : Value(WString(s)) {}
|
|
|
|
bool operator==(const Value& v) const;
|
|
bool operator!=(const Value& v) const { return !operator==(v); }
|
|
bool IsSame(const Value& v) const;
|
|
|
|
int Compare(const Value& v) const;
|
|
bool operator<=(const Value& x) const { return Compare(x) <= 0; }
|
|
bool operator>=(const Value& x) const { return Compare(x) >= 0; }
|
|
bool operator<(const Value& x) const { return Compare(x) < 0; }
|
|
bool operator>(const Value& x) const { return Compare(x) > 0; }
|
|
|
|
String ToString() const;
|
|
String operator ~() const { return ToString(); }
|
|
String GetTypeName() const { return GetName(); }
|
|
|
|
void Serialize(Stream& s);
|
|
void Xmlize(XmlIO& xio);
|
|
void Jsonize(JsonIO& jio);
|
|
|
|
hash_t GetHashValue() const;
|
|
|
|
Value& operator=(const Value& v);
|
|
Value(const Value& v);
|
|
|
|
int GetCount() const;
|
|
const Value& operator[](int i) const;
|
|
const Value& operator[](const String& key) const;
|
|
const Value& operator[](const char *key) const;
|
|
const Value& operator[](const Id& key) const;
|
|
|
|
Value& At(int i);
|
|
Value& operator()(int i) { return At(i); }
|
|
void Add(const Value& src);
|
|
template <typename T>
|
|
Value& operator<<(const T& src) { Add(src); return *this; }
|
|
|
|
Value& GetAdd(const Value& key);
|
|
Value& operator()(const String& key);
|
|
Value& operator()(const char *key);
|
|
Value& operator()(const Id& key);
|
|
|
|
Value() : data((int)Null, VOIDV, String::SPECIAL) { Magic(); }
|
|
~Value() { ClearMagic(); if(IsRef()) RefRelease(); }
|
|
|
|
Value(Void *p, dword type) { InitRef(p, type); Magic(); }
|
|
const Void *GetVoidPtr() const { ASSERT(IsRef()); return ptr(); }
|
|
|
|
friend void Swap(Value& a, Value& b) { Swap(a.data, b.data); }
|
|
|
|
typedef const Value *const_iterator;
|
|
|
|
const_iterator begin() const { return GetVA().begin(); }
|
|
const_iterator end() const { return GetVA().end(); }
|
|
|
|
#ifdef DEPRECATED
|
|
typedef Value value_type;
|
|
typedef const_iterator ConstIterator;
|
|
typedef const Value& const_reference;
|
|
typedef int size_type;
|
|
typedef int difference_type;
|
|
|
|
static void Register(dword w, Void* (*c)(), const char *name = NULL);
|
|
#endif
|
|
};
|
|
|
|
struct ValueTypeError : Exc {
|
|
Value src;
|
|
int target;
|
|
|
|
ValueTypeError(const String& text, const Value& src, int target);
|
|
};
|
|
|
|
template <class T> bool FitsSvoValue() { return sizeof(T) <= 8; }
|
|
template <class T> Value SvoToValue(const T& x) { return Value(x, Value::SMALL); }
|
|
|
|
template <class T> Value RichToValue(const T& data);
|
|
|
|
template <class T> Value RawToValue(const T& data);
|
|
template <class T> Value RawPickToValue(T&& data);
|
|
template <class T> Value RawDeepToValue(const T& data);
|
|
template <class T> T& CreateRawValue(Value& v);
|
|
|
|
Value ErrorValue(const char *s);
|
|
Value ErrorValue(const String& s);
|
|
const Value& ErrorValue();
|
|
|
|
template <class T>
|
|
inline bool IsPolyEqual(const T& x, const Value& v) {
|
|
return false;
|
|
}
|
|
|
|
template <class T>
|
|
inline hash_t ValueGetHashValue(const T& x) {
|
|
return UPP::GetHashValue(x);
|
|
}
|
|
|
|
#define VALUE_COMPARE_V(T, VT) \
|
|
inline bool operator==(const Value& v, T x) { return v.Is<VT>() ? (VT)v == x : v == Value(x); } \
|
|
inline bool operator==(T x, const Value& v) { return v.Is<VT>() ? (VT)v == x : v == Value(x); } \
|
|
inline bool operator!=(const Value& v, T x) { return v.Is<VT>() ? (VT)v != x : v != Value(x); } \
|
|
inline bool operator!=(T x, const Value& v) { return v.Is<VT>() ? (VT)v != x : v != Value(x); } \
|
|
|
|
#define VALUE_COMPARE(T) VALUE_COMPARE_V(T, T)
|
|
|
|
VALUE_COMPARE(int)
|
|
VALUE_COMPARE(int64)
|
|
VALUE_COMPARE(double)
|
|
VALUE_COMPARE(float)
|
|
VALUE_COMPARE(bool)
|
|
VALUE_COMPARE(Date)
|
|
VALUE_COMPARE(Time)
|
|
VALUE_COMPARE(String)
|
|
VALUE_COMPARE(WString)
|
|
VALUE_COMPARE_V(const char *, String)
|
|
VALUE_COMPARE_V(const wchar *, WString)
|
|
|
|
inline bool IsVoidValueTypeNo(int q) { return (dword)q == VOID_V; }
|
|
inline bool IsErrorValueTypeNo(int q) { return (dword)q == ERROR_V; }
|
|
inline bool IsStringValueTypeNo(int q) { return (dword)q == STRING_V || (dword)q == WSTRING_V; }
|
|
|
|
inline bool IsIntegerValueTypeNo(int q) { return (dword)q == INT_V || (dword)q == INT64_V || (dword)q == BOOL_V; }
|
|
inline bool IsFloatValueTypeNo(int q) { return (dword)q == DOUBLE_V || (dword)q == FLOAT_V; }
|
|
|
|
inline bool IsNumberValueTypeNo(int q) { return IsIntegerValueTypeNo(q) || IsFloatValueTypeNo(q); }
|
|
inline bool IsDateTimeValueTypeNo(int q) { return (dword)q == DATE_V || (dword)q == TIME_V; }
|
|
|
|
inline bool IsVoid(const Value& v) { return v.IsVoid(); }
|
|
inline bool IsError(const Value& v) { return v.IsError(); }
|
|
inline bool IsString(const Value& v) { return v.Is<String>() || v.Is<WString>(); }
|
|
inline bool IsNumber(const Value& v) { return v.Is<double>() || v.Is<float>() || v.Is<int>() || v.Is<int64>() || v.Is<bool>(); }
|
|
inline bool IsDateTime(const Value& v) { return v.Is<Date>() || v.Is<Time>(); }
|
|
inline bool IsValueArray(const Value& v) { return v.GetType() == VALUEARRAY_V || v.GetType() == VALUEMAP_V; }
|
|
inline bool IsValueMap(const Value& v) { return IsValueArray(v); }
|
|
|
|
String GetErrorText(const Value& v);
|
|
|
|
inline bool IsNull(const Value& v) { return v.IsNull(); }
|
|
inline const Value& Nvl(const Value& a, const Value& b) { return IsNull(a) ? b : a; }
|
|
|
|
inline bool IsNaN(const Value& v) { return v.Is<double>() && IsNaN((double)v); } |