1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/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 +}