|
|
|
@ -330,6 +330,11 @@ namespace xml { |
|
|
|
|
std::string Node::name() const throw() { |
|
|
|
|
return _name; |
|
|
|
|
} |
|
|
|
|
//! Set a new node's tag name.
|
|
|
|
|
Node& Node::name(const std::string& n) throw() { |
|
|
|
|
_name = n; |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
//! Set minimum number of instances (in a xml::Factory).
|
|
|
|
|
/*! @copydoc limits */ |
|
|
|
|
Node& Node::min(Node::size_type m) throw() { |
|
|
|
@ -598,6 +603,12 @@ namespace xml { |
|
|
|
|
ss>>res; |
|
|
|
|
return res; |
|
|
|
|
} |
|
|
|
|
String::operator char() const throw() { |
|
|
|
|
char res; |
|
|
|
|
std::stringstream ss(text()); |
|
|
|
|
ss>>res; |
|
|
|
|
return res; |
|
|
|
|
} |
|
|
|
|
String::operator signed char() const throw() { |
|
|
|
|
signed char res; |
|
|
|
|
std::stringstream ss(text()); |
|
|
|
@ -849,6 +860,21 @@ namespace xml { |
|
|
|
|
e.line(_line); |
|
|
|
|
throw; |
|
|
|
|
} |
|
|
|
|
void Factory::reset() throw() { |
|
|
|
|
_line = 0; |
|
|
|
|
_open = 0; |
|
|
|
|
_template = xml::Node("<xml::start>"); |
|
|
|
|
} |
|
|
|
|
Node& Factory::operator*() throw(factory_not_valid) try { |
|
|
|
|
return _template[0]; |
|
|
|
|
} catch (...) { |
|
|
|
|
throw factory_not_valid(); |
|
|
|
|
} |
|
|
|
|
Node*const Factory::operator->() throw(factory_not_valid) try { |
|
|
|
|
return &_template[0]; |
|
|
|
|
} catch (...) { |
|
|
|
|
throw factory_not_valid(); |
|
|
|
|
} |
|
|
|
|
bool Factory::ws(char c) throw() { |
|
|
|
|
static char last(0); |
|
|
|
|
if ((c=='\n'||c=='\r')&&last!='\n'&&last!='\r') ++_line; |
|
|
|
@ -995,32 +1021,118 @@ namespace xml { |
|
|
|
|
xml::Node& node) { |
|
|
|
|
//! @todo improve this (inefficient)
|
|
|
|
|
std::stringstream ss; // simple but inefficient: rewrite and reread
|
|
|
|
|
ss<<node[member->_xmlFactory->name()]; |
|
|
|
|
member->loadXml(ss); |
|
|
|
|
ss<<node; |
|
|
|
|
member->loadXml(ss, node.name()); |
|
|
|
|
} |
|
|
|
|
template<> void Serialize::toNode<Serialize>(Serialize* member, |
|
|
|
|
xml::Node& node) const { |
|
|
|
|
//! @todo improve this (inefficient)
|
|
|
|
|
std::stringstream ss; // simple but inefficient: write and reread
|
|
|
|
|
member->saveXml(ss); |
|
|
|
|
node[member->_xmlFactory->name()] = *member->_xmlFactory.read(ss); |
|
|
|
|
std::stringstream ss; |
|
|
|
|
member->saveXml(ss, node.name()); |
|
|
|
|
xml::Factory factory(node); |
|
|
|
|
node = *factory.read(ss); |
|
|
|
|
} |
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
Serialize::Serialize() throw() {} |
|
|
|
|
Serialize::Serialize(const std::string& className) throw(): |
|
|
|
|
_xmlFactory(xml::Node(xml::String(className).limits(1,1))) { |
|
|
|
|
} |
|
|
|
|
Serialize::Serialize(const Serialize& other) throw() { |
|
|
|
|
copy(other); |
|
|
|
|
} |
|
|
|
|
Serialize::~Serialize() { |
|
|
|
|
// Remove my entries from the maps
|
|
|
|
|
clear(); |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::operator=(const Serialize& other) throw() { |
|
|
|
|
copy(other); |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::className(const std::string& name) throw() { |
|
|
|
|
xml::Node node(xml::Node(xml::String(name).limits(1,1))); |
|
|
|
|
if (_xmlFactory) { |
|
|
|
|
for (xml::Node::size_type i(0); i<_xmlFactory->children(); ++i) |
|
|
|
|
node<<(*_xmlFactory)[i]; |
|
|
|
|
} |
|
|
|
|
_xmlFactory=node; |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(Serialize& ser, |
|
|
|
|
const std::string& name) throw() { |
|
|
|
|
if (!ser._xmlFactory) ser.initXmlMembers(); |
|
|
|
|
mapName<Serialize>()[std::make_pair(this, name)] = &ser; |
|
|
|
|
mapMember<Serialize>()[&ser] = name; |
|
|
|
|
_xmlNames[name] = &typeid(Serialize); |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(bool& member, |
|
|
|
|
const std::string& name) throw() { |
|
|
|
|
return persistSimpleType(member, name); |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(char& member, |
|
|
|
|
const std::string& name) throw() { |
|
|
|
|
return persistSimpleType(member, name); |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(unsigned char& member, |
|
|
|
|
const std::string& name) throw() { |
|
|
|
|
return persistSimpleType(member, name); |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(signed char& member, |
|
|
|
|
const std::string& name) throw() { |
|
|
|
|
return persistSimpleType(member, name); |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(unsigned short& member, |
|
|
|
|
const std::string& name) throw() { |
|
|
|
|
return persistSimpleType(member, name); |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(signed short& member, |
|
|
|
|
const std::string& name) throw() { |
|
|
|
|
return persistSimpleType(member, name); |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(unsigned int& member, |
|
|
|
|
const std::string& name) throw() { |
|
|
|
|
return persistSimpleType(member, name); |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(signed int& member, |
|
|
|
|
const std::string& name) throw() { |
|
|
|
|
return persistSimpleType(member, name); |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(unsigned long& member, |
|
|
|
|
const std::string& name) throw() { |
|
|
|
|
return persistSimpleType(member, name); |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(signed long& member, |
|
|
|
|
const std::string& name) throw() { |
|
|
|
|
return persistSimpleType(member, name); |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(float& member, |
|
|
|
|
const std::string& name) throw() { |
|
|
|
|
return persistSimpleType(member, name); |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(double& member, |
|
|
|
|
const std::string& name) throw() { |
|
|
|
|
return persistSimpleType(member, name); |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(std::string& member, |
|
|
|
|
const std::string& name) throw() { |
|
|
|
|
return persistSimpleType(member, name); |
|
|
|
|
} |
|
|
|
|
std::ostream& Serialize::saveXml(std::ostream& os, |
|
|
|
|
const std::string& name) const throw() { |
|
|
|
|
if (!_xmlFactory) const_cast<Serialize*>(this)->initXmlMembers(); |
|
|
|
|
xml::Node node(*_xmlFactory); |
|
|
|
|
if (name.size()) node.name(name); |
|
|
|
|
for (std::map<std::string, const std::type_info*>::const_iterator |
|
|
|
|
it(_xmlNames.begin()); |
|
|
|
|
it!=_xmlNames.end(); ++it) { |
|
|
|
|
#define QWERTZ_CHECK_TYPE_ZTREWQ___XXX(TYPE) \ |
|
|
|
|
if (*it->second==typeid(TYPE)) { \
|
|
|
|
|
mapMember<TYPE>() \
|
|
|
|
|
.erase(mapName<TYPE>()[std::make_pair(this, it->first)]); \
|
|
|
|
|
mapName<TYPE>().erase(std::make_pair(this, it->first)); \
|
|
|
|
|
} else |
|
|
|
|
if (*it->second==typeid(TYPE)) \
|
|
|
|
|
toNode(mapName<TYPE>()[std::make_pair(this, it->first)], \
|
|
|
|
|
node[it->first]); \
|
|
|
|
|
else |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(Serialize) |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(std::string) |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(float) |
|
|
|
@ -1038,34 +1150,24 @@ namespace xml { |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(long) |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(signed long) |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(unsigned long) |
|
|
|
|
{} // ignore coding error here, but memory leaks - better abort?
|
|
|
|
|
throw std::runtime_error(it->second->name()); |
|
|
|
|
#undef QWERTZ_CHECK_TYPE_ZTREWQ___XXX |
|
|
|
|
}
|
|
|
|
|
os<<node; |
|
|
|
|
return os; |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::className(const std::string& name) throw() { |
|
|
|
|
_xmlFactory=xml::Node(xml::String(name).limits(1,1)); |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
Serialize& Serialize::persist(Serialize& ser) throw() { |
|
|
|
|
ser.initXmlMembers(); |
|
|
|
|
std::string name(ser._xmlFactory->name()); |
|
|
|
|
mapName<Serialize>()[std::make_pair(this, name)] = &ser; |
|
|
|
|
mapMember<Serialize>()[&ser] = name; |
|
|
|
|
_xmlNames[name] = &typeid(Serialize); |
|
|
|
|
xml::Node schema(*_xmlFactory); |
|
|
|
|
schema<<*ser._xmlFactory; |
|
|
|
|
_xmlFactory = schema; |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
std::ostream& Serialize::saveXml(std::ostream& os) const throw() { |
|
|
|
|
if (!_xmlFactory) const_cast<Serialize*>(this)->initXmlMembers(); |
|
|
|
|
xml::Node node(*_xmlFactory); |
|
|
|
|
std::istream& Serialize::loadXml(std::istream& is, const std::string& name) { |
|
|
|
|
if (!_xmlFactory) initXmlMembers(); |
|
|
|
|
xml::Factory factory(_xmlFactory); |
|
|
|
|
if (name.size()) factory->name(name); |
|
|
|
|
std::auto_ptr<xml::Node> node(factory.read(is)); |
|
|
|
|
for (std::map<std::string, const std::type_info*>::const_iterator |
|
|
|
|
it(_xmlNames.begin()); |
|
|
|
|
it!=_xmlNames.end(); ++it) { |
|
|
|
|
#define QWERTZ_CHECK_TYPE_ZTREWQ___XXX(TYPE) \ |
|
|
|
|
if (*it->second==typeid(TYPE)) \
|
|
|
|
|
toNode(mapName<TYPE>()[std::make_pair(this, it->first)], node); \
|
|
|
|
|
fromNode(mapName<TYPE>()[std::make_pair(this, it->first)], \
|
|
|
|
|
(*node)[it->first]); \
|
|
|
|
|
else |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(Serialize) |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(std::string) |
|
|
|
@ -1087,25 +1189,32 @@ namespace xml { |
|
|
|
|
throw std::runtime_error(it->second->name()); |
|
|
|
|
#undef QWERTZ_CHECK_TYPE_ZTREWQ___XXX |
|
|
|
|
} |
|
|
|
|
os<<node; |
|
|
|
|
return os; |
|
|
|
|
return is; |
|
|
|
|
} |
|
|
|
|
std::istream& Serialize::loadXml(std::istream& is) { |
|
|
|
|
if (!_xmlFactory) initXmlMembers(); |
|
|
|
|
std::auto_ptr<xml::Node> node(_xmlFactory.read(is)); |
|
|
|
|
std::string Serialize::schema() const throw() { |
|
|
|
|
if (!_xmlFactory) const_cast<Serialize*>(this)->initXmlMembers(); |
|
|
|
|
std::stringstream ss; |
|
|
|
|
ss<<*_xmlFactory; |
|
|
|
|
return ss.str(); |
|
|
|
|
} |
|
|
|
|
void Serialize::initXmlMembers() {} |
|
|
|
|
void Serialize::clear() throw() { |
|
|
|
|
// Remove my entries from the maps
|
|
|
|
|
for (std::map<std::string, const std::type_info*>::const_iterator |
|
|
|
|
it(_xmlNames.begin()); |
|
|
|
|
it!=_xmlNames.end(); ++it) { |
|
|
|
|
#define QWERTZ_CHECK_TYPE_ZTREWQ___XXX(TYPE) \ |
|
|
|
|
if (*it->second==typeid(TYPE)) \
|
|
|
|
|
fromNode(mapName<TYPE>()[std::make_pair(this, it->first)], *node); \
|
|
|
|
|
else |
|
|
|
|
if (*it->second==typeid(TYPE)) { \
|
|
|
|
|
mapMember<TYPE>() \
|
|
|
|
|
.erase(mapName<TYPE>()[std::make_pair(this, it->first)]); \
|
|
|
|
|
mapName<TYPE>().erase(std::make_pair(this, it->first)); \
|
|
|
|
|
} else |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(Serialize) |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(std::string) |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(float) |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(double) |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(bool) |
|
|
|
|
//QWERTZ_CHECK_TYPE_ZTREWQ___XXX(char)
|
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(char) |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(signed char) |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(unsigned char) |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(short) |
|
|
|
@ -1117,11 +1226,14 @@ namespace xml { |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(long) |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(signed long) |
|
|
|
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(unsigned long) |
|
|
|
|
throw std::runtime_error(it->second->name()); |
|
|
|
|
{} // ignore coding error here, but memory leaks - better abort?
|
|
|
|
|
#undef QWERTZ_CHECK_TYPE_ZTREWQ___XXX |
|
|
|
|
} |
|
|
|
|
return is; |
|
|
|
|
} |
|
|
|
|
void Serialize::initXmlMembers() {} |
|
|
|
|
void Serialize::copy(const Serialize& o) throw() { |
|
|
|
|
clear(); |
|
|
|
|
_xmlFactory.reset(); |
|
|
|
|
initXmlMembers(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|