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