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