COIN-OR::LEMON - Graph Library

source: glemon-0.x/xml.h @ 201:879e47e5b731

Last change on this file since 201:879e47e5b731 was 201:879e47e5b731, checked in by Akos Ladanyi, 16 years ago

Merge branches/akos to trunk.

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