diff --git a/uppsrc/Core/Color.cpp b/uppsrc/Core/Color.cpp index 7441f1806..1ae4a69f1 100644 --- a/uppsrc/Core/Color.cpp +++ b/uppsrc/Core/Color.cpp @@ -121,7 +121,7 @@ Color Blend(Color c1, Color c2, int alpha) #ifdef SVO_VALUE INITBLOCK { - Value::SvoRegister(); + Value::SvoRegister("Color"); } #else INITBLOCK { diff --git a/uppsrc/Core/Gtypes.cpp b/uppsrc/Core/Gtypes.cpp index 521eec7da..2291e61b7 100644 --- a/uppsrc/Core/Gtypes.cpp +++ b/uppsrc/Core/Gtypes.cpp @@ -2,43 +2,6 @@ NAMESPACE_UPP -#ifdef SVO_VALUE -template -static void sReg() -{ - if(FitsSvoValue()) - Value::SvoRegister(); - else - Value::Register(); -} - -INITBLOCK -{ - sReg(); - sReg(); - sReg(); - sReg(); - sReg(); - sReg(); - Value::Register(); - Value::Register(); - Value::Register(); -} -#else -INITBLOCK { - Point p; - RichValue::Register(); - RichValue::Register(); - RichValue::Register(); - RichValue::Register(); - RichValue::Register(); - RichValue::Register(); - RichValue::Register(); - RichValue::Register(); - RichValue::Register(); -} -#endif - //template <> //void Rect_::Union(const Rect_& r) { void Rect_double_Union(Rect_& self, const Rect_& r) { diff --git a/uppsrc/Core/JSON.cpp b/uppsrc/Core/JSON.cpp index edb4d964c..f23ac2e9a 100644 --- a/uppsrc/Core/JSON.cpp +++ b/uppsrc/Core/JSON.cpp @@ -112,6 +112,8 @@ String AsJSON(const Value& v, const String& sep, bool pretty) return Format("%.16g", (double)v); if(IsString(v)) return AsCString((String)v); + if(IsNull(v)) + return "null"; NEVER(); return "null"; } diff --git a/uppsrc/Core/OldValue.cpp b/uppsrc/Core/OldValue.cpp index 0c48ec9bc..5a22e9ec4 100644 --- a/uppsrc/Core/OldValue.cpp +++ b/uppsrc/Core/OldValue.cpp @@ -164,7 +164,6 @@ INITBLOCK { sRegisterStd(); } - void Value::Serialize(Stream& s) { sRegisterStd(); dword type; diff --git a/uppsrc/Core/Uuid.cpp b/uppsrc/Core/Uuid.cpp index 6c79d0a5b..ce2e5d0a3 100644 --- a/uppsrc/Core/Uuid.cpp +++ b/uppsrc/Core/Uuid.cpp @@ -6,7 +6,7 @@ NAMESPACE_UPP #ifdef SVO_VALUE INITBLOCK { - Value::Register(); + Value::Register("Uuid"); } #else INITBLOCK { @@ -68,6 +68,16 @@ Uuid ScanUuid(const char *s) return id; } +void Uuid::Xmlize(XmlIO& xio) +{ + String h; + if(xio.IsStoring()) + h = Format(*this); + xio.Attr("value", h); + if(xio.IsLoading()) + *this = ScanUuid(h); +} + String Uuid::ToString() const { return Format(*this); diff --git a/uppsrc/Core/Uuid.h b/uppsrc/Core/Uuid.h index a48840338..79c28da11 100644 --- a/uppsrc/Core/Uuid.h +++ b/uppsrc/Core/Uuid.h @@ -2,6 +2,7 @@ struct Uuid : AssignValueTypeNo > { dword a, b, c, d; void Serialize(Stream& s); + void Xmlize(XmlIO& xio); bool IsNullInstance() const { return a == 0 && b == 0 && c == 0 && d == 0; } void SetNull() { a = b = c = d = 0; } diff --git a/uppsrc/Core/Value.cpp b/uppsrc/Core/Value.cpp index 9de38047a..75cbe682c 100644 --- a/uppsrc/Core/Value.cpp +++ b/uppsrc/Core/Value.cpp @@ -157,6 +157,40 @@ VectorMap& Value::Typemap() return x; } +Index& Value::NameNdx() +{ + static Index x; + return x; +} + +Index& Value::TypeNdx() +{ + static Index x; + return x; +} + +void Value::AddName(dword type, const char *name) +{ + NameNdx().Add(name); + TypeNdx().Add(type); +} + +int Value::GetType(const char *name) +{ + int q = NameNdx().Find(name); + if(q < 0) + return Null; + return TypeNdx()[q]; +} + +String Value::GetName(dword type) +{ + int q = TypeNdx().Find(type); + if(q < 0) + return Null; + return NameNdx()[q]; +} + SVO_FN(s_String, String); SVO_FN(s_int, int); SVO_FN(s_double, double); @@ -215,22 +249,36 @@ Value::Void *ValueMapDataCreate() return new ValueMap::Data; } -static void sRegisterStd() +void Value::RegisterStd() { ONCELOCK { - RichValue::Register(); - RichValue::Register(); - Value::Register(VALUEARRAY_V, ValueArrayDataCreate); - Value::Register(VALUEMAP_V, ValueMapDataCreate); + Value::Register("WString"); + Value::Register("Complex"); + Value::Register(VALUEARRAY_V, ValueArrayDataCreate, "ValueArray"); + Value::Register(VALUEMAP_V, ValueMapDataCreate, "ValueMap"); + Value::AddName(STRING_V, "String"); + Value::AddName(INT_V, "int"); + Value::AddName(DOUBLE_V, "double"); + Value::AddName(VOID_V, "void"); + Value::AddName(DATE_V, "date"); + Value::AddName(TIME_V, "time"); + Value::AddName(INT64_V, "int64"); + Value::AddName(BOOL_V, "bool"); + Value::AddName(ERROR_V, "error"); }; } +void ValueRegisterHelper() +{ + Value::RegisterStd(); +} + INITBLOCK { - sRegisterStd(); + ValueRegisterHelper(); } void Value::Serialize(Stream& s) { - sRegisterStd(); + RegisterStd(); dword type; if(s.IsLoading()) { s / type; @@ -278,15 +326,161 @@ void Value::Serialize(Stream& s) { } } +static String s_binary("serialized_binary"); + void Value::Xmlize(XmlIO& xio) { + RegisterStd(); + if(xio.IsStoring()) { + dword type = GetType(); + String name = GetName(type); + if(name.GetCount() == 0) { + xio.SetAttr("type", s_binary); + String s = HexString(StoreAsString(*this)); + Upp::Xmlize(xio, s); + } + else { + xio.SetAttr("type", name); + 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) + Upp::Xmlize(xio, data); + else + if(IsRef()) + ptr()->Xmlize(xio); + else + svo[st]->Xmlize(&data, xio); + } + } + else { + String name = xio.GetAttr("type"); + if(name == s_binary) { + String s; + Upp::Xmlize(xio, s); + try { + LoadFromString(*this, ScanHexString(s)); + } + catch(LoadingError) { + throw XmlError("serialized_binary Error"); + } + } + else { + int type = GetType(name); + if(Upp::IsNull(type)) + throw XmlError("invalid Value type"); + Free(); + int st = (dword)type == VOID_V ? VOIDV : (dword)type == STRING_V ? STRING : type; + if(st == STRING) + Upp::Xmlize(xio, data); + else + if(st < 255 && svo[st]) { + data.SetSpecial((byte)type); + svo[st]->Xmlize(&data, xio); + } + else { + typedef Void* (*vp)(); + vp *cr = Typemap().FindPtr(type); + if(cr) { + Void *p = (**cr)(); + p->Xmlize(xio); + InitRef(p); + } + else + throw XmlError("invalid Value type"); + } + } + } } void Value::Jsonize(JsonIO& jio) { + RegisterStd(); + if(jio.IsStoring()) { + dword type = GetType(); + String name = GetName(type); + if(name.GetCount() == 0) { + String s = HexString(StoreAsString(*this)); + jio("type", s_binary) + ("value", s); + } + else { + 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; + JsonIO hio; + if(st == STRING) { + String h = data; + Upp::Jsonize(hio, h); + } + else { + if(IsRef()) + ptr()->Jsonize(hio); + else + svo[st]->Jsonize(&data, hio); + } + ValueMap m; + m.Add("type", name); + m.Add("value", hio.GetResult()); + jio.Set(m); + } + } + else { + Value g = jio.Get(); + String name = g["type"]; + Value val = g["value"]; + if(name == s_binary) { + if(!Upp::IsString(val)) + throw JsonizeError("serialized_binary Error"); + String s = val; + try { + LoadFromString(*this, ScanHexString(s)); + } + catch(LoadingError) { + throw JsonizeError("serialized_binary Error"); + } + } + else { + DDUMP(name); + int type = GetType(name); + if(Upp::IsNull(type)) + throw JsonizeError("invalid Value type"); + Free(); + int st = (dword)type == VOID_V ? VOIDV : (dword)type == STRING_V ? STRING : type; + if(st == STRING) { + if(!Upp::IsString(val)) + throw JsonizeError("serialized_binary Error"); + data = val; + } + else { + JsonIO hio(val); + if(st < 255 && svo[st]) { + data.SetSpecial((byte)type); + svo[st]->Jsonize(&data, hio); + } + else { + typedef Void* (*vp)(); + vp *cr = Typemap().FindPtr(type); + if(cr) { + Void *p = (**cr)(); + p->Jsonize(hio); + InitRef(p); + } + else + throw JsonizeError("invalid Value type"); + } + } + } + } } -void Value::Register(dword w, Void* (*c)()) init_ { +void Value::Register(dword w, Void* (*c)(), const char *name) init_ { #ifdef flagCHECKINIT RLOG("Register valuetype " << w); #endif @@ -294,6 +488,7 @@ void Value::Register(dword w, Void* (*c)()) init_ { ASSERT(w != UNKNOWN_V); ASSERT(w < 0x8000000); CHECK(Typemap().GetAdd(w, c) == c); + AddName(w, name); } String Value::ToString() const { diff --git a/uppsrc/Core/Value.h b/uppsrc/Core/Value.h index d31bd5111..cab945878 100644 --- a/uppsrc/Core/Value.h +++ b/uppsrc/Core/Value.h @@ -81,6 +81,8 @@ public: virtual dword GetType() const { return VOID_V; } virtual bool IsNull() const { return true; } virtual void Serialize(Stream& s) {} + virtual void Xmlize(XmlIO& xio) {} + virtual void Jsonize(JsonIO& jio) {} virtual unsigned GetHashValue() const { return 0; } virtual bool IsEqual(const Void *p) { return false; } virtual bool IsPolyEqual(const Value& v) { return false; } @@ -108,6 +110,15 @@ protected: static VectorMap& Typemap(); static Sval *svo[256]; + static Index& NameNdx(); + static Index& TypeNdx(); + + static void AddName(dword type, const char *name); + static int GetType(const char *name); + static String GetName(dword type); + static void RegisterStd(); + + friend void ValueRegisterHelper(); String data; Void *&ptr() { ASSERT(IsRef()); return *(Void **)&data; } @@ -148,12 +159,12 @@ protected: String GetName() const; public: - static void Register(dword w, Void* (*c)()) init_; // Direct use deprecated + static void Register(dword w, Void* (*c)(), const char *name = NULL) init_; // Direct use deprecated template - static void Register(); + static void Register(const char *name = NULL); template - static void SvoRegister(); + static void SvoRegister(const char *name = NULL); dword GetType() const; bool IsError() const { return GetType() == ERROR_V; } diff --git a/uppsrc/Core/Value.hpp b/uppsrc/Core/Value.hpp index ec23a46e4..2e8297051 100644 --- a/uppsrc/Core/Value.hpp +++ b/uppsrc/Core/Value.hpp @@ -144,12 +144,13 @@ T& Value::GetSmall() const } template -void Value::SvoRegister() +void Value::SvoRegister(const char *name) { dword t = GetValueTypeNo(); ASSERT(t < 255); SVO_FN(sval, T) svo[t] = &sval; + AddName(t, name); } template @@ -247,9 +248,10 @@ unsigned Value::GetHashValue() const } template -void Value::Register() +void Value::Register(const char *name) { - Value::Register(GetValueTypeNo(), RichValueRep::Create); + dword t = GetValueTypeNo(); + Value::Register(t, RichValueRep::Create, name); } inline diff --git a/uppsrc/Core/ValueUtil.cpp b/uppsrc/Core/ValueUtil.cpp index bb65e6f52..885142cb0 100644 --- a/uppsrc/Core/ValueUtil.cpp +++ b/uppsrc/Core/ValueUtil.cpp @@ -36,6 +36,11 @@ void ValueArray::Data::Serialize(Stream& s) s % data; } +void ValueArray::Data::Xmlize(XmlIO& io) +{ + Upp::Xmlize(io, data); +} + unsigned ValueArray::Data::GetHashValue() const { CombineHash w(data.GetCount()); @@ -225,6 +230,12 @@ void ValueMap::Data::Serialize(Stream& s) { s % key % value; } +void ValueMap::Data::Xmlize(XmlIO& xio) +{ + Upp::Xmlize(xio, key); + Upp::Xmlize(xio, value); +} + unsigned ValueMap::Data::GetHashValue() const { CombineHash w(key.GetCount()); for(int i = 0; i < key.GetCount(); i++) @@ -484,7 +495,7 @@ void Complex::Jsonize(JsonIO& jio) { double r, i; r = real(); i = imag(); - jio("real", r)("image", i); + jio("real", r)("imag", i); *this = C(r, i); } @@ -496,5 +507,42 @@ void Complex::Serialize(Stream& s) *this = C(r, i); } +#ifdef SVO_VALUE +template +static void sReg(const char *name) +{ + if(FitsSvoValue()) + Value::SvoRegister(name); + else + Value::Register(name); +} + +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::Register(); + RichValue::Register(); + RichValue::Register(); + RichValue::Register(); + RichValue::Register(); + RichValue::Register(); + RichValue::Register(); + RichValue::Register(); + RichValue::Register(); +} +#endif + END_UPP_NAMESPACE diff --git a/uppsrc/Core/ValueUtil.h b/uppsrc/Core/ValueUtil.h index 4863a0f23..6f2e4a53c 100644 --- a/uppsrc/Core/ValueUtil.h +++ b/uppsrc/Core/ValueUtil.h @@ -165,6 +165,7 @@ class ValueArray : AssignValueTypeNo >{ virtual dword GetType() const { return VALUEMAP_V; } virtual bool IsNull() const; virtual void Serialize(Stream& s); + virtual void Xmlize(XmlIO& xio); virtual unsigned GetHashValue() const; virtual bool IsEqual(const Value::Void *p); virtual String AsString() const; diff --git a/uppsrc/Core/Xmlize.cpp b/uppsrc/Core/Xmlize.cpp index 594108fab..eeeaa7035 100644 --- a/uppsrc/Core/Xmlize.cpp +++ b/uppsrc/Core/Xmlize.cpp @@ -211,6 +211,7 @@ void Xmlize(XmlIO& xml, Color& c) c = Color(r, g, b); } +#ifndef SVO_VALUE typedef void (*ValueXmlizer)(XmlIO& xml, Value& v); VectorMap& ValueXmlizeMap() @@ -238,7 +239,6 @@ void RegisterValueXmlize(dword type, void (*xmlize)(XmlIO& xml, Value& v), const ValueXmlizeName().Add(name); } -#ifndef SVO_VALUE REGISTER_VALUE_XMLIZE(String); REGISTER_VALUE_XMLIZE(WString); REGISTER_VALUE_XMLIZE(int); diff --git a/uppsrc/Draw/Draw.h b/uppsrc/Draw/Draw.h index 71b43a2d5..26b9a6fd8 100644 --- a/uppsrc/Draw/Draw.h +++ b/uppsrc/Draw/Draw.h @@ -43,7 +43,7 @@ const int FONT_V = 40; class FontInfo; -class Font : AssignValueTypeNo >{ +class Font : public AssignValueTypeNo >{ union { int64 data; struct { @@ -366,7 +366,7 @@ void SColorDkShadow_Write(Color c); inline Color InvertColor() { return Color(255, 0); } inline Color DefaultInk() { return Black(); } //TODO! -class Painting : AssignValueTypeNo > { +class Painting : public AssignValueTypeNo > { String cmd; ValueArray data; Sizef size; @@ -617,7 +617,7 @@ public: template static void Register(const char *id) { AddFormat(id, &DataDrawer::FactoryFn); } }; -class Drawing : AssignValueTypeNo > { +class Drawing : public AssignValueTypeNo > { Size size; String data; ValueArray val; diff --git a/uppsrc/ide/ide.upp b/uppsrc/ide/ide.upp index 22f9077b7..37e198c6e 100644 --- a/uppsrc/ide/ide.upp +++ b/uppsrc/ide/ide.upp @@ -87,7 +87,7 @@ file Copying; mainconfig - "" = "GUI", + "" = "GUI SVO_VALUE", "" = "GUI .USEMALLOC", "" = ".NOGTK GUI", "" = "GUI HEAPDBG CHECKINIT",