From bdd9f06ee2d6008a8905aecd48495526531c8622 Mon Sep 17 00:00:00 2001 From: cxl Date: Sun, 20 May 2012 14:36:33 +0000 Subject: [PATCH] Core: XmlizeByJsonize git-svn-id: svn://ultimatepp.org/upp/trunk@4975 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Core/JSON.cpp | 646 ++++++++++++++++++++--------------------- uppsrc/Core/Xmlize.cpp | 57 ++++ uppsrc/Core/Xmlize.h | 15 +- 3 files changed, 394 insertions(+), 324 deletions(-) diff --git a/uppsrc/Core/JSON.cpp b/uppsrc/Core/JSON.cpp index 4b34ee0d4..577de40c5 100644 --- a/uppsrc/Core/JSON.cpp +++ b/uppsrc/Core/JSON.cpp @@ -1,323 +1,323 @@ -#include "Core.h" - -NAMESPACE_UPP - -Value ParseJSON(CParser& p) -{ - p.UnicodeEscape(); - if(p.IsDouble()) - return p.ReadDouble(); - if(p.IsString()) - return p.ReadString(); - if(p.Id("null")) - return Null; - if(p.Id("true")) - return true; - if(p.Id("false")) - return false; - if(p.Char('{')) { - ValueMap m; - if(!p.IsChar('}')) - do { - String key = p.ReadString(); - p.PassChar(':'); - m.Add(key, ParseJSON(p)); - } - while(p.Char(',')); - p.PassChar('}'); - return m; - } - if(p.Char('[')) { - ValueArray va; - if(!p.IsChar(']')) - do - va.Add(ParseJSON(p)); - while(p.Char(',')); - p.PassChar(']'); - return va; - } - p.ThrowError("Unrecognized JSON element"); - return Null; -} - -Value ParseJSON(const char *s) -{ - try { - CParser p(s); - return ParseJSON(p); - } - catch(CParser::Error) { - return ErrorValue(); - } -} - -String AsJSON(const Value& v, const String& sep, bool pretty) -{ - String r; - if(v.GetType() == VALUEMAP_V) { - r << "{"; - String sep1; - if(pretty) { - r << "\r\n"; - sep1 = sep + '\t'; - } - ValueMap m = v; - ValueArray va = m.GetValues(); - for(int i = 0; i < m.GetCount(); i++) { - if(i) { - r << ","; - if(pretty) - r << "\r\n"; - } - if(pretty) - r << sep1; - r << AsCString((String)m.GetKeys()[i]) << (pretty ? ": " : ":") - << AsJSON(va[i], sep1, pretty); - } - if(pretty) - r << "\r\n" << sep; - r << "}"; - return r; - } - if(v.GetType() == VALUEARRAY_V) { - r << "["; - String sep1; - if(pretty) { - r << "\r\n"; - sep1 = sep + '\t'; - } - ValueArray va = v; - for(int i = 0; i < va.GetCount(); i++) { - if(i) { - r << ","; - if(pretty) - r << "\r\n"; - } - if(pretty) - r << sep1; - r << AsJSON(va[i], sep1, pretty); - } - if(pretty) - r << "\r\n" << sep; - r << "]"; - return r; - } - if(IsNumber(v) && IsNull(v)) - return "null"; - if(v.GetType() == INT_V) - return Format("%d", (int)v); - if(v.GetType() == BOOL_V) - return (bool)v ? "true" : "false"; - if(IsNumber(v)) - return Format("%.16g", (double)v); - if(IsString(v)) - return AsCString((String)v); - if(IsNull(v)) - return "null"; - NEVER(); - return "null"; -} - -String AsJSON(const Value& v, bool pretty) -{ - return AsJSON(v, String(), pretty); -} - -template<> void Jsonize(JsonIO& io, double& var) -{ - if(io.IsLoading()) { - const Value& v = io.Get(); - if(IsNull(v)) { - var = Null; - return; - } - if(IsNumber(v)) { - var = io.Get(); - return; - } - if(IsString(v)) { - double h = ScanDouble((String)v); - if(!IsNull(h)) { - var = h; - return; - } - } - throw JsonizeError("number expected"); - } - else - io.Set(var); -} - -template<> void Jsonize(JsonIO& io, int& var) -{ - double v = IntDbl(var); - Jsonize(io, v); - if(io.IsLoading()) - if(IsNull(v)) - var = Null; - else - if(v >= INT_MIN && v <= INT_MAX && (int)v == v) - var = (int)v; - else - throw JsonizeError("number is not integer"); -} - -template<> void Jsonize(JsonIO& io, int16& var) -{ - double v = var; - Jsonize(io, v); - if(io.IsLoading()) - if(v >= -32768 && v <= 32767 && (int)v == v) - var = (int16)v; - else - throw JsonizeError("16-bit integer expected"); -} - -template<> void Jsonize(JsonIO& io, bool& var) -{ - if(io.IsLoading()) { - const Value& v = io.Get(); - if(IsNumber(v) && !IsNull(v)) - var = (bool)v; - else - throw JsonizeError("boolean expected"); - } - else - io.Set(var); -} - -template<> void Jsonize(JsonIO& io, int64& var) -{ - if(io.IsLoading()) { - const Value& v = io.Get(); - if(IsNull(v)) { - var = Null; - return; - } - if(v.Is() || v.Is()) { - var = v; - return; - } - if(IsNumber(v)) { - double d = v; - if(d >= INT64_MIN && d <= INT64_MAX) { - var = (int64)d; - return; - } - } - else - if(IsString(v)) { - int64 h = ScanInt64((String)v); - if(!IsNull(h)) { - var = h; - return; - } - } - throw JsonizeError("invalid int64 value"); - } - else - if(IsNull(var)) - io.Set(Null); - else - if(var >= INT_MIN && var <= INT_MAX) - io.Set(var); - else - io.Set(AsString(var)); -} - -template<> void Jsonize(JsonIO& io, String& var) -{ - if(io.IsLoading()) { - const Value& v = io.Get(); - if(IsString(v)) - var = v; - else - throw JsonizeError("string expected"); - } - else - io.Set(var); -} - -template<> void Jsonize(JsonIO& io, WString& var) -{ - if(io.IsLoading()) { - const Value& v = io.Get(); - if(IsString(v)) - var = v; - else - throw JsonizeError("string expected"); - } - else - io.Set(var); -} - -template<> void Jsonize(JsonIO& io, Date& var) -{ - if(io.IsLoading()) { - const Value& v = io.Get(); - if(IsNull(v)) { - var = Null; - return; - } - if(IsString(v)) { - String text = v; - if(text.GetCount() > 6) { - Date d; - d.year = ScanInt(text.Left(4)); - d.month = ScanInt(text.Mid(4, 2)); - d.day = ScanInt(text.Mid(6)); - if(d.IsValid()) { - var = d; - return; - } - } - } - throw JsonizeError("string expected for Date value"); - } - else - if(IsNull(var)) - io.Set(Null); - else - io.Set(Format("%04d%02d%02d", var.year, var.month, var.day)); -} - -template<> void Jsonize(JsonIO& io, Time& var) -{ - if(io.IsLoading()) { - const Value& v = io.Get(); - if(IsNull(v)) { - var = Null; - return; - } - if(IsString(v)) { - String text = v; - if(text.GetCount() > 15) { - Time tm; - tm.year = ScanInt(text.Left(4)); - tm.month = ScanInt(text.Mid(4, 2)); - tm.day = ScanInt(text.Mid(6, 2)); - tm.hour = ScanInt(text.Mid(9, 2)); - tm.minute = ScanInt(text.Mid(12, 2)); - tm.second = ScanInt(text.Mid(15)); - if(tm.IsValid()) { - var = tm; - return; - } - } - } - throw JsonizeError("string expected for Time value"); - } - else - if(IsNull(var)) - io.Set(Null); - else - io.Set(Format("%04d%02d%02d`T%02d:%02d:%02d", - var.year, var.month, var.day, var.hour, var.minute, var.second)); -} - -String sJsonFile(const char *file) -{ - return file ? String(file) : ConfigFile(GetExeTitle() + ".json"); -} - -END_UPP_NAMESPACE +#include "Core.h" + +NAMESPACE_UPP + +Value ParseJSON(CParser& p) +{ + p.UnicodeEscape(); + if(p.IsDouble()) + return p.ReadDouble(); + if(p.IsString()) + return p.ReadString(); + if(p.Id("null")) + return Null; + if(p.Id("true")) + return true; + if(p.Id("false")) + return false; + if(p.Char('{')) { + ValueMap m; + if(!p.IsChar('}')) + do { + String key = p.ReadString(); + p.PassChar(':'); + m.Add(key, ParseJSON(p)); + } + while(p.Char(',')); + p.PassChar('}'); + return m; + } + if(p.Char('[')) { + ValueArray va; + if(!p.IsChar(']')) + do + va.Add(ParseJSON(p)); + while(p.Char(',')); + p.PassChar(']'); + return va; + } + p.ThrowError("Unrecognized JSON element"); + return Null; +} + +Value ParseJSON(const char *s) +{ + try { + CParser p(s); + return ParseJSON(p); + } + catch(CParser::Error) { + return ErrorValue(); + } +} + +String AsJSON(const Value& v, const String& sep, bool pretty) +{ + String r; + if(v.GetType() == VALUEMAP_V) { + r << "{"; + String sep1; + if(pretty) { + r << "\r\n"; + sep1 = sep + '\t'; + } + ValueMap m = v; + ValueArray va = m.GetValues(); + for(int i = 0; i < m.GetCount(); i++) { + if(i) { + r << ","; + if(pretty) + r << "\r\n"; + } + if(pretty) + r << sep1; + r << AsCString((String)m.GetKeys()[i]) << (pretty ? ": " : ":") + << AsJSON(va[i], sep1, pretty); + } + if(pretty) + r << "\r\n" << sep; + r << "}"; + return r; + } + if(v.GetType() == VALUEARRAY_V) { + r << "["; + String sep1; + if(pretty) { + r << "\r\n"; + sep1 = sep + '\t'; + } + ValueArray va = v; + for(int i = 0; i < va.GetCount(); i++) { + if(i) { + r << ","; + if(pretty) + r << "\r\n"; + } + if(pretty) + r << sep1; + r << AsJSON(va[i], sep1, pretty); + } + if(pretty) + r << "\r\n" << sep; + r << "]"; + return r; + } + if(IsNumber(v) && IsNull(v)) + return "null"; + if(v.GetType() == INT_V) + return Format("%d", (int)v); + if(v.GetType() == BOOL_V) + return (bool)v ? "true" : "false"; + if(IsNumber(v)) + return Format("%.16g", (double)v); + if(IsString(v)) + return AsCString((String)v); + if(IsNull(v)) + return "null"; + NEVER(); + return "null"; +} + +String AsJSON(const Value& v, bool pretty) +{ + return AsJSON(v, String(), pretty); +} + +template<> void Jsonize(JsonIO& io, double& var) +{ + if(io.IsLoading()) { + const Value& v = io.Get(); + if(IsNull(v)) { + var = Null; + return; + } + if(IsNumber(v)) { + var = io.Get(); + return; + } + if(IsString(v)) { + double h = ScanDouble((String)v); + if(!IsNull(h)) { + var = h; + return; + } + } + throw JsonizeError("number expected"); + } + else + io.Set(var); +} + +template<> void Jsonize(JsonIO& io, int& var) +{ + double v = IntDbl(var); + Jsonize(io, v); + if(io.IsLoading()) + if(IsNull(v)) + var = Null; + else + if(v >= INT_MIN && v <= INT_MAX && (int)v == v) + var = (int)v; + else + throw JsonizeError("number is not integer"); +} + +template<> void Jsonize(JsonIO& io, int16& var) +{ + double v = var; + Jsonize(io, v); + if(io.IsLoading()) + if(v >= -32768 && v <= 32767 && (int)v == v) + var = (int16)v; + else + throw JsonizeError("16-bit integer expected"); +} + +template<> void Jsonize(JsonIO& io, bool& var) +{ + if(io.IsLoading()) { + const Value& v = io.Get(); + if(IsNumber(v) && !IsNull(v)) + var = (bool)v; + else + throw JsonizeError("boolean expected"); + } + else + io.Set(var); +} + +template<> void Jsonize(JsonIO& io, int64& var) +{ + if(io.IsLoading()) { + const Value& v = io.Get(); + if(IsNull(v)) { + var = Null; + return; + } + if(v.Is() || v.Is()) { + var = v; + return; + } + if(IsNumber(v)) { + double d = v; + if(d >= INT64_MIN && d <= INT64_MAX) { + var = (int64)d; + return; + } + } + else + if(IsString(v)) { + int64 h = ScanInt64((String)v); + if(!IsNull(h)) { + var = h; + return; + } + } + throw JsonizeError("invalid int64 value"); + } + else + if(IsNull(var)) + io.Set(Null); + else + if(var >= INT_MIN && var <= INT_MAX) + io.Set(var); + else + io.Set(AsString(var)); +} + +template<> void Jsonize(JsonIO& io, String& var) +{ + if(io.IsLoading()) { + const Value& v = io.Get(); + if(IsString(v)) + var = v; + else + throw JsonizeError("string expected"); + } + else + io.Set(var); +} + +template<> void Jsonize(JsonIO& io, WString& var) +{ + if(io.IsLoading()) { + const Value& v = io.Get(); + if(IsString(v)) + var = v; + else + throw JsonizeError("string expected"); + } + else + io.Set(var); +} + +template<> void Jsonize(JsonIO& io, Date& var) +{ + if(io.IsLoading()) { + const Value& v = io.Get(); + if(IsNull(v)) { + var = Null; + return; + } + if(IsString(v)) { + String text = v; + if(text.GetCount() > 6) { + Date d; + d.year = ScanInt(text.Left(4)); + d.month = ScanInt(text.Mid(4, 2)); + d.day = ScanInt(text.Mid(6)); + if(d.IsValid()) { + var = d; + return; + } + } + } + throw JsonizeError("string expected for Date value"); + } + else + if(IsNull(var)) + io.Set(Null); + else + io.Set(Format("%04d%02d%02d", var.year, var.month, var.day)); +} + +template<> void Jsonize(JsonIO& io, Time& var) +{ + if(io.IsLoading()) { + const Value& v = io.Get(); + if(IsNull(v)) { + var = Null; + return; + } + if(IsString(v)) { + String text = v; + if(text.GetCount() > 15) { + Time tm; + tm.year = ScanInt(text.Left(4)); + tm.month = ScanInt(text.Mid(4, 2)); + tm.day = ScanInt(text.Mid(6, 2)); + tm.hour = ScanInt(text.Mid(9, 2)); + tm.minute = ScanInt(text.Mid(12, 2)); + tm.second = ScanInt(text.Mid(15)); + if(tm.IsValid()) { + var = tm; + return; + } + } + } + throw JsonizeError("string expected for Time value"); + } + else + if(IsNull(var)) + io.Set(Null); + else + io.Set(Format("%04d%02d%02d`T%02d:%02d:%02d", + var.year, var.month, var.day, var.hour, var.minute, var.second)); +} + +String sJsonFile(const char *file) +{ + return file ? String(file) : ConfigFile(GetExeTitle() + ".json"); +} + +END_UPP_NAMESPACE diff --git a/uppsrc/Core/Xmlize.cpp b/uppsrc/Core/Xmlize.cpp index 830b1d238..e4fc3856a 100644 --- a/uppsrc/Core/Xmlize.cpp +++ b/uppsrc/Core/Xmlize.cpp @@ -389,4 +389,61 @@ bool LoadFromXMLFile(Callback1 xmlize, const char *file) return LoadFromXML(xmlize, LoadFile(sXMLFile(file))); } + +void StoreJsonValue(XmlIO& xio, const Value& v) +{ + if(v.GetType() == VALUEMAP_V) { + ValueMap m = v; + ValueArray va = m.GetValues(); + for(int i = 0; i < m.GetCount(); i++) { + Value h = m.GetValue(i); + XmlIO io = xio.Add((String)m.GetKey(i)); + StoreJsonValue(io, h); + } + return; + } + else + if(v.GetType() == VALUEARRAY_V) { + ValueArray va = v; + for(int i = 0; i < va.GetCount(); i++) { + XmlIO io = xio.Add("item"); + Value h = va[i]; + StoreJsonValue(io, h); + } + } + else + if(v.GetType() == BOOL_V) { + bool b = v; + Xmlize(xio, b); + } + else + if(IsNumber(v)) { + double h = v; + Xmlize(xio, h); + return; + } + else + if(IsString(v)) { + String h = v; + Xmlize(xio, h); + } + else + NEVER(); +} + +Value LoadJsonValue(const XmlNode& n) +{ + String h = n.Attr("value"); + if(h.GetCount()) + return ScanDouble(h); + ValueMap m; + String text; + for(int i = 0; i < n.GetCount(); i++) + if(n[i].IsTag()) + m.Add(n[i].GetTag(), LoadJsonValue(n[i])); + else + return n[i].GetText(); + return m; +} + END_UPP_NAMESPACE diff --git a/uppsrc/Core/Xmlize.h b/uppsrc/Core/Xmlize.h index 38ed29b6a..c6c7ddf50 100644 --- a/uppsrc/Core/Xmlize.h +++ b/uppsrc/Core/Xmlize.h @@ -325,7 +325,7 @@ void XmlizeBySerialize(XmlIO& xio, T& x) { String h; if(xio.IsStoring()) - h = HexString(StoreAsString(x)); + h = HexString(StoreAsString(x)); xio.Attr("data", h); if(xio.IsLoading()) try { @@ -335,3 +335,16 @@ void XmlizeBySerialize(XmlIO& xio, T& x) throw XmlError("xmlize by serialize error"); } } + + +void StoreJsonValue(XmlIO& xio, const Value& v); +Value LoadJsonValue(const XmlNode& n); + +template +void XmlizeByJsonize(XmlIO& xio, T& x) +{ + if(xio.IsStoring()) + StoreJsonValue(xio, StoreAsJsonValue(x)); + else + LoadFromJsonValue(x, LoadJsonValue(xio.Node())); +}