ultimatepp/uppdev/CoreTopics/Value.h
cxl 3cd394812c Merge continued
git-svn-id: svn://ultimatepp.org/upp/trunk@10263 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2016-10-04 08:34:39 +00:00

707 lines
22 KiB
C++

struct IdConst {
const char *text;
mutable int ndx;
};
class Value;
class Id : Moveable<Id> {
protected:
int ndx;
static Index<String>& Ids();
void Set(const String& s);
public:
int AsNdx() const { return ndx; }
String ToString() const;
dword GetHashValue() const { return ndx; }
bool IsNull() const { return ndx == 0; }
void Serialize(Stream& s);
operator String() const { return ToString(); }
String operator~() const { return ToString(); }
bool operator==(Id b) const { return ndx == b.ndx; }
bool operator!=(Id b) const { return ndx != b.ndx; }
static Id Find(const String& s);
static const String& AsString(int n);
operator bool() const { return ndx; }
Id() { ndx = 0; }
Id(const String& s) { Set(s); }
Id(const char *s) { Set(s); }
explicit Id(int n) { ASSERT(n >= 0 && n < Ids().GetCount()); ndx = n; }
Id(const IdConst& cnst);
};
const int INT_NULL = INT_MIN;
const int64 INT64_NULL = INT64_MIN;
const double DOUBLE_NULL = -1.0E+308;
const double DOUBLE_NULL_LIM = -1.0E+307;
class Nuller {
public:
operator int() const { return INT_NULL; }
operator int64() const { return INT64_NULL; }
operator double() const { return DOUBLE_NULL; }
operator bool() const { return false; }
Nuller() {}
};
#ifdef flagSO
static const Nuller Null;
#else
extern const Nuller Null;
#endif
template<> inline bool IsNull(const int& i) { return i == INT_NULL; }
template<> inline bool IsNull(const int64& i) { return i == INT64_NULL; }
template<> inline bool IsNull(const double& r) { return r < DOUBLE_NULL_LIM; }
template<> inline bool IsNull(const bool& r ) { return false; }
template<> inline bool IsNull(const Date& d) { return d.year == -32768; }
template<> inline bool IsNull(const Time& t) { return t.year == -32768; }
inline const String& Nvl(const String& a, const String& b) { return IsNull(a) ? b : a; }
inline int Nvl(int a, int b) { return IsNull(a) ? b : a; }
inline int64 Nvl(int64 a, int64 b) { return IsNull(a) ? b : a; }
inline double Nvl(double a, double b) { return IsNull(a) ? b : a; }
inline Date Nvl(Date a, Date b) { return IsNull(a) ? b : a; }
inline Time Nvl(Time a, Time b) { return IsNull(a) ? b : a; }
inline int Nvl(int a) { return Nvl(a, 0); }
inline int64 Nvl(int64 a) { return Nvl(a, (int64)0); }
inline double Nvl(double a) { return Nvl(a, 0.0); }
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 UNKNOWN_V = (dword)0xffffffff;
class Value : Moveable<Value> {
public:
class Void {
protected:
Atomic refcount;
public:
void Retain() { AtomicInc(refcount); }
void Release() { if(AtomicDec(refcount) == 0) delete this; }
virtual dword GetType() const { return VOID_V; }
virtual bool IsNull() const { return true; }
virtual void Serialize(Stream& s) {}
virtual unsigned 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 ""; }
Void() { AtomicWrite(refcount, 1); }
virtual ~Void() {}
friend class Value;
};
protected:
static VectorMap<dword, Void* (*)(Stream& s) >& Typemap();
Void *ptr;
void SetVoidVal();
public:
static void Register(dword w, Void* (*c)(Stream& s)) init_;
dword GetType() const { return ptr->GetType(); }
bool IsError() const { return GetType() == ERROR_V; }
bool IsVoid() const { return GetType() == VOID_V || IsError(); }
bool IsNull() const { return ptr->IsNull(); }
template <class T>
bool Is() const;
operator String() const;
operator WString() const;
operator Date() const;
operator Time() const;
operator double() const;
operator int() const;
operator int64() const;
operator bool() const;
Value(const String& s);
Value(const WString& s);
Value(const char *s);
Value(int i);
Value(int64 i);
Value(double d);
Value(bool b);
Value(Date d);
Value(Time t);
Value(const Nuller&);
bool operator==(const Value& v) const;
bool operator!=(const Value& v) const { return !operator==(v); }
String ToString() const;
void Serialize(Stream& s);
unsigned GetHashValue() const;
Value& operator=(const Value& v);
Value(const Value& v);
Value();
~Value();
Value(Void *p) { ptr = p; }
const Void *GetVoidPtr() const { return ptr; }
};
#define VALUE_COMPARE(T) \
inline bool operator==(const Value& v, T x) { return (T)v == x; } \
inline bool operator==(T x, const Value& v) { return (T)v == x; } \
inline bool operator!=(const Value& v, T x) { return (T)v != x; } \
inline bool operator!=(T x, const Value& v) { return (T)v != x; } \
VALUE_COMPARE(int)
VALUE_COMPARE(int64)
VALUE_COMPARE(double)
VALUE_COMPARE(bool)
VALUE_COMPARE(Date)
VALUE_COMPARE(Time)
VALUE_COMPARE(String)
VALUE_COMPARE(WString)
inline bool operator==(const Value& v, const char *x) { return (String)v == x; }
inline bool operator==(const char *x, const Value& v) { return (String)v == x; }
inline bool operator!=(const Value& v, const char *x) { return (String)v != x; }
inline bool operator!=(const char *x, const Value& v) { return (String)v != x; }
inline bool operator==(const Value& v, const wchar *x) { return (WString)v == x; }
inline bool operator==(const wchar *x, const Value& v) { return (WString)v == x; }
inline bool operator!=(const Value& v, const wchar *x) { return (WString)v != x; }
inline bool operator!=(const wchar *x, const Value& v) { return (WString)v != x; }
inline bool IsVoid(const Value& v) { return v.GetType() == VOID_V; }
inline bool IsError(const Value& v) { return v.GetType() == ERROR_V; }
inline bool IsString(const Value& v) { return v.GetType() == STRING_V || v.GetType() == WSTRING_V; }
inline bool IsNumber(const Value& v) { return v.GetType() == DOUBLE_V || v.GetType() == INT_V
|| v.GetType() == INT64_V || v.GetType() == BOOL_V; }
inline bool IsDateTime(const Value& v) { return v.GetType() == DATE_V || v.GetType() == TIME_V; }
int StdValueCompare(const Value& a, const Value& b, int language);
int StdValueCompare(const Value& a, const Value& b);
int StdValueCompareDesc(const Value& a, const Value& b, int language);
int StdValueCompareDesc(const Value& a, const Value& b);
struct ValueOrder {
virtual bool operator()(const Value& a, const Value& b) const = 0;
virtual ~ValueOrder() {}
};
struct StdValueOrder : ValueOrder {
int language;
virtual bool operator()(const Value& a, const Value& b) const;
StdValueOrder(int l = -1);
virtual ~StdValueOrder();
};
struct FnValueOrder : ValueOrder {
int (*fn)(const Value& a, const Value& b);
virtual bool operator()(const Value& a, const Value& b) const;
FnValueOrder(int (*fn)(const Value& a, const Value& b));
virtual ~FnValueOrder();
};
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 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 <class T, dword type, class B = EmptyClass>
class AssignValueTypeNo : public B {
public:
friend dword ValueTypeNo(const T&) { return type; }
void operator=(const AssignValueTypeNo&) {} // MSC 6.0 empty base class bug fix
};
template <class T>
bool IsType(const Value& x, T* = 0) { return ValueTypeNo(*(T *)NULL) == x.GetType(); }
template <class T>
inline bool Value::Is() const
{
return IsType<T>(*this);
}
template <class T>
class RawValueRep : public Value::Void {
protected:
T v;
public:
virtual dword GetType() const { return ValueTypeNo(v); }
virtual bool IsNull() const { return false; }
const T& Get() const { return v; }
RawValueRep(const T& v) : v(v) {}
RawValueRep() {}
static const RawValueRep *Cast(const Value::Void *p) {
ASSERT_(dynamic_cast<const RawValueRep *>(p),
String().Cat() << "Invalid value conversion: "
<< typeid(*p).name() << " -> " << typeid(T).name());
return (const RawValueRep *) p;
}
};
template <class T>
bool IsTypeRaw(const Value& value, T * = 0) {
return !IsVoid(value) && dynamic_cast<const RawValueRep<T> *>(value.GetVoidPtr());
}
template <class T>
class RawValue : public Value {
protected:
typedef RawValueRep<T> Rep;
RawValue(Rep *rep) : Value(rep) {}
public:
RawValue(const T& x) : Value(new Rep(x)) {}
static const T& Extract(const Value& v) {
return Rep::Cast(v.GetVoidPtr())->Get();
}
static const T& Extract(const Value& v, const T& dflt) {
return IsTypeRaw<T>(v) ? Rep::Cast(v.GetVoidPtr())->Get() : dflt;
}
};
template <class T>
class RawPickValueRep : public RawValueRep<T> {
public:
RawPickValueRep(pick_ T& _v) { this->v = _v; }
RawPickValueRep(const T& _v, int) { this->v <<= _v; }
RawPickValueRep() {}
};
template <class T>
class RawPickValue : public RawValue<T> {
protected:
typedef RawPickValueRep<T> PickRep;
public:
RawPickValue(pick_ T& x) : RawValue<T>(new PickRep(x)) {}
RawPickValue(const T& x, int) : RawValue<T>(new PickRep(x, 0)) {}
};
template <class T>
class RawValueCreateRep : public RawValueRep<T> {
public:
T& Get() { return this->v; }
};
template <class T>
class RawValueCreate : public RawValue<T> {
protected:
typedef RawValueCreateRep<T> Rep;
public:
RawValueCreate() : RawValue<T>(new Rep()) {}
T& Get() { return ((Rep *)this->GetVoidPtr())->Get(); }
};
template <class T>
inline Value RawToValue(const T& data) { return RawValue<T>(data); }
template <class T>
inline Value RawPickToValue(pick_ T& data) { return RawPickValue<T>(data); }
template <class T>
inline Value RawDeepToValue(const T& data) { return RawPickValue<T>(data, 0); }
template <class T>
inline T& CreateRawValue(Value& v) {
RawValueCreate<T> x;
v = x;
return x.Get();
}
template <class T>
inline const T& ValueTo(const Value& v, T * = 0) { return RawValue<T>::Extract(v); }
template <class T>
inline const T& ValueTo(const Value& v, const T& dflt) { return RawValue<T>::Extract(v, dflt); }
template <class T>
inline bool IsPolyEqual(const T& x, const Value& v) {
return false;
}
template <class T>
inline unsigned ValueGetHashValue(const T& x) {
return UPP::GetHashValue(x);
}
inline bool IsPolyEqual(const bool& x, const Value& v) {
return v.GetType() == DOUBLE_V && int(x) == double(v)
|| v.GetType() == INT64_V && int(x) == int64(v)
|| v.GetType() == INT_V && int(x) == int(v);
}
inline bool IsPolyEqual(const int& x, const Value& v) {
return v.GetType() == DOUBLE_V && x == double(v)
|| v.GetType() == INT64_V && x == int64(v);
}
inline bool IsPolyEqual(const int64& x, const Value& v) {
return v.GetType() == DOUBLE_V && double(x) == double(v);
}
inline bool IsPolyEqual(const Date& x, const Value& v) {
return v.GetType() == TIME_V && ToTime(x) == Time(v);
}
inline bool IsPolyEqual(const WString& x, const Value& v) {
return v.GetType() == STRING_V && WString(v) == x;
}
inline unsigned ValueGetHashValue(const bool& x) {
return UPP::GetHashValue((double)x);
}
inline unsigned ValueGetHashValue(const int& x) {
return UPP::GetHashValue((double)x);
}
inline unsigned ValueGetHashValue(const int64& x) {
return UPP::GetHashValue((double)x);
}
inline unsigned ValueGetHashValue(const Date& x) {
return UPP::GetHashValue(ToTime(x));
}
inline unsigned ValueGetHashValue(const String& x) { // Improve by specialized routines !!!
return UPP::GetHashValue((WString)x);
}
template <class T>
class RichValueRep : public RawValueRep<T> {
public:
virtual bool IsNull() const { return UPP::IsNull(this->v); }
virtual void Serialize(Stream& s) { s % this->v; }
virtual unsigned GetHashValue() const { return UPP::ValueGetHashValue(this->v); }
virtual bool IsEqual(const Value::Void *p) { return Cast(p)->Get() == this->v; }
virtual bool IsPolyEqual(const Value& b) { return UPP::IsPolyEqual(this->v, b); }
virtual String AsString() const { return UPP::AsString(this->v); }
RichValueRep(const T& v) : RawValueRep<T>(v) {}
RichValueRep(Stream& s) { Serialize(s); }
static Value::Void *Create(Stream& s) { return new RichValueRep(s); }
static const RichValueRep *Cast(const Value::Void *p) {
ASSERT_(dynamic_cast<const RichValueRep *>(p),
String().Cat() << "Invalid value conversion: "
<< typeid(*p).name() << " -> " << typeid(T).name());
return (const RichValueRep *) p;
}
};
template <class T>
class RichValue : public Value {
protected:
typedef RichValueRep<T> Rep;
static const T& GetNull() {
static T *q;
ONCELOCK {
static T x(Null);
q = &x;
}
return *q;
}
public:
RichValue(const T& x) : Value(new Rep(x)) {}
const T& Get(const Value& v) {
if(IsNull(v)) return GetNull();
return Rep::Cast(v.GetVoidPtr())->Get();
}
static void Register() init_ {
Value::Register(ValueTypeNo(*(T *)NULL), Rep::Create);
}
static const T& Extract(const Value& v) {
if(v.IsNull()) return GetNull();
return Rep::Cast(v.GetVoidPtr())->Get();
}
};
template <class T>
inline Value RichToValue(const T& data) { return RichValue<T>(data); }
Value ErrorValue(const char *s);
Value ErrorValue(const String& s);
Value ErrorValue();
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; }
Value Scan(dword stdtype, const String& text);
// ----------------------- Ref
struct RefManager {
virtual int GetType() = 0;
virtual Value GetValue(const void *) { return Null; }
virtual bool IsNull(const void *) { return false; }
virtual void SetValue(void *, const Value& v) { NEVER(); }
virtual void SetNull(void *) { NEVER(); }
virtual ~RefManager() {}
};
template <class T>
struct RawRef : public RefManager {
virtual void SetValue(void *p, const Value& v) { *(T *) p = RawValue<T>::Extract(v); }
virtual Value GetValue(const void *p) { return RawValue<T>(*(const T *) p); }
virtual int GetType() { return ValueTypeNo(*(T *)NULL); }
virtual ~RawRef() {}
};
template <class T>
struct RichRef : public RawRef<T> {
virtual Value GetValue(const void *p) { return RichValue<T>(*(T *) p); }
virtual bool IsNull(const void *p) { return UPP::IsNull(*(T *) p); }
virtual void SetValue(void *p, const Value& v) { *(T *) p = T(v); }
virtual void SetNull(void *p) { *(T *) p = T(Null); }
};
class Ref : Moveable<Ref> {
protected:
RefManager *m;
void *ptr;
struct ValueRef;
public:
dword GetType() const { return m ? m->GetType() : VOID_V; }
operator Value() const { return m ? m->GetValue(ptr) : Value(); }
bool IsNull() const { return m ? m->IsNull(ptr) : true; }
void *GetVoidPtr() const { return ptr; }
void SetNull() { if(m) m->SetNull(ptr); }
void SetValue(const Value& v) { ASSERT(m); m->SetValue(ptr, v); }
Ref& operator=(const Value& v) { SetValue(v); return *this; }
Ref(String& s);
Ref(WString& s);
Ref(int& i);
Ref(int64& i);
Ref(double& d);
Ref(Date& d);
Ref(Time& t);
Ref(Value& v);
Ref(void *_ptr, RefManager *_m) { ptr = _ptr, m = _m; }
Ref() { ptr = m = NULL; }
};
template <class T>
T& GetRef(Ref r, T *x = NULL) {
ASSERT(ValueTypeNo(*x) == r.GetType());
return *(T *) r.GetVoidPtr();
}
inline String& RefString(Ref f) { return GetRef<String>(f); }
inline WString& RefWString(Ref f) { return GetRef<WString>(f); }
inline int& RefInt(Ref f) { return GetRef<int>(f); }
inline int64& RefInt64(Ref f) { return GetRef<int64>(f); }
inline double& RefDouble(Ref f) { return GetRef<double>(f); }
inline Date& RefDate(Ref f) { return GetRef<Date>(f); }
inline Time& RefTime(Ref f) { return GetRef<Time>(f); }
inline Value& RefValue(Ref f) { ASSERT(f.GetType() == VALUE_V);
return *(Value *)f.GetVoidPtr(); }
template <class T>
Ref RawAsRef(T& x) {
return Ref(&x, &Single< RawRef<T> >());
}
template <class T>
Ref RichAsRef(T& x) {
return Ref(&x, &Single< RichRef<T> >());
}
#define E__Value(I) Value p##I
#define E__Ref(I) Ref p##I
// ---------------------- Value Array
class ValueArray : AssignValueTypeNo<ValueArray, VALUEARRAY_V, Moveable<ValueArray> > {
struct Data : Value::Void {
virtual dword GetType() const { return VALUEARRAY_V; }
virtual bool IsNull() const;
virtual void Serialize(Stream& s);
virtual unsigned GetHashValue() const;
virtual bool IsEqual(const Value::Void *p);
virtual String AsString() const;
int GetRefCount() const { return AtomicRead(refcount); }
Vector<Value> data;
};
struct NullData : Data {};
Data *data;
Vector<Value>& Create();
Vector<Value>& Clone();
public:
ValueArray();
ValueArray(const ValueArray& v);
explicit ValueArray(pick_ Vector<Value>& values);
explicit ValueArray(const Vector<Value>& values, int deep);
~ValueArray();
ValueArray& operator=(const ValueArray& v);
operator Value() const;
ValueArray(const Value& src);
ValueArray(const Nuller&);
bool IsNull() const { return data->IsNull(); }
void Clear();
void SetCount(int n);
void SetCount(int n, const Value& v);
int GetCount() const { return data->data.GetCount(); }
bool IsEmpty() const { return data->data.IsEmpty(); }
void Add(const Value& v);
void Set(int i, const Value& v);
void Remove(int i);
const Value& Get(int i) const;
const Vector<Value>& Get() const { return data->data; }
const Value& operator[](int i) const { return Get(i); }
unsigned GetHashValue() const { return data->GetHashValue(); }
void Serialize(Stream& s);
bool operator==(const ValueArray& v) const;
bool operator!=(const ValueArray& v) const { return !operator==(v); }
};
template<> inline unsigned GetHashValue(const ValueArray& v) { return v.GetHashValue(); }
template<> inline bool IsNull(const ValueArray& v) { return v.IsNull(); }
template<>
String AsString(const ValueArray& v);
class ValueMap : AssignValueTypeNo<ValueMap, VALUEMAP_V, Moveable<ValueMap> >{
struct Data : Value::Void {
virtual dword GetType() const { return VALUEMAP_V; }
virtual bool IsNull() const;
virtual void Serialize(Stream& s);
virtual unsigned GetHashValue() const;
virtual bool IsEqual(const Value::Void *p);
virtual String AsString() const;
int GetRefCount() const { return AtomicRead(refcount); }
Index<Value> key;
ValueArray value;
};
struct NullData : Data {};
Data *data;
Data& Create();
Data& Clone();
void Init0();
public:
ValueMap() { Init0(); }
ValueMap(const ValueMap& v);
~ValueMap();
ValueMap& operator=(const ValueMap& v);
operator Value() const;
ValueMap(const Value& src);
ValueMap(const Nuller&) { Init0(); }
bool IsNullInstance() const { return data->IsNull(); }
void Clear();
void Add(const Value& key, const Value& value);
void Add(const char *s, const Value& value) { Add(Value(s), value); }
void Add(Id id, const Value& value) { Add(Value(id.ToString()), value); }
const Index<Value>& GetKeys() const { return data->key; }
ValueArray GetValues() const { return data->value; }
operator ValueArray() const { return GetValues(); }
Value operator[](const Value& k) const;
Value operator[](const char *s) const { return operator[](Value(s)); }
Value operator[](const Id& k) const { return operator[](Value(k.ToString())); }
unsigned GetHashValue() const { return data->GetHashValue(); }
void Serialize(Stream& s);
String ToString() const { return data->AsString(); }
bool operator==(const ValueMap& v) const;
bool operator!=(const ValueMap& v) const { return !operator==(v); }
};
inline bool IsValueArray(const Value& v) { return v.GetType() == VALUEARRAY_V || v.GetType() == VALUEMAP_V; }
inline bool IsValueMap(const Value& v) { return IsValueArray(v); }
class ValueGen {
public:
virtual Value Get() = 0;
Value operator++() { return Get(); }
virtual ~ValueGen() {}
};