/* -*- C++ -*- */ #include #include #include #include #include #include class XmlWriter { std::ostream& os; int level; protected: void indent(int level) { os << std::endl; for(int i=0;i'; } void etag(const std::string &_tag) { os << "'; } void itag(const std::string &_tag) { indent();tag(_tag); } void ietag(const std::string &_tag) { indent();etag(_tag); } void beginTag(const std::string &_tag) { itag(_tag); level++; } void endTag(const std::string &_tag) { level--; ietag(_tag); } public: void indent() { if(level>=0) indent(level); else level=0; } ///\e ///\e /// class ContTag { XmlWriter &ix; const std::string _tag; public: ///\e ///\e /// ContTag(XmlWriter &_ix,const std::string &_t) : ix(_ix), _tag(_t) { ix.tag(_tag); } ~ContTag() { ix.etag(_tag);} }; class LineTag { XmlWriter &ix; const std::string _tag; public: ///\e ///\e /// LineTag(XmlWriter &_ix,const std::string &_t) : ix(_ix), _tag(_t) { ix.itag(_tag); } ~LineTag() { ix.etag(_tag);} }; ///\e ///\e /// class Tag { XmlWriter &ix; const std::string _tag; public: ///\e ///\e /// Tag(XmlWriter &_ix,const std::string &_t) : ix(_ix), _tag(_t) { ix.beginTag(_tag); } ~Tag() { ix.endTag(_tag); } }; ///\e ///\e /// XmlWriter(std::ostream& _os) : os(_os),level(-1) {} ~XmlWriter() { os<< std::endl; } XmlWriter &operator()(int v) { if(!(os << v)) throw (std::ios::failure ("data format error")); return *this; } XmlWriter &operator()(const std::string &_tag,int v) { LineTag t(*this,_tag); if(!(os << v)) throw (std::ios::failure ("data format error")); return *this; } XmlWriter &operator()(const std::string &_tag,double v) { LineTag t(*this,_tag); if(os << v) throw (std::ios::failure ("data format error")); return *this; } XmlWriter &operator()(double v) { os << v; return *this; } XmlWriter &operator()(const std::string &v) { for(std::string::const_iterator i=v.begin();i!=v.end();++i) switch(*i) { case '\\': os << "\\\\"; break; case '<': os << "\\<"; break; case '&': os << "\\&"; break; case '\n': os << "\\n"; break; default: os<<*i; break; } return *this; } XmlWriter &operator()(const std::string &_tag,const std::string &v) { LineTag t(*this,_tag); (*this)(v); return *this; } ///\e ///\e /// template XmlWriter &operator()(const std::string &_tag,const V &v) { Tag t(*this,_tag); out(*this,v); return *this; } ///\e ///\e /// template XmlWriter &operator()(const V &v) { out(*this,v); return *this; } }; ////////////////////////////////////////////////////////////////////// class XmlReader { std::istream& is; std::string next_tag; void skipWhiteSpaces() { char c; while (is.get(c) && std::isspace(c,is.getloc())); is.unget(); } protected: ///\e ///\e /// void useTag() {next_tag.clear();} void useTag(const std::string &_tag) { if(nextTag()==_tag) useTag(); else throw (std::ios::failure ("data format error")); } public: ///\e ///\e /// const std::string &nextTag() { if(next_tag.empty()) { char c; skipWhiteSpaces(); if(!is.get(c) || c!='<') throw (std::ios::failure ("data format error")); next_tag.clear(); while (is.get(c) && c!='>') next_tag.push_back(c); if(c!='>') throw (std::ios::failure ("data format error")); } return next_tag; } ///\e ///\e /// class Tag { XmlReader &ix; const std::string tag; public: ///\e ///\e /// Tag(XmlReader &_ix,const std::string &_tag) : ix(_ix), tag(_tag) { ix.useTag(_tag); } ~Tag() { if(!std::uncaught_exception()) ix.useTag('/'+tag); } }; ///\e ///\e /// XmlReader(std::istream& _is) : is(_is) {} int operator()(const std::string &tag,int &v) { Tag t(*this,tag); if(!(is >> v)) throw (std::ios::failure ("data format error")); return v; } double operator()(const std::string &tag,double &v) { Tag t(*this,tag); if(!(is >> v)) throw (std::ios::failure ("data format error")); return v; } std::string &operator()(const std::string &tag,std::string &v) { Tag t(*this,tag); v.clear(); char c; while (is.get(c) && c!='<') if(c=='\\') if(!is.get(c)) throw (std::ios::failure ("data format error")); else switch(c) { case 'n': v.push_back('\n'); break; default: v.push_back(c); break; } else v.push_back(c); if(c!='<') throw (std::ios::failure ("data format error")); is.unget(); return v; } ///\e ///\e /// template V &operator()(const std::string &tag,V &v) { Tag t(*this,tag); in(*this,v); return v; } ///\e ///\e /// template V &operator()(V &v) { in(*this,v); return v; } ///\e ///\e /// template V load(const std::string &tag) { Tag t(*this,tag); V v; (*this)(tag,v); return v; } }; ////////////////////////////////////////////////////////////////////// template void out(XmlWriter &i,const std::pair &v) { i("first",v.first); i("second",v.second); } template void in(XmlReader &i,std::pair &v) { i("first",v.first); i("second",v.second); } ////////////////////////////// template void out(XmlWriter &i,const std::list &v) { for(typename std::list::const_iterator it=v.begin(); it!=v.end();++it) i("item",*it); } template void in(XmlReader &i,std::list &v) { while(i.nextTag()=="item") { v.push_back(T()); i("item",v.back()); } } ////////////////////////////// template void out(XmlWriter &i,const std::vector &v) { for(typename std::vector::const_iterator it=v.begin(); it!=v.end();++it) i("item",*it); } template void in(XmlReader &i,std::vector &v) { while(i.nextTag()=="item") { v.push_back(T()); i("item",v.back()); } } ////////////////////////////// template void out(XmlWriter &i,const std::map &v) { for(typename std::map::const_iterator it=v.begin(); it!=v.end();++it) i("item",*it); } template void in(XmlReader &i,std::map &v) { while(i.nextTag()=="item") { typename std::map::value_type it; i("item",it); v.insert(it); } } ////////////////////////////// template void out(XmlWriter &i,const lemon::xy &v) { // i("x",v.x); // i("y",v.y); { XmlWriter::LineTag t(i,"x"); i(v.x); } { XmlWriter::ContTag t(i,"y"); i(v.y); } } template void in(XmlReader &i,lemon::xy &v) { i("x",v.x); i("y",v.y); } ////////////////////////////// template void out(XmlWriter &i,const lemon::BoundingBox &v) { if(!v.empty()) { i("point",v.bottomLeft()); if(v.bottomLeft()!=v.topRight()) i("point",v.topRight()); } } template void in(XmlReader &i,lemon::BoundingBox &v) { v.clear(); while(i.nextTag()=="point") { lemon::xy co; i("point",co); v+=co; } }