closes #1
This commit is contained in:
@@ -35,10 +35,6 @@ class B: public xml::Serialize {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& fn(std::ostream& os) {
|
|
||||||
os<<std::endl<<"HALLO"<<std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int, char**) {
|
int main(int, char**) {
|
||||||
{ // Serialization as a member
|
{ // Serialization as a member
|
||||||
std::stringstream ss("<b>\n"
|
std::stringstream ss("<b>\n"
|
||||||
@@ -56,7 +52,6 @@ int main(int, char**) {
|
|||||||
std::cout<<"Text B: "<<b.txt<<std::endl;
|
std::cout<<"Text B: "<<b.txt<<std::endl;
|
||||||
std::cout<<"Text A: "<<b.a.txt<<std::endl;
|
std::cout<<"Text A: "<<b.a.txt<<std::endl;
|
||||||
b.saveXml(std::cout)<<std::endl;
|
b.saveXml(std::cout)<<std::endl;
|
||||||
std::cout<<fn;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,7 @@ AM_LDFLAGS = -L${top_builddir}/src -lxml-cxx
|
|||||||
|
|
||||||
noinst_PROGRAMS = address node_macros serialization \
|
noinst_PROGRAMS = address node_macros serialization \
|
||||||
contain_serialization inherit_serialization \
|
contain_serialization inherit_serialization \
|
||||||
list_serialization
|
list_serialization optional_serialization
|
||||||
|
|
||||||
address_SOURCES = address.cxx
|
address_SOURCES = address.cxx
|
||||||
node_macros_SOURCES = node_macros.cxx
|
node_macros_SOURCES = node_macros.cxx
|
||||||
@@ -16,5 +16,6 @@ serialization_SOURCES = serialization.cxx
|
|||||||
contain_serialization_SOURCES = contain_serialization.cxx
|
contain_serialization_SOURCES = contain_serialization.cxx
|
||||||
inherit_serialization_SOURCES = inherit_serialization.cxx
|
inherit_serialization_SOURCES = inherit_serialization.cxx
|
||||||
list_serialization_SOURCES = list_serialization.cxx
|
list_serialization_SOURCES = list_serialization.cxx
|
||||||
|
optional_serialization_SOURCES = optional_serialization.cxx
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = makefile.in
|
MAINTAINERCLEANFILES = makefile.in
|
||||||
|
46
doc/examples/optional_serialization.cxx
Normal file
46
doc/examples/optional_serialization.cxx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*! @file
|
||||||
|
|
||||||
|
@id $Id$
|
||||||
|
*/
|
||||||
|
// 1 2 3 4 5 6 7 8
|
||||||
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||||
|
|
||||||
|
#include <xml-cxx/xml.hxx>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
class A: public xml::Serialize {
|
||||||
|
public:
|
||||||
|
xml::Optional<int> a;
|
||||||
|
xml::Optional<std::string> txt;
|
||||||
|
protected:
|
||||||
|
void initXmlMembers() {
|
||||||
|
className("A");
|
||||||
|
persist(a, "a");
|
||||||
|
persist(txt, "txt");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class B: public xml::Serialize {
|
||||||
|
public:
|
||||||
|
xml::Optional<A> a;
|
||||||
|
xml::Optional<int> i;
|
||||||
|
xml::Optional<std::string> txt;
|
||||||
|
protected:
|
||||||
|
void initXmlMembers() {
|
||||||
|
className("B");
|
||||||
|
persist(a, "a");
|
||||||
|
persist(i, "i");
|
||||||
|
persist(txt, "txt");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
{ // Serialization as a member
|
||||||
|
std::stringstream ss("<B/>");
|
||||||
|
B b;
|
||||||
|
b.loadXml(ss);
|
||||||
|
b.saveXml(std::cout)<<std::endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -165,9 +165,9 @@ class MethodTrace {
|
|||||||
- most standard containers, but in their xml-form,
|
- most standard containers, but in their xml-form,
|
||||||
e.g. xml::List instead of @c std::list
|
e.g. xml::List instead of @c std::list
|
||||||
(xml::List inherits @c std::list)
|
(xml::List inherits @c std::list)
|
||||||
|
- Optional values through xml::Optional
|
||||||
- @c std::bitset, @c std::priority_queue, @c std::queue and
|
- @c std::bitset, @c std::priority_queue, @c std::queue and
|
||||||
@c std::stack are not implemented
|
@c std::stack are not implemented
|
||||||
- Optional values are not yet implemented
|
|
||||||
- Polymorfic serialisation is not yet implemented
|
- Polymorfic serialisation is not yet implemented
|
||||||
|
|
||||||
@page rationale Rationale - Limitations of other libraries
|
@page rationale Rationale - Limitations of other libraries
|
||||||
@@ -787,6 +787,9 @@ namespace xml {
|
|||||||
virtual Node& text(const std::string& txt) throw(tag_expected,
|
virtual Node& text(const std::string& txt) throw(tag_expected,
|
||||||
type_mismatch);
|
type_mismatch);
|
||||||
virtual Node& append(const Node& o) throw(cannot_have_children);
|
virtual Node& append(const Node& o) throw(cannot_have_children);
|
||||||
|
virtual Node& remove(Node& n) throw(access_error);
|
||||||
|
virtual Node& remove(const std::string& n) throw(access_error);
|
||||||
|
virtual Node& remove(size_type n) throw(out_of_range);
|
||||||
virtual Node& set(const Attributes& o) throw();
|
virtual Node& set(const Attributes& o) throw();
|
||||||
Node& clear() throw ();
|
Node& clear() throw ();
|
||||||
std::string name() const throw();
|
std::string name() const throw();
|
||||||
@@ -954,6 +957,7 @@ namespace xml {
|
|||||||
private:
|
private:
|
||||||
friend class stream_error;
|
friend class stream_error;
|
||||||
friend class Serialize;
|
friend class Serialize;
|
||||||
|
template<class T> friend class Optional;
|
||||||
template<class T> friend class Container;
|
template<class T> friend class Container;
|
||||||
template<class T> friend class AssociativeContainer;
|
template<class T> friend class AssociativeContainer;
|
||||||
template<class T> friend class AssociativeMap;
|
template<class T> friend class AssociativeMap;
|
||||||
@@ -1098,9 +1102,9 @@ namespace xml {
|
|||||||
Serialize(const Serialize& other) throw();
|
Serialize(const Serialize& other) throw();
|
||||||
virtual ~Serialize();
|
virtual ~Serialize();
|
||||||
Serialize& operator=(const Serialize& other) throw();
|
Serialize& operator=(const Serialize& other) throw();
|
||||||
Serialize& className(const std::string& name) throw();
|
virtual Serialize& className(const std::string& name) throw();
|
||||||
virtual Serialize& persist(Serialize& member,
|
Serialize& persist(Serialize& member,
|
||||||
const std::string& name) throw();
|
const std::string& name) throw();
|
||||||
Serialize& persist(bool& member,
|
Serialize& persist(bool& member,
|
||||||
const std::string& name) throw();
|
const std::string& name) throw();
|
||||||
Serialize& persist(char& member,
|
Serialize& persist(char& member,
|
||||||
@@ -1136,6 +1140,7 @@ namespace xml {
|
|||||||
static void registerFromNode(FromNodeFunc fromNodeFunc);
|
static void registerFromNode(FromNodeFunc fromNodeFunc);
|
||||||
static void registerToNode(ToNodeFunc toNodeFunc);
|
static void registerToNode(ToNodeFunc toNodeFunc);
|
||||||
static void registerClear(ClearFunc clearFunc);
|
static void registerClear(ClearFunc clearFunc);
|
||||||
|
virtual void clear() throw();
|
||||||
protected:
|
protected:
|
||||||
virtual void initXmlMembers();
|
virtual void initXmlMembers();
|
||||||
void checkInit(const Serialize* const ser=0) const {
|
void checkInit(const Serialize* const ser=0) const {
|
||||||
@@ -1145,11 +1150,15 @@ namespace xml {
|
|||||||
if (!_xmlFactory) const_cast<Serialize*>(this)->initXmlMembers();
|
if (!_xmlFactory) const_cast<Serialize*>(this)->initXmlMembers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void clear() throw();
|
|
||||||
/*! @todo Why does @c protected: not work here?!? Children can't
|
/*! @todo Why does @c protected: not work here?!? Children can't
|
||||||
access the members if they are protected! */
|
access the members if they are protected! */
|
||||||
public:
|
public:
|
||||||
//! @cond INTERNAL
|
//! @cond INTERNAL
|
||||||
|
template<typename TYPE> friend bool assignFromNode(Any member,
|
||||||
|
const xml::Node& node);
|
||||||
|
template<typename TYPE> friend bool assigntoNode(Any member,
|
||||||
|
const xml::Node& node);
|
||||||
|
virtual bool optional() const throw();
|
||||||
void clear(Any member) throw();
|
void clear(Any member) throw();
|
||||||
void reset() throw();
|
void reset() throw();
|
||||||
void copy(const Serialize& o) throw();
|
void copy(const Serialize& o) throw();
|
||||||
@@ -1162,8 +1171,8 @@ namespace xml {
|
|||||||
_xmlFactory = schema;
|
_xmlFactory = schema;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
void fromNode(Any member, const xml::Node& node);
|
virtual void fromNode(Any member, const xml::Node& node);
|
||||||
void toNode(const Any member, xml::Node& node) const;
|
virtual void toNode(const Any member, xml::Node& node) const;
|
||||||
std::map<std::string, Any> _xmlNames;
|
std::map<std::string, Any> _xmlNames;
|
||||||
xml::Factory _xmlFactory;
|
xml::Factory _xmlFactory;
|
||||||
static std::set<FromNodeFunc> _fromNode;
|
static std::set<FromNodeFunc> _fromNode;
|
||||||
@@ -1174,54 +1183,71 @@ namespace xml {
|
|||||||
|
|
||||||
template <class TYPE> class Optional: public Serialize {
|
template <class TYPE> class Optional: public Serialize {
|
||||||
public:
|
public:
|
||||||
Optional() throw() {}
|
Optional() throw(): _valid(false) {}
|
||||||
Optional(const Optional& o) throw(): _member(new TYPE(*o._member)) {}
|
Optional(const Optional& o) throw():
|
||||||
Optional(const TYPE& mem) throw(): _member(new TYPE(mem)) {}
|
_member(o._member), _valid(o.valid) {
|
||||||
|
}
|
||||||
|
Optional(const TYPE& mem) throw():
|
||||||
|
_member(mem), _valid(true) {
|
||||||
|
}
|
||||||
virtual ~Optional() throw() {}
|
virtual ~Optional() throw() {}
|
||||||
Optional& operator=(const Optional& o) throw() {
|
Optional& operator=(const Optional& o) throw() {
|
||||||
_member = new TYPE(*o._member);
|
_member = o._member;
|
||||||
|
_valid = o._valid;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Optional& operator=(const TYPE& mem) throw() {
|
Optional& operator=(const TYPE& mem) throw() {
|
||||||
_member = new TYPE(mem);
|
_member = mem;
|
||||||
|
_valid = true;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
operator bool() const throw() {
|
operator bool() const throw() {
|
||||||
return _member.get();
|
return _valid;
|
||||||
}
|
}
|
||||||
const TYPE& operator*() const throw() {
|
const TYPE& operator*() const throw() {
|
||||||
return *_member;
|
return _member;
|
||||||
}
|
}
|
||||||
TYPE& operator*() throw() {
|
TYPE& operator*() throw() {
|
||||||
return *_member;
|
return _member;
|
||||||
}
|
}
|
||||||
const TYPE*const operator->() const throw() {
|
const TYPE*const operator->() const throw() {
|
||||||
return _member.get();
|
return &_member;
|
||||||
}
|
}
|
||||||
TYPE*const operator->() throw() {
|
TYPE*const operator->() throw() {
|
||||||
return _member.get();
|
return &_member;
|
||||||
}
|
}
|
||||||
Optional& reset() throw() {
|
virtual void clear() throw() {
|
||||||
_member.reset();
|
_valid = false;
|
||||||
|
}
|
||||||
|
virtual Optional& className(const std::string& name) throw() {
|
||||||
|
if (!_xmlFactory) {
|
||||||
|
Serialize::className(name);
|
||||||
|
persist(_member, name);
|
||||||
|
// make the child the root, and it's optional
|
||||||
|
_xmlFactory = (*_xmlFactory)[0];
|
||||||
|
_xmlFactory->limits(0, 1);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
virtual void clear() throw() {
|
virtual bool optional() const throw() {
|
||||||
_member.reset();
|
return true;
|
||||||
}
|
}
|
||||||
virtual std::ostream& saveXml(std::ostream& os,
|
virtual void fromNode(Any member, const xml::Node& node) {
|
||||||
const std::string& name = std::string())
|
_valid = true;
|
||||||
const throw() {
|
Serialize::fromNode(Any(&_member), node);
|
||||||
if (!_member.get()) return os;
|
}
|
||||||
checkInit();
|
virtual void toNode(const Any member, xml::Node& node) const {
|
||||||
xml::Node node(*_xmlFactory);
|
if (!_valid) {
|
||||||
if (name.size()) node.name(name);
|
node.parent().remove(node);
|
||||||
toNode(*_member, node);
|
return;
|
||||||
os<<node;
|
}
|
||||||
return os;
|
const Any mem(&const_cast<Optional*>(this)->_member);
|
||||||
|
Serialize::toNode(mem, node);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::auto_ptr<TYPE> _member;
|
TYPE _member;
|
||||||
|
bool _valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! @addtogroup serialization
|
//! @addtogroup serialization
|
||||||
@@ -1400,17 +1426,13 @@ namespace xml {
|
|||||||
if (name.size()) factory->name(name);
|
if (name.size()) factory->name(name);
|
||||||
std::auto_ptr<xml::Node> node(factory.read(is));
|
std::auto_ptr<xml::Node> node(factory.read(is));
|
||||||
CONTAINER_TYPE::clear();
|
CONTAINER_TYPE::clear();
|
||||||
LOG("READING: "<<*node);
|
|
||||||
for (xml::Node::size_type i(0); i<node->children(); ++i) {
|
for (xml::Node::size_type i(0); i<node->children(); ++i) {
|
||||||
typename CONTAINER_TYPE::key_type key;
|
typename CONTAINER_TYPE::key_type key;
|
||||||
typename CONTAINER_TYPE::mapped_type data;
|
typename CONTAINER_TYPE::mapped_type data;
|
||||||
LOG("READING Key: "<<(*node)[i]<<"Value:"<<(*node)[1+i]);
|
|
||||||
Serialize::fromNode(&key, (*node)[i]); // reads into tmp
|
Serialize::fromNode(&key, (*node)[i]); // reads into tmp
|
||||||
Serialize::fromNode(&data, (*node)[++i]); // key&value
|
Serialize::fromNode(&data, (*node)[++i]); // key&value
|
||||||
insert(typename CONTAINER_TYPE::value_type(key, data));
|
insert(typename CONTAINER_TYPE::value_type(key, data));
|
||||||
LOG("READ");
|
|
||||||
}
|
}
|
||||||
LOG("DONE");
|
|
||||||
return is;
|
return is;
|
||||||
}
|
}
|
||||||
virtual std::ostream& saveXml(std::ostream& os,
|
virtual std::ostream& saveXml(std::ostream& os,
|
||||||
|
58
src/xml.cxx
58
src/xml.cxx
@@ -9,6 +9,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
unsigned int MethodTrace::_level(0);
|
unsigned int MethodTrace::_level(0);
|
||||||
|
|
||||||
@@ -310,6 +311,25 @@ namespace xml {
|
|||||||
_contents.push_back(o.clone(this).release());
|
_contents.push_back(o.clone(this).release());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
//! Removes a given child node.
|
||||||
|
Node& Node::remove(Node& n) throw(access_error) {
|
||||||
|
Contents::iterator it(std::find(_contents.begin(), _contents.end(), &n));
|
||||||
|
if (it==_contents.end()) throw access_error(*this, n.name());
|
||||||
|
_contents.erase(it);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
//! Removes the first child node of a given name.
|
||||||
|
Node& Node::remove(const std::string& n) throw(access_error) {
|
||||||
|
Node* t(find(n));
|
||||||
|
if (!t) throw access_error(*this, n);
|
||||||
|
return remove(*t);
|
||||||
|
}
|
||||||
|
//! Removes the child node of a given position.
|
||||||
|
Node& Node::remove(size_type n) throw(out_of_range) {
|
||||||
|
if (n>=children()) throw out_of_range(*this, n);
|
||||||
|
_contents.erase(_contents.begin()+n);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
//! Set a list of attributes.
|
//! Set a list of attributes.
|
||||||
/*! Existing attributes with the same name are overwritten. */
|
/*! Existing attributes with the same name are overwritten. */
|
||||||
Node& Node::set(const Attributes& o) throw() {
|
Node& Node::set(const Attributes& o) throw() {
|
||||||
@@ -1020,13 +1040,21 @@ namespace xml {
|
|||||||
}
|
}
|
||||||
Serialize& Serialize::persist(Serialize& ser,
|
Serialize& Serialize::persist(Serialize& ser,
|
||||||
const std::string& name) throw() {
|
const std::string& name) throw() {
|
||||||
ser.checkInit();
|
if (ser.optional()) {
|
||||||
_xmlNames[name] = &ser;
|
_xmlNames[name] = &ser;
|
||||||
xml::Node schema(*_xmlFactory);
|
ser.className(name);
|
||||||
xml::Node node(xml::Node(name).limits(1,1));
|
*_xmlFactory<<*ser._xmlFactory;
|
||||||
for (xml::Node::size_type i(0); i<ser._xmlFactory->children(); ++i)
|
std::stringstream ss;
|
||||||
node<<(*ser._xmlFactory)[i];
|
} else {
|
||||||
_xmlFactory = schema<<node;
|
ser.checkInit();
|
||||||
|
_xmlNames[name] = &ser;
|
||||||
|
xml::Node schema(*_xmlFactory);
|
||||||
|
xml::Node node(xml::Node(name).limits(1,1));
|
||||||
|
for (xml::Node::size_type i(0); i<ser._xmlFactory->children(); ++i)
|
||||||
|
node<<(*ser._xmlFactory)[i];
|
||||||
|
_xmlFactory = schema<<node;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Serialize& Serialize::persist(bool& member,
|
Serialize& Serialize::persist(bool& member,
|
||||||
@@ -1123,13 +1151,13 @@ namespace xml {
|
|||||||
void Serialize::registerClear(Serialize::ClearFunc clearFunc) {
|
void Serialize::registerClear(Serialize::ClearFunc clearFunc) {
|
||||||
_clear.insert(clearFunc);
|
_clear.insert(clearFunc);
|
||||||
}
|
}
|
||||||
|
void Serialize::initXmlMembers() {}
|
||||||
void Serialize::clear() throw() {
|
void Serialize::clear() throw() {
|
||||||
for (std::map<std::string, Any>::const_iterator
|
for (std::map<std::string, Any>::const_iterator
|
||||||
it(_xmlNames.begin());
|
it(_xmlNames.begin());
|
||||||
it!=_xmlNames.end(); ++it)
|
it!=_xmlNames.end(); ++it)
|
||||||
clear(it->second);
|
clear(it->second);
|
||||||
}
|
}
|
||||||
void Serialize::initXmlMembers() {}
|
|
||||||
void Serialize::reset() throw() {
|
void Serialize::reset() throw() {
|
||||||
_xmlFactory.reset();
|
_xmlFactory.reset();
|
||||||
_xmlNames.clear();
|
_xmlNames.clear();
|
||||||
@@ -1156,6 +1184,10 @@ namespace xml {
|
|||||||
if ((**it)(member)) return; // found match
|
if ((**it)(member)) return; // found match
|
||||||
throw type_not_registered(member.type().name());
|
throw type_not_registered(member.type().name());
|
||||||
}
|
}
|
||||||
|
bool Serialize::optional() const throw() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::set<Serialize::FromNodeFunc> Serialize::_fromNode;
|
std::set<Serialize::FromNodeFunc> Serialize::_fromNode;
|
||||||
std::set<Serialize::ToNodeFunc> Serialize::_toNode;
|
std::set<Serialize::ToNodeFunc> Serialize::_toNode;
|
||||||
std::set<Serialize::ClearFunc> Serialize::_clear;
|
std::set<Serialize::ClearFunc> Serialize::_clear;
|
||||||
@@ -1201,6 +1233,10 @@ namespace xml {
|
|||||||
template<> bool assignFromNode<Serialize>(Any member,
|
template<> bool assignFromNode<Serialize>(Any member,
|
||||||
const xml::Node& node) {
|
const xml::Node& node) {
|
||||||
if (!any_cast<Serialize>(&member)) return false;
|
if (!any_cast<Serialize>(&member)) return false;
|
||||||
|
if (any_cast<Serialize>(member)->optional()) {
|
||||||
|
(*any_cast<Serialize>(member)).fromNode(member, node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
//! @todo improve this (inefficient)
|
//! @todo improve this (inefficient)
|
||||||
std::stringstream ss; // simple but inefficient: rewrite and reread
|
std::stringstream ss; // simple but inefficient: rewrite and reread
|
||||||
ss<<node;
|
ss<<node;
|
||||||
@@ -1214,6 +1250,10 @@ namespace xml {
|
|||||||
template<> bool assignToNode<Serialize>(const Any member,
|
template<> bool assignToNode<Serialize>(const Any member,
|
||||||
xml::Node& node) {
|
xml::Node& node) {
|
||||||
if (!any_cast<Serialize>(&member)) return false;
|
if (!any_cast<Serialize>(&member)) return false;
|
||||||
|
if (any_cast<Serialize>(member)->optional()) {
|
||||||
|
any_cast<Serialize>(member)->toNode(member, node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
any_cast<Serialize>(member)->saveXml(ss, node.name());
|
any_cast<Serialize>(member)->saveXml(ss, node.name());
|
||||||
xml::Factory factory(node);
|
xml::Factory factory(node);
|
||||||
@@ -1238,7 +1278,7 @@ namespace xml {
|
|||||||
}
|
}
|
||||||
template<> bool clearMember<Serialize>(Any member) {
|
template<> bool clearMember<Serialize>(Any member) {
|
||||||
if (!any_cast<Serialize>(&member)) return false;
|
if (!any_cast<Serialize>(&member)) return false;
|
||||||
any_cast<std::string>(member)->clear();
|
any_cast<Serialize>(member)->clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Init To and From Node ---------------------------------------------------
|
// Init To and From Node ---------------------------------------------------
|
||||||
|
@@ -7,12 +7,15 @@ AM_CXXFLAGS += -I ${top_srcdir}/src
|
|||||||
AM_LDFLAGS = -L${top_builddir}/src
|
AM_LDFLAGS = -L${top_builddir}/src
|
||||||
LDADD = -lcppunit -lxml-cxx
|
LDADD = -lcppunit -lxml-cxx
|
||||||
|
|
||||||
check_PROGRAMS = xml_test serialization_test container_serialization_test
|
check_PROGRAMS = xml_test serialization_test \
|
||||||
|
container_serialization_test optional_serialization_test
|
||||||
|
|
||||||
TESTS=${check_PROGRAMS}
|
TESTS=${check_PROGRAMS}
|
||||||
|
|
||||||
xml_test_SOURCES = xml_test.cxx
|
xml_test_SOURCES = xml_test.cxx
|
||||||
serialization_test_SOURCES = serialization_test.cxx
|
serialization_test_SOURCES = serialization_test.cxx
|
||||||
container_serialization_test_SOURCES = container_serialization_test.cxx
|
container_serialization_test_SOURCES = container_serialization_test.cxx
|
||||||
|
optional_serialization_test_SOURCES = optional_serialization_test.cxx
|
||||||
|
|
||||||
CLEANFILES =
|
CLEANFILES =
|
||||||
MAINTAINERCLEANFILES = makefile.in
|
MAINTAINERCLEANFILES = makefile.in
|
||||||
|
118
test/optional_serialization_test.cxx
Normal file
118
test/optional_serialization_test.cxx
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
/*! @file
|
||||||
|
|
||||||
|
@id $Id: serialization_test.cxx 31 2009-04-28 07:36:07Z $
|
||||||
|
*/
|
||||||
|
// 1 2 3 4 5 6 7 8
|
||||||
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||||
|
|
||||||
|
#include <xml-cxx/xml.hxx>
|
||||||
|
#include <cppunit/TestFixture.h>
|
||||||
|
#include <cppunit/ui/text/TestRunner.h>
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
#include <cppunit/extensions/TestFactoryRegistry.h>
|
||||||
|
#include <cppunit/XmlOutputter.h>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
class A: public xml::Serialize {
|
||||||
|
public:
|
||||||
|
xml::Optional<int> _int;
|
||||||
|
protected:
|
||||||
|
void initXmlMembers() {
|
||||||
|
className("A");
|
||||||
|
persist(_int, "int");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class B: public xml::Serialize {
|
||||||
|
public:
|
||||||
|
xml::Optional<long> _long;
|
||||||
|
xml::Optional<short> _short;
|
||||||
|
protected:
|
||||||
|
void initXmlMembers() {
|
||||||
|
className("B");
|
||||||
|
persist(_long, "long");
|
||||||
|
persist(_short, "short");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class B1: public B {
|
||||||
|
public:
|
||||||
|
xml::Optional<A> _a1;
|
||||||
|
xml::Optional<A> _a2;
|
||||||
|
xml::Optional<A> _a3;
|
||||||
|
protected:
|
||||||
|
void initXmlMembers() {
|
||||||
|
B::initXmlMembers();
|
||||||
|
className("B1");
|
||||||
|
persist(_a1, "a1");
|
||||||
|
persist(_a2, "a2");
|
||||||
|
persist(_a3, "a3");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OptionalSerializationTest: public CppUnit::TestFixture {
|
||||||
|
public:
|
||||||
|
void checkOptional() {
|
||||||
|
std::string with("<A>\n"
|
||||||
|
"\t<int>13</int>\n"
|
||||||
|
"</A>");
|
||||||
|
std::string without("<A/>");
|
||||||
|
A a;
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("<A>\n"
|
||||||
|
"\t<int/>\n"
|
||||||
|
"</A>"), a.schema());
|
||||||
|
std::stringstream ss1a(with);
|
||||||
|
CPPUNIT_ASSERT_NO_THROW(a.loadXml(ss1a));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, (bool)a._int);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(13, *a._int);
|
||||||
|
std::stringstream ss1b;
|
||||||
|
CPPUNIT_ASSERT_NO_THROW(a.saveXml(ss1b));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(with, ss1b.str());
|
||||||
|
std::stringstream ss2a(without);
|
||||||
|
CPPUNIT_ASSERT_NO_THROW(a.loadXml(ss2a));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(false, (bool)a._int);
|
||||||
|
std::stringstream ss2b;
|
||||||
|
CPPUNIT_ASSERT_NO_THROW(a.saveXml(ss2b));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(without, ss2b.str());
|
||||||
|
}
|
||||||
|
void checkMoreOptional() {
|
||||||
|
std::string first("<B1>\n"
|
||||||
|
"\t<short>13</short>\n"
|
||||||
|
"\t<a2/>\n"
|
||||||
|
"\t<a3>\n"
|
||||||
|
"\t\t<int>42</int>\n"
|
||||||
|
"\t</a3>\n"
|
||||||
|
"</B1>");
|
||||||
|
B1 b;
|
||||||
|
std::stringstream ifirst(first);
|
||||||
|
CPPUNIT_ASSERT_NO_THROW(b.loadXml(ifirst));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(false, (bool)b._long);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, (bool)b._short);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((short)13, *b._short);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(false, (bool)b._a1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, (bool)b._a2);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(false, (bool)b._a2->_int);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, (bool)b._a3);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, (bool)b._a3->_int);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(42, *b._a3->_int);
|
||||||
|
std::stringstream ofirst;
|
||||||
|
CPPUNIT_ASSERT_NO_THROW(b.saveXml(ofirst));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(first, ofirst.str());
|
||||||
|
}
|
||||||
|
CPPUNIT_TEST_SUITE(OptionalSerializationTest);
|
||||||
|
CPPUNIT_TEST(checkOptional);
|
||||||
|
CPPUNIT_TEST(checkMoreOptional);
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
};
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(OptionalSerializationTest);
|
||||||
|
|
||||||
|
int main(int argc, char** argv) try {
|
||||||
|
std::ofstream ofs((*argv+std::string(".xml")).c_str());
|
||||||
|
CppUnit::TextUi::TestRunner runner;
|
||||||
|
//runner.setOutputter(new CppUnit::XmlOutputter(&runner.result(), ofs));
|
||||||
|
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
|
||||||
|
return runner.run() ? 0 : 1;
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
std::cerr<<"***Exception: "<<e.what()<<std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
Reference in New Issue
Block a user