COIN-OR::LEMON - Graph Library

source: glemon/xml.h

tip
Last change on this file was 7:f227a74db59d, checked in by Alpar Juttner <alpar@…>, 16 years ago

Update to compile with the latest LEMON (version 1.0 or [5e12d7734036])

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