diff --git a/uppsrc/Core/Core.upp b/uppsrc/Core/Core.upp index cc086f158..f273dd626 100644 --- a/uppsrc/Core/Core.upp +++ b/uppsrc/Core/Core.upp @@ -155,6 +155,7 @@ file XML.h, XML.cpp, Xmlize.h, + Xmlize.hpp, Xmlize.cpp, JSON.h, JSON.cpp, diff --git a/uppsrc/Core/InVector.hpp b/uppsrc/Core/InVector.hpp index bc4a46819..55c4609ec 100644 --- a/uppsrc/Core/InVector.hpp +++ b/uppsrc/Core/InVector.hpp @@ -687,7 +687,6 @@ void InVector::Swap(InVector& b) Upp::Swap(slave, b.slave); } -#ifdef UPP template void InVector::Xmlize(XmlIO& xio, const char *itemtag) { @@ -706,8 +705,6 @@ String InVector::ToString() const return AsStringArray(*this); } -#endif - template void InVector::DumpIndex() const { diff --git a/uppsrc/Core/JSON.h b/uppsrc/Core/JSON.h index de77de9e0..4bb43e1a3 100644 --- a/uppsrc/Core/JSON.h +++ b/uppsrc/Core/JSON.h @@ -105,6 +105,15 @@ public: template JsonIO& operator()(const char *key, T& value, const T& defvalue); + + template + JsonIO& List(const char *key, const char *, T& var) { return operator()(key, var); } + + template + JsonIO& Var(const char *key, T& value, X item_jsonize); + + template + JsonIO& Array(const char *key, T& value, X item_jsonize, const char * = NULL); JsonIO(const Value& src) : src(&src) {} JsonIO() { src = NULL; } @@ -144,6 +153,77 @@ JsonIO& JsonIO::operator()(const char *key, T& value) return *this; } +template +JsonIO& JsonIO::Var(const char *key, T& value, X jsonize) +{ + if(IsLoading()) { + const Value& v = (*src)[key]; + if(!v.IsVoid()) { + JsonIO jio(v); + jsonize(jio, value); + } + } + else { + ASSERT(tgt.IsVoid()); + if(!map) + map.Create(); + JsonIO jio; + jsonize(jio, value); + if(jio.map) + map->Add(key, *jio.map); + else + map->Add(key, jio.tgt); + } + return *this; +} + + +template +void JsonizeArray(JsonIO& io, T& array, X item_jsonize) +{ + if(io.IsLoading()) { + const Value& va = io.Get(); + array.SetCount(va.GetCount()); + for(int i = 0; i < va.GetCount(); i++) { + JsonIO jio(va[i]); + item_jsonize(jio, array[i]); + } + } + else { + Vector va; + va.SetCount(array.GetCount()); + for(int i = 0; i < array.GetCount(); i++) { + JsonIO jio; + item_jsonize(jio, array[i]); + jio.Put(va[i]); + } + io.Set(ValueArray(pick(va))); + } +} + +template JsonIO& JsonIO::Array(const char *key, T& value, X item_jsonize, const char *) +{ + if(IsLoading()) { + const Value& v = (*src)[key]; + if(!v.IsVoid()) { + JsonIO jio(v); + JsonizeArray(jio, value, item_jsonize); + } + } + else { + ASSERT(tgt.IsVoid()); + if(!map) + map.Create(); + JsonIO jio; + JsonizeArray(jio, value, item_jsonize); + if(jio.map) + map->Add(key, *jio.map); + else + map->Add(key, jio.tgt); + } + return *this; +} + template JsonIO& JsonIO::operator()(const char *key, T& value, const T& defvalue) { @@ -234,24 +314,7 @@ template<> void Jsonize(JsonIO& io, Time& var); template void JsonizeArray(JsonIO& io, T& array) { - if(io.IsLoading()) { - const Value& va = io.Get(); - array.SetCount(va.GetCount()); - for(int i = 0; i < va.GetCount(); i++) { - JsonIO jio(va[i]); - Jsonize(jio, array[i]); - } - } - else { - Vector va; - va.SetCount(array.GetCount()); - for(int i = 0; i < array.GetCount(); i++) { - JsonIO jio; - Jsonize(jio, array[i]); - jio.Put(va[i]); - } - io.Set(ValueArray(pick(va))); - } + JsonizeArray(io, array, [](JsonIO& io, ValueTypeOf& item) { Jsonize(io, item); }); } template diff --git a/uppsrc/Core/XML.h b/uppsrc/Core/XML.h index 07d113b11..2f03e4a5b 100644 --- a/uppsrc/Core/XML.h +++ b/uppsrc/Core/XML.h @@ -8,7 +8,6 @@ String XmlDocType(const char *text); String XmlDoc(const char *name, const char *xmlbody); String XmlComment(const char *text); - class XmlTag : Moveable { String tag; String end; diff --git a/uppsrc/Core/Xmlize.h b/uppsrc/Core/Xmlize.h index 3fb3fda92..d8e1893b8 100644 --- a/uppsrc/Core/Xmlize.h +++ b/uppsrc/Core/Xmlize.h @@ -31,6 +31,8 @@ public: template XmlIO operator()(const char *tag, T& var); template XmlIO List(const char *tag, const char *itemtag, T& var); + template XmlIO Var(const char *tag, T& var, X var_xmlize); + template XmlIO Array(const char *tag, T& var, X item_xmlize, const char *itemtag = "item"); template XmlIO operator()(const char *tag, T& var, const D& def); template XmlIO List(const char *tag, const char *itemtag, T& var, const D& def); @@ -68,54 +70,6 @@ public: XmlIO(XmlIO xml, const char *tag) : node(xml.node.GetAdd(tag)), loading(xml.loading), userdata(xml.userdata) {} }; -template -void Xmlize(XmlIO& xml, T& var) -{ - var.Xmlize(xml); -} - -template -void Xmlize(XmlIO& xml, const char* itemtag, T& var) -{ - var.Xmlize(xml, itemtag); -} - -template XmlIO XmlIO::operator()(const char *tag, T& var) { - XmlIO n(*this, tag); - if(IsLoading() && n.Node().GetCount() == 0 && n.Node().GetAttrCount() == 0) - return *this; - Xmlize(n, var); - return *this; -} - -template XmlIO XmlIO::List(const char *tag, const char *itemtag, T& var) { - XmlIO n(*this, tag); - if(IsLoading() && n.Node().GetCount() == 0 && n.Node().GetAttrCount() == 0) - return *this; - Xmlize(n, itemtag, var); - return *this; -} - -template XmlIO XmlIO::operator()(const char *tag, T& var, const D& def) -{ - XmlIO n(*this, tag); - if(IsLoading() && n.Node().GetCount() == 0 && n.Node().GetAttrCount() == 0) - var = def; - else - Xmlize(n, var); - return *this; -} - -template XmlIO XmlIO::List(const char *tag, const char *itemtag, T& var, const D& def) -{ - XmlIO n(*this, tag); - if(IsLoading() && n.Node().GetCount() == 0 && n.Node().GetAttrCount() == 0) - var = def; - else - Xmlize(n, itemtag, var); - return *this; -} - template<> inline void XmlAttrLoad(String& var, const String& text) { var = text; } template<> inline String XmlAttrStore(const String& var) { return var; } @@ -155,24 +109,33 @@ template<> void Xmlize(XmlIO& xml, byte& var); void XmlizeLangAttr(XmlIO& xml, int& lang, const char *id = "lang"); void XmlizeLang(XmlIO& xml, const char *tag, int& lang, const char *id = "id"); -template -void XmlizeContainer(XmlIO& xml, const char *tag, T& data) +template +void Xmlize(XmlIO& xml, T& var) { - if(xml.IsStoring()) - for(int i = 0; i < data.GetCount(); i++) { - XmlIO io = xml.Add(tag); - Xmlize(io, data[i]); - } - else { - data.Clear(); - for(int i = 0; i < xml->GetCount(); i++) - if(xml->Node(i).IsTag(tag)) { - XmlIO io = xml.At(i); - Xmlize(io, data.Add()); - } - } + var.Xmlize(xml); } +template +void Xmlize(XmlIO& xml, const char* itemtag, T& var) +{ + var.Xmlize(xml, itemtag); +} + +template +void XmlizeContainer(XmlIO& xml, const char *tag, T& data, X item_xmlize); + +template +void XmlizeContainer(XmlIO& xml, const char *tag, T& data); + +template +void XmlizeMap(XmlIO& xml, const char *keytag, const char *valuetag, T& data); + +template +void XmlizeSortedMap(XmlIO& xml, const char *keytag, const char *valuetag, T& data); + +template +void XmlizeIndex(XmlIO& xml, const char *keytag, T& data); + template void XmlizeStore(XmlIO& xml, const T& data) { @@ -180,77 +143,6 @@ void XmlizeStore(XmlIO& xml, const T& data) Xmlize(xml, const_cast(data)); } -template -void XmlizeMap(XmlIO& xml, const char *keytag, const char *valuetag, T& data) -{ - if(xml.IsStoring()) { - for(int i = 0; i < data.GetCount(); i++) - if(!data.IsUnlinked(i)) { - XmlIO k = xml.Add(keytag); - XmlizeStore(k, data.GetKey(i)); - XmlIO v = xml.Add(valuetag); - XmlizeStore(v, data[i]); - } - } - else { - data.Clear(); - int i = 0; - while(i < xml->GetCount() - 1 && xml->Node(i).IsTag(keytag) && xml->Node(i + 1).IsTag(valuetag)) { - K key; - XmlIO k = xml.At(i++); - Xmlize(k, key); - XmlIO v = xml.At(i++); - Xmlize(v, data.Add(key)); - } - } -} - -template -void XmlizeSortedMap(XmlIO& xml, const char *keytag, const char *valuetag, T& data) -{ - if(xml.IsStoring()) { - for(int i = 0; i < data.GetCount(); i++) { - XmlIO k = xml.Add(keytag); - XmlizeStore(k, data.GetKey(i)); - XmlIO v = xml.Add(valuetag); - XmlizeStore(v, data[i]); - } - } - else { - data.Clear(); - int i = 0; - while(i < xml->GetCount() - 1 && xml->Node(i).IsTag(keytag) && xml->Node(i + 1).IsTag(valuetag)) { - K key; - XmlIO k = xml.At(i++); - Xmlize(k, key); - XmlIO v = xml.At(i++); - Xmlize(v, data.Add(key)); - } - } -} - -template -void XmlizeIndex(XmlIO& xml, const char *keytag, T& data) -{ - if(xml.IsStoring()) { - for(int i = 0; i < data.GetCount(); i++) - if(!data.IsUnlinked(i)) { - XmlIO io = xml.Add(keytag); - XmlizeStore(io, data[i]); - } - } - else { - data.Clear(); - int i = 0; - while(i < xml->GetCount() && xml->Node(i).IsTag(keytag)) { - K k; - XmlIO io = xml.At(i++); - Xmlize(io, k); - data.Add(k); - } - } -} - template struct ParamHelper__ { T& data; @@ -344,3 +236,5 @@ void XmlizeByJsonize(XmlIO& xio, T& x) } } } + +#include "Xmlize.hpp" \ No newline at end of file diff --git a/uppsrc/Core/Xmlize.hpp b/uppsrc/Core/Xmlize.hpp new file mode 100644 index 000000000..cff18e0a9 --- /dev/null +++ b/uppsrc/Core/Xmlize.hpp @@ -0,0 +1,140 @@ +template XmlIO XmlIO::Var(const char *tag, T& var, X item_xmlize) +{ + XmlIO n(*this, tag); + if(IsLoading() && n.Node().GetCount() == 0 && n.Node().GetAttrCount() == 0) + return *this; + item_xmlize(n, var); + return *this; +} + +template XmlIO XmlIO::operator()(const char *tag, T& var) { + return Var(tag, var, [](XmlIO& io, T& var) { Xmlize(io, var); }); +} + +template XmlIO XmlIO::Array(const char *tag, T& var, X item_xmlize, const char *itemtag) +{ + XmlIO n(*this, tag); + if(IsLoading() && n.Node().GetCount() == 0 && n.Node().GetAttrCount() == 0) + return *this; + XmlizeContainer(n, itemtag, var, item_xmlize); + return *this; +} + +template XmlIO XmlIO::List(const char *tag, const char *itemtag, T& var) { + return Array(tag, var, [](XmlIO& io, ValueTypeOf& data) { Xmlize(io, data); }, itemtag); +} + +template XmlIO XmlIO::operator()(const char *tag, T& var, const D& def) +{ + XmlIO n(*this, tag); + if(IsLoading() && n.Node().GetCount() == 0 && n.Node().GetAttrCount() == 0) + var = def; + else + Xmlize(n, var); + return *this; +} + +template XmlIO XmlIO::List(const char *tag, const char *itemtag, T& var, const D& def) +{ + XmlIO n(*this, tag); + if(IsLoading() && n.Node().GetCount() == 0 && n.Node().GetAttrCount() == 0) + var = def; + else + Xmlize(n, itemtag, var); + return *this; +} + +template +void XmlizeContainer(XmlIO& xml, const char *tag, T& data, X item_xmlize) +{ + if(xml.IsStoring()) + for(int i = 0; i < data.GetCount(); i++) { + XmlIO io = xml.Add(tag); + item_xmlize(io, data[i]); + } + else { + data.Clear(); + for(int i = 0; i < xml->GetCount(); i++) + if(xml->Node(i).IsTag(tag)) { + XmlIO io = xml.At(i); + item_xmlize(io, data.Add()); + } + } +} + +template +void XmlizeContainer(XmlIO& xml, const char *tag, T& data) +{ + XmlizeContainer(xml, tag, data, [](XmlIO& xml, ValueTypeOf& data) { Xmlize(xml, data); }); +} + +template +void XmlizeMap(XmlIO& xml, const char *keytag, const char *valuetag, T& data) +{ + if(xml.IsStoring()) { + for(int i = 0; i < data.GetCount(); i++) + if(!data.IsUnlinked(i)) { + XmlIO k = xml.Add(keytag); + XmlizeStore(k, data.GetKey(i)); + XmlIO v = xml.Add(valuetag); + XmlizeStore(v, data[i]); + } + } + else { + data.Clear(); + int i = 0; + while(i < xml->GetCount() - 1 && xml->Node(i).IsTag(keytag) && xml->Node(i + 1).IsTag(valuetag)) { + K key; + XmlIO k = xml.At(i++); + Xmlize(k, key); + XmlIO v = xml.At(i++); + Xmlize(v, data.Add(key)); + } + } +} + +template +void XmlizeSortedMap(XmlIO& xml, const char *keytag, const char *valuetag, T& data) +{ + if(xml.IsStoring()) { + for(int i = 0; i < data.GetCount(); i++) { + XmlIO k = xml.Add(keytag); + XmlizeStore(k, data.GetKey(i)); + XmlIO v = xml.Add(valuetag); + XmlizeStore(v, data[i]); + } + } + else { + data.Clear(); + int i = 0; + while(i < xml->GetCount() - 1 && xml->Node(i).IsTag(keytag) && xml->Node(i + 1).IsTag(valuetag)) { + K key; + XmlIO k = xml.At(i++); + Xmlize(k, key); + XmlIO v = xml.At(i++); + Xmlize(v, data.Add(key)); + } + } +} + +template +void XmlizeIndex(XmlIO& xml, const char *keytag, T& data) +{ + if(xml.IsStoring()) { + for(int i = 0; i < data.GetCount(); i++) + if(!data.IsUnlinked(i)) { + XmlIO io = xml.Add(keytag); + XmlizeStore(io, data[i]); + } + } + else { + data.Clear(); + int i = 0; + while(i < xml->GetCount() && xml->Node(i).IsTag(keytag)) { + K k; + XmlIO io = xml.At(i++); + Xmlize(io, k); + data.Add(k); + } + } +} diff --git a/uppsrc/Core/src.tpp/Jsonize_en-us.tpp b/uppsrc/Core/src.tpp/Jsonize_en-us.tpp index 4017c5d0d..d687e5a46 100644 --- a/uppsrc/Core/src.tpp/Jsonize_en-us.tpp +++ b/uppsrc/Core/src.tpp/Jsonize_en-us.tpp @@ -71,6 +71,34 @@ calling global Jsonize function, whose general form invokes Jsonize method). When loading and [%-*@3 key] is missing in source data, [%-*@3 defvalue] is assigned to [%-*@3 value].&] [s3;%% &] +[s4; &] +[s5;:Upp`:`:JsonIO`:`:List`(const char`*`,const char`*`,T`&`): [@(0.0.255) template]_<[@(0.0.255) c +lass]_[*@4 T]>_[_^Upp`:`:JsonIO^ JsonIO][@(0.0.255) `&]_[* List]([@(0.0.255) const]_[@(0.0.255) c +har]_`*[*@3 key], [@(0.0.255) const]_[@(0.0.255) char]_`*, [*@4 T][@(0.0.255) `&]_[*@3 var])&] +[s2;%% Same as operator()([%-*@3 key], [%-*@3 var]). Provides compatibility +with Xmlize for common template routines that provide both Jsonize +and Xmlize code.&] +[s3;%% &] +[s4; &] +[s5;:Upp`:`:JsonIO`:`:Var`(const char`*`,T`&`,X`): [@(0.0.255) template]_<[@(0.0.255) cla +ss]_[*@4 T], [@(0.0.255) class]_[*@4 X]>_[_^Upp`:`:JsonIO^ JsonIO][@(0.0.255) `&]_[* Var]([@(0.0.255) c +onst]_[@(0.0.255) char]_`*[*@3 key], [*@4 T][@(0.0.255) `&]_[*@3 value], +[*@4 X]_[*@3 item`_jsonize])&] +[s2;%% Similar to operator()([%-*@3 key], [%-*@3 value]), but instead +of using global Jsonize function, it uses [%-*@3 item`_jsonize] +to define the structure.&] +[s3;%% &] +[s4; &] +[s5;:Upp`:`:JsonIO`:`:Array`(const char`*`,T`&`,X`,const char`*`): [@(0.0.255) template +]_<[@(0.0.255) class]_[*@4 T], [@(0.0.255) class]_[*@4 X]>_[_^Upp`:`:JsonIO^ JsonIO][@(0.0.255) `& +]_[* Array]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 key], [*@4 T][@(0.0.255) `&]_[*@3 value +], [*@4 X]_[*@3 item`_jsonize], [@(0.0.255) const]_[@(0.0.255) char]_`*_`=_NULL)&] +[s2;%% Jsonizes array container (must have GetCount, Add and operator`[`] +methods), using [%-*@3 item`_jsonize] to define the structure of +elements. The last parameter is ignored and is included to provide +compatibility with Xmlize code for common template routines that +provide both Jsonize and Xmlize code.&] +[s3;%% &] [s4;%% &] [s5;:JsonIO`:`:JsonIO`(const Value`&`): [* JsonIO]([@(0.0.255) const]_[_^Value^ Value][@(0.0.255) `& ]_[*@3 src])&] diff --git a/uppsrc/Core/src.tpp/XmlIO_en-us.tpp b/uppsrc/Core/src.tpp/XmlIO_en-us.tpp index 7712917c8..813ed681f 100644 --- a/uppsrc/Core/src.tpp/XmlIO_en-us.tpp +++ b/uppsrc/Core/src.tpp/XmlIO_en-us.tpp @@ -94,6 +94,25 @@ default value when there is no corresponding tag on loading. Variant without [%-*@3 def] leaves [%-*@3 var] unchanged in this case.&] [s3;%% &] +[s4; &] +[s5;:Upp`:`:XmlIO`:`:Var`(const char`*`,T`&`,X`): [@(0.0.255) template]_<[@(0.0.255) clas +s]_[*@4 T], [@(0.0.255) class]_[*@4 X]>_[_^Upp`:`:XmlIO^ XmlIO]_[* Var]([@(0.0.255) const]_[@(0.0.255) c +har]_`*[*@3 tag], [*@4 T][@(0.0.255) `&]_[*@3 var], [*@4 X]_[*@3 var`_xmlize])&] +[s2;%% Creates subtag of current XmlNode [%-*@3 tag], forms a new XmlIO +for it and calls global [%-*@3 item`_xmlize][* ]callable with this +new XmlIO and [%-*@3 var] as parameters. This allows for in`-place +definition of XML structure used to represent [%-*@3 var].&] +[s3;%% &] +[s4; &] +[s5;:Upp`:`:XmlIO`:`:Array`(const char`*`,T`&`,X`,const char`*`): [@(0.0.255) template]_ +<[@(0.0.255) class]_[*@4 T], [@(0.0.255) class]_[*@4 X]>_[_^Upp`:`:XmlIO^ XmlIO]_[* Array]([@(0.0.255) c +onst]_[@(0.0.255) char]_`*[*@3 tag], [*@4 T][@(0.0.255) `&]_[*@3 var], +[*@4 X]_[*@3 item`_xmlize], [@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 itemtag] +`=[*@3 `"item`"])&] +[s2;%% Xmlizes array container (must have GetCount, Add and operator`[`] +methods), using [%-*@3 item`_xmlize] to define the structure of +elements. [%-*@3 itemtag] provides the tags of individual elements.&] +[s3;%% &] [s4;%% &] [s5;:XmlIO`:`:Attr`(const char`*`,T`&`): [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T]> _[_^XmlIO^ XmlIO]_[* Attr]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 id],