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