COIN-OR::LEMON - Graph Library

source: lemon-0.x/gui/xml.h @ 1881:f40cdc2057c2

Last change on this file since 1881:f40cdc2057c2 was 1875:98698b69a902, checked in by Alpar Juttner, 18 years ago

Happy new year to LEMON

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