Metatemplateprogramming is really cool
This commit is contained in:
@@ -14,11 +14,12 @@
|
|||||||
|
|
||||||
class A: public xml::Serialize {
|
class A: public xml::Serialize {
|
||||||
public:
|
public:
|
||||||
std::list<std::string> list;
|
xml::List<std::string> list;
|
||||||
protected:
|
protected:
|
||||||
void initXmlMembers() {
|
void initXmlMembers() {
|
||||||
|
LOG("A::initXmlMembers");
|
||||||
className("A");
|
className("A");
|
||||||
persist(list, "list", "item");
|
persist(list, "list");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -35,8 +36,8 @@ int main(int, char**) {
|
|||||||
A a;
|
A a;
|
||||||
std::cout<<"Schema:\n"<<a.schema()<<std::endl;
|
std::cout<<"Schema:\n"<<a.schema()<<std::endl;
|
||||||
a.loadXml(ss);
|
a.loadXml(ss);
|
||||||
if (a.list.front()=="Hello") a.list.front()="Good Bye";
|
// if (a.list.front()=="Hello") a.list.front()="Good Bye";
|
||||||
if (a.list.back()=="you") a.list.back()="we";
|
// if (a.list.back()=="you") a.list.back()="we";
|
||||||
a.saveXml(std::cout)<<std::endl;
|
a.saveXml(std::cout)<<std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -829,25 +829,8 @@ namespace xml {
|
|||||||
virtual ~Serialize();
|
virtual ~Serialize();
|
||||||
Serialize& operator=(const Serialize& other) throw();
|
Serialize& operator=(const Serialize& other) throw();
|
||||||
Serialize& className(const std::string& name) throw();
|
Serialize& className(const std::string& name) throw();
|
||||||
Serialize& persist(Serialize& member,
|
virtual Serialize& persist(Serialize& member,
|
||||||
const std::string& name) throw();
|
const std::string& name) throw();
|
||||||
template<typename TYPE, class ALLOC>
|
|
||||||
Serialize& persist(std::list<TYPE, ALLOC>& member,
|
|
||||||
const std::string& name) throw() {
|
|
||||||
return persist(member, name, name);
|
|
||||||
}
|
|
||||||
template<typename TYPE, class ALLOC>
|
|
||||||
Serialize& persist(std::list<TYPE, ALLOC>& member,
|
|
||||||
const std::string& list,
|
|
||||||
const std::string& item) throw() {
|
|
||||||
_xmlNames[list] = &member;
|
|
||||||
Serialize ser(list);
|
|
||||||
TYPE dummy;
|
|
||||||
ser.persist(dummy, item);
|
|
||||||
*_xmlFactory<<(xml::Node(list).limits(1,1)
|
|
||||||
<<(*ser._xmlFactory)[0].limits(0, 0));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
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,
|
||||||
@@ -885,6 +868,7 @@ namespace xml {
|
|||||||
protected:
|
protected:
|
||||||
virtual void initXmlMembers();
|
virtual void initXmlMembers();
|
||||||
private:
|
private:
|
||||||
|
public: //! @todo
|
||||||
void clear() throw();
|
void clear() throw();
|
||||||
void copy(const Serialize& o) throw();
|
void copy(const Serialize& o) throw();
|
||||||
template<typename TYPE>
|
template<typename TYPE>
|
||||||
@@ -896,8 +880,8 @@ namespace xml {
|
|||||||
_xmlFactory = schema;
|
_xmlFactory = schema;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
void fromNode(boost::any member, const xml::Node& node);
|
virtual void fromNode(boost::any member, const xml::Node& node);
|
||||||
void toNode(const boost::any member, xml::Node& node) const;
|
virtual void toNode(const boost::any member, xml::Node& node) const;
|
||||||
/*
|
/*
|
||||||
template<typename TYPE, class ALLOC>
|
template<typename TYPE, class ALLOC>
|
||||||
void fromNode(std::list<TYPE, ALLOC>* member, xml::Node& node) {
|
void fromNode(std::list<TYPE, ALLOC>* member, xml::Node& node) {
|
||||||
@@ -911,6 +895,35 @@ namespace xml {
|
|||||||
static std::set<ToNodeFunc> _toNode;
|
static std::set<ToNodeFunc> _toNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class TYPE, class ALLOC=std::allocator<TYPE> > class List:
|
||||||
|
public std::list<TYPE, ALLOC>, public Serialize {
|
||||||
|
public:
|
||||||
|
List() {}
|
||||||
|
List(const List& o): std::list<TYPE, ALLOC>(o), Serialize(o) {}
|
||||||
|
List(const std::string& className) throw(): Serialize(className) {}
|
||||||
|
virtual ~List() {}
|
||||||
|
protected:
|
||||||
|
/*virtual void initXmlMembers() {
|
||||||
|
LOG("initXmlMembers std::list");
|
||||||
|
//_xmlNames[list] = this;
|
||||||
|
TYPE dummy;
|
||||||
|
std::string itemName("item");
|
||||||
|
if (typeid(TYPE*)==typeid(Serialize*)) {
|
||||||
|
Serialize* ser((Serialize*)&dummy);
|
||||||
|
if (!ser->_xmlFactory) ser->initXmlMembers();
|
||||||
|
itemName = **ser->_xmlFactory;
|
||||||
|
}
|
||||||
|
persist(dummy, itemName);
|
||||||
|
_xmlFactory->limits(0, 0);
|
||||||
|
}
|
||||||
|
virtual void fromNode(boost::any member, const xml::Node& node) {
|
||||||
|
LOG("fromNode std::list");
|
||||||
|
}
|
||||||
|
virtual void toNode(const boost::any member, xml::Node& node) const {
|
||||||
|
LOG("toNode std::list");
|
||||||
|
}*/
|
||||||
|
};
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
181
src/xml.cxx
181
src/xml.cxx
@@ -1135,130 +1135,75 @@ namespace xml {
|
|||||||
}
|
}
|
||||||
template<typename TYPE> bool assignFromNode(boost::any member,
|
template<typename TYPE> bool assignFromNode(boost::any member,
|
||||||
const xml::Node& node) {
|
const xml::Node& node) {
|
||||||
if (member.type()==typeid(TYPE*)) {
|
if (member.type()!=typeid(TYPE*)) return false;
|
||||||
*boost::any_cast<TYPE*>(member) =
|
*boost::any_cast<TYPE*>(member) =
|
||||||
(TYPE)dynamic_cast<const xml::String&>(node);
|
(TYPE)dynamic_cast<const xml::String&>(node);
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
template<typename TYPE> bool assignToNode(const boost::any member,
|
template<typename TYPE> bool assignToNode(const boost::any member,
|
||||||
xml::Node& node) {
|
xml::Node& node) {
|
||||||
if (member.type()==typeid(TYPE*)) {
|
if (member.type()!=typeid(TYPE*)) return false;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss<<*boost::any_cast<TYPE*>(member);
|
ss<<*boost::any_cast<TYPE*>(member);
|
||||||
node.text(ss.str());
|
node.text(ss.str());
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
template<> bool assignFromNode<bool>(boost::any member,
|
template<> bool assignFromNode<bool>(boost::any member,
|
||||||
const xml::Node& node) {
|
const xml::Node& node) {
|
||||||
if (member.type()==typeid(bool*)) {
|
if (member.type()!=typeid(bool*)) return false;
|
||||||
std::string s(*dynamic_cast<const xml::String&>(node));
|
std::string s(*dynamic_cast<const xml::String&>(node));
|
||||||
std::string::size_type
|
std::string::size_type
|
||||||
start(s.find_first_not_of(" \t\n\r")),
|
start(s.find_first_not_of(" \t\n\r")),
|
||||||
end(s.find_last_not_of(" \t\n\r"));
|
end(s.find_last_not_of(" \t\n\r"));
|
||||||
if (start==std::string::npos) {
|
if (start==std::string::npos) {
|
||||||
*boost::any_cast<bool*>(member) = false;
|
*boost::any_cast<bool*>(member) = false;
|
||||||
} else {
|
} else {
|
||||||
s = s.substr(start, end-start+1);
|
s = s.substr(start, end-start+1);
|
||||||
*boost::any_cast<bool*>(member) =
|
*boost::any_cast<bool*>(member) =
|
||||||
s!="0" && s!="false" && s!="no" && s!="off";
|
s!="0" && s!="false" && s!="no" && s!="off";
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
template<> bool assignToNode<bool>(const boost::any member,
|
template<> bool assignToNode<bool>(const boost::any member,
|
||||||
xml::Node& node) {
|
xml::Node& node) {
|
||||||
if (member.type()==typeid(bool*)) {
|
if (member.type()!=typeid(bool*)) return false;
|
||||||
node.text(*boost::any_cast<bool*>(member)?"true":"false");
|
node.text(*boost::any_cast<bool*>(member)?"true":"false");
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
template<> bool assignFromNode<Serialize>(boost::any member,
|
template<> bool assignFromNode<Serialize>(boost::any member,
|
||||||
const xml::Node& node) {
|
const xml::Node& node) {
|
||||||
if (member.type()==typeid(Serialize*)) {
|
if (member.type()!=typeid(Serialize*)) return false;
|
||||||
//! @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;
|
||||||
boost::any_cast<Serialize*>(member)->loadXml(ss, node.name());
|
boost::any_cast<Serialize*>(member)->loadXml(ss, node.name());
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
template<> bool assignToNode<Serialize>(const boost::any member,
|
template<> bool assignToNode<Serialize>(const boost::any member,
|
||||||
xml::Node& node) {
|
xml::Node& node) {
|
||||||
if (member.type()==typeid(Serialize*)) {
|
if (member.type()!=typeid(Serialize*)) return false;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
boost::any_cast<Serialize*>(member)->saveXml(ss, node.name());
|
boost::any_cast<Serialize*>(member)->saveXml(ss, node.name());
|
||||||
xml::Factory factory(node);
|
xml::Factory factory(node);
|
||||||
node = *factory.read(ss);
|
node = *factory.read(ss);
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
template<typename TYPE, class ALLOC>
|
|
||||||
bool containerFromNode(boost::any member,
|
|
||||||
const xml::Node& node) {
|
|
||||||
LOG("ASSIGN List");
|
|
||||||
}
|
}
|
||||||
|
// template<typename TYPE, template<class TYPE> class CONTAINER>
|
||||||
|
// bool containerFromNode(boost::any member,
|
||||||
|
// const xml::Node& node) {
|
||||||
|
// if (member.type()!=typeid(TYPE*)) return false;
|
||||||
|
// LOG("ASSIGN List");
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
// template<typename TYPE, class ALLOC>
|
// template<typename TYPE, class ALLOC>
|
||||||
// bool assignToNode(const boost::any member, xml::Node& node) {
|
// bool assignToNode(const boost::any member, xml::Node& node) {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
void Serialize::registerFromNode(Serialize::FromNodeFunc fromNodeFunc) {
|
void Serialize::registerFromNode(Serialize::FromNodeFunc fromNodeFunc) {
|
||||||
if (!_fromNode.size()) { // initial initialization
|
|
||||||
_fromNode.insert(&assignFromNode<Serialize>);
|
|
||||||
_fromNode.insert(&assignFromNode<std::string>);
|
|
||||||
_fromNode.insert(&assignFromNode<float>);
|
|
||||||
_fromNode.insert(&assignFromNode<double>);
|
|
||||||
_fromNode.insert(&assignFromNode<bool>);
|
|
||||||
_fromNode.insert(&assignFromNode<char>);
|
|
||||||
_fromNode.insert(&assignFromNode<signed char>);
|
|
||||||
_fromNode.insert(&assignFromNode<unsigned char>);
|
|
||||||
_fromNode.insert(&assignFromNode<short>);
|
|
||||||
_fromNode.insert(&assignFromNode<signed short>);
|
|
||||||
_fromNode.insert(&assignFromNode<unsigned short>);
|
|
||||||
_fromNode.insert(&assignFromNode<int>);
|
|
||||||
_fromNode.insert(&assignFromNode<signed int>);
|
|
||||||
_fromNode.insert(&assignFromNode<unsigned int>);
|
|
||||||
_fromNode.insert(&assignFromNode<long>);
|
|
||||||
_fromNode.insert(&assignFromNode<signed long>);
|
|
||||||
_fromNode.insert(&assignFromNode<unsigned long>);
|
|
||||||
}
|
|
||||||
_fromNode.insert(fromNodeFunc);
|
_fromNode.insert(fromNodeFunc);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
//typedef boost::mpl::vector<Serialize, std::string, float, double, bool, char, signed char, unsigned char, short, signed short, unsigned short, int, signed int, unsigned int, long, signed long, unsigned long> BasicTypes;
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
//typedef boost::mpl::vector<Serialize, std::string, float, double, bool, char, signed char, unsigned char, short, signed short, unsigned short, int, signed int, unsigned int, long, signed long, unsigned long> BasicTypes;
|
|
||||||
template<typename TYPE> class RegisterAssignToNode {
|
|
||||||
RegisterAssignToNode() {
|
|
||||||
registerToNode(&assignToNode<TYPE>);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
void Serialize::registerToNode(Serialize::ToNodeFunc toNodeFunc) {
|
void Serialize::registerToNode(Serialize::ToNodeFunc toNodeFunc) {
|
||||||
if (!_toNode.size()) { // initial initialization
|
|
||||||
_toNode.insert(&assignToNode<Serialize>);
|
|
||||||
_toNode.insert(&assignToNode<std::string>);
|
|
||||||
_toNode.insert(&assignToNode<float>);
|
|
||||||
_toNode.insert(&assignToNode<double>);
|
|
||||||
_toNode.insert(&assignToNode<bool>);
|
|
||||||
_toNode.insert(&assignToNode<char>);
|
|
||||||
_toNode.insert(&assignToNode<signed char>);
|
|
||||||
_toNode.insert(&assignToNode<unsigned char>);
|
|
||||||
_toNode.insert(&assignToNode<short>);
|
|
||||||
_toNode.insert(&assignToNode<signed short>);
|
|
||||||
_toNode.insert(&assignToNode<unsigned short>);
|
|
||||||
_toNode.insert(&assignToNode<int>);
|
|
||||||
_toNode.insert(&assignToNode<signed int>);
|
|
||||||
_toNode.insert(&assignToNode<unsigned int>);
|
|
||||||
_toNode.insert(&assignToNode<long>);
|
|
||||||
_toNode.insert(&assignToNode<signed long>);
|
|
||||||
_toNode.insert(&assignToNode<unsigned long>);
|
|
||||||
}
|
|
||||||
_toNode.insert(toNodeFunc);
|
_toNode.insert(toNodeFunc);
|
||||||
}
|
}
|
||||||
void Serialize::initXmlMembers() {}
|
void Serialize::initXmlMembers() {}
|
||||||
@@ -1287,4 +1232,40 @@ namespace xml {
|
|||||||
std::set<Serialize::FromNodeFunc> Serialize::_fromNode;
|
std::set<Serialize::FromNodeFunc> Serialize::_fromNode;
|
||||||
std::set<Serialize::ToNodeFunc> Serialize::_toNode;
|
std::set<Serialize::ToNodeFunc> Serialize::_toNode;
|
||||||
|
|
||||||
|
// Register for all simple Types =============================================
|
||||||
|
template<int NUM> struct SimpleTypes {};
|
||||||
|
template<> struct SimpleTypes<1> {typedef std::string Type;};
|
||||||
|
template<> struct SimpleTypes<2> {typedef Serialize Type;};
|
||||||
|
template<> struct SimpleTypes<3> {typedef bool Type;};
|
||||||
|
template<> struct SimpleTypes<4> {typedef unsigned char Type;};
|
||||||
|
template<> struct SimpleTypes<5> {typedef signed char Type;};
|
||||||
|
template<> struct SimpleTypes<6> {typedef char Type;};
|
||||||
|
template<> struct SimpleTypes<7> {typedef unsigned short Type;};
|
||||||
|
template<> struct SimpleTypes<8> {typedef signed short Type;};
|
||||||
|
template<> struct SimpleTypes<9> {typedef short Type;};
|
||||||
|
template<> struct SimpleTypes<10> {typedef unsigned int Type;};
|
||||||
|
template<> struct SimpleTypes<11> {typedef signed int Type;};
|
||||||
|
template<> struct SimpleTypes<12> {typedef int Type;};
|
||||||
|
template<> struct SimpleTypes<13> {typedef unsigned long Type;};
|
||||||
|
template<> struct SimpleTypes<14> {typedef signed long Type;};
|
||||||
|
template<> struct SimpleTypes<15> {typedef long Type;};
|
||||||
|
template<> struct SimpleTypes<16> {typedef float Type;};
|
||||||
|
template<> struct SimpleTypes<17> {typedef double Type;};
|
||||||
|
const int START_NUM(17);
|
||||||
|
// Init To and From Node ---------------------------------------------------
|
||||||
|
namespace {
|
||||||
|
template<int NUM=START_NUM> struct RegisterTemplateForStdTypes {
|
||||||
|
RegisterTemplateForStdTypes<NUM-1> next; // recurse to next until 0
|
||||||
|
RegisterTemplateForStdTypes() {
|
||||||
|
Serialize::registerToNode
|
||||||
|
(&assignToNode<typename SimpleTypes<NUM>::Type>);
|
||||||
|
Serialize::registerFromNode
|
||||||
|
(&assignFromNode<typename SimpleTypes<NUM>::Type>);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<> struct RegisterTemplateForStdTypes<0> {}; // stop recursion
|
||||||
|
static RegisterTemplateForStdTypes<> init; // execute initialisation
|
||||||
|
}
|
||||||
|
// ===========================================================================
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user