COIN-OR::LEMON - Graph Library

source: glemon-0.x/xml.h @ 197:c1084e2bff10

Last change on this file since 197:c1084e2bff10 was 174:95872af46fc4, checked in by Alpar Juttner, 18 years ago

Add copyright headers

File size: 8.8 KB
RevLine 
[83]1/* -*- C++ -*-
2 *
[174]3 * This file is a part of LEMON, a generic C++ optimization library
4 *
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
[83]7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 *
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.
12 *
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
15 * purpose.
16 *
17 */
[2]18
19#include <iostream>
20#include <string>
21#include <vector>
22#include <list>
23#include <map>
[39]24#include <lemon/error.h>
[150]25#include <lemon/dim2.h>
[2]26
[39]27namespace lemon {
[2]28
[83]29  class XmlIo
[39]30  {
[83]31    bool _writeMode;
32  public:
33    ///Check if XmlIo is in write mode.
34    bool write() { return _writeMode;}
35    ///Check if XmlIo is in read mode.
36    bool read() { return !_writeMode;}
37
[39]38    std::ostream& os;
39    int level;
[83]40   
[39]41  protected:
42    void indent(int level) {
43      os << std::endl;
44      for(int i=0;i<level;i++) os << ' ';
45    }
46    void tag(const std::string &_tag) {
47      os << '<' << _tag << '>';
48    }
49    void etag(const std::string &_tag) {
50      os << "</" << _tag << '>';
51    }
52    void itag(const std::string &_tag) { indent();tag(_tag); }
53    void ietag(const std::string &_tag) { indent();etag(_tag); }
[2]54
[39]55    void beginTag(const std::string &_tag) {
56      itag(_tag);
57      level++;
58    }
59    void endTag(const std::string &_tag) {
60      level--;
61      ietag(_tag);
62    }
[2]63
[39]64  public:
[83]65    ///Indent the line according to its level.
[39]66
[83]67    ///\warning It can only be used in write mode.
68    ///
69    void indent()
[39]70    {
[83]71      if(write())
72        if(level>=0) indent(level);
73        else level=0;
74      else throw LogicError(); 
[39]75    }
[2]76 
[83]77    ///Read/write a tag
[2]78 
[83]79    ///Read/write a tag.
80    ///In write mode it does not start a new line.
[39]81    class ContTag
82    {
[83]83      XmlIo &ix;
[39]84      const std::string _tag;
85    public:
86      ///\e
[2]87 
[39]88      ///\e
89      ///
[83]90      ContTag(XmlIo &_ix,const std::string &_t) :
[39]91        ix(_ix), _tag(_t)
92      {
[83]93        if(ix.write()) ix.tag(_tag);
94        else ix.useTag(_tag);
[39]95      }
[83]96      ~ContTag() {
97        if(ix.write()) ix.etag(_tag);
98        else if(!std::uncaught_exception()) ix.useTag('/'+_tag);     
99      }
[39]100    };
101
[83]102    ///Read/write a tag
103 
104    ///Read/write a tag.
[124]105    ///The whole \<foo\> ... \</foo\> will be placed in a single line.
[39]106    class LineTag
[2]107    {
[83]108      XmlIo &ix;
[39]109      const std::string _tag;
110    public:
111      ///\e
112   
113      ///\e
114      ///
[83]115      LineTag(XmlIo &_ix,const std::string &_t) :
[39]116        ix(_ix), _tag(_t)
117      {
[83]118        if(ix.write()) ix.itag(_tag);
119        else ix.useTag(_tag);
[39]120      }
[83]121      ~LineTag() {
122        if(ix.write()) ix.etag(_tag);
123        else if(!std::uncaught_exception()) ix.useTag('/'+_tag);
124      }
[39]125    };
126
[83]127    ///Read/write a tag
[39]128 
[83]129    ///Read/write a tag.
[39]130    ///
131    class Tag
132    {
[83]133      XmlIo &ix;
[39]134      const std::string _tag;
135    public:
136      ///\e
137 
138      ///\e
139      ///
[83]140      Tag(XmlIo &_ix,const std::string &_t) :
[39]141        ix(_ix), _tag(_t)
142      {
[83]143        if(ix.write()) ix.beginTag(_tag);
144        else ix.useTag(_tag);
[39]145      }
[83]146      ~Tag() {
147        if(ix.write()) ix.endTag(_tag);
148        else if(!std::uncaught_exception()) ix.useTag('/'+_tag);
[39]149      }
150    };
[83]151
152  private:
153    std::istream& is;
154    std::string next_tag;
155    int line_number;
156
157    void skipWhiteSpaces()
158    {
159      if(write()) throw LogicError();
160      {
161        char c;
162        while (is.get(c) && std::isspace(c,is.getloc()))
163          if(c=='\n') line_number++;
164        is.unget();
165      }
166    }
167  protected:
168    /// Use the next tag.
169
170    ///\e
171    ///
172    void useTag() {next_tag.clear();}
173 
174    ///Use the next tag and check if it is equal with \c _tag
175 
176    ///\e
177    ///
178    void useTag(const std::string &_tag) {
179      if(nextTag()==_tag) useTag();
180      else throw DataFormatError("",line_number,"Unexpected token name");
181    }
182  public:
183    ///Return the next tag (if a tag follows on the stream).
184 
185    ///\warning It can only be used in read mode.
186    ///
187    const std::string &nextTag()
188    {
189      if(write()) throw LogicError();
190      else if(next_tag.empty()) {
191        char c;
192        skipWhiteSpaces();
193        if(!is.get(c) || c!='<')
194          throw DataFormatError("",line_number,"Bad format");
195        next_tag.clear();
196        while (is.get(c) && c!='>') next_tag.push_back(c);
197        if(c!='>')
198          throw DataFormatError("",line_number,"Bad format");
199      }
200      return next_tag;
201    }
202
203    /**********************************************************************/
204
205
[39]206    ///\e
207 
208    ///\e
209    ///
[83]210    XmlIo(std::ostream& _os) : _writeMode(true), os(_os),
211                               level(-1),
[127]212                               is(std::cin) {}
[83]213    ///\e
214    ///
215    XmlIo(std::istream& _is) : _writeMode(false),
[127]216                               os(std::cout), is(_is),
[83]217                               line_number(1) {}
218
219    ~XmlIo() { if(write()) os<< std::endl; }
[39]220 
[83]221
222
223    XmlIo &operator()(const int &v)
[39]224    {
[83]225      if(write()) os << v;
226      else {
227        skipWhiteSpaces();
228        if(!(is >> const_cast<int &>(v)))
229          throw DataFormatError("",line_number,"Not an 'int'");
230      }
[39]231      return *this;
[2]232    }
[83]233    XmlIo &operator()(const double &v)
234    {
235      if(write()) os << v;
236      else {
237        skipWhiteSpaces();
238        if(!(is >> const_cast<double &>(v)))
239          throw DataFormatError("",line_number,"Not an 'double'");
240      }
241      return *this;
242    }
243    XmlIo &operator()(const std::string &v)
244    {
245      if(write())
246        for(std::string::const_iterator i=v.begin();i!=v.end();++i)
247          switch(*i) {
248          case '\\':
249            os << "\\\\";
250            break;
251          case '<':
252            os << "\\<";
253            break;
254          case '&':
255            os << "\\&";
256            break;
257          case '\n':
258            os << "\\n";
259            break;
260          default:
261            os<<*i;
262            break;
263          }
264      else {
265        std::string &w = const_cast<std::string &>(v);
266        w.clear();
267        char c;
268        while (is.get(c) && c!='<')
269          if(c=='\\')
270            if(!is.get(c))
271              throw DataFormatError("",line_number,"Bad string");
272            else switch(c) {
273            case 'n':
274              w.push_back('\n');
275              break;
276            default:
277              w.push_back(c);
278              break;
279            }
280          else {
281            if(c=='\n') line_number++;
282            w.push_back(c);
283          }
284        if(c!='<')
285          throw DataFormatError("",line_number,"Unexpected eof");
286        is.unget();
287      }
288      return *this;
289    }
290
291
292    XmlIo &operator()(const std::string &_tag,const int &v)
[39]293    {
294      LineTag t(*this,_tag);
295      (*this)(v);
296      return *this;
297    }
[83]298    XmlIo &operator()(const std::string &_tag,const double &v)
[39]299    {
300      LineTag t(*this,_tag);
301      (*this)(v);
302      return *this;
303    }
[83]304    XmlIo &operator()(const std::string &_tag,const std::string &v)
[39]305    {
306      LineTag t(*this,_tag);
307      (*this)(v);
308      return *this;
309    }
310    ///\e
311 
312    ///\e
313    ///
314    template<class V>
[83]315    XmlIo &operator()(const std::string &_tag,const V &v)
[39]316    {
317      Tag t(*this,_tag);
[83]318      xml(*this,const_cast<V &>(v));
[39]319      return *this;
320    }
321    ///\e
322 
323    ///\e
324    ///
325    template<class V>
[83]326    XmlIo &operator()(const V &v)
[39]327    {
[83]328      xml(*this,const_cast<V &>(v));
[39]329      return *this;
330    }
[83]331    };
[2]332
[39]333  //////////////////////////////////////////////////////////////////////
334  //////////////////////////////////////////////////////////////////////
335
[83]336  ///\e
337 
338  ///\relates XmlIo
339  ///
[39]340  template<class A>
[83]341  void xml(XmlIo &x,std::auto_ptr<A> &v)
[39]342  {
[83]343    if(x.write()) v=new A;
[39]344    x(*v);
345  }
[83]346 
347  ///\e
348 
349  ///\relates XmlIo
350  ///
[39]351  template<class A,class B>
[83]352  void xml(XmlIo &x,std::pair<A,B> &v)
[39]353  {
354    x("first",v.first);
355    x("second",v.second);
356  }
357
[83]358  ///\e
359 
360  ///\relates XmlIo
361  ///
362  template<class T>
363  void xml(XmlIo &x,std::list<T> &v)
[39]364  {
[83]365    if(x.write())
366      for(typename std::list<T>::const_iterator it=v.begin();
367          it!=v.end();++it) x("item",*it);
368    else while(x.nextTag()=="item")
[39]369      {
370        v.push_back(T());
371        x("item",v.back());
372      }
373  }
[83]374  ///\e
375 
376  ///\relates XmlIo
377  ///
[39]378  template<class T>
[83]379  void xml(XmlIo &x,std::vector<T> &v)
[39]380  {
[83]381    if(x.write())
382      for(typename std::vector<T>::const_iterator it=v.begin();
383          it!=v.end();++it) x("item",*it);
384    else while(x.nextTag()=="item")
[39]385      {
386        v.push_back(T());
387        x("item",v.back());     
388      }
389  }
390
[83]391  ///\e
392 
393  ///\relates XmlIo
394  ///
[39]395  template<class K,class V>
[83]396  void xml(XmlIo &x,std::map<K,V> &v)
[39]397  {
[83]398    if(x.write())
399      for(typename std::map<K,V>::const_iterator it=v.begin();
400          it!=v.end();++it) x("item",*it);
401    else while(x.nextTag()=="item")
[39]402      {
403        typename std::map<K,V>::value_type it;
404        x("item",it);
405        v.insert(it);
406      }
407  }
408
[83]409  ///\e
410 
411  ///\relates XmlIo
412  ///
[39]413  template<class T>
[150]414  void xml(XmlIo &x,lemon::dim2::Point<T> &v)
[39]415  {
[83]416    { XmlIo::LineTag t(x,"x"); x(v.x); }
417    { XmlIo::ContTag t(x,"y"); x(v.y); }
[39]418  }
419
[83]420  ///\e
421 
422  ///\relates XmlIo
423  ///
[39]424  template<class T>
[150]425  void xml(XmlIo &x,lemon::dim2::BoundingBox<T> &v)
[39]426  {
[83]427    if(x.write()) {
428      if(!v.empty()) {
429        x("point",v.bottomLeft());
430        if(v.bottomLeft()!=v.topRight()) x("point",v.topRight());
431      }
[39]432    }
[83]433    else {
434      v.clear();
435      while(x.nextTag()=="point") {
[150]436        lemon::dim2::Point<T> co;
[83]437        x("point",co);
438        v.add(co);
439      }
[39]440    }
441  }
[2]442 
443}
[83]444
Note: See TracBrowser for help on using the repository browser.