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:
cxl 2012-01-30 14:53:29 +00:00
parent 3083aefbc3
commit 8afe5fef70
22 changed files with 3122 additions and 1224 deletions

View file

@ -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)
{

View file

@ -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);

View file

@ -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) {

View file

@ -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"

View file

@ -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,

View file

@ -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

View file

@ -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) {

View file

@ -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
View 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
View 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

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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() {}

View file

@ -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

View file

@ -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
View 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
View 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
View 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

View file

@ -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);

View file

@ -91,7 +91,8 @@ mainconfig
"" = ".NOGTK GUI",
"" = "GUI HEAPDBG CHECKINIT",
"" = "GUI TESTINSTALL",
"" = "GUI CHECKCLIPBOARD";
"" = "GUI CHECKCLIPBOARD",
"" = "GUI SVO_VALUE";
custom() "",
"",