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