Distribute xml.h too.
2 * gui/xml.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
22 #include <lemon/error.h>
31 ///Check if XmlIo is in write mode.
32 bool write() { return _writeMode;}
33 ///Check if XmlIo is in read mode.
34 bool read() { return !_writeMode;}
40 void indent(int level) {
42 for(int i=0;i<level;i++) os << ' ';
44 void tag(const std::string &_tag) {
45 os << '<' << _tag << '>';
47 void etag(const std::string &_tag) {
48 os << "</" << _tag << '>';
50 void itag(const std::string &_tag) { indent();tag(_tag); }
51 void ietag(const std::string &_tag) { indent();etag(_tag); }
53 void beginTag(const std::string &_tag) {
57 void endTag(const std::string &_tag) {
63 ///Indent the line according to its level.
65 ///\warning It can only be used in write mode.
70 if(level>=0) indent(level);
72 else throw LogicError();
78 ///In write mode it does not start a new line.
82 const std::string _tag;
88 ContTag(XmlIo &_ix,const std::string &_t) :
91 if(ix.write()) ix.tag(_tag);
95 if(ix.write()) ix.etag(_tag);
96 else if(!std::uncaught_exception()) ix.useTag('/'+_tag);
103 ///The whole <foo> ... </foo> will be places in a single line.
107 const std::string _tag;
113 LineTag(XmlIo &_ix,const std::string &_t) :
116 if(ix.write()) ix.itag(_tag);
117 else ix.useTag(_tag);
120 if(ix.write()) ix.etag(_tag);
121 else if(!std::uncaught_exception()) ix.useTag('/'+_tag);
132 const std::string _tag;
138 Tag(XmlIo &_ix,const std::string &_t) :
141 if(ix.write()) ix.beginTag(_tag);
142 else ix.useTag(_tag);
145 if(ix.write()) ix.endTag(_tag);
146 else if(!std::uncaught_exception()) ix.useTag('/'+_tag);
152 std::string next_tag;
155 void skipWhiteSpaces()
157 if(write()) throw LogicError();
160 while (is.get(c) && std::isspace(c,is.getloc()))
161 if(c=='\n') line_number++;
166 /// Use the next tag.
170 void useTag() {next_tag.clear();}
172 ///Use the next tag and check if it is equal with \c _tag
176 void useTag(const std::string &_tag) {
177 if(nextTag()==_tag) useTag();
178 else throw DataFormatError("",line_number,"Unexpected token name");
181 ///Return the next tag (if a tag follows on the stream).
183 ///\warning It can only be used in read mode.
185 const std::string &nextTag()
187 if(write()) throw LogicError();
188 else if(next_tag.empty()) {
191 if(!is.get(c) || c!='<')
192 throw DataFormatError("",line_number,"Bad format");
194 while (is.get(c) && c!='>') next_tag.push_back(c);
196 throw DataFormatError("",line_number,"Bad format");
201 /**********************************************************************/
208 XmlIo(std::ostream& _os) : _writeMode(true), os(_os),
210 is(*(std::istream*)(NULL)) {}
213 XmlIo(std::istream& _is) : _writeMode(false),
214 os(*(std::ostream*)(NULL)), is(_is),
217 ~XmlIo() { if(write()) os<< std::endl; }
221 XmlIo &operator()(const int &v)
226 if(!(is >> const_cast<int &>(v)))
227 throw DataFormatError("",line_number,"Not an 'int'");
231 XmlIo &operator()(const double &v)
236 if(!(is >> const_cast<double &>(v)))
237 throw DataFormatError("",line_number,"Not an 'double'");
241 XmlIo &operator()(const std::string &v)
244 for(std::string::const_iterator i=v.begin();i!=v.end();++i)
263 std::string &w = const_cast<std::string &>(v);
266 while (is.get(c) && c!='<')
269 throw DataFormatError("",line_number,"Bad string");
279 if(c=='\n') line_number++;
283 throw DataFormatError("",line_number,"Unexpected eof");
290 XmlIo &operator()(const std::string &_tag,const int &v)
292 LineTag t(*this,_tag);
296 XmlIo &operator()(const std::string &_tag,const double &v)
298 LineTag t(*this,_tag);
302 XmlIo &operator()(const std::string &_tag,const std::string &v)
304 LineTag t(*this,_tag);
313 XmlIo &operator()(const std::string &_tag,const V &v)
316 xml(*this,const_cast<V &>(v));
324 XmlIo &operator()(const V &v)
326 xml(*this,const_cast<V &>(v));
331 //////////////////////////////////////////////////////////////////////
332 //////////////////////////////////////////////////////////////////////
339 void xml(XmlIo &x,std::auto_ptr<A> &v)
341 if(x.write()) v=new A;
349 template<class A,class B>
350 void xml(XmlIo &x,std::pair<A,B> &v)
353 x("second",v.second);
361 void xml(XmlIo &x,std::list<T> &v)
364 for(typename std::list<T>::const_iterator it=v.begin();
365 it!=v.end();++it) x("item",*it);
366 else while(x.nextTag()=="item")
377 void xml(XmlIo &x,std::vector<T> &v)
380 for(typename std::vector<T>::const_iterator it=v.begin();
381 it!=v.end();++it) x("item",*it);
382 else while(x.nextTag()=="item")
393 template<class K,class V>
394 void xml(XmlIo &x,std::map<K,V> &v)
397 for(typename std::map<K,V>::const_iterator it=v.begin();
398 it!=v.end();++it) x("item",*it);
399 else while(x.nextTag()=="item")
401 typename std::map<K,V>::value_type it;
412 void xml(XmlIo &x,lemon::xy<T> &v)
414 { XmlIo::LineTag t(x,"x"); x(v.x); }
415 { XmlIo::ContTag t(x,"y"); x(v.y); }
423 void xml(XmlIo &x,lemon::BoundingBox<T> &v)
427 x("point",v.bottomLeft());
428 if(v.bottomLeft()!=v.topRight()) x("point",v.topRight());
433 while(x.nextTag()=="point") {