# HG changeset patch # User alpar # Date 1130141481 0 # Node ID 6c0db51a1d999a904aaacf24aaeb06e88d3dfe1b # Parent ee009c0f4bcf4961ce804c2b5928cf6a349d5671 New version of XML reader/writer. Now, there are only a single XmlIo class both for reading and writing. diff -r ee009c0f4bcf -r 6c0db51a1d99 xml.h --- a/xml.h Fri Oct 21 13:32:12 2005 +0000 +++ b/xml.h Mon Oct 24 08:11:21 2005 +0000 @@ -1,4 +1,18 @@ -/* -*- C++ -*- */ +/* -*- C++ -*- + * gui/xml.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ #include #include @@ -10,11 +24,18 @@ namespace lemon { - class XmlWriter + class XmlIo { + bool _writeMode; + public: + ///Check if XmlIo is in write mode. + bool write() { return _writeMode;} + ///Check if XmlIo is in read mode. + bool read() { return !_writeMode;} + std::ostream& os; int level; - + protected: void indent(int level) { os << std::endl; @@ -39,126 +60,246 @@ } public: + ///Indent the line according to its level. - void indent() + ///\warning It can only be used in write mode. + /// + void indent() { - if(level>=0) indent(level); - else level=0; + if(write()) + if(level>=0) indent(level); + else level=0; + else throw LogicError(); } - ///\e + ///Read/write a tag - ///\e - /// + ///Read/write a tag. + ///In write mode it does not start a new line. class ContTag { - XmlWriter &ix; + XmlIo &ix; const std::string _tag; public: ///\e ///\e /// - ContTag(XmlWriter &_ix,const std::string &_t) : + ContTag(XmlIo &_ix,const std::string &_t) : ix(_ix), _tag(_t) { - ix.tag(_tag); + if(ix.write()) ix.tag(_tag); + else ix.useTag(_tag); } - ~ContTag() { ix.etag(_tag);} + ~ContTag() { + if(ix.write()) ix.etag(_tag); + else if(!std::uncaught_exception()) ix.useTag('/'+_tag); + } }; + ///Read/write a tag + + ///Read/write a tag. + ///The whole ... will be places in a single line. class LineTag { - XmlWriter &ix; + XmlIo &ix; const std::string _tag; public: ///\e ///\e /// - LineTag(XmlWriter &_ix,const std::string &_t) : + LineTag(XmlIo &_ix,const std::string &_t) : ix(_ix), _tag(_t) { - ix.itag(_tag); + if(ix.write()) ix.itag(_tag); + else ix.useTag(_tag); } - ~LineTag() { ix.etag(_tag);} + ~LineTag() { + if(ix.write()) ix.etag(_tag); + else if(!std::uncaught_exception()) ix.useTag('/'+_tag); + } }; - ///\e + ///Read/write a tag - ///\e + ///Read/write a tag. /// class Tag { - XmlWriter &ix; + XmlIo &ix; const std::string _tag; public: ///\e ///\e /// - Tag(XmlWriter &_ix,const std::string &_t) : + Tag(XmlIo &_ix,const std::string &_t) : ix(_ix), _tag(_t) { - ix.beginTag(_tag); + if(ix.write()) ix.beginTag(_tag); + else ix.useTag(_tag); } - ~Tag() { - ix.endTag(_tag); + ~Tag() { + if(ix.write()) ix.endTag(_tag); + else if(!std::uncaught_exception()) ix.useTag('/'+_tag); } }; - + + private: + std::istream& is; + std::string next_tag; + int line_number; + + void skipWhiteSpaces() + { + if(write()) throw LogicError(); + { + char c; + while (is.get(c) && std::isspace(c,is.getloc())) + if(c=='\n') line_number++; + is.unget(); + } + } + protected: + /// Use the next tag. + + ///\e + /// + void useTag() {next_tag.clear();} + + ///Use the next tag and check if it is equal with \c _tag + + ///\e + /// + void useTag(const std::string &_tag) { + if(nextTag()==_tag) useTag(); + else throw DataFormatError("",line_number,"Unexpected token name"); + } + public: + ///Return the next tag (if a tag follows on the stream). + + ///\warning It can only be used in read mode. + /// + const std::string &nextTag() + { + if(write()) throw LogicError(); + else if(next_tag.empty()) { + char c; + skipWhiteSpaces(); + if(!is.get(c) || c!='<') + throw DataFormatError("",line_number,"Bad format"); + next_tag.clear(); + while (is.get(c) && c!='>') next_tag.push_back(c); + if(c!='>') + throw DataFormatError("",line_number,"Bad format"); + } + return next_tag; + } + + /**********************************************************************/ + + ///\e ///\e /// - XmlWriter(std::ostream& _os) : os(_os),level(-1) {} - ~XmlWriter() { os<< std::endl; } + XmlIo(std::ostream& _os) : _writeMode(true), os(_os), + level(-1), + is(*(std::istream*)(NULL)) {} + ///\e + /// + XmlIo(std::istream& _is) : _writeMode(false), + os(*(std::ostream*)(NULL)), is(_is), + line_number(1) {} + + ~XmlIo() { if(write()) os<< std::endl; } - XmlWriter &operator()(int v) + + + XmlIo &operator()(const int &v) { - os << v; + if(write()) os << v; + else { + skipWhiteSpaces(); + if(!(is >> const_cast(v))) + throw DataFormatError("",line_number,"Not an 'int'"); + } return *this; } - XmlWriter &operator()(const std::string &_tag,int v) + XmlIo &operator()(const double &v) + { + if(write()) os << v; + else { + skipWhiteSpaces(); + if(!(is >> const_cast(v))) + throw DataFormatError("",line_number,"Not an 'double'"); + } + return *this; + } + XmlIo &operator()(const std::string &v) + { + if(write()) + 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; + } + else { + std::string &w = const_cast(v); + w.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': + w.push_back('\n'); + break; + default: + w.push_back(c); + break; + } + else { + if(c=='\n') line_number++; + w.push_back(c); + } + if(c!='<') + throw DataFormatError("",line_number,"Unexpected eof"); + is.unget(); + } + return *this; + } + + + XmlIo &operator()(const std::string &_tag,const 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) + XmlIo &operator()(const std::string &_tag,const 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) + XmlIo &operator()(const std::string &_tag,const std::string &v) { LineTag t(*this,_tag); (*this)(v); @@ -169,10 +310,10 @@ ///\e /// template - XmlWriter &operator()(const std::string &_tag,const V &v) + XmlIo &operator()(const std::string &_tag,const V &v) { Tag t(*this,_tag); - out(*this,v); + xml(*this,const_cast(v)); return *this; } ///\e @@ -180,246 +321,82 @@ ///\e /// template - XmlWriter &operator()(const V &v) + XmlIo &operator()(const V &v) { - out(*this,v); + xml(*this,const_cast(v)); return *this; } - }; + }; ////////////////////////////////////////////////////////////////////// - - class XmlReader - { - 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 - /// - void useTag() {next_tag.clear();} - - void useTag(const std::string &_tag) { - if(nextTag()==_tag) useTag(); - else throw DataFormatError("",line_number,"Unexpected token name"); - } - public: - ///\e - - ///\e - /// - const std::string &nextTag() - { - 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; - } - - ///\e - - ///\e - /// - class 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; - } - 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 + + ///\relates XmlIo + /// template - void out(XmlWriter &x,const std::auto_ptr &v) + void xml(XmlIo &x,std::auto_ptr &v) { + if(x.write()) v=new A; x(*v); } - - template - void in(XmlReader &x,std::auto_ptr &v) - { - v=new A; - x(*v); - } - - ////////////////////////////// - + + ///\e + + ///\relates XmlIo + /// template - void out(XmlWriter &x,const std::pair &v) + void xml(XmlIo &x,std::pair &v) { x("first",v.first); x("second",v.second); } - template - void in(XmlReader &x,std::pair &v) + ///\e + + ///\relates XmlIo + /// + template + void xml(XmlIo &x,std::list &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") + if(x.write()) + for(typename std::list::const_iterator it=v.begin(); + it!=v.end();++it) x("item",*it); + else while(x.nextTag()=="item") { v.push_back(T()); x("item",v.back()); } } - - ////////////////////////////// - + ///\e + + ///\relates XmlIo + /// template - void out(XmlWriter &x,const std::vector &v) + void xml(XmlIo &x,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") + if(x.write()) + for(typename std::vector::const_iterator it=v.begin(); + it!=v.end();++it) x("item",*it); + else while(x.nextTag()=="item") { v.push_back(T()); x("item",v.back()); } } - ////////////////////////////// - + ///\e + + ///\relates XmlIo + /// template - void out(XmlWriter &x,const std::map &v) + void xml(XmlIo &x,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") + if(x.write()) + for(typename std::map::const_iterator it=v.begin(); + it!=v.end();++it) x("item",*it); + else while(x.nextTag()=="item") { typename std::map::value_type it; x("item",it); @@ -427,44 +404,39 @@ } } - ////////////////////////////// - + ///\e + + ///\relates XmlIo + /// template - void out(XmlWriter &x,const lemon::xy &v) + void xml(XmlIo &x,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); } + { XmlIo::LineTag t(x,"x"); x(v.x); } + { XmlIo::ContTag t(x,"y"); x(v.y); } } + ///\e + + ///\relates XmlIo + /// template - void in(XmlReader &x,lemon::xy &v) + void xml(XmlIo &x,lemon::BoundingBox &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()); + if(x.write()) { + 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); + else { + v.clear(); + while(x.nextTag()=="point") { + lemon::xy co; + x("point",co); + v.add(co); + } } } } +