A very simple xml parser
authoralpar
Thu, 19 May 2005 11:46:42 +0000
changeset 14289ba88ddc629c
parent 1427 14c75970840e
child 1429 4283998fb2be
A very simple xml parser
src/gui/xml.h
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/gui/xml.h	Thu May 19 11:46:42 2005 +0000
     1.3 @@ -0,0 +1,442 @@
     1.4 +/* -*- C++ -*- */
     1.5 +
     1.6 +#include <iostream>
     1.7 +#include <string>
     1.8 +#include <vector>
     1.9 +#include <list>
    1.10 +#include <map>
    1.11 +#include <lemon/xy.h>
    1.12 +
    1.13 +class XmlWriter 
    1.14 +{
    1.15 +  std::ostream& os;
    1.16 +  int level;
    1.17 +
    1.18 +protected:
    1.19 +  void indent(int level) {
    1.20 +    os << std::endl;
    1.21 +    for(int i=0;i<level;i++) os << ' ';
    1.22 +  }
    1.23 +  void tag(const std::string &_tag) {
    1.24 +    os << '<' << _tag << '>';
    1.25 +  }
    1.26 +  void etag(const std::string &_tag) {
    1.27 +    os << "</" << _tag << '>';
    1.28 +  }
    1.29 +  void itag(const std::string &_tag) { indent();tag(_tag); }
    1.30 +  void ietag(const std::string &_tag) { indent();etag(_tag); }
    1.31 +
    1.32 +  void beginTag(const std::string &_tag) {
    1.33 +    itag(_tag);
    1.34 +    level++;
    1.35 +  }
    1.36 +  void endTag(const std::string &_tag) {
    1.37 +    level--;
    1.38 +    ietag(_tag);
    1.39 +  }
    1.40 +
    1.41 +public:
    1.42 +
    1.43 +  void indent() 
    1.44 +  {
    1.45 +    if(level>=0) indent(level);
    1.46 +    else level=0;
    1.47 +  }
    1.48 +  
    1.49 +  ///\e
    1.50 +  
    1.51 +  ///\e
    1.52 +  ///
    1.53 +  class ContTag
    1.54 +  {
    1.55 +    XmlWriter &ix;
    1.56 +    const std::string _tag;
    1.57 +  public:
    1.58 +  ///\e
    1.59 +  
    1.60 +  ///\e
    1.61 +  ///
    1.62 +    ContTag(XmlWriter &_ix,const std::string &_t) :
    1.63 +      ix(_ix), _tag(_t)
    1.64 +    {
    1.65 +      ix.tag(_tag);
    1.66 +    }
    1.67 +    ~ContTag() { ix.etag(_tag);}
    1.68 +  };
    1.69 +
    1.70 +  class LineTag
    1.71 +  {
    1.72 +    XmlWriter &ix;
    1.73 +    const std::string _tag;
    1.74 +  public:
    1.75 +    ///\e
    1.76 +    
    1.77 +    ///\e
    1.78 +    ///
    1.79 +    LineTag(XmlWriter &_ix,const std::string &_t) :
    1.80 +      ix(_ix), _tag(_t)
    1.81 +    {
    1.82 +      ix.itag(_tag);
    1.83 +    }
    1.84 +    ~LineTag() { ix.etag(_tag);}
    1.85 +  };
    1.86 +
    1.87 +  ///\e
    1.88 +  
    1.89 +  ///\e
    1.90 +  ///
    1.91 +  class Tag
    1.92 +  {
    1.93 +    XmlWriter &ix;
    1.94 +    const std::string _tag;
    1.95 +  public:
    1.96 +    ///\e
    1.97 +  
    1.98 +    ///\e
    1.99 +    ///
   1.100 +    Tag(XmlWriter &_ix,const std::string &_t) :
   1.101 +      ix(_ix), _tag(_t)
   1.102 +    {
   1.103 +      ix.beginTag(_tag);
   1.104 +    }
   1.105 +    ~Tag() { 
   1.106 +      ix.endTag(_tag);
   1.107 +    }
   1.108 +  };
   1.109 +      
   1.110 +  ///\e
   1.111 +  
   1.112 +  ///\e
   1.113 +  ///
   1.114 +  XmlWriter(std::ostream& _os) : os(_os),level(-1) {}
   1.115 +  ~XmlWriter() { os<< std::endl; }
   1.116 +  
   1.117 +  XmlWriter &operator()(int v) 
   1.118 +  { 
   1.119 +    if(!(os << v)) throw (std::ios::failure ("data format error"));
   1.120 +    return *this;
   1.121 +  }
   1.122 +  XmlWriter &operator()(const std::string &_tag,int v) 
   1.123 +  { 
   1.124 +    LineTag t(*this,_tag);
   1.125 +    if(!(os << v)) throw (std::ios::failure ("data format error"));
   1.126 +    return *this;
   1.127 +  }
   1.128 +  XmlWriter &operator()(const std::string &_tag,double v) 
   1.129 +  {
   1.130 +    LineTag t(*this,_tag);
   1.131 +    if(os << v) throw (std::ios::failure ("data format error"));
   1.132 +    return *this;
   1.133 +  }
   1.134 +  XmlWriter &operator()(double v) 
   1.135 +  {
   1.136 +    os << v;
   1.137 +    return *this;
   1.138 +  }
   1.139 +  XmlWriter &operator()(const std::string &v)
   1.140 +  {
   1.141 +    for(std::string::const_iterator i=v.begin();i!=v.end();++i)
   1.142 +      switch(*i) {
   1.143 +      case '\\':
   1.144 +	os << "\\\\";
   1.145 +	break;
   1.146 +      case '<':
   1.147 +	os << "\\<";
   1.148 +	break;
   1.149 +      case '&':
   1.150 +	os << "\\&";
   1.151 +	break;
   1.152 +      case '\n':
   1.153 +	os << "\\n";
   1.154 +	break;
   1.155 +      default:
   1.156 +	os<<*i;
   1.157 +	break;
   1.158 +      }
   1.159 +    return *this;
   1.160 +  }
   1.161 +  XmlWriter &operator()(const std::string &_tag,const std::string &v)
   1.162 +  {
   1.163 +    LineTag t(*this,_tag);
   1.164 +    (*this)(v);
   1.165 +    return *this;
   1.166 +  }
   1.167 +  ///\e
   1.168 +  
   1.169 +  ///\e
   1.170 +  ///
   1.171 +  template<class V>
   1.172 +  XmlWriter &operator()(const std::string &_tag,const V &v)
   1.173 +  {
   1.174 +    Tag t(*this,_tag);
   1.175 +    out(*this,v);
   1.176 +    return *this;
   1.177 +  }
   1.178 +  ///\e
   1.179 +  
   1.180 +  ///\e
   1.181 +  ///
   1.182 +  template<class V>
   1.183 +  XmlWriter &operator()(const V &v)
   1.184 +  {
   1.185 +    out(*this,v);
   1.186 +    return *this;
   1.187 +  }
   1.188 +};
   1.189 +
   1.190 +//////////////////////////////////////////////////////////////////////
   1.191 +
   1.192 +class XmlReader 
   1.193 +{
   1.194 +  std::istream& is;
   1.195 +  
   1.196 +  std::string next_tag;
   1.197 +  void skipWhiteSpaces()
   1.198 +  {
   1.199 +    char c;
   1.200 +    while (is.get(c) && std::isspace(c,is.getloc()));
   1.201 +    is.unget();
   1.202 +  }
   1.203 +protected:
   1.204 +  ///\e
   1.205 +  
   1.206 +  ///\e
   1.207 +  ///
   1.208 +  void useTag() {next_tag.clear();}
   1.209 +  
   1.210 +  void useTag(const std::string &_tag) {
   1.211 +    if(nextTag()==_tag) useTag();
   1.212 +    else throw (std::ios::failure ("data format error"));
   1.213 +  }
   1.214 +public:
   1.215 +  ///\e
   1.216 +  
   1.217 +  ///\e
   1.218 +  ///
   1.219 +  const std::string &nextTag() 
   1.220 +  {
   1.221 +    if(next_tag.empty()) {
   1.222 +      char c;
   1.223 +      skipWhiteSpaces();
   1.224 +      if(!is.get(c) || c!='<')
   1.225 +	throw (std::ios::failure ("data format error"));
   1.226 +      next_tag.clear();
   1.227 +      while (is.get(c) && c!='>') next_tag.push_back(c);
   1.228 +      if(c!='>')
   1.229 +	throw (std::ios::failure ("data format error"));
   1.230 +    }
   1.231 +    return next_tag;
   1.232 +  }
   1.233 +  
   1.234 +  ///\e
   1.235 +  
   1.236 +  ///\e
   1.237 +  ///
   1.238 +  class Tag
   1.239 +  {
   1.240 +    XmlReader &ix;
   1.241 +    const std::string tag;
   1.242 +  public:
   1.243 +    ///\e
   1.244 +    
   1.245 +    ///\e
   1.246 +    ///
   1.247 +    Tag(XmlReader &_ix,const std::string &_tag) :
   1.248 +      ix(_ix), tag(_tag)
   1.249 +    {
   1.250 +      ix.useTag(_tag);
   1.251 +    }
   1.252 +    ~Tag() {
   1.253 +      if(!std::uncaught_exception()) 
   1.254 +	ix.useTag('/'+tag);
   1.255 +    }
   1.256 +  };
   1.257 +
   1.258 +  ///\e
   1.259 +  
   1.260 +  ///\e
   1.261 +  ///
   1.262 +  XmlReader(std::istream& _is) : is(_is) {}
   1.263 +  
   1.264 +  int operator()(const std::string &tag,int &v)
   1.265 +  { 
   1.266 +    Tag t(*this,tag);
   1.267 +    if(!(is >> v)) throw (std::ios::failure ("data format error"));
   1.268 +    return v;
   1.269 +  }
   1.270 +  double operator()(const std::string &tag,double &v) 
   1.271 +  {
   1.272 +    Tag t(*this,tag);
   1.273 +    if(!(is >> v)) throw (std::ios::failure ("data format error"));
   1.274 +    return v;
   1.275 +  }
   1.276 +  std::string &operator()(const std::string &tag,std::string &v)
   1.277 +  {
   1.278 +    Tag t(*this,tag);
   1.279 +    v.clear();
   1.280 +    char c;
   1.281 +    while (is.get(c) && c!='<')
   1.282 +      if(c=='\\')
   1.283 +	if(!is.get(c)) throw (std::ios::failure ("data format error"));
   1.284 +	else switch(c) {
   1.285 +	case 'n':
   1.286 +	  v.push_back('\n');
   1.287 +	  break;
   1.288 +	default:
   1.289 +	  v.push_back(c);
   1.290 +	  break;
   1.291 +	}
   1.292 +      else v.push_back(c);
   1.293 +    if(c!='<')
   1.294 +	throw (std::ios::failure ("data format error"));
   1.295 +    is.unget();
   1.296 +    return v;
   1.297 +  }
   1.298 +  ///\e
   1.299 +  
   1.300 +  ///\e
   1.301 +  ///
   1.302 +  template<class V>
   1.303 +  V &operator()(const std::string &tag,V &v)
   1.304 +  {
   1.305 +    Tag t(*this,tag);
   1.306 +    in(*this,v);
   1.307 +    return v;
   1.308 +  }
   1.309 +  ///\e
   1.310 +  
   1.311 +  ///\e
   1.312 +  ///
   1.313 +  template<class V>
   1.314 +  V &operator()(V &v)
   1.315 +  {
   1.316 +    in(*this,v);
   1.317 +    return v;
   1.318 +  }
   1.319 +  ///\e
   1.320 +  
   1.321 +  ///\e
   1.322 +  ///
   1.323 +  template<class V>
   1.324 +  V load(const std::string &tag)
   1.325 +  {
   1.326 +    Tag t(*this,tag);
   1.327 +    V v;
   1.328 +    (*this)(tag,v);
   1.329 +    return v;
   1.330 +  }
   1.331 +};
   1.332 +
   1.333 +//////////////////////////////////////////////////////////////////////
   1.334 +
   1.335 +template<class A,class B>
   1.336 +void out(XmlWriter &i,const std::pair<A,B> &v)
   1.337 +{
   1.338 +  i("first",v.first);
   1.339 +  i("second",v.second);
   1.340 +}
   1.341 +
   1.342 +template<class A,class B>
   1.343 +void in(XmlReader &i,std::pair<A,B> &v)
   1.344 +{
   1.345 +  i("first",v.first);
   1.346 +  i("second",v.second);
   1.347 +}
   1.348 +
   1.349 +//////////////////////////////
   1.350 +
   1.351 +template<class T>
   1.352 +void out(XmlWriter &i,const std::list<T> &v)
   1.353 +{
   1.354 +  for(typename std::list<T>::const_iterator it=v.begin();
   1.355 +      it!=v.end();++it) i("item",*it);
   1.356 +}
   1.357 +
   1.358 +template<class T>
   1.359 +void in(XmlReader &i,std::list<T> &v)
   1.360 +{
   1.361 +  while(i.nextTag()=="item")
   1.362 +    {
   1.363 +      v.push_back(T());
   1.364 +      i("item",v.back());
   1.365 +    }
   1.366 +}
   1.367 +
   1.368 +//////////////////////////////
   1.369 +
   1.370 +template<class T>
   1.371 +void out(XmlWriter &i,const std::vector<T> &v)
   1.372 +{
   1.373 +  for(typename std::vector<T>::const_iterator it=v.begin();
   1.374 +      it!=v.end();++it) i("item",*it);
   1.375 +}
   1.376 +
   1.377 +template<class T>
   1.378 +void in(XmlReader &i,std::vector<T> &v)
   1.379 +{
   1.380 +  while(i.nextTag()=="item")
   1.381 +    {
   1.382 +      v.push_back(T());
   1.383 +      i("item",v.back());      
   1.384 +    }
   1.385 +}
   1.386 +
   1.387 +//////////////////////////////
   1.388 +
   1.389 +template<class K,class V>
   1.390 +void out(XmlWriter &i,const std::map<K,V> &v)
   1.391 +{
   1.392 +  for(typename std::map<K,V>::const_iterator it=v.begin();
   1.393 +      it!=v.end();++it) i("item",*it);
   1.394 +}
   1.395 +
   1.396 +template<class K,class V>
   1.397 +void in(XmlReader &i,std::map<K,V> &v)
   1.398 +{
   1.399 +  while(i.nextTag()=="item")
   1.400 +    {
   1.401 +      typename std::map<K,V>::value_type it;
   1.402 +      i("item",it);
   1.403 +      v.insert(it);
   1.404 +    }
   1.405 +}
   1.406 +
   1.407 +//////////////////////////////
   1.408 +
   1.409 +template<class T>
   1.410 +void out(XmlWriter &i,const lemon::xy<T> &v)
   1.411 +{
   1.412 +//   i("x",v.x);
   1.413 +//   i("y",v.y);
   1.414 +  { XmlWriter::LineTag t(i,"x"); i(v.x); }
   1.415 +  { XmlWriter::ContTag t(i,"y"); i(v.y); }
   1.416 +}
   1.417 +
   1.418 +template<class T>
   1.419 +void in(XmlReader &i,lemon::xy<T> &v)
   1.420 +{
   1.421 +  i("x",v.x);
   1.422 +  i("y",v.y);
   1.423 +}
   1.424 +
   1.425 +//////////////////////////////
   1.426 +
   1.427 +template<class T>
   1.428 +void out(XmlWriter &i,const lemon::BoundingBox<T> &v)
   1.429 +{
   1.430 +  if(!v.empty()) {
   1.431 +    i("point",v.bottomLeft());
   1.432 +    if(v.bottomLeft()!=v.topRight()) i("point",v.topRight());
   1.433 +  }
   1.434 +}
   1.435 +
   1.436 +template<class T>
   1.437 +void in(XmlReader &i,lemon::BoundingBox<T> &v)
   1.438 +{
   1.439 +  v.clear();
   1.440 +  while(i.nextTag()=="point") {
   1.441 +    lemon::xy<T> co;
   1.442 +    i("point",co);
   1.443 +    v+=co;
   1.444 +  }
   1.445 +}