Core: Lambda Jsonize/Xmlize methods

git-svn-id: svn://ultimatepp.org/upp/trunk@12540 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2018-11-15 08:26:08 +00:00
parent 8bbf8a34e4
commit 5592836f83
8 changed files with 297 additions and 156 deletions

View file

@ -155,6 +155,7 @@ file
XML.h,
XML.cpp,
Xmlize.h,
Xmlize.hpp,
Xmlize.cpp,
JSON.h,
JSON.cpp,

View file

@ -687,7 +687,6 @@ void InVector<T>::Swap(InVector& b)
Upp::Swap(slave, b.slave);
}
#ifdef UPP
template <class T>
void InVector<T>::Xmlize(XmlIO& xio, const char *itemtag)
{
@ -706,8 +705,6 @@ String InVector<T>::ToString() const
return AsStringArray(*this);
}
#endif
template <class T>
void InVector<T>::DumpIndex() const
{

View file

@ -105,6 +105,15 @@ public:
template <class T>
JsonIO& operator()(const char *key, T& value, const T& defvalue);
template <class T>
JsonIO& List(const char *key, const char *, T& var) { return operator()(key, var); }
template <class T, class X>
JsonIO& Var(const char *key, T& value, X item_jsonize);
template <class T, class X>
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 <class T, class X>
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 <class T, class X>
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<Value> 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 <class T, class X> 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 <class T>
JsonIO& JsonIO::operator()(const char *key, T& value, const T& defvalue)
{
@ -234,24 +314,7 @@ template<> void Jsonize(JsonIO& io, Time& var);
template <class T>
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<Value> 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<T>& item) { Jsonize(io, item); });
}
template <class T, class K, class V>

View file

@ -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<XmlTag> {
String tag;
String end;

View file

@ -31,6 +31,8 @@ public:
template <class T> XmlIO operator()(const char *tag, T& var);
template <class T> XmlIO List(const char *tag, const char *itemtag, T& var);
template <class T, class X> XmlIO Var(const char *tag, T& var, X var_xmlize);
template <class T, class X> XmlIO Array(const char *tag, T& var, X item_xmlize, const char *itemtag = "item");
template <class T, class D> XmlIO operator()(const char *tag, T& var, const D& def);
template <class T, class D> 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 <class T>
void Xmlize(XmlIO& xml, T& var)
{
var.Xmlize(xml);
}
template <class T>
void Xmlize(XmlIO& xml, const char* itemtag, T& var)
{
var.Xmlize(xml, itemtag);
}
template <class T> 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 <class T> 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 <class T, class D> 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 <class T, class D> 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<class T>
void XmlizeContainer(XmlIO& xml, const char *tag, T& data)
template <class T>
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 <class T>
void Xmlize(XmlIO& xml, const char* itemtag, T& var)
{
var.Xmlize(xml, itemtag);
}
template <class T, class X>
void XmlizeContainer(XmlIO& xml, const char *tag, T& data, X item_xmlize);
template<class T>
void XmlizeContainer(XmlIO& xml, const char *tag, T& data);
template<class K, class V, class T>
void XmlizeMap(XmlIO& xml, const char *keytag, const char *valuetag, T& data);
template<class K, class V, class T>
void XmlizeSortedMap(XmlIO& xml, const char *keytag, const char *valuetag, T& data);
template<class K, class T>
void XmlizeIndex(XmlIO& xml, const char *keytag, T& data);
template<class T>
void XmlizeStore(XmlIO& xml, const T& data)
{
@ -180,77 +143,6 @@ void XmlizeStore(XmlIO& xml, const T& data)
Xmlize(xml, const_cast<T&>(data));
}
template<class K, class V, class T>
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<class K, class V, class T>
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<class K, class T>
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 <class T>
struct ParamHelper__ {
T& data;
@ -344,3 +236,5 @@ void XmlizeByJsonize(XmlIO& xio, T& x)
}
}
}
#include "Xmlize.hpp"

140
uppsrc/Core/Xmlize.hpp Normal file
View file

@ -0,0 +1,140 @@
template <class T, class X> 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 <class T> XmlIO XmlIO::operator()(const char *tag, T& var) {
return Var(tag, var, [](XmlIO& io, T& var) { Xmlize(io, var); });
}
template <class T, class X> 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 <class T> XmlIO XmlIO::List(const char *tag, const char *itemtag, T& var) {
return Array(tag, var, [](XmlIO& io, ValueTypeOf<T>& data) { Xmlize(io, data); }, itemtag);
}
template <class T, class D> 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 <class T, class D> 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 <class T, class X>
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<class T>
void XmlizeContainer(XmlIO& xml, const char *tag, T& data)
{
XmlizeContainer(xml, tag, data, [](XmlIO& xml, ValueTypeOf<T>& data) { Xmlize(xml, data); });
}
template<class K, class V, class T>
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<class K, class V, class T>
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<class K, class T>
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);
}
}
}

View file

@ -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])&]

View file

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