COIN-OR::LEMON - Graph Library

source: glemon-0.x/xml.h

Last change on this file was 174:95872af46fc4, checked in by Alpar Juttner, 17 years ago

Add copyright headers

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#include <iostream>
20#include <string>
21#include <vector>
22#include <list>
23#include <map>
24#include <lemon/error.h>
25#include <lemon/dim2.h>
26
27namespace lemon {
28
29  class XmlIo
30  {
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
38    std::ostream& os;
39    int level;
40   
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); }
54
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    }
63
64  public:
65    ///Indent the line according to its level.
66
67    ///\warning It can only be used in write mode.
68    ///
69    void indent()
70    {
71      if(write())
72        if(level>=0) indent(level);
73        else level=0;
74      else throw LogicError(); 
75    }
76 
77    ///Read/write a tag
78 
79    ///Read/write a tag.
80    ///In write mode it does not start a new line.
81    class ContTag
82    {
83      XmlIo &ix;
84      const std::string _tag;
85    public:
86      ///\e
87 
88      ///\e
89      ///
90      ContTag(XmlIo &_ix,const std::string &_t) :
91        ix(_ix), _tag(_t)
92      {
93        if(ix.write()) ix.tag(_tag);
94        else ix.useTag(_tag);
95      }
96      ~ContTag() {
97        if(ix.write()) ix.etag(_tag);
98        else if(!std::uncaught_exception()) ix.useTag('/'+_tag);     
99      }
100    };
101
102    ///Read/write a tag
103 
104    ///Read/write a tag.
105    ///The whole \<foo\> ... \</foo\> will be placed in a single line.
106    class LineTag
107    {
108      XmlIo &ix;
109      const std::string _tag;
110    public:
111      ///\e
112   
113      ///\e
114      ///
115      LineTag(XmlIo &_ix,const std::string &_t) :
116        ix(_ix), _tag(_t)
117      {
118        if(ix.write()) ix.itag(_tag);
119        else ix.useTag(_tag);
120      }
121      ~LineTag() {
122        if(ix.write()) ix.etag(_tag);
123        else if(!std::uncaught_exception()) ix.useTag('/'+_tag);
124      }
125    };
126
127    ///Read/write a tag
128 
129    ///Read/write a tag.
130    ///
131    class Tag
132    {
133      XmlIo &ix;
134      const std::string _tag;
135    public:
136      ///\e
137 
138      ///\e
139      ///
140      Tag(XmlIo &_ix,const std::string &_t) :
141        ix(_ix), _tag(_t)
142      {
143        if(ix.write()) ix.beginTag(_tag);
144        else ix.useTag(_tag);
145      }
146      ~Tag() {
147        if(ix.write()) ix.endTag(_tag);
148        else if(!std::uncaught_exception()) ix.useTag('/'+_tag);
149      }
150    };
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
206    ///\e
207 
208    ///\e
209    ///
210    XmlIo(std::ostream& _os) : _writeMode(true), os(_os),
211                               level(-1),
212                               is(std::cin) {}
213    ///\e
214    ///
215    XmlIo(std::istream& _is) : _writeMode(false),
216                               os(std::cout), is(_is),
217                               line_number(1) {}
218
219    ~XmlIo() { if(write()) os<< std::endl; }
220 
221
222
223    XmlIo &operator()(const int &v)
224    {
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      }
231      return *this;
232    }
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)
293    {
294      LineTag t(*this,_tag);
295      (*this)(v);
296      return *this;
297    }
298    XmlIo &operator()(const std::string &_tag,const double &v)
299    {
300      LineTag t(*this,_tag);
301      (*this)(v);
302      return *this;
303    }
304    XmlIo &operator()(const std::string &_tag,const std::string &v)
305    {
306      LineTag t(*this,_tag);
307      (*this)(v);
308      return *this;
309    }
310    ///\e
311 
312    ///\e
313    ///
314    template<class V>
315    XmlIo &operator()(const std::string &_tag,const V &v)
316    {
317      Tag t(*this,_tag);
318      xml(*this,const_cast<V &>(v));
319      return *this;
320    }
321    ///\e
322 
323    ///\e
324    ///
325    template<class V>
326    XmlIo &operator()(const V &v)
327    {
328      xml(*this,const_cast<V &>(v));
329      return *this;
330    }
331    };
332
333  //////////////////////////////////////////////////////////////////////
334  //////////////////////////////////////////////////////////////////////
335
336  ///\e
337 
338  ///\relates XmlIo
339  ///
340  template<class A>
341  void xml(XmlIo &x,std::auto_ptr<A> &v)
342  {
343    if(x.write()) v=new A;
344    x(*v);
345  }
346 
347  ///\e
348 
349  ///\relates XmlIo
350  ///
351  template<class A,class B>
352  void xml(XmlIo &x,std::pair<A,B> &v)
353  {
354    x("first",v.first);
355    x("second",v.second);
356  }
357
358  ///\e
359 
360  ///\relates XmlIo
361  ///
362  template<class T>
363  void xml(XmlIo &x,std::list<T> &v)
364  {
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")
369      {
370        v.push_back(T());
371        x("item",v.back());
372      }
373  }
374  ///\e
375 
376  ///\relates XmlIo
377  ///
378  template<class T>
379  void xml(XmlIo &x,std::vector<T> &v)
380  {
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")
385      {
386        v.push_back(T());
387        x("item",v.back());     
388      }
389  }
390
391  ///\e
392 
393  ///\relates XmlIo
394  ///
395  template<class K,class V>
396  void xml(XmlIo &x,std::map<K,V> &v)
397  {
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")
402      {
403        typename std::map<K,V>::value_type it;
404        x("item",it);
405        v.insert(it);
406      }
407  }
408
409  ///\e
410 
411  ///\relates XmlIo
412  ///
413  template<class T>
414  void xml(XmlIo &x,lemon::dim2::Point<T> &v)
415  {
416    { XmlIo::LineTag t(x,"x"); x(v.x); }
417    { XmlIo::ContTag t(x,"y"); x(v.y); }
418  }
419
420  ///\e
421 
422  ///\relates XmlIo
423  ///
424  template<class T>
425  void xml(XmlIo &x,lemon::dim2::BoundingBox<T> &v)
426  {
427    if(x.write()) {
428      if(!v.empty()) {
429        x("point",v.bottomLeft());
430        if(v.bottomLeft()!=v.topRight()) x("point",v.topRight());
431      }
432    }
433    else {
434      v.clear();
435      while(x.nextTag()=="point") {
436        lemon::dim2::Point<T> co;
437        x("point",co);
438        v.add(co);
439      }
440    }
441  }
442 
443}
444
Note: See TracBrowser for help on using the repository browser.