mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-21 22:04:56 -06:00
Core: new Value reintegrated for conditional compilation (SVO_VALUE flag)
git-svn-id: svn://ultimatepp.org/upp/trunk@4495 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
3083aefbc3
commit
8afe5fef70
22 changed files with 3122 additions and 1224 deletions
|
|
@ -119,9 +119,15 @@ Color Blend(Color c1, Color c2, int alpha)
|
|||
min(((a * (c2.GetB() - c1.GetB())) >> 8) + c1.GetB(), 255));
|
||||
}
|
||||
|
||||
#ifdef SVO_VALUE
|
||||
INITBLOCK {
|
||||
Value::SvoRegister<Color>();
|
||||
}
|
||||
#else
|
||||
INITBLOCK {
|
||||
RichValue<Color>::Register();
|
||||
}
|
||||
#endif
|
||||
|
||||
int Grayscale(const Color& c)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -52,8 +52,13 @@ public:
|
|||
|
||||
Color(const Nuller&) { SetNull(); }
|
||||
|
||||
#ifdef SVO_VALUE
|
||||
operator Value() const { return SvoToValue(*this); }
|
||||
Color(const Value& q) { color = q.Get<Color>().color; }
|
||||
#else
|
||||
operator Value() const { return RichValue<Color>(*this); }
|
||||
Color(const Value& q) { color = RichValue<Color>::Extract(q).color; }
|
||||
#endif
|
||||
|
||||
operator RGBA() const;
|
||||
Color(RGBA rgba);
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ Value StrIntValue(const char *s)
|
|||
int64 q = ScanInt64(s);
|
||||
return IsNull(q) ? ErrorValue(t_("Invalid number !")) : Value(q);
|
||||
}
|
||||
return Null;
|
||||
return (int)Null;
|
||||
}
|
||||
|
||||
Value StrDblValue(const char *s)
|
||||
|
|
@ -209,7 +209,7 @@ Value StrDblValue(const char *s)
|
|||
double q = ScanDouble(s);
|
||||
return IsNull(q) ? ErrorValue(t_("Invalid number !")) : Value(q);
|
||||
}
|
||||
return Null;
|
||||
return (double)Null;
|
||||
}
|
||||
|
||||
Value Scan(dword qtype, const String& text, const Value& def) {
|
||||
|
|
|
|||
|
|
@ -240,7 +240,15 @@ NAMESPACE_UPP
|
|||
#include "Vcont.hpp"
|
||||
#include "Index.hpp"
|
||||
|
||||
#ifdef flagSVO_VALUE
|
||||
#define SVO_VALUE
|
||||
#endif
|
||||
|
||||
#include "OldValue.h"
|
||||
|
||||
#include "Value.h"
|
||||
#include "ValueUtil.h"
|
||||
|
||||
#include "Gtypes.h"
|
||||
#include "Color.h"
|
||||
#include "Complex.h"
|
||||
|
|
|
|||
|
|
@ -97,8 +97,13 @@ file
|
|||
Callback.cpp optimize_speed,
|
||||
TimeDate.h,
|
||||
TimeDate.cpp optimize_speed,
|
||||
OldValue.h,
|
||||
OldValue.cpp optimize_speed,
|
||||
Value.h,
|
||||
Value.cpp optimize_speed,
|
||||
Value.hpp,
|
||||
Value.cpp,
|
||||
ValueUtil.h,
|
||||
ValueUtil.cpp,
|
||||
Complex.h,
|
||||
Format.h,
|
||||
Format.cpp optimize_speed,
|
||||
|
|
|
|||
|
|
@ -317,22 +317,6 @@ extern "C" int COMBINE(i, _length)[]; \
|
|||
extern "C" int COMBINE(i, _count); \
|
||||
extern "C" char *COMBINE(i, _files)[];
|
||||
|
||||
int RegisterTypeNo__(const char *type);
|
||||
|
||||
template <class T>
|
||||
int RegisterTypeNo___()
|
||||
{
|
||||
return RegisterTypeNo__(typeid(T).name());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline int StaticTypeNo() {
|
||||
static int typeno = -1;
|
||||
if(typeno < 0)
|
||||
typeno = RegisterTypeNo___<T>();
|
||||
return typeno;
|
||||
}
|
||||
|
||||
class NoCopy {
|
||||
private:
|
||||
NoCopy(const NoCopy&);
|
||||
|
|
@ -520,6 +504,14 @@ inline void Poke16be(const void *ptr, int val) { ((byte *)ptr)[1] = LOBYTE(
|
|||
inline void Poke32be(const void *ptr, int val) { Poke16be(ptr, HIWORD(val)); Poke16be((byte *)ptr + 2, LOWORD(val)); }
|
||||
inline void Poke64be(const void *ptr, int64 val) { Poke32be(ptr, HIDWORD(val)); Poke32be((byte *)ptr + 4, LODWORD(val)); }
|
||||
|
||||
#ifdef CPU_LITTLE_ENDIAN
|
||||
#define MAKE2B(b0, b1) MAKEWORD(b0, b1);
|
||||
#define MAKE4B(b0, b1, b2, b3) MAKELONG(MAKEWORD(b0, b1), MAKEWORD(b2, b3))
|
||||
#else
|
||||
#define MAKE2B(b0, b1) MAKEWORD(b1, b0);
|
||||
#define MAKE4B(b0, b1, b2, b3) MAKELONG(MAKEWORD(b2, b3), MAKEWORD(b0, b1))
|
||||
#endif
|
||||
|
||||
#if defined(CPU_X86) && (defined(COMPILER_GCC) || defined(COMPILER_MSC))
|
||||
#ifdef COMPILER_GCC
|
||||
#ifdef CPU_64
|
||||
|
|
|
|||
|
|
@ -2,6 +2,29 @@
|
|||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifdef SVO_VALUE
|
||||
template <class T>
|
||||
static void sReg()
|
||||
{
|
||||
if(FitsSvoValue<T>())
|
||||
Value::SvoRegister<T>();
|
||||
else
|
||||
Value::Register<T>();
|
||||
}
|
||||
|
||||
INITBLOCK
|
||||
{
|
||||
sReg<Point>();
|
||||
sReg<Point64>();
|
||||
sReg<Pointf>();
|
||||
sReg<Size>();
|
||||
sReg<Size64>();
|
||||
sReg<Sizef>();
|
||||
Value::Register<Rect>();
|
||||
Value::Register<Rect64>();
|
||||
Value::Register<Rectf>();
|
||||
}
|
||||
#else
|
||||
INITBLOCK {
|
||||
Point p;
|
||||
RichValue<Point>::Register();
|
||||
|
|
@ -14,6 +37,7 @@ INITBLOCK {
|
|||
RichValue<Rect64>::Register();
|
||||
RichValue<Rectf>::Register();
|
||||
}
|
||||
#endif
|
||||
|
||||
//template <>
|
||||
//void Rect_<double>::Union(const Rect_<double>& r) {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ struct Size_ : Moveable< Size_<T> > {
|
|||
friend T Squared(Size_ a) { return a.cx * a.cx + a.cy * a.cy; }
|
||||
friend double Length(Size_ a) { return hypot(a.cx, a.cy); }
|
||||
|
||||
unsigned GetHashValue() const { return UPP::GetHashValue(cx) ^ UPP::GetHashValue(cy); }
|
||||
unsigned GetHashValue() const { return CombineHash(cx, cy); }
|
||||
|
||||
String ToString() const;
|
||||
|
||||
|
|
@ -72,8 +72,13 @@ struct Size_ : Moveable< Size_<T> > {
|
|||
|
||||
Size_(const Nuller&) { cx = cy = Null; }
|
||||
|
||||
#ifdef SVO_VALUE
|
||||
operator Value() const { return FitsSvoValue<Size_>() ? SvoToValue(*this) : RichToValue(*this); }
|
||||
Size_(const Value& src) { *this = src.Get<Size_>(); }
|
||||
#else
|
||||
operator Value() const { return RichValue<Size_>(*this); }
|
||||
Size_(const Value& src) { *this = RichValue<Size_>::Extract(src); }
|
||||
#endif
|
||||
|
||||
void Serialize(Stream& s) { s % cx % cy; }
|
||||
|
||||
|
|
@ -158,7 +163,7 @@ struct Point_ : Moveable< Point_<T> > {
|
|||
|
||||
friend Point_ Nvl(Point_ a, Point_ b) { return IsNull(a) ? b : a; }
|
||||
|
||||
unsigned GetHashValue() const { return UPP::GetHashValue(x) ^ UPP::GetHashValue(y); }
|
||||
unsigned GetHashValue() const { return CombineHash(x, y); }
|
||||
|
||||
String ToString() const;
|
||||
|
||||
|
|
@ -174,8 +179,13 @@ struct Point_ : Moveable< Point_<T> > {
|
|||
|
||||
Point_(const Nuller&) { x = y = Null; }
|
||||
|
||||
#ifdef SVO_VALUE
|
||||
operator Value() const { return FitsSvoValue<Point_>() ? SvoToValue(*this) : RichToValue(*this); }
|
||||
Point_(const Value& src) { *this = src.Get<Point_>(); }
|
||||
#else
|
||||
operator Value() const { return RichValue<Point_>(*this); }
|
||||
/*explicit */Point_(const Value& src) { *this = RichValue<Point_>::Extract(src); }
|
||||
Point_(const Value& src) { *this = RichValue<Point_>::Extract(src); }
|
||||
#endif
|
||||
|
||||
void Serialize(Stream& s) { s % x % y; }
|
||||
|
||||
|
|
@ -336,7 +346,7 @@ struct Rect_ : Moveable< Rect_<T> > {
|
|||
|
||||
friend const Rect_& Nvl(const Rect_& a, const Rect_& b) { return IsNull(a) ? b : a; }
|
||||
|
||||
unsigned GetHashValue() const { return UPP::GetHashValue(left) ^ UPP::GetHashValue(top) ^ UPP::GetHashValue(right) ^ UPP::GetHashValue(bottom); }
|
||||
unsigned GetHashValue() const { return CombineHash(left, top, right, bottom); }
|
||||
|
||||
String ToString() const;
|
||||
|
||||
|
|
|
|||
686
uppsrc/Core/OldValue.cpp
Normal file
686
uppsrc/Core/OldValue.cpp
Normal file
|
|
@ -0,0 +1,686 @@
|
|||
#include "Core.h"
|
||||
|
||||
#ifndef SVO_VALUE
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifndef flagSO
|
||||
const Nuller Null;
|
||||
#endif
|
||||
|
||||
#define LTIMING(x) // RTIMING(x)
|
||||
|
||||
unsigned Value::GetHashValue() const {
|
||||
return IsNull() ? 0 : ptr->GetHashValue();
|
||||
}
|
||||
|
||||
Value& Value::operator=(const Value& v) {
|
||||
if(this == &v) return *this;
|
||||
ptr->Release();
|
||||
ptr = v.ptr;
|
||||
ptr->Retain();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Value::Value(const Value& v) {
|
||||
ptr = v.ptr;
|
||||
ptr->Retain();
|
||||
}
|
||||
|
||||
void Value::SetVoidVal()
|
||||
{
|
||||
ptr = &Single<Void>();
|
||||
ptr->Retain();
|
||||
}
|
||||
|
||||
Value::Value() {
|
||||
SetVoidVal();
|
||||
}
|
||||
|
||||
Value::~Value() {
|
||||
ptr->Release();
|
||||
}
|
||||
|
||||
bool Value::operator==(const Value& v) const {
|
||||
if(ptr == v.ptr) return true;
|
||||
bool an = IsNull();
|
||||
bool bn = v.IsNull();
|
||||
if(an || bn) return an && bn;
|
||||
if(GetType() == v.GetType())
|
||||
return ptr->IsEqual(v.ptr);
|
||||
return ptr->IsPolyEqual(v) || v.ptr->IsPolyEqual(*this);
|
||||
}
|
||||
|
||||
Value::Value(const String& s) { ptr = new RichValueRep<String>(s); }
|
||||
Value::Value(const WString& s) { ptr = new RichValueRep<WString>(s); }
|
||||
Value::Value(const char *s) { ptr = new RichValueRep<String>(s); }
|
||||
Value::Value(int i) { ptr = new RichValueRep<int>(i); }
|
||||
Value::Value(int64 i) { ptr = new RichValueRep<int64>(i); }
|
||||
Value::Value(double d) { ptr = new RichValueRep<double>(d); }
|
||||
Value::Value(bool b) { ptr = new RichValueRep<bool>(b); }
|
||||
Value::Value(Date d) { ptr = new RichValueRep<Date>(d); }
|
||||
Value::Value(Time t) { ptr = new RichValueRep<Time>(t); }
|
||||
Value::Value(const Nuller&) { ptr = new RichValueRep<int>(Null); }
|
||||
|
||||
Value::operator String() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return GetType() == WSTRING_V ? RichValue<WString>::Extract(*this).ToString()
|
||||
: RichValue<String>::Extract(*this);
|
||||
}
|
||||
|
||||
Value::operator WString() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return GetType() == WSTRING_V ? RichValue<WString>::Extract(*this)
|
||||
: RichValue<String>::Extract(*this).ToWString();
|
||||
}
|
||||
|
||||
Value::operator Date() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return GetType() == DATE_V ? RichValue<Date>::Extract(*this)
|
||||
: Date(RichValue<Time>::Extract(*this));
|
||||
}
|
||||
|
||||
Value::operator Time() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return GetType() == DATE_V ? ToTime(RichValue<Date>::Extract(*this))
|
||||
: RichValue<Time>::Extract(*this);
|
||||
}
|
||||
|
||||
Value::operator double() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return GetType() == INT_V ? double(RichValue<int>::Extract(*this))
|
||||
: GetType() == BOOL_V ? double(RichValue<bool>::Extract(*this))
|
||||
: GetType() == INT64_V ? double(RichValue<int64>::Extract(*this))
|
||||
: RichValue<double>::Extract(*this);
|
||||
}
|
||||
|
||||
Value::operator int() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return GetType() == INT_V ? RichValue<int>::Extract(*this)
|
||||
: GetType() == BOOL_V ? int(RichValue<bool>::Extract(*this))
|
||||
: GetType() == INT64_V ? int(RichValue<int64>::Extract(*this))
|
||||
: int(RichValue<double>::Extract(*this));
|
||||
}
|
||||
|
||||
Value::operator int64() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return GetType() == INT_V ? int64(RichValue<int>::Extract(*this))
|
||||
: GetType() == BOOL_V ? int64(RichValue<bool>::Extract(*this))
|
||||
: GetType() == INT64_V ? RichValue<int64>::Extract(*this)
|
||||
: int64(RichValue<double>::Extract(*this));
|
||||
}
|
||||
|
||||
Value::operator bool() const
|
||||
{
|
||||
if(IsNull()) return false;
|
||||
return operator int();
|
||||
}
|
||||
|
||||
VectorMap<dword, Value::Void *(*)(Stream& s)>& Value::Typemap()
|
||||
{
|
||||
static VectorMap<dword, Value::Void *(*)(Stream& s)> x;
|
||||
return x;
|
||||
}
|
||||
|
||||
Value::Void *ValueArrayDataCreate(Stream& s)
|
||||
{
|
||||
ValueArray::Data *a = new ValueArray::Data;
|
||||
a->Serialize(s);
|
||||
return a;
|
||||
}
|
||||
|
||||
Value::Void *ValueMapDataCreate(Stream& s)
|
||||
{
|
||||
ValueMap::Data *a = new ValueMap::Data;
|
||||
a->Serialize(s);
|
||||
return a;
|
||||
}
|
||||
|
||||
static void sRegisterStd()
|
||||
{
|
||||
ONCELOCK {
|
||||
RichValue<int>::Register();
|
||||
RichValue<int64>::Register();
|
||||
RichValue<bool>::Register();
|
||||
RichValue<double>::Register();
|
||||
RichValue<String>::Register();
|
||||
RichValue<WString>::Register();
|
||||
RichValue<Date>::Register();
|
||||
RichValue<Time>::Register();
|
||||
RichValue<Complex>::Register();
|
||||
Value::Register(VALUEARRAY_V, ValueArrayDataCreate);
|
||||
Value::Register(VALUEMAP_V, ValueMapDataCreate);
|
||||
};
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
sRegisterStd();
|
||||
}
|
||||
|
||||
|
||||
void Value::Serialize(Stream& s) {
|
||||
sRegisterStd();
|
||||
dword type;
|
||||
if(s.IsLoading()) {
|
||||
s / type;
|
||||
ptr->Release();
|
||||
typedef Void* (*vp)(Stream& s);
|
||||
vp *cr = Typemap().FindPtr(type);
|
||||
if(cr)
|
||||
ptr = (**cr)(s);
|
||||
else {
|
||||
SetVoidVal();
|
||||
if(type != VOID_V && type != ERROR_V)
|
||||
s.LoadError();
|
||||
}
|
||||
}
|
||||
else {
|
||||
type = GetType();
|
||||
ASSERT_(!type || type == ERROR_V || type == UNKNOWN_V || Typemap().Find(type) >= 0, "Missing RichValueType<" + AsString(type) + ">::Register");
|
||||
s / type;
|
||||
ptr->Serialize(s);
|
||||
}
|
||||
}
|
||||
|
||||
void Value::Register(dword w, Void* (*c)(Stream& s)) init_ {
|
||||
#ifdef flagCHECKINIT
|
||||
RLOG("Register valuetype " << w);
|
||||
#endif
|
||||
AssertST();
|
||||
ASSERT(w != UNKNOWN_V);
|
||||
ASSERT(w < 0x8000000);
|
||||
CHECK(Typemap().GetAdd(w, c) == c);
|
||||
}
|
||||
|
||||
String Value::ToString() const {
|
||||
return ptr->AsString();
|
||||
}
|
||||
|
||||
class ValueErrorCls : public RichValueRep<String> {
|
||||
public:
|
||||
virtual dword GetType() const { return ERROR_V; }
|
||||
virtual bool IsNull() const { return true; }
|
||||
virtual void Serialize(Stream& s) {}
|
||||
virtual String AsString() const { return "<error: \'" + v + "\'>"; }
|
||||
|
||||
ValueErrorCls(const String& s) : RichValueRep<String>(s) {}
|
||||
};
|
||||
|
||||
Value ErrorValue(const String& s) {
|
||||
return Value(new ValueErrorCls(s));
|
||||
}
|
||||
|
||||
Value ErrorValue(const char *s) {
|
||||
return ErrorValue(String(s));
|
||||
}
|
||||
|
||||
const Value& ErrorValue() {
|
||||
static Value *p;
|
||||
ONCELOCK {
|
||||
static Value v = ErrorValue(String());
|
||||
p = &v;
|
||||
}
|
||||
return *p;
|
||||
}
|
||||
|
||||
String GetErrorText(const Value& v) {
|
||||
ASSERT(IsError(v));
|
||||
return ((RichValueRep<String> *)v.GetVoidPtr())->Get();
|
||||
}
|
||||
|
||||
// ----------------------------------
|
||||
|
||||
struct Ref::ValueRef : public RefManager {
|
||||
virtual int GetType() { return VALUE_V; }
|
||||
virtual Value GetValue(const void *ptr) { return *(Value *) ptr; }
|
||||
virtual bool IsNull(const void *ptr) { return UPP::IsNull(*(Value *) ptr); }
|
||||
virtual void SetValue(void *ptr, const Value& v) { *(Value *) ptr = v; }
|
||||
virtual void SetNull(void *ptr) { *(Value *) ptr = Null; }
|
||||
};
|
||||
|
||||
Ref::Ref(String& s) { ptr = &s; m = &Single< RichRef<String> >(); }
|
||||
Ref::Ref(WString& s) { ptr = &s; m = &Single< RichRef<WString> >(); }
|
||||
Ref::Ref(int& i) { ptr = &i; m = &Single< RichRef<int> >(); }
|
||||
Ref::Ref(int64& i) { ptr = &i; m = &Single< RichRef<int64> >(); }
|
||||
Ref::Ref(double& d) { ptr = &d; m = &Single< RichRef<double> >(); }
|
||||
Ref::Ref(bool& b) { ptr = &b; m = &Single< RichRef<bool> >(); }
|
||||
Ref::Ref(Date& d) { ptr = &d; m = &Single< RichRef<Date> >(); }
|
||||
Ref::Ref(Time& t) { ptr = &t; m = &Single< RichRef<Time> >(); }
|
||||
Ref::Ref(Value& v) { ptr = &v; m = &Single< ValueRef >(); }
|
||||
|
||||
// ----------------------------------
|
||||
|
||||
bool ValueArray::Data::IsNull() const
|
||||
{
|
||||
return this == &Single<ValueArray::NullData>();
|
||||
}
|
||||
|
||||
void ValueArray::Data::Serialize(Stream& s)
|
||||
{
|
||||
s % data;
|
||||
}
|
||||
|
||||
unsigned ValueArray::Data::GetHashValue() const
|
||||
{
|
||||
CombineHash w(data.GetCount());
|
||||
for(int i = 0; i < data.GetCount(); i++)
|
||||
w.Put(data[i].GetHashValue());
|
||||
return w;
|
||||
}
|
||||
|
||||
static bool sCmp(const Vector<Value>& a, const Vector<Value>& b)
|
||||
{
|
||||
if(&a == &b) return true;
|
||||
if(a.GetCount() != b.GetCount()) return false;
|
||||
for(int i = 0; i < a.GetCount(); i++)
|
||||
if(a[i] != b[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValueArray::Data::IsEqual(const Value::Void *p)
|
||||
{
|
||||
return sCmp(((Data *)p)->data, data);
|
||||
}
|
||||
|
||||
bool ValueArray::operator==(const ValueArray& v) const
|
||||
{
|
||||
return sCmp(data->data, v.data->data);
|
||||
}
|
||||
|
||||
static String sAsString(const Vector<Value>& v)
|
||||
{
|
||||
String s;
|
||||
s << "[";
|
||||
for(int i = 0; i < v.GetCount(); i++) {
|
||||
if(i) s << ", ";
|
||||
s << v[i];
|
||||
}
|
||||
s << "]";
|
||||
return s;
|
||||
}
|
||||
|
||||
String ValueArray::Data::AsString() const
|
||||
{
|
||||
return sAsString(data);
|
||||
}
|
||||
|
||||
Vector<Value>& ValueArray::Create()
|
||||
{
|
||||
data = new Data;
|
||||
return data->data;
|
||||
}
|
||||
|
||||
Vector<Value>& ValueArray::Clone() {
|
||||
if(data->GetRefCount() != 1) {
|
||||
Data *d = new Data;
|
||||
d->data <<= data->data;
|
||||
data->Release();
|
||||
data = d;
|
||||
}
|
||||
return data->data;
|
||||
}
|
||||
|
||||
void ValueArray::Init0()
|
||||
{
|
||||
data = &Single<NullData>();
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
ValueArray::ValueArray(const ValueArray& v) {
|
||||
data = v.data;
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
ValueArray::ValueArray(pick_ Vector<Value>& v)
|
||||
{
|
||||
Create() = v;
|
||||
}
|
||||
|
||||
ValueArray::ValueArray(const Vector<Value>& v, int deep)
|
||||
{
|
||||
Create() <<= v;
|
||||
}
|
||||
|
||||
ValueArray::operator Value() const {
|
||||
data->Retain();
|
||||
return Value(data);
|
||||
}
|
||||
|
||||
ValueArray::ValueArray(const Value& src)
|
||||
{
|
||||
if(!UPP::IsNull(src)) {
|
||||
if(IsType<ValueMap>(src)) {
|
||||
ValueArray v = ValueMap(src);
|
||||
data = v.data;
|
||||
data->Retain();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ASSERT(dynamic_cast<const ValueArray::Data *>(src.GetVoidPtr()));
|
||||
data = (ValueArray::Data *)src.GetVoidPtr();
|
||||
}
|
||||
}
|
||||
else
|
||||
data = &Single<NullData>();
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
void ValueArray::Serialize(Stream& s) {
|
||||
if(s.IsLoading()) {
|
||||
data->Release();
|
||||
Create();
|
||||
}
|
||||
data->Serialize(s);
|
||||
}
|
||||
|
||||
ValueArray::~ValueArray() {
|
||||
ASSERT(data->GetRefCount() > 0);
|
||||
data->Release();
|
||||
}
|
||||
|
||||
ValueArray& ValueArray::operator=(const ValueArray& v) {
|
||||
v.data->Retain();
|
||||
data->Release();
|
||||
data = v.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ValueArray::SetCount(int n) {
|
||||
Clone().SetCount(n);
|
||||
}
|
||||
|
||||
void ValueArray::SetCount(int n, const Value& v)
|
||||
{
|
||||
Clone().SetCount(n, v);
|
||||
}
|
||||
|
||||
void ValueArray::Clear() {
|
||||
Clone().Clear();
|
||||
}
|
||||
|
||||
void ValueArray::Add(const Value& v) {
|
||||
Clone().Add(v);
|
||||
}
|
||||
|
||||
void ValueArray::Set(int i, const Value& v) {
|
||||
ASSERT(i >= 0);
|
||||
Clone().At(i) = v;
|
||||
}
|
||||
|
||||
void ValueArray::Remove(int i, int count)
|
||||
{
|
||||
Clone().Remove(i, count);
|
||||
}
|
||||
|
||||
void ValueArray::Insert(int i, const ValueArray& va)
|
||||
{
|
||||
if(va.data == data) {
|
||||
ValueArray va2 = va;
|
||||
Clone().Insert(i, va2.Get());
|
||||
}
|
||||
else
|
||||
Clone().Insert(i, va.Get());
|
||||
}
|
||||
|
||||
const Value& ValueArray::Get(int i) const {
|
||||
ASSERT(i >= 0 && i < GetCount());
|
||||
return data->data[i];
|
||||
}
|
||||
|
||||
template<>
|
||||
String AsString(const ValueArray& v) {
|
||||
return sAsString(v.Get());
|
||||
}
|
||||
|
||||
bool ValueMap::Data::IsNull() const {
|
||||
return this == &Single<ValueMap::NullData>();
|
||||
}
|
||||
|
||||
void ValueMap::Data::Serialize(Stream& s) {
|
||||
s % key % value;
|
||||
}
|
||||
|
||||
unsigned ValueMap::Data::GetHashValue() const {
|
||||
CombineHash w(key.GetCount());
|
||||
for(int i = 0; i < key.GetCount(); i++)
|
||||
w.Put(key[i].GetHashValue());
|
||||
w.Put(value.GetHashValue());
|
||||
return w;
|
||||
}
|
||||
|
||||
static bool sIsEqual(const Index<Value>& a, const Index<Value>& b) {
|
||||
if(&a == &b) return true;
|
||||
if(a.GetCount() != b.GetCount()) return false;
|
||||
for(int i = 0; i < a.GetCount(); i++) {
|
||||
if(a[i] != b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValueMap::Data::IsEqual(const Value::Void *p) {
|
||||
return sIsEqual(((Data *)p)->key, key) && ((Data *)p)->value == value;
|
||||
}
|
||||
|
||||
bool ValueMap::operator==(const ValueMap& v) const {
|
||||
return sIsEqual(data->key, v.data->key) && data->value == v.data->value;
|
||||
}
|
||||
|
||||
String ValueMap::Data::AsString() const
|
||||
{
|
||||
String s;
|
||||
s << "{ ";
|
||||
for(int i = 0; i < key.GetCount(); i++) {
|
||||
if(i) s << ", ";
|
||||
s << key[i] << ": " << value[i];
|
||||
}
|
||||
s << " }";
|
||||
return s;
|
||||
}
|
||||
|
||||
ValueMap::Data& ValueMap::Create()
|
||||
{
|
||||
data = new Data;
|
||||
return *data;
|
||||
}
|
||||
|
||||
ValueMap::Data& ValueMap::Clone() {
|
||||
if(data->GetRefCount() != 1) {
|
||||
Data *d = new Data;
|
||||
d->key <<= data->key;
|
||||
d->value = data->value;
|
||||
data->Release();
|
||||
data = d;
|
||||
}
|
||||
return *data;
|
||||
}
|
||||
|
||||
void ValueMap::Init0()
|
||||
{
|
||||
data = &Single<NullData>();
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
ValueMap::ValueMap(const ValueMap& v)
|
||||
{
|
||||
data = v.data;
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
ValueMap::ValueMap(pick_ Index<Value>& k, pick_ Vector<Value>& v)
|
||||
{
|
||||
Data& d = Create();
|
||||
d.key = k;
|
||||
d.value = ValueArray(v);
|
||||
}
|
||||
|
||||
ValueMap::ValueMap(const Index<Value>& k, const Vector<Value>& v, int deep)
|
||||
{
|
||||
Data& d = Create();
|
||||
d.key <<= k;
|
||||
Vector<Value> _v(v, 0);
|
||||
d.value = ValueArray(_v);
|
||||
}
|
||||
|
||||
ValueMap::operator Value() const {
|
||||
data->Retain();
|
||||
return Value(data);
|
||||
}
|
||||
|
||||
ValueMap::ValueMap(const Value& src)
|
||||
{
|
||||
if(!IsNull(src)) {
|
||||
if(IsType<ValueArray>(src)) {
|
||||
ValueArray va = src;
|
||||
Init0();
|
||||
for(int i = 0; i < va.GetCount(); i++)
|
||||
Add(i, va[i]);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ASSERT(dynamic_cast<const ValueMap::Data *>(src.GetVoidPtr()));
|
||||
data = (ValueMap::Data *)src.GetVoidPtr();
|
||||
}
|
||||
}
|
||||
else
|
||||
data = &Single<NullData>();
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
void ValueMap::Serialize(Stream& s) {
|
||||
if(s.IsLoading()) {
|
||||
data->Release();
|
||||
Create();
|
||||
}
|
||||
data->Serialize(s);
|
||||
}
|
||||
|
||||
ValueMap::~ValueMap() {
|
||||
ASSERT(data->GetRefCount() > 0);
|
||||
data->Release();
|
||||
}
|
||||
|
||||
ValueMap& ValueMap::operator=(const ValueMap& v) {
|
||||
v.data->Retain();
|
||||
data->Release();
|
||||
data = v.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ValueMap::Clear() {
|
||||
data->Release();
|
||||
Init0();
|
||||
}
|
||||
|
||||
void ValueMap::Add(const Value& key, const Value& value) {
|
||||
Data& d = Clone();
|
||||
d.key.Add(key);
|
||||
d.value.Add(value);
|
||||
}
|
||||
|
||||
void ValueMap::Set(const Value& key, const Value& value)
|
||||
{
|
||||
Data& d = Clone();
|
||||
int i = d.key.Find(key);
|
||||
if(i >= 0)
|
||||
d.value.Set(i, value);
|
||||
else {
|
||||
d.key.Add(key);
|
||||
d.value.Add(value);
|
||||
}
|
||||
}
|
||||
|
||||
void ValueMap::SetAt(int i, const Value& v) {
|
||||
Clone().value.Set(i, v);
|
||||
}
|
||||
|
||||
void ValueMap::SetKey(int i, const Value& k) {
|
||||
Clone().key.Set(i, k);
|
||||
}
|
||||
|
||||
void ValueMap::Remove(int i)
|
||||
{
|
||||
Data& d = Clone();
|
||||
d.key.Remove(i);
|
||||
d.value.Remove(i);
|
||||
}
|
||||
|
||||
const Value& ValueMap::operator[](const Value& key) const
|
||||
{
|
||||
int q = data->key.Find(key);
|
||||
return q >= 0 ? data->value[q] : ErrorValue();
|
||||
}
|
||||
|
||||
// ----------------------------------
|
||||
|
||||
int StdValueCompare(const Value& a, const Value& b, int language)
|
||||
{
|
||||
LTIMING("StdValueCompare");
|
||||
|
||||
bool na = IsNull(a), nb = IsNull(b);
|
||||
if(na || nb)
|
||||
return !na ? 1 : !nb ? -1 : 0;
|
||||
dword ta = a.GetType(), tb = b.GetType();
|
||||
if((ta == INT_V || ta == BOOL_V) && (tb == INT_V || tb == BOOL_V))
|
||||
return cmp<int>(a, b);
|
||||
if((ta == BOOL_V || ta == INT_V || ta == INT64_V || ta == DOUBLE_V)
|
||||
&& (tb == BOOL_V || tb == INT_V || tb == INT64_V || tb == DOUBLE_V))
|
||||
return cmp<double>(a, b);
|
||||
if(ta == DATE_V && tb == DATE_V)
|
||||
return cmp<Date>(a, b);
|
||||
if((ta == DATE_V || ta == TIME_V) && (tb == DATE_V || tb == TIME_V))
|
||||
return cmp<Time>(a, b);
|
||||
if((ta == STRING_V || ta == WSTRING_V) && (tb == STRING_V || tb == WSTRING_V))
|
||||
return GetLanguageInfo(language).Compare(WString(a), WString(b));
|
||||
return cmp<int>(ta, tb);
|
||||
}
|
||||
|
||||
int StdValueCompare(const Value& a, const Value& b)
|
||||
{
|
||||
return StdValueCompare(a, b, GetCurrentLanguage());
|
||||
}
|
||||
|
||||
int StdValueCompareDesc(const Value& a, const Value& b, int language)
|
||||
{
|
||||
return -StdValueCompare(a, b, language);
|
||||
}
|
||||
|
||||
int StdValueCompareDesc(const Value& a, const Value& b)
|
||||
{
|
||||
return -StdValueCompare(a, b);
|
||||
}
|
||||
|
||||
StdValueOrder::StdValueOrder(int l) : language(l) {}
|
||||
|
||||
bool StdValueOrder::operator()(const Value& a, const Value& b) const
|
||||
{
|
||||
return StdValueCompare(a, b, language) < 0;
|
||||
}
|
||||
|
||||
bool FnValueOrder::operator()(const Value& a, const Value& b) const
|
||||
{
|
||||
return (*fn)(a, b) < 0;
|
||||
}
|
||||
|
||||
bool StdValuePairOrder::operator()(const Value& k1, const Value& v1, const Value& k2, const Value& v2) const
|
||||
{
|
||||
int q = StdValueCompare(k1, k2, language);
|
||||
if(q) return q < 0;
|
||||
return StdValueCompare(v1, v2, language);
|
||||
}
|
||||
|
||||
bool FnValuePairOrder::operator()(const Value& keya, const Value& valuea, const Value& keyb, const Value& valueb) const
|
||||
{
|
||||
return (*fn)(keya, valuea, keyb, valueb) < 0;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
||||
762
uppsrc/Core/OldValue.h
Normal file
762
uppsrc/Core/OldValue.h
Normal file
|
|
@ -0,0 +1,762 @@
|
|||
#ifndef SVO_VALUE
|
||||
class Value;
|
||||
|
||||
class Id : Moveable<Id> {
|
||||
String id;
|
||||
|
||||
public:
|
||||
const String& ToString() const { return id; }
|
||||
dword GetHashValue() const { return UPP::GetHashValue(id); }
|
||||
bool IsNull() const { return UPP::IsNull(id); }
|
||||
|
||||
operator const String&() const { return ToString(); }
|
||||
const String& operator~() const { return ToString(); }
|
||||
bool operator==(const Id& b) const { return id == b.id; }
|
||||
bool operator!=(const Id& b) const { return id != b.id; }
|
||||
|
||||
operator bool() const { return id.GetCount(); }
|
||||
|
||||
Id() {}
|
||||
Id(const String& s) { id = s; }
|
||||
Id(const char *s) { id = s; }
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
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();
|
||||
~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 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; }
|
||||
|
||||
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.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);
|
||||
};
|
||||
|
||||
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)) : fn(fn) {}
|
||||
};
|
||||
|
||||
struct ValuePairOrder {
|
||||
virtual bool operator()(const Value& keya, const Value& valuea, const Value& keyb, const Value& valueb) const = 0;
|
||||
virtual ~ValuePairOrder() {}
|
||||
};
|
||||
|
||||
struct StdValuePairOrder : ValuePairOrder {
|
||||
int language;
|
||||
|
||||
virtual bool operator()(const Value& keya, const Value& valuea, const Value& keyb, const Value& valueb) const;
|
||||
|
||||
StdValuePairOrder(int l = -1);
|
||||
};
|
||||
|
||||
struct FnValuePairOrder : ValuePairOrder {
|
||||
int (*fn)(const Value& k1, const Value& v1, const Value& k2, const Value& v2);
|
||||
|
||||
virtual bool operator()(const Value& keya, const Value& valuea, const Value& keyb, const Value& valueb) const;
|
||||
|
||||
FnValuePairOrder(int (*fn)(const Value& k1, const Value& v1, const Value& k2, const Value& v2)) : fn(fn) {}
|
||||
};
|
||||
|
||||
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>
|
||||
dword GetValueTypeNo() { return ValueTypeNo((T*)NULL); }
|
||||
|
||||
template <class T>
|
||||
bool IsType(const Value& x, T* = 0) { return GetValueTypeNo<T>() == 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 GetValueTypeNo<T>(); }
|
||||
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; SetNull(x);
|
||||
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(GetValueTypeNo<T>(), 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);
|
||||
const 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, const Value& def = Null);
|
||||
|
||||
// ----------------------- 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 GetValueTypeNo<T>(); }
|
||||
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) { UPP::SetNull(*(T *)p); }
|
||||
};
|
||||
|
||||
class Ref : Moveable<Ref> {
|
||||
protected:
|
||||
RefManager *m;
|
||||
void *ptr;
|
||||
struct ValueRef;
|
||||
|
||||
public:
|
||||
dword GetType() const { return m ? m->GetType() : VOID_V; }
|
||||
bool IsNull() const { return m ? m->IsNull(ptr) : true; }
|
||||
|
||||
void *GetVoidPtr() const { return ptr; }
|
||||
|
||||
void SetNull() { if(m) m->SetNull(ptr); }
|
||||
Value GetValue() const { return m ? m->GetValue(ptr) : Value(); }
|
||||
void SetValue(const Value& v) { ASSERT(m); m->SetValue(ptr, v); }
|
||||
|
||||
operator Value() const { return GetValue(); }
|
||||
Value operator~() const { return GetValue(); }
|
||||
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(bool& b);
|
||||
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(GetValueTypeNo<T>() == 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 bool& RefBool(Ref f) { return GetRef<bool>(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();
|
||||
void Init0();
|
||||
|
||||
friend Value::Void *ValueArrayDataCreate(Stream& s);
|
||||
|
||||
public:
|
||||
ValueArray() { Init0(); }
|
||||
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&) { Init0(); }
|
||||
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);
|
||||
ValueArray& operator<<(const Value& v) { Add(v); return *this; }
|
||||
void Set(int i, const Value& v);
|
||||
const Value& Get(int i) const;
|
||||
const Vector<Value>& Get() const { return data->data; }
|
||||
|
||||
void Remove(int i, int count = 1);
|
||||
void Insert(int i, const ValueArray& va);
|
||||
void Append(const ValueArray& va) { Insert(GetCount(), va); }
|
||||
|
||||
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();
|
||||
|
||||
friend Value::Void *ValueMapDataCreate(Stream& s);
|
||||
|
||||
public:
|
||||
ValueMap() { Init0(); }
|
||||
ValueMap(const ValueMap& v);
|
||||
ValueMap(pick_ Index<Value>& k, pick_ Vector<Value>& v);
|
||||
ValueMap(const Index<Value>& k, const Vector<Value>& v, int deep);
|
||||
~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();
|
||||
int GetCount() const { return data->value.GetCount(); }
|
||||
bool IsEmpty() const { return data->value.IsEmpty(); }
|
||||
|
||||
void Add(const Value& key, const Value& value);
|
||||
void Add(const String& s, const Value& value) { Add(Value(s), 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); }
|
||||
|
||||
void Set(const Value& key, const Value& value);
|
||||
void Set(const String& s, const Value& value) { Set(Value(s), value); }
|
||||
void Set(const char *s, const Value& value) { Set(Value(s), value); }
|
||||
void Set(Id id, const Value& value) { Set(Value(id.ToString()), value); }
|
||||
|
||||
void SetAt(int i, const Value& v);
|
||||
void SetKey(int i, const Value& k);
|
||||
void SetKey(int i, const String& s) { SetKey(i, Value(s)); }
|
||||
void SetKey(int i, const char* s) { SetKey(i, Value(s)); }
|
||||
void SetKey(int i, Id id) { SetKey(i, Value(id.ToString())); }
|
||||
void Remove(int i);
|
||||
|
||||
const Index<Value>& GetKeys() const { return data->key; }
|
||||
ValueArray GetValues() const { return data->value; }
|
||||
|
||||
operator ValueArray() const { return GetValues(); }
|
||||
|
||||
const Value& operator[](const Value& k) const;
|
||||
const Value& operator[](const String& s) const{ return operator[](Value(s)); }
|
||||
const Value& operator[](const char *s) const { return operator[](Value(s)); }
|
||||
const 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); }
|
||||
|
||||
inline
|
||||
int Value::GetCount() const
|
||||
{
|
||||
return IsValueArray(*this) ? ValueArray(*this).GetCount() : 0;
|
||||
}
|
||||
|
||||
inline
|
||||
const Value& Value::operator[](int i) const
|
||||
{
|
||||
ASSERT(IsValueArray(*this));
|
||||
return ValueArray(*this)[i];
|
||||
}
|
||||
|
||||
inline
|
||||
const Value& Value::operator[](const String& key) const
|
||||
{
|
||||
return IsValueMap(*this) ? ValueMap(*this)[key] : ErrorValue();
|
||||
}
|
||||
|
||||
inline
|
||||
const Value& Value::operator[](const char *key) const
|
||||
{
|
||||
return IsValueMap(*this) ? ValueMap(*this)[key] : ErrorValue();
|
||||
}
|
||||
|
||||
inline
|
||||
const Value& Value::operator[](const Id& key) const
|
||||
{
|
||||
return IsValueMap(*this) ? ValueMap(*this)[key] : ErrorValue();
|
||||
}
|
||||
|
||||
class ValueGen {
|
||||
public:
|
||||
virtual Value Get() = 0;
|
||||
Value operator++() { return Get(); }
|
||||
virtual ~ValueGen() {}
|
||||
};
|
||||
#endif
|
||||
|
|
@ -8,6 +8,17 @@ T& Single() {
|
|||
return *p;
|
||||
}
|
||||
|
||||
int RegisterTypeNo__(const char *type);
|
||||
|
||||
template <class T>
|
||||
int StaticTypeNo() {
|
||||
static int typeno;
|
||||
ONCELOCK {
|
||||
typeno = RegisterTypeNo__(typeid(T).name());
|
||||
}
|
||||
return typeno;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class One : MoveableAndDeepCopyOption< One<T> > {
|
||||
mutable T *ptr;
|
||||
|
|
|
|||
|
|
@ -144,13 +144,8 @@ public:
|
|||
};
|
||||
|
||||
class String0 : Moveable<String0> {
|
||||
enum { SMALL, MEDIUM = 31 };
|
||||
enum { KIND = 14, SLEN = 15, LLEN = 2 };
|
||||
|
||||
#if defined(_DEBUG) && defined(COMPILER_GCC)
|
||||
int len;
|
||||
const char *s;
|
||||
#endif
|
||||
enum { SMALL = 0, MEDIUM = 31 }; // SMALL has to be 0 because of GetSpecial and because is it ending zero
|
||||
enum { KIND = 14, SLEN = 15, LLEN = 2, SPECIAL = 13 };
|
||||
|
||||
struct Rc {
|
||||
Atomic refcount;
|
||||
|
|
@ -171,6 +166,12 @@ class String0 : Moveable<String0> {
|
|||
qword q[2];
|
||||
};
|
||||
|
||||
|
||||
#if defined(_DEBUG) && defined(COMPILER_GCC)
|
||||
int len;
|
||||
const char *s;
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
void Dsyn();
|
||||
#else
|
||||
|
|
@ -205,23 +206,31 @@ class String0 : Moveable<String0> {
|
|||
|
||||
static String0::Rc voidptr[2];
|
||||
|
||||
void Swap(String0& b) { UPP::Swap(q[0], b.q[0]); UPP::Swap(q[1], b.q[1]); Dsyn(); b.Dsyn(); }
|
||||
|
||||
void Swap(String0& b) { UPP::Swap(q[0], b.q[0]); UPP::Swap(q[1], b.q[1]); Dsyn(); b.Dsyn(); }
|
||||
|
||||
void SetSpecial0(byte st) { w[3] = MAKE4B(0, st, 0, 0); }
|
||||
void SetSpecial(byte st) { ASSERT(IsSmall() && GetCount() == 0); SetSpecial0(st); }
|
||||
byte GetSpecial() const { return (chr[SLEN] | chr[KIND]) == 0 ? chr[SPECIAL] : 0; }
|
||||
byte GetSt() const { return chr[SPECIAL]; }
|
||||
bool IsSpecial() const { return !v[7] && v[6]; }
|
||||
bool IsSpecial(byte st) const { return w[3] == MAKE4B(0, st, 0, 0); }
|
||||
|
||||
friend class String;
|
||||
friend class StringBuffer;
|
||||
friend class Value;
|
||||
|
||||
protected:
|
||||
void Zero() { q[0] = q[1] = 0; Dsyn(); }
|
||||
void Free() { if(IsLarge()) LFree(); }
|
||||
void Zero() { q[0] = q[1] = 0; Dsyn(); }
|
||||
void Free() { if(IsLarge()) LFree(); }
|
||||
void SetSmall(const String0& s) { q[0] = s.q[0]; q[1] = s.q[1]; }
|
||||
void Set(const String0& s) {
|
||||
if(s.IsSmall()) { q[0] = s.q[0]; q[1] = s.q[1]; }
|
||||
else LSet(s);
|
||||
if(s.IsSmall()) SetSmall(s); else LSet(s);
|
||||
Dsyn();
|
||||
}
|
||||
void Assign(const String0& s) {
|
||||
if(s.IsSmall()) {
|
||||
if(IsLarge()) LFree();
|
||||
q[0] = s.q[0]; q[1] = s.q[1];
|
||||
Free();
|
||||
SetSmall(s);
|
||||
}
|
||||
else
|
||||
if(this != &s) {
|
||||
|
|
@ -288,8 +297,8 @@ public:
|
|||
|
||||
String0& operator=(const String0& s) { Free(); Set(s); return *this; }
|
||||
|
||||
String0() { Zero(); }
|
||||
~String0() { Free(); }
|
||||
String0() {}
|
||||
~String0() { Free(); }
|
||||
};
|
||||
|
||||
class String : public Moveable<String, AString<String0> > {
|
||||
|
|
@ -304,7 +313,18 @@ class String : public Moveable<String, AString<String0> > {
|
|||
#endif
|
||||
|
||||
void AssignLen(const char *s, int slen);
|
||||
|
||||
enum SSPECIAL { SPECIAL };
|
||||
|
||||
template <class T>
|
||||
String(const T& x, byte st, SSPECIAL) {
|
||||
*(T*)chr = x;
|
||||
SetSpecial0(st);
|
||||
}
|
||||
String(SSPECIAL) {}
|
||||
|
||||
friend class Value;
|
||||
|
||||
public:
|
||||
const String& operator+=(char c) { Cat(c); return *this; }
|
||||
const String& operator+=(const char *s) { Cat(s); return *this; }
|
||||
|
|
@ -318,8 +338,8 @@ public:
|
|||
void Shrink() { *this = String(Begin(), GetLength()); }
|
||||
int GetCharCount() const;
|
||||
|
||||
String() {}
|
||||
String(const Nuller&) {}
|
||||
String() { Zero(); }
|
||||
String(const Nuller&) { Zero(); }
|
||||
String(const String& s) { String0::Set(s); }
|
||||
String(const char *s);
|
||||
String(const String& s, int n) { ASSERT(n >= 0 && n <= s.GetLength()); String0::Set(~s, n); }
|
||||
|
|
@ -488,7 +508,7 @@ template<>
|
|||
inline String AsString(const String& s) { return s; }
|
||||
|
||||
template<>
|
||||
inline unsigned GetHashValue(const String& s) { return memhash(~s, s.GetLength()); }
|
||||
inline unsigned GetHashValue(const String& s) { return s.GetHashValue(); }
|
||||
|
||||
int CompareNoCase(const String& a, const String& b, byte encoding = 0);
|
||||
int CompareNoCase(const String& a, const char *b, byte encoding = 0);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ inline bool operator==(Date a, Date b) {
|
|||
return a.day == b.day && a.month == b.month && a.year == b.year;
|
||||
}
|
||||
|
||||
template<> inline bool IsNull(const Date& d) { return d.year == -32768; }
|
||||
|
||||
bool operator<(Date a, Date b);
|
||||
|
||||
int operator-(Date a, Date b);
|
||||
|
|
@ -113,6 +115,8 @@ inline unsigned GetHashValue(Time t) {
|
|||
32 * (t.minute + 32 * (t.hour + 16 * (t.day + 32 * (t.month + 8 * t.year))));
|
||||
}
|
||||
|
||||
template<> inline bool IsNull(const Time& t) { return t.year == -32768; }
|
||||
|
||||
bool operator==(Time a, Time b);
|
||||
bool operator<(Time a, Time b);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,15 @@ NAMESPACE_UPP
|
|||
|
||||
//#BLITZ_APPROVE
|
||||
|
||||
#ifdef SVO_VALUE
|
||||
INITBLOCK {
|
||||
Value::Register<Uuid>();
|
||||
}
|
||||
#else
|
||||
INITBLOCK {
|
||||
RichValue<Uuid>::Register();
|
||||
}
|
||||
#endif
|
||||
|
||||
void Uuid::Serialize(Stream& s) {
|
||||
int version = 0;
|
||||
|
|
|
|||
|
|
@ -5,8 +5,13 @@ struct Uuid : AssignValueTypeNo<Uuid, 50, Moveable<Uuid> > {
|
|||
bool IsNullInstance() const { return a == 0 && b == 0 && c == 0 && d == 0; }
|
||||
void SetNull() { a = b = c = d = 0; }
|
||||
|
||||
#ifdef SVO_VALUE
|
||||
operator Value() const { return RichToValue(*this); }
|
||||
Uuid(const Value& q) { *this = q.Get<Uuid>(); }
|
||||
#else
|
||||
operator Value() const { return RichValue<Uuid>(*this); }
|
||||
Uuid(const Value& q) { *this = RichValue<Uuid>::Extract(q); }
|
||||
#endif
|
||||
Uuid(const Nuller&) { SetNull(); }
|
||||
Uuid() {}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#include "Core.h"
|
||||
|
||||
#ifdef SVO_VALUE
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifndef flagSO
|
||||
|
|
@ -8,117 +10,145 @@ const Nuller Null;
|
|||
|
||||
#define LTIMING(x) // RTIMING(x)
|
||||
|
||||
unsigned Value::GetHashValue() const {
|
||||
return IsNull() ? 0 : ptr->GetHashValue();
|
||||
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;
|
||||
ptr->Release();
|
||||
ptr = v.ptr;
|
||||
ptr->Retain();
|
||||
Free();
|
||||
data = v.data;
|
||||
if(IsRef())
|
||||
ptr()->Retain();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Value::Value(const Value& v) {
|
||||
ptr = v.ptr;
|
||||
ptr->Retain();
|
||||
}
|
||||
|
||||
void Value::SetVoidVal()
|
||||
void Value::SetLarge(const Value& v)
|
||||
{
|
||||
ptr = &Single<Void>();
|
||||
ptr->Retain();
|
||||
if(v.IsRef()) {
|
||||
data.SetSmall(v.data);
|
||||
RefRetain();
|
||||
}
|
||||
else
|
||||
data.LSet(v.data);
|
||||
}
|
||||
|
||||
Value::Value() {
|
||||
SetVoidVal();
|
||||
dword Value::GetType() const
|
||||
{
|
||||
if(IsString())
|
||||
return STRING_V;
|
||||
byte st = data.GetSt();
|
||||
return st == REF ? ptr()->GetType() : st == VOIDV ? VOID_V : st;
|
||||
}
|
||||
|
||||
Value::~Value() {
|
||||
ptr->Release();
|
||||
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(ptr == v.ptr) return true;
|
||||
bool an = IsNull();
|
||||
bool bn = v.IsNull();
|
||||
if(an || bn) return an && bn;
|
||||
if(GetType() == v.GetType())
|
||||
return ptr->IsEqual(v.ptr);
|
||||
return ptr->IsPolyEqual(v) || v.ptr->IsPolyEqual(*this);
|
||||
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);
|
||||
}
|
||||
|
||||
Value::Value(const String& s) { ptr = new RichValueRep<String>(s); }
|
||||
Value::Value(const WString& s) { ptr = new RichValueRep<WString>(s); }
|
||||
Value::Value(const char *s) { ptr = new RichValueRep<String>(s); }
|
||||
Value::Value(int i) { ptr = new RichValueRep<int>(i); }
|
||||
Value::Value(int64 i) { ptr = new RichValueRep<int64>(i); }
|
||||
Value::Value(double d) { ptr = new RichValueRep<double>(d); }
|
||||
Value::Value(bool b) { ptr = new RichValueRep<bool>(b); }
|
||||
Value::Value(Date d) { ptr = new RichValueRep<Date>(d); }
|
||||
Value::Value(Time t) { ptr = new RichValueRep<Time>(t); }
|
||||
Value::Value(const Nuller&) { ptr = new RichValueRep<int>(Null); }
|
||||
|
||||
Value::operator String() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return GetType() == WSTRING_V ? RichValue<WString>::Extract(*this).ToString()
|
||||
: RichValue<String>::Extract(*this);
|
||||
}
|
||||
Value::Value(const WString& s) { InitRef(new RichValueRep<WString>(s)); }
|
||||
|
||||
Value::operator WString() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return GetType() == WSTRING_V ? RichValue<WString>::Extract(*this)
|
||||
: RichValue<String>::Extract(*this).ToWString();
|
||||
: ((String)(*this)).ToWString();//!!!
|
||||
}
|
||||
|
||||
Value::operator Date() const
|
||||
Date Value::GetOtherDate() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return GetType() == DATE_V ? RichValue<Date>::Extract(*this)
|
||||
: Date(RichValue<Time>::Extract(*this));
|
||||
return GetSmall<Time>();
|
||||
}
|
||||
|
||||
Value::operator Time() const
|
||||
Time Value::GetOtherTime() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return GetType() == DATE_V ? ToTime(RichValue<Date>::Extract(*this))
|
||||
: RichValue<Time>::Extract(*this);
|
||||
return ToTime(GetSmall<Date>());
|
||||
}
|
||||
|
||||
Value::operator double() const
|
||||
String Value::GetOtherString() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return GetType() == INT_V ? double(RichValue<int>::Extract(*this))
|
||||
: GetType() == BOOL_V ? double(RichValue<bool>::Extract(*this))
|
||||
: GetType() == INT64_V ? double(RichValue<int64>::Extract(*this))
|
||||
: RichValue<double>::Extract(*this);
|
||||
return RichValue<WString>::Extract(*this).ToString();
|
||||
}
|
||||
|
||||
Value::operator int() const
|
||||
int Value::GetOtherInt() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return GetType() == INT_V ? RichValue<int>::Extract(*this)
|
||||
: GetType() == BOOL_V ? int(RichValue<bool>::Extract(*this))
|
||||
: GetType() == INT64_V ? int(RichValue<int64>::Extract(*this))
|
||||
: int(RichValue<double>::Extract(*this));
|
||||
return data.IsSpecial(BOOL_V) ? (int)GetSmall<bool>() :
|
||||
data.IsSpecial(INT64_V) ? (int)GetSmall<int64>() :
|
||||
(int)GetSmall<double>();
|
||||
}
|
||||
|
||||
Value::operator int64() const
|
||||
int64 Value::GetOtherInt64() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return GetType() == INT_V ? int64(RichValue<int>::Extract(*this))
|
||||
: GetType() == BOOL_V ? int64(RichValue<bool>::Extract(*this))
|
||||
: GetType() == INT64_V ? RichValue<int64>::Extract(*this)
|
||||
: int64(RichValue<double>::Extract(*this));
|
||||
return data.IsSpecial(BOOL_V) ? (int64)GetSmall<bool>() :
|
||||
data.IsSpecial(INT_V) ? (int64)GetSmall<int>() :
|
||||
(int64)GetSmall<double>();
|
||||
}
|
||||
|
||||
Value::operator bool() const
|
||||
double Value::GetOtherDouble() const
|
||||
{
|
||||
if(IsNull()) return false;
|
||||
return operator int();
|
||||
if(IsNull()) return Null;
|
||||
return data.IsSpecial(BOOL_V) ? (double)GetSmall<bool>() :
|
||||
data.IsSpecial(INT_V) ? (double)GetSmall<int>() :
|
||||
(double)GetSmall<int64>();
|
||||
}
|
||||
|
||||
bool Value::GetOtherBool() const
|
||||
{
|
||||
if(IsNull()) return Null;
|
||||
return data.IsSpecial(DOUBLE_V) ? (bool)GetSmall<double>() :
|
||||
data.IsSpecial(INT_V) ? (bool)GetSmall<int>() :
|
||||
(bool)GetSmall<int64>();
|
||||
}
|
||||
|
||||
VectorMap<dword, Value::Void *(*)(Stream& s)>& Value::Typemap()
|
||||
|
|
@ -127,6 +157,51 @@ VectorMap<dword, Value::Void *(*)(Stream& s)>& Value::Typemap()
|
|||
return x;
|
||||
}
|
||||
|
||||
SVO_FN(s_String, String);
|
||||
SVO_FN(s_int, int);
|
||||
SVO_FN(s_double, double);
|
||||
SVO_FN(s_int64, int64);
|
||||
SVO_FN(s_bool, bool);
|
||||
SVO_FN(s_date, Date);
|
||||
SVO_FN(s_time, Time);
|
||||
|
||||
struct SvoVoidFn {
|
||||
static bool IsNull(const void *p) { return true; }
|
||||
static void Serialize(void *p, Stream& s) {}
|
||||
static unsigned GetHashValue(const void *p) { return 0; }
|
||||
static bool IsEqual(const void *p1, const void *p2) { return true; }
|
||||
static bool IsPolyEqual(const void *p, const Value& v) { return false; }
|
||||
static String AsString(const void *p) { return String(); }
|
||||
};
|
||||
|
||||
static Value::Sval s_void = { \
|
||||
SvoVoidFn::IsNull, SvoVoidFn::Serialize, SvoVoidFn::GetHashValue, SvoVoidFn::IsEqual,
|
||||
SvoVoidFn::IsPolyEqual, SvoVoidFn::AsString
|
||||
};
|
||||
|
||||
Value::Sval *Value::svo[256] = {
|
||||
&s_String, // STRING_V
|
||||
&s_int, // INT_V
|
||||
|
||||
&s_double, //DOUBLE_V = 2;
|
||||
&s_void, //VOIDV_V = 3;
|
||||
&s_date, //DATE_V = 4;
|
||||
&s_time, //TIME_V = 5;
|
||||
|
||||
NULL, //ERROR_V = 6;
|
||||
|
||||
NULL, //VALUE_V = 7;
|
||||
|
||||
NULL, //WSTRING_V = 8;
|
||||
|
||||
NULL, //VALUEARRAY_V = 9;
|
||||
|
||||
&s_int64, //INT64_V = 10;
|
||||
&s_bool, //BOOL_V = 11;
|
||||
|
||||
NULL, //VALUEMAP_V = 12;
|
||||
};
|
||||
|
||||
Value::Void *ValueArrayDataCreate(Stream& s)
|
||||
{
|
||||
ValueArray::Data *a = new ValueArray::Data;
|
||||
|
|
@ -144,14 +219,7 @@ Value::Void *ValueMapDataCreate(Stream& s)
|
|||
static void sRegisterStd()
|
||||
{
|
||||
ONCELOCK {
|
||||
RichValue<int>::Register();
|
||||
RichValue<int64>::Register();
|
||||
RichValue<bool>::Register();
|
||||
RichValue<double>::Register();
|
||||
RichValue<String>::Register();
|
||||
RichValue<WString>::Register();
|
||||
RichValue<Date>::Register();
|
||||
RichValue<Time>::Register();
|
||||
RichValue<Complex>::Register();
|
||||
Value::Register(VALUEARRAY_V, ValueArrayDataCreate);
|
||||
Value::Register(VALUEMAP_V, ValueMapDataCreate);
|
||||
|
|
@ -162,28 +230,49 @@ INITBLOCK {
|
|||
sRegisterStd();
|
||||
}
|
||||
|
||||
|
||||
void Value::Serialize(Stream& s) {
|
||||
sRegisterStd();
|
||||
dword type;
|
||||
if(s.IsLoading()) {
|
||||
s / type;
|
||||
ptr->Release();
|
||||
typedef Void* (*vp)(Stream& s);
|
||||
vp *cr = Typemap().FindPtr(type);
|
||||
if(cr)
|
||||
ptr = (**cr)(s);
|
||||
Free();
|
||||
int st = type == VOID_V ? VOIDV : type == STRING_V ? STRING : type;
|
||||
if(st == STRING)
|
||||
s % data;
|
||||
else
|
||||
if(st < 255 && svo[st]) {
|
||||
data.SetSpecial((byte)type);
|
||||
svo[st]->Serialize(&data, s);
|
||||
}
|
||||
else {
|
||||
SetVoidVal();
|
||||
if(type != VOID_V && type != ERROR_V)
|
||||
s.LoadError();
|
||||
typedef Void* (*vp)(Stream& s);
|
||||
vp *cr = Typemap().FindPtr(type);
|
||||
if(cr)
|
||||
InitRef((**cr)(s));
|
||||
else {
|
||||
Free();
|
||||
data.SetSpecial(3);
|
||||
if(type != VOID_V && type != ERROR_V)
|
||||
s.LoadError();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
type = GetType();
|
||||
ASSERT_(!type || type == ERROR_V || type == UNKNOWN_V || Typemap().Find(type) >= 0, "Missing RichValueType<" + AsString(type) + ">::Register");
|
||||
s / type;
|
||||
ptr->Serialize(s);
|
||||
int st = data.GetSpecial();
|
||||
ASSERT_(!type || type == ERROR_V || type == UNKNOWN_V || st == STRING ||
|
||||
(IsRef() ? Typemap().Find(type) >= 0 : st < 255 && svo[st]),
|
||||
AsString(type) + " is not registred for serialization");
|
||||
if(st == VOIDV)
|
||||
return;
|
||||
if(st == STRING)
|
||||
s % data;
|
||||
else
|
||||
if(IsRef())
|
||||
ptr()->Serialize(s);
|
||||
else
|
||||
svo[st]->Serialize(&data, s);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -198,7 +287,64 @@ void Value::Register(dword w, Void* (*c)(Stream& s)) init_ {
|
|||
}
|
||||
|
||||
String Value::ToString() const {
|
||||
return ptr->AsString();
|
||||
if(IsNull())
|
||||
return Null;
|
||||
if(IsString())
|
||||
return data;
|
||||
if(IsRef())
|
||||
return ptr()->AsString();
|
||||
int st = data.GetSpecial();
|
||||
return svo[st]->AsString(&data);
|
||||
}
|
||||
|
||||
int Value::GetCount() const
|
||||
{
|
||||
if(IsRef()) {
|
||||
dword t = ptr()->GetType();
|
||||
if(t == VALUEARRAY_V)
|
||||
return ((ValueArray::Data *)ptr())->data.GetCount();
|
||||
if(t == VALUEMAP_V)
|
||||
return ((ValueMap::Data *)ptr())->value.GetCount();
|
||||
}
|
||||
return ErrorValue();
|
||||
}
|
||||
|
||||
const Value& Value::operator[](int i) const
|
||||
{
|
||||
if(IsRef()) {
|
||||
dword t = ptr()->GetType();
|
||||
if(t == VALUEARRAY_V)
|
||||
return ((ValueArray::Data *)ptr())->data[i];
|
||||
if(t == VALUEMAP_V)
|
||||
return ((ValueMap::Data *)ptr())->value[i];
|
||||
}
|
||||
return ErrorValue();
|
||||
}
|
||||
|
||||
const Value& Value::operator[](const String& key) const
|
||||
{
|
||||
if(IsRef() && ptr()->GetType() == VALUEMAP_V)
|
||||
return ((ValueMap::Data *)ptr())->Get(key);
|
||||
return ErrorValue();
|
||||
}
|
||||
|
||||
String Value::GetName() const
|
||||
{
|
||||
if(IsRef())
|
||||
return typeid(*ptr()).name();
|
||||
if(IsString())
|
||||
return "String";
|
||||
static Tuple2<byte, const char *> tp[] = {
|
||||
{ INT_V, "int" },
|
||||
{ DOUBLE_V, "double" },
|
||||
{ VOIDV, "void" },
|
||||
{ DATE_V, "Date" },
|
||||
{ TIME_V, "Time" },
|
||||
{ INT64_V, "int64" },
|
||||
{ BOOL_V, "bool" },
|
||||
};
|
||||
Tuple2<byte, const char *> *x = FindTuple(tp, __countof(tp), data.GetSpecial());
|
||||
return x ? String(x->b) : AsString(GetType());
|
||||
}
|
||||
|
||||
class ValueErrorCls : public RichValueRep<String> {
|
||||
|
|
@ -233,449 +379,6 @@ String GetErrorText(const Value& v) {
|
|||
return ((RichValueRep<String> *)v.GetVoidPtr())->Get();
|
||||
}
|
||||
|
||||
// ----------------------------------
|
||||
|
||||
struct Ref::ValueRef : public RefManager {
|
||||
virtual int GetType() { return VALUE_V; }
|
||||
virtual Value GetValue(const void *ptr) { return *(Value *) ptr; }
|
||||
virtual bool IsNull(const void *ptr) { return UPP::IsNull(*(Value *) ptr); }
|
||||
virtual void SetValue(void *ptr, const Value& v) { *(Value *) ptr = v; }
|
||||
virtual void SetNull(void *ptr) { *(Value *) ptr = Null; }
|
||||
};
|
||||
|
||||
Ref::Ref(String& s) { ptr = &s; m = &Single< RichRef<String> >(); }
|
||||
Ref::Ref(WString& s) { ptr = &s; m = &Single< RichRef<WString> >(); }
|
||||
Ref::Ref(int& i) { ptr = &i; m = &Single< RichRef<int> >(); }
|
||||
Ref::Ref(int64& i) { ptr = &i; m = &Single< RichRef<int64> >(); }
|
||||
Ref::Ref(double& d) { ptr = &d; m = &Single< RichRef<double> >(); }
|
||||
Ref::Ref(bool& b) { ptr = &b; m = &Single< RichRef<bool> >(); }
|
||||
Ref::Ref(Date& d) { ptr = &d; m = &Single< RichRef<Date> >(); }
|
||||
Ref::Ref(Time& t) { ptr = &t; m = &Single< RichRef<Time> >(); }
|
||||
Ref::Ref(Value& v) { ptr = &v; m = &Single< ValueRef >(); }
|
||||
|
||||
// ----------------------------------
|
||||
|
||||
bool ValueArray::Data::IsNull() const
|
||||
{
|
||||
return this == &Single<ValueArray::NullData>();
|
||||
}
|
||||
|
||||
void ValueArray::Data::Serialize(Stream& s)
|
||||
{
|
||||
s % data;
|
||||
}
|
||||
|
||||
unsigned ValueArray::Data::GetHashValue() const
|
||||
{
|
||||
CombineHash w(data.GetCount());
|
||||
for(int i = 0; i < data.GetCount(); i++)
|
||||
w.Put(data[i].GetHashValue());
|
||||
return w;
|
||||
}
|
||||
|
||||
static bool sCmp(const Vector<Value>& a, const Vector<Value>& b)
|
||||
{
|
||||
if(&a == &b) return true;
|
||||
if(a.GetCount() != b.GetCount()) return false;
|
||||
for(int i = 0; i < a.GetCount(); i++)
|
||||
if(a[i] != b[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValueArray::Data::IsEqual(const Value::Void *p)
|
||||
{
|
||||
return sCmp(((Data *)p)->data, data);
|
||||
}
|
||||
|
||||
bool ValueArray::operator==(const ValueArray& v) const
|
||||
{
|
||||
return sCmp(data->data, v.data->data);
|
||||
}
|
||||
|
||||
static String sAsString(const Vector<Value>& v)
|
||||
{
|
||||
String s;
|
||||
s << "[";
|
||||
for(int i = 0; i < v.GetCount(); i++) {
|
||||
if(i) s << ", ";
|
||||
s << v[i];
|
||||
}
|
||||
s << "]";
|
||||
return s;
|
||||
}
|
||||
|
||||
String ValueArray::Data::AsString() const
|
||||
{
|
||||
return sAsString(data);
|
||||
}
|
||||
|
||||
Vector<Value>& ValueArray::Create()
|
||||
{
|
||||
data = new Data;
|
||||
return data->data;
|
||||
}
|
||||
|
||||
Vector<Value>& ValueArray::Clone() {
|
||||
if(data->GetRefCount() != 1) {
|
||||
Data *d = new Data;
|
||||
d->data <<= data->data;
|
||||
data->Release();
|
||||
data = d;
|
||||
}
|
||||
return data->data;
|
||||
}
|
||||
|
||||
void ValueArray::Init0()
|
||||
{
|
||||
data = &Single<NullData>();
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
ValueArray::ValueArray(const ValueArray& v) {
|
||||
data = v.data;
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
ValueArray::ValueArray(pick_ Vector<Value>& v)
|
||||
{
|
||||
Create() = v;
|
||||
}
|
||||
|
||||
ValueArray::ValueArray(const Vector<Value>& v, int deep)
|
||||
{
|
||||
Create() <<= v;
|
||||
}
|
||||
|
||||
ValueArray::operator Value() const {
|
||||
data->Retain();
|
||||
return Value(data);
|
||||
}
|
||||
|
||||
ValueArray::ValueArray(const Value& src)
|
||||
{
|
||||
if(!UPP::IsNull(src)) {
|
||||
if(IsType<ValueMap>(src)) {
|
||||
ValueArray v = ValueMap(src);
|
||||
data = v.data;
|
||||
data->Retain();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ASSERT(dynamic_cast<const ValueArray::Data *>(src.GetVoidPtr()));
|
||||
data = (ValueArray::Data *)src.GetVoidPtr();
|
||||
}
|
||||
}
|
||||
else
|
||||
data = &Single<NullData>();
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
void ValueArray::Serialize(Stream& s) {
|
||||
if(s.IsLoading()) {
|
||||
data->Release();
|
||||
Create();
|
||||
}
|
||||
data->Serialize(s);
|
||||
}
|
||||
|
||||
ValueArray::~ValueArray() {
|
||||
ASSERT(data->GetRefCount() > 0);
|
||||
data->Release();
|
||||
}
|
||||
|
||||
ValueArray& ValueArray::operator=(const ValueArray& v) {
|
||||
v.data->Retain();
|
||||
data->Release();
|
||||
data = v.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ValueArray::SetCount(int n) {
|
||||
Clone().SetCount(n);
|
||||
}
|
||||
|
||||
void ValueArray::SetCount(int n, const Value& v)
|
||||
{
|
||||
Clone().SetCount(n, v);
|
||||
}
|
||||
|
||||
void ValueArray::Clear() {
|
||||
Clone().Clear();
|
||||
}
|
||||
|
||||
void ValueArray::Add(const Value& v) {
|
||||
Clone().Add(v);
|
||||
}
|
||||
|
||||
void ValueArray::Set(int i, const Value& v) {
|
||||
ASSERT(i >= 0);
|
||||
Clone().At(i) = v;
|
||||
}
|
||||
|
||||
void ValueArray::Remove(int i, int count)
|
||||
{
|
||||
Clone().Remove(i, count);
|
||||
}
|
||||
|
||||
void ValueArray::Insert(int i, const ValueArray& va)
|
||||
{
|
||||
if(va.data == data) {
|
||||
ValueArray va2 = va;
|
||||
Clone().Insert(i, va2.Get());
|
||||
}
|
||||
else
|
||||
Clone().Insert(i, va.Get());
|
||||
}
|
||||
|
||||
const Value& ValueArray::Get(int i) const {
|
||||
ASSERT(i >= 0 && i < GetCount());
|
||||
return data->data[i];
|
||||
}
|
||||
|
||||
template<>
|
||||
String AsString(const ValueArray& v) {
|
||||
return sAsString(v.Get());
|
||||
}
|
||||
|
||||
bool ValueMap::Data::IsNull() const {
|
||||
return this == &Single<ValueMap::NullData>();
|
||||
}
|
||||
|
||||
void ValueMap::Data::Serialize(Stream& s) {
|
||||
s % key % value;
|
||||
}
|
||||
|
||||
unsigned ValueMap::Data::GetHashValue() const {
|
||||
CombineHash w(key.GetCount());
|
||||
for(int i = 0; i < key.GetCount(); i++)
|
||||
w.Put(key[i].GetHashValue());
|
||||
w.Put(value.GetHashValue());
|
||||
return w;
|
||||
}
|
||||
|
||||
static bool sIsEqual(const Index<Value>& a, const Index<Value>& b) {
|
||||
if(&a == &b) return true;
|
||||
if(a.GetCount() != b.GetCount()) return false;
|
||||
for(int i = 0; i < a.GetCount(); i++) {
|
||||
if(a[i] != b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValueMap::Data::IsEqual(const Value::Void *p) {
|
||||
return sIsEqual(((Data *)p)->key, key) && ((Data *)p)->value == value;
|
||||
}
|
||||
|
||||
bool ValueMap::operator==(const ValueMap& v) const {
|
||||
return sIsEqual(data->key, v.data->key) && data->value == v.data->value;
|
||||
}
|
||||
|
||||
String ValueMap::Data::AsString() const
|
||||
{
|
||||
String s;
|
||||
s << "{ ";
|
||||
for(int i = 0; i < key.GetCount(); i++) {
|
||||
if(i) s << ", ";
|
||||
s << key[i] << ": " << value[i];
|
||||
}
|
||||
s << " }";
|
||||
return s;
|
||||
}
|
||||
|
||||
ValueMap::Data& ValueMap::Create()
|
||||
{
|
||||
data = new Data;
|
||||
return *data;
|
||||
}
|
||||
|
||||
ValueMap::Data& ValueMap::Clone() {
|
||||
if(data->GetRefCount() != 1) {
|
||||
Data *d = new Data;
|
||||
d->key <<= data->key;
|
||||
d->value = data->value;
|
||||
data->Release();
|
||||
data = d;
|
||||
}
|
||||
return *data;
|
||||
}
|
||||
|
||||
void ValueMap::Init0()
|
||||
{
|
||||
data = &Single<NullData>();
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
ValueMap::ValueMap(const ValueMap& v)
|
||||
{
|
||||
data = v.data;
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
ValueMap::ValueMap(pick_ Index<Value>& k, pick_ Vector<Value>& v)
|
||||
{
|
||||
Data& d = Create();
|
||||
d.key = k;
|
||||
d.value = ValueArray(v);
|
||||
}
|
||||
|
||||
ValueMap::ValueMap(const Index<Value>& k, const Vector<Value>& v, int deep)
|
||||
{
|
||||
Data& d = Create();
|
||||
d.key <<= k;
|
||||
Vector<Value> _v(v, 0);
|
||||
d.value = ValueArray(_v);
|
||||
}
|
||||
|
||||
ValueMap::operator Value() const {
|
||||
data->Retain();
|
||||
return Value(data);
|
||||
}
|
||||
|
||||
ValueMap::ValueMap(const Value& src)
|
||||
{
|
||||
if(!IsNull(src)) {
|
||||
if(IsType<ValueArray>(src)) {
|
||||
ValueArray va = src;
|
||||
Init0();
|
||||
for(int i = 0; i < va.GetCount(); i++)
|
||||
Add(i, va[i]);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ASSERT(dynamic_cast<const ValueMap::Data *>(src.GetVoidPtr()));
|
||||
data = (ValueMap::Data *)src.GetVoidPtr();
|
||||
}
|
||||
}
|
||||
else
|
||||
data = &Single<NullData>();
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
void ValueMap::Serialize(Stream& s) {
|
||||
if(s.IsLoading()) {
|
||||
data->Release();
|
||||
Create();
|
||||
}
|
||||
data->Serialize(s);
|
||||
}
|
||||
|
||||
ValueMap::~ValueMap() {
|
||||
ASSERT(data->GetRefCount() > 0);
|
||||
data->Release();
|
||||
}
|
||||
|
||||
ValueMap& ValueMap::operator=(const ValueMap& v) {
|
||||
v.data->Retain();
|
||||
data->Release();
|
||||
data = v.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ValueMap::Clear() {
|
||||
data->Release();
|
||||
Init0();
|
||||
}
|
||||
|
||||
void ValueMap::Add(const Value& key, const Value& value) {
|
||||
Data& d = Clone();
|
||||
d.key.Add(key);
|
||||
d.value.Add(value);
|
||||
}
|
||||
|
||||
void ValueMap::Set(const Value& key, const Value& value)
|
||||
{
|
||||
Data& d = Clone();
|
||||
int i = d.key.Find(key);
|
||||
if(i >= 0)
|
||||
d.value.Set(i, value);
|
||||
else {
|
||||
d.key.Add(key);
|
||||
d.value.Add(value);
|
||||
}
|
||||
}
|
||||
|
||||
void ValueMap::SetAt(int i, const Value& v) {
|
||||
Clone().value.Set(i, v);
|
||||
}
|
||||
|
||||
void ValueMap::SetKey(int i, const Value& k) {
|
||||
Clone().key.Set(i, k);
|
||||
}
|
||||
|
||||
void ValueMap::Remove(int i)
|
||||
{
|
||||
Data& d = Clone();
|
||||
d.key.Remove(i);
|
||||
d.value.Remove(i);
|
||||
}
|
||||
|
||||
const Value& ValueMap::operator[](const Value& key) const
|
||||
{
|
||||
int q = data->key.Find(key);
|
||||
return q >= 0 ? data->value[q] : ErrorValue();
|
||||
}
|
||||
|
||||
// ----------------------------------
|
||||
|
||||
int StdValueCompare(const Value& a, const Value& b, int language)
|
||||
{
|
||||
LTIMING("StdValueCompare");
|
||||
|
||||
bool na = IsNull(a), nb = IsNull(b);
|
||||
if(na || nb)
|
||||
return !na ? 1 : !nb ? -1 : 0;
|
||||
dword ta = a.GetType(), tb = b.GetType();
|
||||
if((ta == INT_V || ta == BOOL_V) && (tb == INT_V || tb == BOOL_V))
|
||||
return cmp<int>(a, b);
|
||||
if((ta == BOOL_V || ta == INT_V || ta == INT64_V || ta == DOUBLE_V)
|
||||
&& (tb == BOOL_V || tb == INT_V || tb == INT64_V || tb == DOUBLE_V))
|
||||
return cmp<double>(a, b);
|
||||
if(ta == DATE_V && tb == DATE_V)
|
||||
return cmp<Date>(a, b);
|
||||
if((ta == DATE_V || ta == TIME_V) && (tb == DATE_V || tb == TIME_V))
|
||||
return cmp<Time>(a, b);
|
||||
if((ta == STRING_V || ta == WSTRING_V) && (tb == STRING_V || tb == WSTRING_V))
|
||||
return GetLanguageInfo(language).Compare(WString(a), WString(b));
|
||||
return cmp<int>(ta, tb);
|
||||
}
|
||||
|
||||
int StdValueCompare(const Value& a, const Value& b)
|
||||
{
|
||||
return StdValueCompare(a, b, GetCurrentLanguage());
|
||||
}
|
||||
|
||||
int StdValueCompareDesc(const Value& a, const Value& b, int language)
|
||||
{
|
||||
return -StdValueCompare(a, b, language);
|
||||
}
|
||||
|
||||
int StdValueCompareDesc(const Value& a, const Value& b)
|
||||
{
|
||||
return -StdValueCompare(a, b);
|
||||
}
|
||||
|
||||
StdValueOrder::StdValueOrder(int l) : language(l) {}
|
||||
|
||||
bool StdValueOrder::operator()(const Value& a, const Value& b) const
|
||||
{
|
||||
return StdValueCompare(a, b, language) < 0;
|
||||
}
|
||||
|
||||
bool FnValueOrder::operator()(const Value& a, const Value& b) const
|
||||
{
|
||||
return (*fn)(a, b) < 0;
|
||||
}
|
||||
|
||||
bool StdValuePairOrder::operator()(const Value& k1, const Value& v1, const Value& k2, const Value& v2) const
|
||||
{
|
||||
int q = StdValueCompare(k1, k2, language);
|
||||
if(q) return q < 0;
|
||||
return StdValueCompare(v1, v2, language);
|
||||
}
|
||||
|
||||
bool FnValuePairOrder::operator()(const Value& keya, const Value& valuea, const Value& keyb, const Value& valueb) const
|
||||
{
|
||||
return (*fn)(keya, valuea, keyb, valueb) < 0;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
|
@ -1,39 +1,10 @@
|
|||
#ifdef SVO_VALUE
|
||||
|
||||
class Value;
|
||||
class Id;
|
||||
class ValueArray;
|
||||
class ValueMap;
|
||||
|
||||
class Id : Moveable<Id> {
|
||||
String id;
|
||||
|
||||
public:
|
||||
const String& ToString() const { return id; }
|
||||
dword GetHashValue() const { return UPP::GetHashValue(id); }
|
||||
bool IsNull() const { return UPP::IsNull(id); }
|
||||
|
||||
operator const String&() const { return ToString(); }
|
||||
const String& operator~() const { return ToString(); }
|
||||
bool operator==(const Id& b) const { return id == b.id; }
|
||||
bool operator!=(const Id& b) const { return id != b.id; }
|
||||
|
||||
operator bool() const { return id.GetCount(); }
|
||||
|
||||
Id() {}
|
||||
Id(const String& s) { id = s; }
|
||||
Id(const char *s) { id = s; }
|
||||
};
|
||||
|
||||
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); }
|
||||
#define SVO_VALUE
|
||||
|
||||
const dword VOID_V = 0;
|
||||
|
||||
|
|
@ -58,6 +29,27 @@ const dword VALUEMAP_V = 12;
|
|||
|
||||
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 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; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
dword GetValueTypeNo() { return ValueTypeNo((T*)NULL); }
|
||||
|
||||
class Value : Moveable<Value> {
|
||||
public:
|
||||
class Void {
|
||||
|
|
@ -67,6 +59,7 @@ public:
|
|||
public:
|
||||
void Retain() { AtomicInc(refcount); }
|
||||
void Release() { if(AtomicDec(refcount) == 0) delete this; }
|
||||
int GetRefCount() const { return AtomicRead(refcount); }
|
||||
|
||||
virtual dword GetType() const { return VOID_V; }
|
||||
virtual bool IsNull() const { return true; }
|
||||
|
|
@ -76,49 +69,104 @@ public:
|
|||
virtual bool IsPolyEqual(const Value& v) { return false; }
|
||||
virtual String AsString() const { return ""; }
|
||||
|
||||
Void() { AtomicWrite(refcount, 1); }
|
||||
Void() { refcount = 1; }
|
||||
virtual ~Void() {}
|
||||
|
||||
friend class Value;
|
||||
};
|
||||
|
||||
struct Sval {
|
||||
bool (*IsNull)(const void *p);
|
||||
void (*Serialize)(void *p, Stream& s);
|
||||
unsigned (*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);
|
||||
};
|
||||
|
||||
protected:
|
||||
enum { STRING = 0, REF = 255, VOIDV = 3 };
|
||||
|
||||
static VectorMap<dword, Void* (*)(Stream& s) >& Typemap();
|
||||
static Sval *svo[256];
|
||||
|
||||
Void *ptr;
|
||||
String data;
|
||||
Void *&ptr() { ASSERT(IsRef()); return *(Void **)&data; }
|
||||
Void *ptr() const { ASSERT(IsRef()); return *(Void **)&data; }
|
||||
|
||||
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) { data.SetSpecial(REF); ptr() = p; }
|
||||
void RefRelease();
|
||||
void RefRetain();
|
||||
void Free() { if(IsRef()) RefRelease(); }
|
||||
void SetLarge(const Value& v);
|
||||
|
||||
void SetVoidVal();
|
||||
template <class T>
|
||||
void InitSmall(const T& init);
|
||||
template <class T>
|
||||
T& GetSmall() const;
|
||||
|
||||
int GetOtherInt() const;
|
||||
int64 GetOtherInt64() const;
|
||||
double GetOtherDouble() const;
|
||||
bool GetOtherBool() const;
|
||||
Date GetOtherDate() const;
|
||||
Time GetOtherTime() const;
|
||||
String GetOtherString() const;
|
||||
unsigned 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;
|
||||
|
||||
public:
|
||||
static void Register(dword w, Void* (*c)(Stream& s)) init_;
|
||||
|
||||
template <class T>
|
||||
static void Register();
|
||||
template <class T>
|
||||
static void SvoRegister();
|
||||
|
||||
dword GetType() const { return ptr->GetType(); }
|
||||
dword GetType() const;
|
||||
bool IsError() const { return GetType() == ERROR_V; }
|
||||
bool IsVoid() const { return GetType() == VOID_V || IsError(); }
|
||||
bool IsNull() const { return ptr->IsNull(); }
|
||||
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;
|
||||
operator String() const { return IsString() ? data : GetOtherString(); }
|
||||
operator WString() const;
|
||||
operator Date() const;
|
||||
operator Time() const;
|
||||
operator double() const;
|
||||
operator int() const;
|
||||
operator int64() const;
|
||||
operator bool() const;
|
||||
operator Date() const { return Is(DATE_V) ? GetSmall<Date>() : GetOtherDate(); }
|
||||
operator Time() const { return Is(TIME_V) ? GetSmall<Time>() : GetOtherTime(); }
|
||||
operator double() const { return Is(DOUBLE_V) ? GetSmall<double>() : GetOtherDouble(); }
|
||||
operator int() const { return Is(INT_V) ? GetSmall<int>() : GetOtherInt(); }
|
||||
operator int64() const { return Is(INT64_V) ? GetSmall<int64>() : GetOtherInt64(); }
|
||||
operator bool() const { return Is(BOOL_V) ? GetSmall<bool>() : GetOtherBool(); }
|
||||
|
||||
Value(const String& s);
|
||||
Value(const String& s) : data(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&);
|
||||
Value(const char *s) : data(s) {}
|
||||
Value(int i) : data(i, INT_V, String::SPECIAL) {}
|
||||
Value(int64 i) : data(i, INT64_V, String::SPECIAL) {}
|
||||
Value(double d) : data(d, DOUBLE_V, String::SPECIAL) {}
|
||||
Value(bool b) : data(b, BOOL_V, String::SPECIAL) {}
|
||||
Value(Date d) : data(d, DATE_V, String::SPECIAL) {}
|
||||
Value(Time t) : data(t, TIME_V, String::SPECIAL) {}
|
||||
Value(const Nuller&) : data((int)Null, INT_V, String::SPECIAL) {}
|
||||
|
||||
bool operator==(const Value& v) const;
|
||||
bool operator!=(const Value& v) const { return !operator==(v); }
|
||||
|
|
@ -138,232 +186,24 @@ public:
|
|||
const Value& operator[](const char *key) const;
|
||||
const Value& operator[](const Id& key) const;
|
||||
|
||||
Value();
|
||||
~Value();
|
||||
Value() : data((int)Null, VOIDV, String::SPECIAL) {}
|
||||
~Value() { if(IsRef()) RefRelease(); }
|
||||
|
||||
Value(Void *p) { ptr = p; }
|
||||
const Void *GetVoidPtr() const { return ptr; }
|
||||
Value(Void *p) { InitRef(p); }
|
||||
const Void *GetVoidPtr() const { ASSERT(IsRef()); return ptr(); }
|
||||
|
||||
friend void Swap(Value& a, Value& b) { Swap(a.data, b.data); }
|
||||
};
|
||||
|
||||
#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; } \
|
||||
template <class T> bool FitsSvoValue() { return sizeof(T) <= 8; }
|
||||
template <class T> Value SvoToValue(const T& x) { return Value(x, Value::SMALL); }
|
||||
|
||||
VALUE_COMPARE(int)
|
||||
VALUE_COMPARE(int64)
|
||||
VALUE_COMPARE(double)
|
||||
VALUE_COMPARE(bool)
|
||||
VALUE_COMPARE(Date)
|
||||
VALUE_COMPARE(Time)
|
||||
VALUE_COMPARE(String)
|
||||
VALUE_COMPARE(WString)
|
||||
template <class T> Value RichToValue(const T& data);
|
||||
|
||||
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 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; }
|
||||
|
||||
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.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);
|
||||
};
|
||||
|
||||
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)) : fn(fn) {}
|
||||
};
|
||||
|
||||
struct ValuePairOrder {
|
||||
virtual bool operator()(const Value& keya, const Value& valuea, const Value& keyb, const Value& valueb) const = 0;
|
||||
virtual ~ValuePairOrder() {}
|
||||
};
|
||||
|
||||
struct StdValuePairOrder : ValuePairOrder {
|
||||
int language;
|
||||
|
||||
virtual bool operator()(const Value& keya, const Value& valuea, const Value& keyb, const Value& valueb) const;
|
||||
|
||||
StdValuePairOrder(int l = -1);
|
||||
};
|
||||
|
||||
struct FnValuePairOrder : ValuePairOrder {
|
||||
int (*fn)(const Value& k1, const Value& v1, const Value& k2, const Value& v2);
|
||||
|
||||
virtual bool operator()(const Value& keya, const Value& valuea, const Value& keyb, const Value& valueb) const;
|
||||
|
||||
FnValuePairOrder(int (*fn)(const Value& k1, const Value& v1, const Value& k2, const Value& v2)) : fn(fn) {}
|
||||
};
|
||||
|
||||
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>
|
||||
dword GetValueTypeNo() { return ValueTypeNo((T*)NULL); }
|
||||
|
||||
template <class T>
|
||||
bool IsType(const Value& x, T* = 0) { return GetValueTypeNo<T>() == 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 GetValueTypeNo<T>(); }
|
||||
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> Value RawToValue(const T& data);
|
||||
template <class T> Value RawPickToValue(pick_ T& data);
|
||||
template <class T> Value RawDeepToValue(const T& data);
|
||||
template <class T> T& CreateRawValue(Value& v);
|
||||
|
||||
template <class T>
|
||||
inline bool IsPolyEqual(const T& x, const Value& v) {
|
||||
|
|
@ -375,390 +215,50 @@ 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);
|
||||
}
|
||||
#define VALUE_COMPARE_V(T, VT) \
|
||||
inline bool operator==(const Value& v, T x) { return (VT)v == x; } \
|
||||
inline bool operator==(T x, const Value& v) { return (VT)v == x; } \
|
||||
inline bool operator!=(const Value& v, T x) { return (VT)v != x; } \
|
||||
inline bool operator!=(T x, const Value& v) { return (VT)v != x; } \
|
||||
|
||||
inline bool IsPolyEqual(const int& x, const Value& v) {
|
||||
return v.GetType() == DOUBLE_V && x == double(v)
|
||||
|| v.GetType() == INT64_V && x == int64(v);
|
||||
}
|
||||
#define VALUE_COMPARE(T) VALUE_COMPARE_V(T, T)
|
||||
|
||||
inline bool IsPolyEqual(const int64& x, const Value& v) {
|
||||
return v.GetType() == DOUBLE_V && double(x) == double(v);
|
||||
}
|
||||
VALUE_COMPARE(int)
|
||||
VALUE_COMPARE(int64)
|
||||
VALUE_COMPARE(double)
|
||||
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 IsPolyEqual(const Date& x, const Value& v) {
|
||||
return v.GetType() == TIME_V && ToTime(x) == Time(v);
|
||||
}
|
||||
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 IsPolyEqual(const WString& x, const Value& v) {
|
||||
return v.GetType() == STRING_V && WString(v) == x;
|
||||
}
|
||||
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; }
|
||||
|
||||
inline unsigned ValueGetHashValue(const bool& x) {
|
||||
return UPP::GetHashValue((double)x);
|
||||
}
|
||||
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 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; SetNull(x);
|
||||
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(GetValueTypeNo<T>(), 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); }
|
||||
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<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); }
|
||||
|
||||
Value ErrorValue(const char *s);
|
||||
Value ErrorValue(const String& s);
|
||||
const Value& ErrorValue();
|
||||
|
||||
String GetErrorText(const Value& 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; }
|
||||
|
||||
Value Scan(dword stdtype, const String& text, const Value& def = Null);
|
||||
|
||||
// ----------------------- 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 GetValueTypeNo<T>(); }
|
||||
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) { UPP::SetNull(*(T *)p); }
|
||||
};
|
||||
|
||||
class Ref : Moveable<Ref> {
|
||||
protected:
|
||||
RefManager *m;
|
||||
void *ptr;
|
||||
struct ValueRef;
|
||||
|
||||
public:
|
||||
dword GetType() const { return m ? m->GetType() : VOID_V; }
|
||||
bool IsNull() const { return m ? m->IsNull(ptr) : true; }
|
||||
|
||||
void *GetVoidPtr() const { return ptr; }
|
||||
|
||||
void SetNull() { if(m) m->SetNull(ptr); }
|
||||
Value GetValue() const { return m ? m->GetValue(ptr) : Value(); }
|
||||
void SetValue(const Value& v) { ASSERT(m); m->SetValue(ptr, v); }
|
||||
|
||||
operator Value() const { return GetValue(); }
|
||||
Value operator~() const { return GetValue(); }
|
||||
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(bool& b);
|
||||
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(GetValueTypeNo<T>() == 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 bool& RefBool(Ref f) { return GetRef<bool>(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();
|
||||
void Init0();
|
||||
|
||||
friend Value::Void *ValueArrayDataCreate(Stream& s);
|
||||
|
||||
public:
|
||||
ValueArray() { Init0(); }
|
||||
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&) { Init0(); }
|
||||
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);
|
||||
ValueArray& operator<<(const Value& v) { Add(v); return *this; }
|
||||
void Set(int i, const Value& v);
|
||||
const Value& Get(int i) const;
|
||||
const Vector<Value>& Get() const { return data->data; }
|
||||
|
||||
void Remove(int i, int count = 1);
|
||||
void Insert(int i, const ValueArray& va);
|
||||
void Append(const ValueArray& va) { Insert(GetCount(), va); }
|
||||
|
||||
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();
|
||||
|
||||
friend Value::Void *ValueMapDataCreate(Stream& s);
|
||||
|
||||
public:
|
||||
ValueMap() { Init0(); }
|
||||
ValueMap(const ValueMap& v);
|
||||
ValueMap(pick_ Index<Value>& k, pick_ Vector<Value>& v);
|
||||
ValueMap(const Index<Value>& k, const Vector<Value>& v, int deep);
|
||||
~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();
|
||||
int GetCount() const { return data->value.GetCount(); }
|
||||
bool IsEmpty() const { return data->value.IsEmpty(); }
|
||||
|
||||
void Add(const Value& key, const Value& value);
|
||||
void Add(const String& s, const Value& value) { Add(Value(s), 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); }
|
||||
|
||||
void Set(const Value& key, const Value& value);
|
||||
void Set(const String& s, const Value& value) { Set(Value(s), value); }
|
||||
void Set(const char *s, const Value& value) { Set(Value(s), value); }
|
||||
void Set(Id id, const Value& value) { Set(Value(id.ToString()), value); }
|
||||
|
||||
void SetAt(int i, const Value& v);
|
||||
void SetKey(int i, const Value& k);
|
||||
void SetKey(int i, const String& s) { SetKey(i, Value(s)); }
|
||||
void SetKey(int i, const char* s) { SetKey(i, Value(s)); }
|
||||
void SetKey(int i, Id id) { SetKey(i, Value(id.ToString())); }
|
||||
void Remove(int i);
|
||||
|
||||
const Index<Value>& GetKeys() const { return data->key; }
|
||||
ValueArray GetValues() const { return data->value; }
|
||||
|
||||
operator ValueArray() const { return GetValues(); }
|
||||
|
||||
const Value& operator[](const Value& k) const;
|
||||
const Value& operator[](const String& s) const{ return operator[](Value(s)); }
|
||||
const Value& operator[](const char *s) const { return operator[](Value(s)); }
|
||||
const 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); }
|
||||
|
||||
inline
|
||||
int Value::GetCount() const
|
||||
{
|
||||
return IsValueArray(*this) ? ValueArray(*this).GetCount() : 0;
|
||||
}
|
||||
|
||||
inline
|
||||
const Value& Value::operator[](int i) const
|
||||
{
|
||||
ASSERT(IsValueArray(*this));
|
||||
return ValueArray(*this)[i];
|
||||
}
|
||||
|
||||
inline
|
||||
const Value& Value::operator[](const String& key) const
|
||||
{
|
||||
return IsValueMap(*this) ? ValueMap(*this)[key] : ErrorValue();
|
||||
}
|
||||
|
||||
inline
|
||||
const Value& Value::operator[](const char *key) const
|
||||
{
|
||||
return IsValueMap(*this) ? ValueMap(*this)[key] : ErrorValue();
|
||||
}
|
||||
|
||||
inline
|
||||
const Value& Value::operator[](const Id& key) const
|
||||
{
|
||||
return IsValueMap(*this) ? ValueMap(*this)[key] : ErrorValue();
|
||||
}
|
||||
|
||||
class ValueGen {
|
||||
public:
|
||||
virtual Value Get() = 0;
|
||||
Value operator++() { return Get(); }
|
||||
virtual ~ValueGen() {}
|
||||
};
|
||||
#endif
|
||||
349
uppsrc/Core/Value.hpp
Normal file
349
uppsrc/Core/Value.hpp
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
#ifdef SVO_VALUE
|
||||
|
||||
inline
|
||||
Value::Value(const Value& v)
|
||||
: data(String::SPECIAL)
|
||||
{
|
||||
if(v.IsRef() || v.data.IsLarge())
|
||||
SetLarge(v);
|
||||
else
|
||||
data.SetSmall(v.data);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool IsPolyEqual(const bool& x, const Value& v) {
|
||||
return v.Is<double>() && int(x) == double(v)
|
||||
|| v.Is<int64>() && int(x) == int64(v)
|
||||
|| v.Is<int>() && int(x) == int(v);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool IsPolyEqual(const int& x, const Value& v) {
|
||||
return v.Is<double>() && x == double(v)
|
||||
|| v.Is<int64>() && x == int64(v);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool IsPolyEqual(const int64& x, const Value& v) {
|
||||
return v.Is<double>() && double(x) == double(v);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool IsPolyEqual(const Date& x, const Value& v) {
|
||||
return v.Is<Time>() && ToTime(x) == Time(v);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool IsPolyEqual(const WString& x, const Value& v) {
|
||||
return v.GetType() == STRING_V && WString(v) == x;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline unsigned ValueGetHashValue(const bool& x) {
|
||||
return UPP::GetHashValue((int64)x);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline unsigned ValueGetHashValue(const int& x) {
|
||||
return UPP::GetHashValue((int64)x);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline unsigned ValueGetHashValue(const double& x) {
|
||||
if(x >= INT64_MIN && x <= INT64_MAX && (int64)x == x)
|
||||
return UPP::GetHashValue((int64)x);
|
||||
return UPP::GetHashValue(x);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline unsigned ValueGetHashValue(const Date& x) {
|
||||
return UPP::GetHashValue(ToTime(x));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline unsigned ValueGetHashValue(const WString& x) {
|
||||
return UPP::GetHashValue(x.ToString());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class RawValueRep : public Value::Void {
|
||||
public:
|
||||
virtual dword GetType() const { return GetValueTypeNo<T>(); }
|
||||
virtual bool IsNull() const { return false; }
|
||||
|
||||
T v;
|
||||
|
||||
enum VPICK { PICK };
|
||||
enum VDEEP { DEEP };
|
||||
|
||||
const T& Get() const { return v; }
|
||||
T& Get() { return v; }
|
||||
|
||||
RawValueRep(const T& v) : v(v) {}
|
||||
RawValueRep(pick_ T& v, VPICK) : v(v) {}
|
||||
RawValueRep(const T& v, VDEEP) : v(v, 1) {}
|
||||
RawValueRep() {}
|
||||
};
|
||||
|
||||
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) { ASSERT(dynamic_cast<const RawValueRep<T> *>(p));
|
||||
return static_cast<const RawValueRep<T> *>(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); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct SvoFn {
|
||||
static bool IsNull(const void *p) { return UPP::IsNull(*(T *)p); }
|
||||
static void Serialize(void *p, Stream& s) { s % *(T*)p; }
|
||||
static unsigned GetHashValue(const void *p) { return UPP::ValueGetHashValue(*(T*)p); }
|
||||
static bool IsEqual(const void *p1, const void *p2) { return *(T*)p1 == *(T*)p2; }
|
||||
static bool IsPolyEqual(const void *p, const Value& v) { return UPP::IsPolyEqual(*(T*)p, v); }
|
||||
static String AsString(const void *p) { return UPP::AsString(*(T*)p); }
|
||||
};
|
||||
|
||||
#define SVO_FN(id, T) \
|
||||
static Value::Sval id = { \
|
||||
SvoFn<T>::IsNull, SvoFn<T>::Serialize, SvoFn<T>::GetHashValue, SvoFn<T>::IsEqual, \
|
||||
SvoFn<T>::IsPolyEqual, SvoFn<T>::AsString \
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void Value::InitSmall(const T& init)
|
||||
{
|
||||
ASSERT(sizeof(T) <= 8);
|
||||
SVO_FN(sval, T)
|
||||
int typeno = GetValueTypeNo<T>();
|
||||
ASSERT(typeno >= 0 && typeno < 256);
|
||||
svo[typeno] = &sval;
|
||||
data.SetSpecial(typeno);
|
||||
new(&data) T(init);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T& Value::GetSmall() const
|
||||
{
|
||||
dword t = GetValueTypeNo<T>();
|
||||
ASSERT(t < 255 && (t == STRING_V ? IsString() : Is((byte)t)));
|
||||
return *(T*)&data;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Value::SvoRegister()
|
||||
{
|
||||
dword t = GetValueTypeNo<T>();
|
||||
ASSERT(t < 255);
|
||||
SVO_FN(sval, T)
|
||||
svo[t] = &sval;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline const T& Value::To() const
|
||||
{
|
||||
dword t = GetValueTypeNo<T>();
|
||||
ASSERT(t != VALUEARRAY_V && t != VALUEMAP_V);
|
||||
#ifndef _DEBUG
|
||||
if(t == VALUEARRAY_V) {
|
||||
ASSERT(ptr()->GetType() == VALUEARRAY_V);
|
||||
return *(T*)this; // Illegal, but works -> better than crash in release mode
|
||||
}
|
||||
if(t == VALUEMAP_V) {
|
||||
ASSERT(ptr()->GetType() == VALUEMAP_V);
|
||||
return *(T*)this; // Illegal, but works -> better than crash in release mode
|
||||
}
|
||||
#endif
|
||||
if(t == STRING_V) {
|
||||
ASSERT(IsString());
|
||||
return *reinterpret_cast<const T*>(&data); // Only active when T is String
|
||||
}
|
||||
if(t == INT_V || t == INT64_V || t == DOUBLE_V || t == BOOL_V ||
|
||||
t == DATE_V || t == TIME_V || !IsRef()) {
|
||||
dword t = GetValueTypeNo<T>();
|
||||
ASSERT_(t < 255 && (t == STRING_V ? IsString() : Is((byte)t)),
|
||||
String().Cat() << "Invalid value conversion: "
|
||||
<< GetName() << " -> " << typeid(T).name());
|
||||
return *(T*)&data;
|
||||
}
|
||||
const RawValueRep<T> *x = dynamic_cast<const RawValueRep<T>*>(ptr());
|
||||
ASSERT_(x,
|
||||
String().Cat() << "Invalid value conversion: "
|
||||
<< GetName() << " -> " << typeid(T).name());
|
||||
return x->Get();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool Value::Is() const
|
||||
{
|
||||
dword t = GetValueTypeNo<T>();
|
||||
if(t > 0x80000000)
|
||||
return IsRef() && dynamic_cast<const RawValueRep<T> *>(ptr());
|
||||
if(t == STRING_V)
|
||||
return IsString();
|
||||
if(t == VOID_V)
|
||||
return IsVoid();
|
||||
if(t == INT_V || t == INT64_V || t == DOUBLE_V || t == BOOL_V ||
|
||||
t == DATE_V || t == TIME_V)
|
||||
return Is((byte)t);
|
||||
return t < 255 && Is((byte)t) || IsRef() && ptr()->GetType() == t;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T& GetStaticNull()
|
||||
{
|
||||
static T *q;
|
||||
ONCELOCK {
|
||||
static T x;
|
||||
SetNull(x);
|
||||
q = &x;
|
||||
}
|
||||
return *q;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline const T& Value::Get() const
|
||||
{
|
||||
#ifndef _DEBUG
|
||||
dword t = GetValueTypeNo<T>();
|
||||
if(t == VALUEARRAY_V) {
|
||||
ASSERT(ptr()->GetType() == VALUEARRAY_V);
|
||||
return *(T*)this; // Illegal, but works -> better than crash in release mode
|
||||
}
|
||||
if(t == VALUEMAP_V) {
|
||||
ASSERT(ptr()->GetType() == VALUEMAP_V);
|
||||
return *(T*)this; // Illegal, but works -> better than crash in release mode
|
||||
}
|
||||
#endif
|
||||
if(IsNull())
|
||||
return GetStaticNull<T>();
|
||||
return To<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Value::Value(const T& x, VSMALL)
|
||||
{
|
||||
InitSmall(x);
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned Value::GetHashValue() const
|
||||
{
|
||||
return IsString() ? data.GetCount() ? data.GetHashValue() : 0
|
||||
: GetOtherHashValue();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Value::Register()
|
||||
{
|
||||
Value::Register(GetValueTypeNo<T>(), RichValueRep<T>::Create);
|
||||
}
|
||||
|
||||
inline
|
||||
const Value& Value::operator[](const char *key) const
|
||||
{
|
||||
return operator[](String(key));
|
||||
}
|
||||
|
||||
inline
|
||||
const Value& Value::operator[](const Id& key) const
|
||||
{
|
||||
return operator[](~key);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline Value RawToValue(const T& data)
|
||||
{
|
||||
return Value(new RawValueRep<T>(data));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline Value RawPickToValue(pick_ T& data)
|
||||
{
|
||||
typedef RawValueRep<T> R;
|
||||
return Value(new R(data, R::PICK));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline Value RawDeepToValue(const T& data)
|
||||
{
|
||||
typedef RawValueRep<T> R;
|
||||
return Value(new R(data, R::DEEP));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T& CreateRawValue(Value& v) {
|
||||
typedef RawValueRep<T> R;
|
||||
R *r = new R;
|
||||
v = Value(r);
|
||||
return r->Get();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline Value RichToValue(const T& data)
|
||||
{
|
||||
return Value(new RichValueRep<T>(data));
|
||||
}
|
||||
|
||||
template <class T> // Deprecated, use Value::Is
|
||||
bool IsTypeRaw(const Value& value, T * = 0) { return value.Is<T>(); }
|
||||
|
||||
template <class T> // deprecated, use Value::Is
|
||||
bool IsType(const Value& x, T* = 0) { return x.Is<T>(); }
|
||||
|
||||
template <class T>
|
||||
struct RawValue : public Value { // Deprecated, use RawToValue and Value::To
|
||||
RawValue(const T& x) : Value(RawToValue(x)) {}
|
||||
static const T& Extract(const Value& v) { return v.To<T>(); }
|
||||
static const T& Extract(const Value& v, const T& dflt) { return v.Is<T>() ? v.To<T>() : dflt; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct RichValue : public Value { // Deprecated, use RichToValue and Value::To
|
||||
public:
|
||||
RichValue(const T& x) : Value(RichToValue<T>(x)) {}
|
||||
static void Register() init_ { Value::Register<T>(); }
|
||||
static const T& Extract(const Value& v) { return v.Get<T>(); }
|
||||
};
|
||||
|
||||
template <class T> // Deprecated, use Value::To
|
||||
inline const T& ValueTo(const Value& v) { return v.To<T>(); }
|
||||
|
||||
template <class T> // Deprecated, use Value::To
|
||||
inline const T& ValueTo(const Value& v, const T& dflt) { return v.Is<T>() ? v.To<T>() : dflt; }
|
||||
|
||||
|
||||
template <class T> // Deprecated (?)
|
||||
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 GetValueTypeNo<T>(); }
|
||||
virtual ~RawRef() {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
Ref RawAsRef(T& x) { // Deprecated (?)
|
||||
return Ref(&x, &Single< RawRef<T> >());
|
||||
}
|
||||
|
||||
template <class T> // Deprecated
|
||||
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) { UPP::SetNull(*(T *)p); }
|
||||
};
|
||||
|
||||
template <class T> // Deprecated
|
||||
Ref RichAsRef(T& x) {
|
||||
return Ref(&x, &Single< RichRef<T> >());
|
||||
}
|
||||
#endif
|
||||
475
uppsrc/Core/ValueUtil.cpp
Normal file
475
uppsrc/Core/ValueUtil.cpp
Normal file
|
|
@ -0,0 +1,475 @@
|
|||
#include "Core.h"
|
||||
|
||||
#ifdef SVO_VALUE
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#define LTIMING(x) // RTIMING(x)
|
||||
|
||||
struct Ref::ValueRef : public RefManager {
|
||||
virtual int GetType() { return VALUE_V; }
|
||||
virtual Value GetValue(const void *ptr) { return *(Value *) ptr; }
|
||||
virtual bool IsNull(const void *ptr) { return UPP::IsNull(*(Value *) ptr); }
|
||||
virtual void SetValue(void *ptr, const Value& v) { *(Value *) ptr = v; }
|
||||
virtual void SetNull(void *ptr) { *(Value *) ptr = Null; }
|
||||
};
|
||||
|
||||
Ref::Ref(String& s) { ptr = &s; m = &Single< StdRef<String> >(); }
|
||||
Ref::Ref(WString& s) { ptr = &s; m = &Single< StdRef<WString> >(); }
|
||||
Ref::Ref(int& i) { ptr = &i; m = &Single< StdRef<int> >(); }
|
||||
Ref::Ref(int64& i) { ptr = &i; m = &Single< StdRef<int64> >(); }
|
||||
Ref::Ref(double& d) { ptr = &d; m = &Single< StdRef<double> >(); }
|
||||
Ref::Ref(bool& b) { ptr = &b; m = &Single< StdRef<bool> >(); }
|
||||
Ref::Ref(Date& d) { ptr = &d; m = &Single< StdRef<Date> >(); }
|
||||
Ref::Ref(Time& t) { ptr = &t; m = &Single< StdRef<Time> >(); }
|
||||
Ref::Ref(Value& v) { ptr = &v; m = &Single< ValueRef >(); }
|
||||
|
||||
// ----------------------------------
|
||||
|
||||
bool ValueArray::Data::IsNull() const
|
||||
{
|
||||
return this == &Single<ValueArray::NullData>();
|
||||
}
|
||||
|
||||
void ValueArray::Data::Serialize(Stream& s)
|
||||
{
|
||||
s % data;
|
||||
}
|
||||
|
||||
unsigned ValueArray::Data::GetHashValue() const
|
||||
{
|
||||
CombineHash w(data.GetCount());
|
||||
for(int i = 0; i < data.GetCount(); i++)
|
||||
w.Put(data[i].GetHashValue());
|
||||
return w;
|
||||
}
|
||||
|
||||
static bool sCmp(const Vector<Value>& a, const Vector<Value>& b)
|
||||
{
|
||||
if(&a == &b) return true;
|
||||
if(a.GetCount() != b.GetCount()) return false;
|
||||
for(int i = 0; i < a.GetCount(); i++)
|
||||
if(a[i] != b[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValueArray::Data::IsEqual(const Value::Void *p)
|
||||
{
|
||||
return sCmp(((Data *)p)->data, data);
|
||||
}
|
||||
|
||||
bool ValueArray::operator==(const ValueArray& v) const
|
||||
{
|
||||
return sCmp(data->data, v.data->data);
|
||||
}
|
||||
|
||||
static String sAsString(const Vector<Value>& v)
|
||||
{
|
||||
String s;
|
||||
s << "[";
|
||||
for(int i = 0; i < v.GetCount(); i++) {
|
||||
if(i) s << ", ";
|
||||
s << v[i];
|
||||
}
|
||||
s << "]";
|
||||
return s;
|
||||
}
|
||||
|
||||
String ValueArray::Data::AsString() const
|
||||
{
|
||||
return sAsString(data);
|
||||
}
|
||||
|
||||
Vector<Value>& ValueArray::Create()
|
||||
{
|
||||
data = new Data;
|
||||
return data->data;
|
||||
}
|
||||
|
||||
Vector<Value>& ValueArray::Clone() {
|
||||
if(data->GetRefCount() != 1) {
|
||||
Data *d = new Data;
|
||||
d->data <<= data->data;
|
||||
data->Release();
|
||||
data = d;
|
||||
}
|
||||
return data->data;
|
||||
}
|
||||
|
||||
void ValueArray::Init0()
|
||||
{
|
||||
data = &Single<NullData>();
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
ValueArray::ValueArray(const ValueArray& v) {
|
||||
data = v.data;
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
ValueArray::ValueArray(pick_ Vector<Value>& v)
|
||||
{
|
||||
Create() = v;
|
||||
}
|
||||
|
||||
ValueArray::ValueArray(const Vector<Value>& v, int deep)
|
||||
{
|
||||
Create() <<= v;
|
||||
}
|
||||
|
||||
ValueArray::operator Value() const {
|
||||
data->Retain();
|
||||
return Value(data);
|
||||
}
|
||||
|
||||
ValueArray::ValueArray(const Value& src)
|
||||
{
|
||||
if(!UPP::IsNull(src)) {
|
||||
if(IsType<ValueMap>(src)) {
|
||||
ValueArray v = ValueMap(src);
|
||||
data = v.data;
|
||||
data->Retain();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ASSERT(dynamic_cast<const ValueArray::Data *>(src.GetVoidPtr()));
|
||||
data = (ValueArray::Data *)src.GetVoidPtr();
|
||||
}
|
||||
}
|
||||
else
|
||||
data = &Single<NullData>();
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
void ValueArray::Serialize(Stream& s) {
|
||||
if(s.IsLoading()) {
|
||||
data->Release();
|
||||
Create();
|
||||
}
|
||||
data->Serialize(s);
|
||||
}
|
||||
|
||||
ValueArray::~ValueArray() {
|
||||
ASSERT(data->GetRefCount() > 0);
|
||||
data->Release();
|
||||
}
|
||||
|
||||
ValueArray& ValueArray::operator=(const ValueArray& v) {
|
||||
v.data->Retain();
|
||||
data->Release();
|
||||
data = v.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ValueArray::SetCount(int n) {
|
||||
Clone().SetCount(n);
|
||||
}
|
||||
|
||||
void ValueArray::SetCount(int n, const Value& v)
|
||||
{
|
||||
Clone().SetCount(n, v);
|
||||
}
|
||||
|
||||
void ValueArray::Clear() {
|
||||
Clone().Clear();
|
||||
}
|
||||
|
||||
void ValueArray::Add(const Value& v) {
|
||||
Clone().Add(v);
|
||||
}
|
||||
|
||||
void ValueArray::Set(int i, const Value& v) {
|
||||
ASSERT(i >= 0);
|
||||
Clone().At(i) = v;
|
||||
}
|
||||
|
||||
void ValueArray::Remove(int i, int count)
|
||||
{
|
||||
Clone().Remove(i, count);
|
||||
}
|
||||
|
||||
void ValueArray::Insert(int i, const ValueArray& va)
|
||||
{
|
||||
if(va.data == data) {
|
||||
ValueArray va2 = va;
|
||||
Clone().Insert(i, va2.Get());
|
||||
}
|
||||
else
|
||||
Clone().Insert(i, va.Get());
|
||||
}
|
||||
|
||||
const Value& ValueArray::Get(int i) const {
|
||||
ASSERT(i >= 0 && i < GetCount());
|
||||
return data->data[i];
|
||||
}
|
||||
|
||||
Value ValueArray::GetAndClear(int i)
|
||||
{
|
||||
ASSERT(i >= 0 && i < GetCount());
|
||||
Vector<Value>& x = Clone();
|
||||
Value v = x[i];
|
||||
x[i] = Value();
|
||||
return v;
|
||||
}
|
||||
|
||||
template<>
|
||||
String AsString(const ValueArray& v) {
|
||||
return sAsString(v.Get());
|
||||
}
|
||||
|
||||
bool ValueMap::Data::IsNull() const {
|
||||
return this == &Single<ValueMap::NullData>();
|
||||
}
|
||||
|
||||
void ValueMap::Data::Serialize(Stream& s) {
|
||||
s % key % value;
|
||||
}
|
||||
|
||||
unsigned ValueMap::Data::GetHashValue() const {
|
||||
CombineHash w(key.GetCount());
|
||||
for(int i = 0; i < key.GetCount(); i++)
|
||||
w.Put(key[i].GetHashValue());
|
||||
w.Put(value.GetHashValue());
|
||||
return w;
|
||||
}
|
||||
|
||||
static bool sIsEqual(const Index<Value>& a, const Index<Value>& b) {
|
||||
if(&a == &b) return true;
|
||||
if(a.GetCount() != b.GetCount()) return false;
|
||||
for(int i = 0; i < a.GetCount(); i++) {
|
||||
if(a[i] != b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValueMap::Data::IsEqual(const Value::Void *p) {
|
||||
return sIsEqual(((Data *)p)->key, key) && ((Data *)p)->value == value;
|
||||
}
|
||||
|
||||
bool ValueMap::operator==(const ValueMap& v) const {
|
||||
return sIsEqual(data->key, v.data->key) && data->value == v.data->value;
|
||||
}
|
||||
|
||||
String ValueMap::Data::AsString() const
|
||||
{
|
||||
String s;
|
||||
s << "{ ";
|
||||
for(int i = 0; i < key.GetCount(); i++) {
|
||||
if(i) s << ", ";
|
||||
s << key[i] << ": " << value[i];
|
||||
}
|
||||
s << " }";
|
||||
return s;
|
||||
}
|
||||
|
||||
ValueMap::Data& ValueMap::Create()
|
||||
{
|
||||
data = new Data;
|
||||
return *data;
|
||||
}
|
||||
|
||||
const Value& ValueMap::Data::Get(const Value& k) const
|
||||
{
|
||||
int q = key.Find(k);
|
||||
return q >= 0 ? value[q] : ErrorValue();
|
||||
}
|
||||
|
||||
ValueMap::Data& ValueMap::Clone() {
|
||||
if(data->GetRefCount() != 1) {
|
||||
Data *d = new Data;
|
||||
d->key <<= data->key;
|
||||
d->value = data->value;
|
||||
data->Release();
|
||||
data = d;
|
||||
}
|
||||
return *data;
|
||||
}
|
||||
|
||||
void ValueMap::Init0()
|
||||
{
|
||||
data = &Single<NullData>();
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
ValueMap::ValueMap(const ValueMap& v)
|
||||
{
|
||||
data = v.data;
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
ValueMap::ValueMap(pick_ Index<Value>& k, pick_ Vector<Value>& v)
|
||||
{
|
||||
Data& d = Create();
|
||||
d.key = k;
|
||||
d.value = ValueArray(v);
|
||||
}
|
||||
|
||||
ValueMap::ValueMap(const Index<Value>& k, const Vector<Value>& v, int deep)
|
||||
{
|
||||
Data& d = Create();
|
||||
d.key <<= k;
|
||||
Vector<Value> _v(v, 0);
|
||||
d.value = ValueArray(_v);
|
||||
}
|
||||
|
||||
ValueMap::operator Value() const {
|
||||
data->Retain();
|
||||
return Value(data);
|
||||
}
|
||||
|
||||
ValueMap::ValueMap(const Value& src)
|
||||
{
|
||||
if(!IsNull(src)) {
|
||||
if(IsType<ValueArray>(src)) {
|
||||
ValueArray va = src;
|
||||
Init0();
|
||||
for(int i = 0; i < va.GetCount(); i++)
|
||||
Add(i, va[i]);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ASSERT(dynamic_cast<const ValueMap::Data *>(src.GetVoidPtr()));
|
||||
data = (ValueMap::Data *)src.GetVoidPtr();
|
||||
}
|
||||
}
|
||||
else
|
||||
data = &Single<NullData>();
|
||||
data->Retain();
|
||||
}
|
||||
|
||||
void ValueMap::Serialize(Stream& s) {
|
||||
if(s.IsLoading()) {
|
||||
data->Release();
|
||||
Create();
|
||||
}
|
||||
data->Serialize(s);
|
||||
}
|
||||
|
||||
ValueMap::~ValueMap() {
|
||||
ASSERT(data->GetRefCount() > 0);
|
||||
data->Release();
|
||||
}
|
||||
|
||||
ValueMap& ValueMap::operator=(const ValueMap& v) {
|
||||
v.data->Retain();
|
||||
data->Release();
|
||||
data = v.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ValueMap::Clear() {
|
||||
data->Release();
|
||||
Init0();
|
||||
}
|
||||
|
||||
void ValueMap::Add(const Value& key, const Value& value) {
|
||||
Data& d = Clone();
|
||||
d.key.Add(key);
|
||||
d.value.Add(value);
|
||||
}
|
||||
|
||||
void ValueMap::Set(const Value& key, const Value& value)
|
||||
{
|
||||
Data& d = Clone();
|
||||
int i = d.key.Find(key);
|
||||
if(i >= 0)
|
||||
d.value.Set(i, value);
|
||||
else {
|
||||
d.key.Add(key);
|
||||
d.value.Add(value);
|
||||
}
|
||||
}
|
||||
|
||||
void ValueMap::SetAt(int i, const Value& v) {
|
||||
Clone().value.Set(i, v);
|
||||
}
|
||||
|
||||
void ValueMap::SetKey(int i, const Value& k) {
|
||||
Clone().key.Set(i, k);
|
||||
}
|
||||
|
||||
void ValueMap::Remove(int i)
|
||||
{
|
||||
Data& d = Clone();
|
||||
d.key.Remove(i);
|
||||
d.value.Remove(i);
|
||||
}
|
||||
|
||||
const Value& ValueMap::operator[](const Value& key) const
|
||||
{
|
||||
return data->Get(key);
|
||||
}
|
||||
|
||||
Value ValueMap::GetAndClear(const Value& key)
|
||||
{
|
||||
Data& d = Clone();
|
||||
int q = d.key.Find(key);
|
||||
return q < 0 ? ErrorValue() : d.value.GetAndClear(q);
|
||||
}
|
||||
|
||||
// ----------------------------------
|
||||
|
||||
int StdValueCompare(const Value& a, const Value& b, int language)
|
||||
{
|
||||
LTIMING("StdValueCompare");
|
||||
|
||||
bool na = IsNull(a), nb = IsNull(b);
|
||||
if(na || nb)
|
||||
return !na ? 1 : !nb ? -1 : 0;
|
||||
dword ta = a.GetType(), tb = b.GetType();
|
||||
if((ta == INT_V || ta == BOOL_V) && (tb == INT_V || tb == BOOL_V))
|
||||
return cmp<int>(a, b);
|
||||
if((ta == BOOL_V || ta == INT_V || ta == INT64_V || ta == DOUBLE_V)
|
||||
&& (tb == BOOL_V || tb == INT_V || tb == INT64_V || tb == DOUBLE_V))
|
||||
return cmp<double>(a, b);
|
||||
if(ta == DATE_V && tb == DATE_V)
|
||||
return cmp<Date>(a, b);
|
||||
if((ta == DATE_V || ta == TIME_V) && (tb == DATE_V || tb == TIME_V))
|
||||
return cmp<Time>(a, b);
|
||||
if((ta == STRING_V || ta == WSTRING_V) && (tb == STRING_V || tb == WSTRING_V))
|
||||
return GetLanguageInfo(language).Compare(WString(a), WString(b));
|
||||
return cmp<int>(ta, tb);
|
||||
}
|
||||
|
||||
int StdValueCompare(const Value& a, const Value& b)
|
||||
{
|
||||
return StdValueCompare(a, b, GetCurrentLanguage());
|
||||
}
|
||||
|
||||
int StdValueCompareDesc(const Value& a, const Value& b, int language)
|
||||
{
|
||||
return -StdValueCompare(a, b, language);
|
||||
}
|
||||
|
||||
int StdValueCompareDesc(const Value& a, const Value& b)
|
||||
{
|
||||
return -StdValueCompare(a, b);
|
||||
}
|
||||
|
||||
StdValueOrder::StdValueOrder(int l) : language(l) {}
|
||||
|
||||
bool StdValueOrder::operator()(const Value& a, const Value& b) const
|
||||
{
|
||||
return StdValueCompare(a, b, language) < 0;
|
||||
}
|
||||
|
||||
bool FnValueOrder::operator()(const Value& a, const Value& b) const
|
||||
{
|
||||
return (*fn)(a, b) < 0;
|
||||
}
|
||||
|
||||
bool StdValuePairOrder::operator()(const Value& k1, const Value& v1, const Value& k2, const Value& v2) const
|
||||
{
|
||||
int q = StdValueCompare(k1, k2, language);
|
||||
if(q) return q < 0;
|
||||
return StdValueCompare(v1, v2, language);
|
||||
}
|
||||
|
||||
bool FnValuePairOrder::operator()(const Value& keya, const Value& valuea, const Value& keyb, const Value& valueb) const
|
||||
{
|
||||
return (*fn)(keya, valuea, keyb, valueb) < 0;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
#endif
|
||||
326
uppsrc/Core/ValueUtil.h
Normal file
326
uppsrc/Core/ValueUtil.h
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
#ifdef SVO_VALUE
|
||||
|
||||
Value Scan(dword stdtype, const String& text, const Value& def = Null);
|
||||
|
||||
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); }
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
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)) : fn(fn) {}
|
||||
};
|
||||
|
||||
struct ValuePairOrder {
|
||||
virtual bool operator()(const Value& keya, const Value& valuea, const Value& keyb, const Value& valueb) const = 0;
|
||||
virtual ~ValuePairOrder() {}
|
||||
};
|
||||
|
||||
struct StdValuePairOrder : ValuePairOrder {
|
||||
int language;
|
||||
|
||||
virtual bool operator()(const Value& keya, const Value& valuea, const Value& keyb, const Value& valueb) const;
|
||||
|
||||
StdValuePairOrder(int l = -1);
|
||||
};
|
||||
|
||||
struct FnValuePairOrder : ValuePairOrder {
|
||||
int (*fn)(const Value& k1, const Value& v1, const Value& k2, const Value& v2);
|
||||
|
||||
virtual bool operator()(const Value& keya, const Value& valuea, const Value& keyb, const Value& valueb) const;
|
||||
|
||||
FnValuePairOrder(int (*fn)(const Value& k1, const Value& v1, const Value& k2, const Value& v2)) : fn(fn) {}
|
||||
};
|
||||
|
||||
class Id : Moveable<Id> {
|
||||
String id;
|
||||
|
||||
public:
|
||||
const String& ToString() const { return id; }
|
||||
dword GetHashValue() const { return UPP::GetHashValue(id); }
|
||||
bool IsNull() const { return UPP::IsNull(id); }
|
||||
|
||||
operator const String&() const { return ToString(); }
|
||||
const String& operator~() const { return ToString(); }
|
||||
bool operator==(const Id& b) const { return id == b.id; }
|
||||
bool operator!=(const Id& b) const { return id != b.id; }
|
||||
|
||||
operator bool() const { return id.GetCount(); }
|
||||
|
||||
Id() {}
|
||||
Id(const String& s) { id = s; }
|
||||
Id(const char *s) { id = s; }
|
||||
};
|
||||
|
||||
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 StdRef : public RefManager {
|
||||
virtual void SetValue(void *p, const Value& v) { *(T *) p = (T)v; }
|
||||
virtual Value GetValue(const void *p) { return *(const T *) p; }
|
||||
virtual int GetType() { return GetValueTypeNo<T>(); }
|
||||
virtual bool IsNull(const void *p) { return UPP::IsNull(*(T *) p); }
|
||||
virtual void SetNull(void *p) { UPP::SetNull(*(T *)p); }
|
||||
virtual ~StdRef() {}
|
||||
};
|
||||
|
||||
class Ref : Moveable<Ref> {
|
||||
protected:
|
||||
RefManager *m;
|
||||
void *ptr;
|
||||
struct ValueRef;
|
||||
|
||||
public:
|
||||
dword GetType() const { return m ? m->GetType() : VOID_V; }
|
||||
bool IsNull() const { return m ? m->IsNull(ptr) : true; }
|
||||
|
||||
void *GetVoidPtr() const { return ptr; }
|
||||
|
||||
void SetNull() { if(m) m->SetNull(ptr); }
|
||||
Value GetValue() const { return m ? m->GetValue(ptr) : Value(); }
|
||||
void SetValue(const Value& v) { ASSERT(m); m->SetValue(ptr, v); }
|
||||
|
||||
operator Value() const { return GetValue(); }
|
||||
Value operator~() const { return GetValue(); }
|
||||
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(bool& b);
|
||||
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(GetValueTypeNo<T>() == 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 bool& RefBool(Ref f) { return GetRef<bool>(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 AsRef(T& x) {
|
||||
return Ref(&x, &Single< StdRef<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();
|
||||
void Init0();
|
||||
|
||||
friend Value::Void *ValueArrayDataCreate(Stream& s);
|
||||
friend class Value;
|
||||
|
||||
public:
|
||||
ValueArray() { Init0(); }
|
||||
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&) { Init0(); }
|
||||
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);
|
||||
ValueArray& operator<<(const Value& v) { Add(v); return *this; }
|
||||
void Set(int i, const Value& v);
|
||||
const Value& Get(int i) const;
|
||||
Value GetAndClear(int i);
|
||||
const Vector<Value>& Get() const { return data->data; }
|
||||
|
||||
void Remove(int i, int count = 1);
|
||||
void Insert(int i, const ValueArray& va);
|
||||
void Append(const ValueArray& va) { Insert(GetCount(), va); }
|
||||
|
||||
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;
|
||||
|
||||
const Value& Get(const Value& key) const;
|
||||
|
||||
Index<Value> key;
|
||||
ValueArray value;
|
||||
};
|
||||
|
||||
struct NullData : Data {};
|
||||
Data *data;
|
||||
|
||||
Data& Create();
|
||||
Data& Clone();
|
||||
void Init0();
|
||||
|
||||
friend Value::Void *ValueMapDataCreate(Stream& s);
|
||||
friend class Value;
|
||||
|
||||
public:
|
||||
ValueMap() { Init0(); }
|
||||
ValueMap(const ValueMap& v);
|
||||
ValueMap(pick_ Index<Value>& k, pick_ Vector<Value>& v);
|
||||
ValueMap(const Index<Value>& k, const Vector<Value>& v, int deep);
|
||||
~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();
|
||||
int GetCount() const { return data->value.GetCount(); }
|
||||
bool IsEmpty() const { return data->value.IsEmpty(); }
|
||||
const Value& GetKey(int i) const { return data->key[i]; }
|
||||
const Value& GetValue(int i) const { return data->value[i]; }
|
||||
|
||||
void Add(const Value& key, const Value& value);
|
||||
void Add(const String& s, const Value& value) { Add(Value(s), 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); }
|
||||
|
||||
void Set(const Value& key, const Value& value);
|
||||
void Set(const String& s, const Value& value) { Set(Value(s), value); }
|
||||
void Set(const char *s, const Value& value) { Set(Value(s), value); }
|
||||
void Set(Id id, const Value& value) { Set(Value(id.ToString()), value); }
|
||||
|
||||
void SetAt(int i, const Value& v);
|
||||
void SetKey(int i, const Value& k);
|
||||
void SetKey(int i, const String& s) { SetKey(i, Value(s)); }
|
||||
void SetKey(int i, const char* s) { SetKey(i, Value(s)); }
|
||||
void SetKey(int i, Id id) { SetKey(i, Value(id.ToString())); }
|
||||
void Remove(int i);
|
||||
|
||||
const Index<Value>& GetKeys() const { return data->key; }
|
||||
ValueArray GetValues() const { return data->value; }
|
||||
|
||||
operator ValueArray() const { return GetValues(); }
|
||||
|
||||
const Value& operator[](const Value& k) const;
|
||||
const Value& operator[](const String& s) const{ return operator[](Value(s)); }
|
||||
const Value& operator[](const char *s) const { return operator[](Value(s)); }
|
||||
const Value& operator[](const Id& k) const { return operator[](Value(k.ToString())); }
|
||||
|
||||
Value GetAndClear(const Value& key);
|
||||
|
||||
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); }
|
||||
};
|
||||
|
||||
class ValueGen {
|
||||
public:
|
||||
virtual Value Get() = 0;
|
||||
Value operator++() { return Get(); }
|
||||
virtual ~ValueGen() {}
|
||||
};
|
||||
|
||||
|
||||
#include "Value.hpp"
|
||||
|
||||
#endif
|
||||
|
|
@ -208,7 +208,7 @@ public:
|
|||
void Move(int i1, int i2);
|
||||
|
||||
T *Detach(int i) { T *t = &Get(i); vector.Remove(i); return t; }
|
||||
T *Swap(int i, T *newt) { T *tmp = vector[i]; vector[i] = newt; return tmp; }
|
||||
T *Swap(int i, T *newt) { T *tmp = (T*)vector[i]; vector[i] = newt; return tmp; }
|
||||
T& Set(int i, T *newt) { delete (T *)vector[i]; vector[i] = newt; return *newt; }
|
||||
T& Insert(int i, T *newt);
|
||||
|
||||
|
|
|
|||
|
|
@ -91,7 +91,8 @@ mainconfig
|
|||
"" = ".NOGTK GUI",
|
||||
"" = "GUI HEAPDBG CHECKINIT",
|
||||
"" = "GUI TESTINSTALL",
|
||||
"" = "GUI CHECKCLIPBOARD";
|
||||
"" = "GUI CHECKCLIPBOARD",
|
||||
"" = "GUI SVO_VALUE";
|
||||
|
||||
custom() "",
|
||||
"",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue