diff -r 9cab23d9b124 -r 959c499e3b65 xml.h --- a/xml.h Mon Jul 25 11:17:23 2005 +0000 +++ b/xml.h Tue Jul 26 14:31:29 2005 +0000 @@ -5,438 +5,466 @@ #include #include #include +#include #include -class XmlWriter -{ - std::ostream& os; - int level; +namespace lemon { -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); } + class XmlWriter + { + std::ostream& os; + int level; - void beginTag(const std::string &_tag) { - itag(_tag); - level++; - } - void endTag(const std::string &_tag) { - level--; - ietag(_tag); - } + 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); } -public: + void beginTag(const std::string &_tag) { + itag(_tag); + level++; + } + void endTag(const std::string &_tag) { + level--; + ietag(_tag); + } - void indent() - { - if(level>=0) indent(level); - else level=0; - } + public: + + void indent() + { + if(level>=0) indent(level); + else level=0; + } - ///\e + ///\e - ///\e - /// - class ContTag - { - XmlWriter &ix; - const std::string _tag; - public: - ///\e + ///\e + /// + class ContTag + { + XmlWriter &ix; + const std::string _tag; + public: + ///\e - ///\e - /// - ContTag(XmlWriter &_ix,const std::string &_t) : - ix(_ix), _tag(_t) + ///\e + /// + ContTag(XmlWriter &_ix,const std::string &_t) : + ix(_ix), _tag(_t) + { + ix.tag(_tag); + } + ~ContTag() { ix.etag(_tag);} + }; + + class LineTag { - ix.tag(_tag); + 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) + { + os << v; + return *this; } - ~ContTag() { ix.etag(_tag);} + XmlWriter &operator()(const std::string &_tag,int v) + { + LineTag t(*this,_tag); + (*this)(v); + return *this; + } + XmlWriter &operator()(double v) + { + os << v; + return *this; + } + XmlWriter &operator()(const std::string &_tag,double v) + { + LineTag t(*this,_tag); + (*this)(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 LineTag + ////////////////////////////////////////////////////////////////////// + + class XmlReader { - XmlWriter &ix; - const std::string _tag; - public: + std::istream& is; + std::string next_tag; + int line_number; + + void skipWhiteSpaces() + { + char c; + while (is.get(c) && std::isspace(c,is.getloc())) if(c=='\n') line_number++; + is.unget(); + } + protected: ///\e - + ///\e /// - LineTag(XmlWriter &_ix,const std::string &_t) : - ix(_ix), _tag(_t) - { - ix.itag(_tag); + void useTag() {next_tag.clear();} + + void useTag(const std::string &_tag) { + if(nextTag()==_tag) useTag(); + else throw DataFormatError("",line_number,"Unexpected token name"); } - ~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) + const std::string &nextTag() { - ix.beginTag(_tag); + if(next_tag.empty()) { + char c; + skipWhiteSpaces(); + if(!is.get(c) || c!='<') + throw DataFormatError("",line_number,"Bad token"); + next_tag.clear(); + while (is.get(c) && c!='>') next_tag.push_back(c); + if(c!='>') + throw DataFormatError("",line_number,"Bad token"); + } + return next_tag; } - ~Tag() { - ix.endTag(_tag); - } - }; - - ///\e - ///\e - /// - XmlWriter(std::ostream& _os) : os(_os),level(-1) {} - ~XmlWriter() { os<< std::endl; } + ///\e - 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) + class Tag { - ix.useTag(_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), line_number(1) {} + + int operator()(const std::string &tag,int &v) + { + Tag t(*this,tag); + skipWhiteSpaces(); + if(!(is >> v)) throw DataFormatError("",line_number,"Not an 'int'"); + return v; } - ~Tag() { - if(!std::uncaught_exception()) - ix.useTag('/'+tag); + double operator()(const std::string &tag,double &v) + { + Tag t(*this,tag); + skipWhiteSpaces(); + if(!(is >> v)) + throw DataFormatError("",line_number,"Not a 'double'"); + 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 DataFormatError("",line_number,"Bad string"); + else switch(c) { + case 'n': + v.push_back('\n'); + break; + default: + v.push_back(c); + break; + } + else { + if(c=='\n') line_number++; + v.push_back(c); + } + if(c!='<') + throw DataFormatError("",line_number,"Unexpected eof"); + 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; } }; - ///\e + ////////////////////////////////////////////////////////////////////// + + template + void out(XmlWriter &x,const std::auto_ptr &v) + { + x(*v); + } + + template + void in(XmlReader &x,std::auto_ptr &v) + { + v=new A; + x(*v); + } + + ////////////////////////////// + + template + void out(XmlWriter &x,const std::pair &v) + { + x("first",v.first); + x("second",v.second); + } + + template + void in(XmlReader &x,std::pair &v) + { + x("first",v.first); + x("second",v.second); + } + + ////////////////////////////// + + template + void out(XmlWriter &x,const std::list &v) + { + for(typename std::list::const_iterator it=v.begin(); + it!=v.end();++it) x("item",*it); + } + + template + void in(XmlReader &x,std::list &v) + { + while(x.nextTag()=="item") + { + v.push_back(T()); + x("item",v.back()); + } + } + + ////////////////////////////// + + template + void out(XmlWriter &x,const std::vector &v) + { + for(typename std::vector::const_iterator it=v.begin(); + it!=v.end();++it) x("item",*it); + } + + template + void in(XmlReader &x,std::vector &v) + { + while(x.nextTag()=="item") + { + v.push_back(T()); + x("item",v.back()); + } + } + + ////////////////////////////// + + template + void out(XmlWriter &x,const std::map &v) + { + for(typename std::map::const_iterator it=v.begin(); + it!=v.end();++it) x("item",*it); + } + + template + void in(XmlReader &x,std::map &v) + { + while(x.nextTag()=="item") + { + typename std::map::value_type it; + x("item",it); + v.insert(it); + } + } + + ////////////////////////////// + + template + void out(XmlWriter &x,const lemon::xy &v) + { + // x("x",v.x); + // x("y",v.y); + { XmlWriter::LineTag t(x,"x"); x(v.x); } + { XmlWriter::ContTag t(x,"y"); x(v.y); } + } + + template + void in(XmlReader &x,lemon::xy &v) + { + x("x",v.x); + x("y",v.y); + } + + ////////////////////////////// + + template + void out(XmlWriter &x,const lemon::BoundingBox &v) + { + if(!v.empty()) { + x("point",v.bottomLeft()); + if(v.bottomLeft()!=v.topRight()) x("point",v.topRight()); + } + } + + template + void in(XmlReader &x,lemon::BoundingBox &v) + { + v.clear(); + while(x.nextTag()=="point") { + lemon::xy co; + x("point",co); + v.add(co); + } + } - ///\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; - } -}