3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
27 #include <lemon/error.h>
28 #include <lemon/assert.h>
29 #include <lemon/dim2.h>
37 ///Check if XmlIo is in write mode.
38 bool write() { return _writeMode;}
39 ///Check if XmlIo is in read mode.
40 bool read() { return !_writeMode;}
46 void indent(int level) {
48 for(int i=0;i<level;i++) os << ' ';
50 void tag(const std::string &_tag) {
51 os << '<' << _tag << '>';
53 void etag(const std::string &_tag) {
54 os << "</" << _tag << '>';
56 void itag(const std::string &_tag) { indent();tag(_tag); }
57 void ietag(const std::string &_tag) { indent();etag(_tag); }
59 void beginTag(const std::string &_tag) {
63 void endTag(const std::string &_tag) {
69 ///Indent the line according to its level.
71 ///\warning It can only be used in write mode.
76 if(level>=0) indent(level);
78 else LEMON_ASSERT(true, "Invalid indentation.");
84 ///In write mode it does not start a new line.
88 const std::string _tag;
94 ContTag(XmlIo &_ix,const std::string &_t) :
97 if(ix.write()) ix.tag(_tag);
101 if(ix.write()) ix.etag(_tag);
102 else if(!std::uncaught_exception()) ix.useTag('/'+_tag);
109 ///The whole \<foo\> ... \</foo\> will be placed in a single line.
113 const std::string _tag;
119 LineTag(XmlIo &_ix,const std::string &_t) :
122 if(ix.write()) ix.itag(_tag);
123 else ix.useTag(_tag);
126 if(ix.write()) ix.etag(_tag);
127 else if(!std::uncaught_exception()) ix.useTag('/'+_tag);
138 const std::string _tag;
144 Tag(XmlIo &_ix,const std::string &_t) :
147 if(ix.write()) ix.beginTag(_tag);
148 else ix.useTag(_tag);
151 if(ix.write()) ix.endTag(_tag);
152 else if(!std::uncaught_exception()) ix.useTag('/'+_tag);
158 std::string next_tag;
161 void skipWhiteSpaces()
163 if(write()) LEMON_ASSERT(true, "Can't skip whitespaces in write mode.");
166 while (is.get(c) && std::isspace(c,is.getloc()))
167 if(c=='\n') line_number++;
172 /// Use the next tag.
176 void useTag() {next_tag.clear();}
178 ///Use the next tag and check if it is equal with \c _tag
182 void useTag(const std::string &_tag) {
183 if(nextTag()==_tag) useTag();
184 else throw FormatError("Unexpected token name","",line_number);
187 ///Return the next tag (if a tag follows on the stream).
189 ///\warning It can only be used in read mode.
191 const std::string &nextTag()
193 if(write()) LEMON_ASSERT(true,"Don't use nextTag() in write mode");
194 else if(next_tag.empty()) {
197 if(!is.get(c) || c!='<')
198 throw FormatError("Bad format","",line_number);
200 while (is.get(c) && c!='>') next_tag.push_back(c);
202 throw FormatError("Bad format","",line_number);
207 /**********************************************************************/
214 XmlIo(std::ostream& _os) : _writeMode(true), os(_os),
219 XmlIo(std::istream& _is) : _writeMode(false),
220 os(std::cout), is(_is),
223 ~XmlIo() { if(write()) os<< std::endl; }
227 XmlIo &operator()(const int &v)
232 if(!(is >> const_cast<int &>(v)))
233 throw FormatError("Not an 'int'","",line_number);
237 XmlIo &operator()(const double &v)
242 if(!(is >> const_cast<double &>(v)))
243 throw FormatError("Not an 'double'","",line_number);
247 XmlIo &operator()(const std::string &v)
250 for(std::string::const_iterator i=v.begin();i!=v.end();++i)
269 std::string &w = const_cast<std::string &>(v);
272 while (is.get(c) && c!='<')
275 throw FormatError("Bad string","",line_number);
285 if(c=='\n') line_number++;
289 throw FormatError("Unexpected eof","",line_number);
296 XmlIo &operator()(const std::string &_tag,const int &v)
298 LineTag t(*this,_tag);
302 XmlIo &operator()(const std::string &_tag,const double &v)
304 LineTag t(*this,_tag);
308 XmlIo &operator()(const std::string &_tag,const std::string &v)
310 LineTag t(*this,_tag);
319 XmlIo &operator()(const std::string &_tag,const V &v)
322 xml(*this,const_cast<V &>(v));
330 XmlIo &operator()(const V &v)
332 xml(*this,const_cast<V &>(v));
337 //////////////////////////////////////////////////////////////////////
338 //////////////////////////////////////////////////////////////////////
345 void xml(XmlIo &x,std::auto_ptr<A> &v)
347 if(x.write()) v=new A;
355 template<class A,class B>
356 void xml(XmlIo &x,std::pair<A,B> &v)
359 x("second",v.second);
367 void xml(XmlIo &x,std::list<T> &v)
370 for(typename std::list<T>::const_iterator it=v.begin();
371 it!=v.end();++it) x("item",*it);
372 else while(x.nextTag()=="item")
383 void xml(XmlIo &x,std::vector<T> &v)
386 for(typename std::vector<T>::const_iterator it=v.begin();
387 it!=v.end();++it) x("item",*it);
388 else while(x.nextTag()=="item")
399 template<class K,class V>
400 void xml(XmlIo &x,std::map<K,V> &v)
403 for(typename std::map<K,V>::const_iterator it=v.begin();
404 it!=v.end();++it) x("item",*it);
405 else while(x.nextTag()=="item")
407 typename std::map<K,V>::value_type it;
418 void xml(XmlIo &x,lemon::dim2::Point<T> &v)
420 { XmlIo::LineTag t(x,"x"); x(v.x); }
421 { XmlIo::ContTag t(x,"y"); x(v.y); }
429 void xml(XmlIo &x,lemon::dim2::Box<T> &v)
433 x("point",v.bottomLeft());
434 if(v.bottomLeft()!=v.topRight()) x("point",v.topRight());
439 while(x.nextTag()=="point") {
440 lemon::dim2::Point<T> co;