New version of XML reader/writer.
authoralpar
Mon, 24 Oct 2005 08:11:21 +0000
changeset 173541e96cd91d6d
parent 1734 2fb5ceac10e7
child 1736 35f667e7dd7e
New version of XML reader/writer.
Now, there are only a single XmlIo class both for reading and writing.
gui/xml.h
     1.1 --- a/gui/xml.h	Mon Oct 24 08:09:59 2005 +0000
     1.2 +++ b/gui/xml.h	Mon Oct 24 08:11:21 2005 +0000
     1.3 @@ -1,4 +1,18 @@
     1.4 -/* -*- C++ -*- */
     1.5 +/* -*- C++ -*-
     1.6 + * gui/xml.h - Part of LEMON, a generic C++ optimization library
     1.7 + *
     1.8 + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     1.9 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
    1.10 + *
    1.11 + * Permission to use, modify and distribute this software is granted
    1.12 + * provided that this copyright notice appears in all copies. For
    1.13 + * precise terms see the accompanying LICENSE file.
    1.14 + *
    1.15 + * This software is provided "AS IS" with no warranty of any kind,
    1.16 + * express or implied, and with no claim as to its suitability for any
    1.17 + * purpose.
    1.18 + *
    1.19 + */
    1.20  
    1.21  #include <iostream>
    1.22  #include <string>
    1.23 @@ -10,11 +24,18 @@
    1.24  
    1.25  namespace lemon {
    1.26  
    1.27 -  class XmlWriter 
    1.28 +  class XmlIo 
    1.29    {
    1.30 +    bool _writeMode;
    1.31 +  public:
    1.32 +    ///Check if XmlIo is in write mode.
    1.33 +    bool write() { return _writeMode;}
    1.34 +    ///Check if XmlIo is in read mode.
    1.35 +    bool read() { return !_writeMode;}
    1.36 +
    1.37      std::ostream& os;
    1.38      int level;
    1.39 -
    1.40 +    
    1.41    protected:
    1.42      void indent(int level) {
    1.43        os << std::endl;
    1.44 @@ -39,126 +60,246 @@
    1.45      }
    1.46  
    1.47    public:
    1.48 +    ///Indent the line according to its level.
    1.49  
    1.50 -    void indent() 
    1.51 +    ///\warning It can only be used in write mode.
    1.52 +    ///
    1.53 +    void indent()
    1.54      {
    1.55 -      if(level>=0) indent(level);
    1.56 -      else level=0;
    1.57 +      if(write())
    1.58 +	if(level>=0) indent(level);
    1.59 +	else level=0;
    1.60 +      else throw LogicError();	
    1.61      }
    1.62    
    1.63 -    ///\e
    1.64 +    ///Read/write a tag
    1.65    
    1.66 -    ///\e
    1.67 -    ///
    1.68 +    ///Read/write a tag.
    1.69 +    ///In write mode it does not start a new line.
    1.70      class ContTag
    1.71      {
    1.72 -      XmlWriter &ix;
    1.73 +      XmlIo &ix;
    1.74        const std::string _tag;
    1.75      public:
    1.76        ///\e
    1.77    
    1.78        ///\e
    1.79        ///
    1.80 -      ContTag(XmlWriter &_ix,const std::string &_t) :
    1.81 +      ContTag(XmlIo &_ix,const std::string &_t) :
    1.82  	ix(_ix), _tag(_t)
    1.83        {
    1.84 -	ix.tag(_tag);
    1.85 +	if(ix.write()) ix.tag(_tag);
    1.86 +	else ix.useTag(_tag);
    1.87        }
    1.88 -      ~ContTag() { ix.etag(_tag);}
    1.89 +      ~ContTag() { 
    1.90 +	if(ix.write()) ix.etag(_tag);
    1.91 +	else if(!std::uncaught_exception()) ix.useTag('/'+_tag);      
    1.92 +      }
    1.93      };
    1.94  
    1.95 +    ///Read/write a tag
    1.96 +  
    1.97 +    ///Read/write a tag.
    1.98 +    ///The whole <foo> ... </foo> will be places in a single line.
    1.99      class LineTag
   1.100      {
   1.101 -      XmlWriter &ix;
   1.102 +      XmlIo &ix;
   1.103        const std::string _tag;
   1.104      public:
   1.105        ///\e
   1.106      
   1.107        ///\e
   1.108        ///
   1.109 -      LineTag(XmlWriter &_ix,const std::string &_t) :
   1.110 +      LineTag(XmlIo &_ix,const std::string &_t) :
   1.111  	ix(_ix), _tag(_t)
   1.112        {
   1.113 -	ix.itag(_tag);
   1.114 +	if(ix.write()) ix.itag(_tag);
   1.115 +	else ix.useTag(_tag);
   1.116        }
   1.117 -      ~LineTag() { ix.etag(_tag);}
   1.118 +      ~LineTag() { 
   1.119 +	if(ix.write()) ix.etag(_tag);
   1.120 +	else if(!std::uncaught_exception()) ix.useTag('/'+_tag);
   1.121 +      }
   1.122      };
   1.123  
   1.124 -    ///\e
   1.125 +    ///Read/write a tag
   1.126    
   1.127 -    ///\e
   1.128 +    ///Read/write a tag.
   1.129      ///
   1.130      class Tag
   1.131      {
   1.132 -      XmlWriter &ix;
   1.133 +      XmlIo &ix;
   1.134        const std::string _tag;
   1.135      public:
   1.136        ///\e
   1.137    
   1.138        ///\e
   1.139        ///
   1.140 -      Tag(XmlWriter &_ix,const std::string &_t) :
   1.141 +      Tag(XmlIo &_ix,const std::string &_t) :
   1.142  	ix(_ix), _tag(_t)
   1.143        {
   1.144 -	ix.beginTag(_tag);
   1.145 +	if(ix.write()) ix.beginTag(_tag);
   1.146 +	else ix.useTag(_tag);
   1.147        }
   1.148 -      ~Tag() { 
   1.149 -	ix.endTag(_tag);
   1.150 +      ~Tag() {
   1.151 +	if(ix.write()) ix.endTag(_tag);
   1.152 +	else if(!std::uncaught_exception()) ix.useTag('/'+_tag);
   1.153        }
   1.154      };
   1.155 -      
   1.156 +
   1.157 +  private:
   1.158 +    std::istream& is;
   1.159 +    std::string next_tag;
   1.160 +    int line_number;
   1.161 +
   1.162 +    void skipWhiteSpaces()
   1.163 +    {
   1.164 +      if(write()) throw LogicError();
   1.165 +      {
   1.166 +	char c;
   1.167 +	while (is.get(c) && std::isspace(c,is.getloc()))
   1.168 +	  if(c=='\n') line_number++;
   1.169 +	is.unget();
   1.170 +      }
   1.171 +    }
   1.172 +  protected:
   1.173 +    /// Use the next tag.
   1.174 +
   1.175 +    ///\e
   1.176 +    ///
   1.177 +    void useTag() {next_tag.clear();}
   1.178 +  
   1.179 +    ///Use the next tag and check if it is equal with \c _tag
   1.180 +  
   1.181 +    ///\e
   1.182 +    ///
   1.183 +    void useTag(const std::string &_tag) {
   1.184 +      if(nextTag()==_tag) useTag();
   1.185 +      else throw DataFormatError("",line_number,"Unexpected token name");
   1.186 +    }
   1.187 +  public:
   1.188 +    ///Return the next tag (if a tag follows on the stream).
   1.189 +  
   1.190 +    ///\warning It can only be used in read mode.
   1.191 +    ///
   1.192 +    const std::string &nextTag() 
   1.193 +    {
   1.194 +      if(write()) throw LogicError();
   1.195 +      else if(next_tag.empty()) {
   1.196 +	char c;
   1.197 +	skipWhiteSpaces();
   1.198 +	if(!is.get(c) || c!='<')
   1.199 +	  throw DataFormatError("",line_number,"Bad format");
   1.200 +	next_tag.clear();
   1.201 +	while (is.get(c) && c!='>') next_tag.push_back(c);
   1.202 +	if(c!='>')
   1.203 +	  throw DataFormatError("",line_number,"Bad format");
   1.204 +      }
   1.205 +      return next_tag;
   1.206 +    }
   1.207 +
   1.208 +    /**********************************************************************/
   1.209 +
   1.210 +
   1.211      ///\e
   1.212    
   1.213      ///\e
   1.214      ///
   1.215 -    XmlWriter(std::ostream& _os) : os(_os),level(-1) {}
   1.216 -    ~XmlWriter() { os<< std::endl; }
   1.217 +    XmlIo(std::ostream& _os) : _writeMode(true), os(_os),
   1.218 +			       level(-1),
   1.219 +			       is(*(std::istream*)(NULL)) {}
   1.220 +    ///\e
   1.221 +    ///
   1.222 +    XmlIo(std::istream& _is) : _writeMode(false),
   1.223 +			       os(*(std::ostream*)(NULL)), is(_is),
   1.224 +			       line_number(1) {}
   1.225 +
   1.226 +    ~XmlIo() { if(write()) os<< std::endl; }
   1.227    
   1.228 -    XmlWriter &operator()(int v) 
   1.229 +
   1.230 +
   1.231 +    XmlIo &operator()(const int &v) 
   1.232      { 
   1.233 -      os << v;
   1.234 +      if(write()) os << v;
   1.235 +      else {
   1.236 +	skipWhiteSpaces();
   1.237 +	if(!(is >> const_cast<int &>(v))) 
   1.238 +	  throw DataFormatError("",line_number,"Not an 'int'");
   1.239 +      }
   1.240        return *this;
   1.241      }
   1.242 -    XmlWriter &operator()(const std::string &_tag,int v) 
   1.243 +    XmlIo &operator()(const double &v) 
   1.244 +    {
   1.245 +      if(write()) os << v;
   1.246 +      else {
   1.247 +	skipWhiteSpaces();
   1.248 +	if(!(is >> const_cast<double &>(v))) 
   1.249 +	  throw DataFormatError("",line_number,"Not an 'double'");
   1.250 +      }
   1.251 +      return *this;
   1.252 +    }
   1.253 +    XmlIo &operator()(const std::string &v)
   1.254 +    {
   1.255 +      if(write())
   1.256 +	for(std::string::const_iterator i=v.begin();i!=v.end();++i)
   1.257 +	  switch(*i) {
   1.258 +	  case '\\':
   1.259 +	    os << "\\\\";
   1.260 +	    break;
   1.261 +	  case '<':
   1.262 +	    os << "\\<";
   1.263 +	    break;
   1.264 +	  case '&':
   1.265 +	    os << "\\&";
   1.266 +	    break;
   1.267 +	  case '\n':
   1.268 +	    os << "\\n";
   1.269 +	    break;
   1.270 +	  default:
   1.271 +	    os<<*i;
   1.272 +	    break;
   1.273 +	  }
   1.274 +      else {
   1.275 +	std::string &w = const_cast<std::string &>(v);
   1.276 +	w.clear();
   1.277 +	char c;
   1.278 +	while (is.get(c) && c!='<')
   1.279 +	  if(c=='\\')
   1.280 +	    if(!is.get(c))
   1.281 +	      throw DataFormatError("",line_number,"Bad string");
   1.282 +	    else switch(c) {
   1.283 +	    case 'n':
   1.284 +	      w.push_back('\n');
   1.285 +	      break;
   1.286 +	    default:
   1.287 +	      w.push_back(c);
   1.288 +	      break;
   1.289 +	    }
   1.290 +	  else {
   1.291 +	    if(c=='\n') line_number++;
   1.292 +	    w.push_back(c);
   1.293 +	  }
   1.294 +	if(c!='<')
   1.295 +	  throw DataFormatError("",line_number,"Unexpected eof");
   1.296 +	is.unget();
   1.297 +      }
   1.298 +      return *this;
   1.299 +    }
   1.300 +
   1.301 +
   1.302 +    XmlIo &operator()(const std::string &_tag,const int &v) 
   1.303      { 
   1.304        LineTag t(*this,_tag);
   1.305        (*this)(v);
   1.306        return *this;
   1.307      }
   1.308 -    XmlWriter &operator()(double v) 
   1.309 -    {
   1.310 -      os << v;
   1.311 -      return *this;
   1.312 -    }
   1.313 -    XmlWriter &operator()(const std::string &_tag,double v) 
   1.314 +    XmlIo &operator()(const std::string &_tag,const double &v) 
   1.315      {
   1.316        LineTag t(*this,_tag);
   1.317        (*this)(v);
   1.318        return *this;
   1.319      }
   1.320 -    XmlWriter &operator()(const std::string &v)
   1.321 -    {
   1.322 -      for(std::string::const_iterator i=v.begin();i!=v.end();++i)
   1.323 -	switch(*i) {
   1.324 -	case '\\':
   1.325 -	  os << "\\\\";
   1.326 -	  break;
   1.327 -	case '<':
   1.328 -	  os << "\\<";
   1.329 -	  break;
   1.330 -	case '&':
   1.331 -	  os << "\\&";
   1.332 -	  break;
   1.333 -	case '\n':
   1.334 -	  os << "\\n";
   1.335 -	  break;
   1.336 -	default:
   1.337 -	  os<<*i;
   1.338 -	  break;
   1.339 -	}
   1.340 -      return *this;
   1.341 -    }
   1.342 -    XmlWriter &operator()(const std::string &_tag,const std::string &v)
   1.343 +    XmlIo &operator()(const std::string &_tag,const std::string &v)
   1.344      {
   1.345        LineTag t(*this,_tag);
   1.346        (*this)(v);
   1.347 @@ -169,10 +310,10 @@
   1.348      ///\e
   1.349      ///
   1.350      template<class V>
   1.351 -    XmlWriter &operator()(const std::string &_tag,const V &v)
   1.352 +    XmlIo &operator()(const std::string &_tag,const V &v)
   1.353      {
   1.354        Tag t(*this,_tag);
   1.355 -      out(*this,v);
   1.356 +      xml(*this,const_cast<V &>(v));
   1.357        return *this;
   1.358      }
   1.359      ///\e
   1.360 @@ -180,246 +321,82 @@
   1.361      ///\e
   1.362      ///
   1.363      template<class V>
   1.364 -    XmlWriter &operator()(const V &v)
   1.365 +    XmlIo &operator()(const V &v)
   1.366      {
   1.367 -      out(*this,v);
   1.368 +      xml(*this,const_cast<V &>(v));
   1.369        return *this;
   1.370      }
   1.371 -  };
   1.372 +    };
   1.373  
   1.374    //////////////////////////////////////////////////////////////////////
   1.375 -
   1.376 -  class XmlReader 
   1.377 -  {
   1.378 -    std::istream& is;
   1.379 -    std::string next_tag;
   1.380 -    int line_number;
   1.381 -
   1.382 -    void skipWhiteSpaces()
   1.383 -    {
   1.384 -      char c;
   1.385 -      while (is.get(c) && std::isspace(c,is.getloc())) if(c=='\n') line_number++;
   1.386 -      is.unget();
   1.387 -    }
   1.388 -  protected:
   1.389 -    ///\e
   1.390 -  
   1.391 -    ///\e
   1.392 -    ///
   1.393 -    void useTag() {next_tag.clear();}
   1.394 -  
   1.395 -    void useTag(const std::string &_tag) {
   1.396 -      if(nextTag()==_tag) useTag();
   1.397 -      else throw DataFormatError("",line_number,"Unexpected token name");
   1.398 -    }
   1.399 -  public:
   1.400 -    ///\e
   1.401 -  
   1.402 -    ///\e
   1.403 -    ///
   1.404 -    const std::string &nextTag() 
   1.405 -    {
   1.406 -      if(next_tag.empty()) {
   1.407 -	char c;
   1.408 -	skipWhiteSpaces();
   1.409 -	if(!is.get(c) || c!='<')
   1.410 -	  throw DataFormatError("",line_number,"Bad token");
   1.411 -	next_tag.clear();
   1.412 -	while (is.get(c) && c!='>') next_tag.push_back(c);
   1.413 -	if(c!='>')
   1.414 -	  throw DataFormatError("",line_number,"Bad token");
   1.415 -      }
   1.416 -      return next_tag;
   1.417 -    }
   1.418 -  
   1.419 -    ///\e
   1.420 -  
   1.421 -    ///\e
   1.422 -    ///
   1.423 -    class Tag
   1.424 -    {
   1.425 -      XmlReader &ix;
   1.426 -      const std::string tag;
   1.427 -    public:
   1.428 -      ///\e
   1.429 -    
   1.430 -      ///\e
   1.431 -      ///
   1.432 -      Tag(XmlReader &_ix,const std::string &_tag) :
   1.433 -	ix(_ix), tag(_tag)
   1.434 -      {
   1.435 -	ix.useTag(_tag);
   1.436 -      }
   1.437 -      ~Tag() {
   1.438 -	if(!std::uncaught_exception()) 
   1.439 -	  ix.useTag('/'+tag);
   1.440 -      }
   1.441 -    };
   1.442 -
   1.443 -    ///\e
   1.444 -  
   1.445 -    ///\e
   1.446 -    ///
   1.447 -    XmlReader(std::istream& _is) : is(_is), line_number(1) {}
   1.448 -  
   1.449 -    int operator()(const std::string &tag,int &v)
   1.450 -    { 
   1.451 -      Tag t(*this,tag);
   1.452 -      skipWhiteSpaces();
   1.453 -      if(!(is >> v)) throw DataFormatError("",line_number,"Not an 'int'");
   1.454 -      return v;
   1.455 -    }
   1.456 -    double operator()(const std::string &tag,double &v) 
   1.457 -    {
   1.458 -      Tag t(*this,tag);
   1.459 -      skipWhiteSpaces();
   1.460 -      if(!(is >> v))
   1.461 -	throw DataFormatError("",line_number,"Not a 'double'");
   1.462 -      return v;
   1.463 -    }
   1.464 -    std::string &operator()(const std::string &tag,std::string &v)
   1.465 -    {
   1.466 -      Tag t(*this,tag);
   1.467 -      v.clear();
   1.468 -      char c;
   1.469 -      while (is.get(c) && c!='<')
   1.470 -	if(c=='\\')
   1.471 -	  if(!is.get(c))
   1.472 -	    throw DataFormatError("",line_number,"Bad string");
   1.473 -	  else switch(c) {
   1.474 -	  case 'n':
   1.475 -	    v.push_back('\n');
   1.476 -	    break;
   1.477 -	  default:
   1.478 -	    v.push_back(c);
   1.479 -	    break;
   1.480 -	  }
   1.481 -	else {
   1.482 -	  if(c=='\n') line_number++;
   1.483 -	  v.push_back(c);
   1.484 -	}
   1.485 -      if(c!='<')
   1.486 -	throw DataFormatError("",line_number,"Unexpected eof");
   1.487 -      is.unget();
   1.488 -      return v;
   1.489 -    }
   1.490 -    ///\e
   1.491 -  
   1.492 -    ///\e
   1.493 -    ///
   1.494 -    template<class V>
   1.495 -    V &operator()(const std::string &tag,V &v)
   1.496 -    {
   1.497 -      Tag t(*this,tag);
   1.498 -      in(*this,v);
   1.499 -      return v;
   1.500 -    }
   1.501 -    ///\e
   1.502 -  
   1.503 -    ///\e
   1.504 -    ///
   1.505 -    template<class V>
   1.506 -    V &operator()(V &v)
   1.507 -    {
   1.508 -      in(*this,v);
   1.509 -      return v;
   1.510 -    }
   1.511 -    ///\e
   1.512 -  
   1.513 -    ///\e
   1.514 -    ///
   1.515 -    template<class V>
   1.516 -    V load(const std::string &tag)
   1.517 -    {
   1.518 -      Tag t(*this,tag);
   1.519 -      V v;
   1.520 -      (*this)(tag,v);
   1.521 -      return v;
   1.522 -    }
   1.523 -  };
   1.524 -
   1.525    //////////////////////////////////////////////////////////////////////
   1.526  
   1.527 +  ///\e
   1.528 +  
   1.529 +  ///\relates XmlIo
   1.530 +  ///
   1.531    template<class A>
   1.532 -  void out(XmlWriter &x,const std::auto_ptr<A> &v)
   1.533 +  void xml(XmlIo &x,std::auto_ptr<A> &v)
   1.534    {
   1.535 +    if(x.write()) v=new A;
   1.536      x(*v);
   1.537    }
   1.538 -
   1.539 -  template<class A>
   1.540 -  void in(XmlReader &x,std::auto_ptr<A> &v)
   1.541 -  {
   1.542 -    v=new A;
   1.543 -    x(*v);
   1.544 -  }
   1.545 -
   1.546 -  //////////////////////////////
   1.547 -
   1.548 +  
   1.549 +  ///\e
   1.550 +  
   1.551 +  ///\relates XmlIo
   1.552 +  ///
   1.553    template<class A,class B>
   1.554 -  void out(XmlWriter &x,const std::pair<A,B> &v)
   1.555 +  void xml(XmlIo &x,std::pair<A,B> &v)
   1.556    {
   1.557      x("first",v.first);
   1.558      x("second",v.second);
   1.559    }
   1.560  
   1.561 -  template<class A,class B>
   1.562 -  void in(XmlReader &x,std::pair<A,B> &v)
   1.563 +  ///\e
   1.564 +  
   1.565 +  ///\relates XmlIo
   1.566 +  ///
   1.567 +  template<class T>
   1.568 +  void xml(XmlIo &x,std::list<T> &v)
   1.569    {
   1.570 -    x("first",v.first);
   1.571 -    x("second",v.second);
   1.572 -  }
   1.573 -
   1.574 -  //////////////////////////////
   1.575 -
   1.576 -  template<class T>
   1.577 -  void out(XmlWriter &x,const std::list<T> &v)
   1.578 -  {
   1.579 -    for(typename std::list<T>::const_iterator it=v.begin();
   1.580 -	it!=v.end();++it) x("item",*it);
   1.581 -  }
   1.582 -
   1.583 -  template<class T>
   1.584 -  void in(XmlReader &x,std::list<T> &v)
   1.585 -  {
   1.586 -    while(x.nextTag()=="item")
   1.587 +    if(x.write())
   1.588 +      for(typename std::list<T>::const_iterator it=v.begin();
   1.589 +	  it!=v.end();++it) x("item",*it);
   1.590 +    else while(x.nextTag()=="item")
   1.591        {
   1.592  	v.push_back(T());
   1.593  	x("item",v.back());
   1.594        }
   1.595    }
   1.596 -
   1.597 -  //////////////////////////////
   1.598 -
   1.599 +  ///\e
   1.600 +  
   1.601 +  ///\relates XmlIo
   1.602 +  ///
   1.603    template<class T>
   1.604 -  void out(XmlWriter &x,const std::vector<T> &v)
   1.605 +  void xml(XmlIo &x,std::vector<T> &v)
   1.606    {
   1.607 -    for(typename std::vector<T>::const_iterator it=v.begin();
   1.608 -	it!=v.end();++it) x("item",*it);
   1.609 -  }
   1.610 -
   1.611 -  template<class T>
   1.612 -  void in(XmlReader &x,std::vector<T> &v)
   1.613 -  {
   1.614 -    while(x.nextTag()=="item")
   1.615 +    if(x.write())
   1.616 +      for(typename std::vector<T>::const_iterator it=v.begin();
   1.617 +	  it!=v.end();++it) x("item",*it);
   1.618 +    else while(x.nextTag()=="item")
   1.619        {
   1.620  	v.push_back(T());
   1.621  	x("item",v.back());      
   1.622        }
   1.623    }
   1.624  
   1.625 -  //////////////////////////////
   1.626 -
   1.627 +  ///\e
   1.628 +  
   1.629 +  ///\relates XmlIo
   1.630 +  ///
   1.631    template<class K,class V>
   1.632 -  void out(XmlWriter &x,const std::map<K,V> &v)
   1.633 +  void xml(XmlIo &x,std::map<K,V> &v)
   1.634    {
   1.635 -    for(typename std::map<K,V>::const_iterator it=v.begin();
   1.636 -	it!=v.end();++it) x("item",*it);
   1.637 -  }
   1.638 -
   1.639 -  template<class K,class V>
   1.640 -  void in(XmlReader &x,std::map<K,V> &v)
   1.641 -  {
   1.642 -    while(x.nextTag()=="item")
   1.643 +    if(x.write()) 
   1.644 +      for(typename std::map<K,V>::const_iterator it=v.begin();
   1.645 +	  it!=v.end();++it) x("item",*it);
   1.646 +    else while(x.nextTag()=="item")
   1.647        {
   1.648  	typename std::map<K,V>::value_type it;
   1.649  	x("item",it);
   1.650 @@ -427,44 +404,39 @@
   1.651        }
   1.652    }
   1.653  
   1.654 -  //////////////////////////////
   1.655 -
   1.656 +  ///\e
   1.657 +  
   1.658 +  ///\relates XmlIo
   1.659 +  ///
   1.660    template<class T>
   1.661 -  void out(XmlWriter &x,const lemon::xy<T> &v)
   1.662 +  void xml(XmlIo &x,lemon::xy<T> &v)
   1.663    {
   1.664 -    //   x("x",v.x);
   1.665 -    //   x("y",v.y);
   1.666 -    { XmlWriter::LineTag t(x,"x"); x(v.x); }
   1.667 -    { XmlWriter::ContTag t(x,"y"); x(v.y); }
   1.668 +    { XmlIo::LineTag t(x,"x"); x(v.x); }
   1.669 +    { XmlIo::ContTag t(x,"y"); x(v.y); }
   1.670    }
   1.671  
   1.672 +  ///\e
   1.673 +  
   1.674 +  ///\relates XmlIo
   1.675 +  ///
   1.676    template<class T>
   1.677 -  void in(XmlReader &x,lemon::xy<T> &v)
   1.678 +  void xml(XmlIo &x,lemon::BoundingBox<T> &v)
   1.679    {
   1.680 -    x("x",v.x);
   1.681 -    x("y",v.y);
   1.682 -  }
   1.683 -
   1.684 -  //////////////////////////////
   1.685 -
   1.686 -  template<class T>
   1.687 -  void out(XmlWriter &x,const lemon::BoundingBox<T> &v)
   1.688 -  {
   1.689 -    if(!v.empty()) {
   1.690 -      x("point",v.bottomLeft());
   1.691 -      if(v.bottomLeft()!=v.topRight()) x("point",v.topRight());
   1.692 +    if(x.write()) {
   1.693 +      if(!v.empty()) {
   1.694 +	x("point",v.bottomLeft());
   1.695 +	if(v.bottomLeft()!=v.topRight()) x("point",v.topRight());
   1.696 +      }
   1.697      }
   1.698 -  }
   1.699 -
   1.700 -  template<class T>
   1.701 -  void in(XmlReader &x,lemon::BoundingBox<T> &v)
   1.702 -  {
   1.703 -    v.clear();
   1.704 -    while(x.nextTag()=="point") {
   1.705 -      lemon::xy<T> co;
   1.706 -      x("point",co);
   1.707 -      v.add(co);
   1.708 +    else {
   1.709 +      v.clear();
   1.710 +      while(x.nextTag()=="point") {
   1.711 +	lemon::xy<T> co;
   1.712 +	x("point",co);
   1.713 +	v.add(co);
   1.714 +      }
   1.715      }
   1.716    }
   1.717    
   1.718  }
   1.719 +