COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/gui/xml.h @ 1428:9ba88ddc629c

Last change on this file since 1428:9ba88ddc629c was 1428:9ba88ddc629c, checked in by Alpar Juttner, 14 years ago

A very simple xml parser

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