Index: gui/xml.h
===================================================================
--- gui/xml.h	(revision 1435)
+++ gui/xml.h	(revision 1588)
@@ -6,437 +6,465 @@
 #include <list>
 #include <map>
+#include <lemon/error.h>
 #include <lemon/xy.h>
 
-class XmlWriter 
-{
-  std::ostream& os;
-  int level;
-
-protected:
-  void indent(int level) {
-    os << std::endl;
-    for(int i=0;i<level;i++) os << ' ';
-  }
-  void tag(const std::string &_tag) {
-    os << '<' << _tag << '>';
-  }
-  void etag(const std::string &_tag) {
-    os << "</" << _tag << '>';
-  }
-  void itag(const std::string &_tag) { indent();tag(_tag); }
-  void ietag(const std::string &_tag) { indent();etag(_tag); }
-
-  void beginTag(const std::string &_tag) {
-    itag(_tag);
-    level++;
-  }
-  void endTag(const std::string &_tag) {
-    level--;
-    ietag(_tag);
-  }
-
-public:
-
-  void indent() 
-  {
-    if(level>=0) indent(level);
-    else level=0;
-  }
-  
-  ///\e
-  
-  ///\e
-  ///
-  class ContTag
-  {
-    XmlWriter &ix;
-    const std::string _tag;
+namespace lemon {
+
+  class XmlWriter 
+  {
+    std::ostream& os;
+    int level;
+
+  protected:
+    void indent(int level) {
+      os << std::endl;
+      for(int i=0;i<level;i++) os << ' ';
+    }
+    void tag(const std::string &_tag) {
+      os << '<' << _tag << '>';
+    }
+    void etag(const std::string &_tag) {
+      os << "</" << _tag << '>';
+    }
+    void itag(const std::string &_tag) { indent();tag(_tag); }
+    void ietag(const std::string &_tag) { indent();etag(_tag); }
+
+    void beginTag(const std::string &_tag) {
+      itag(_tag);
+      level++;
+    }
+    void endTag(const std::string &_tag) {
+      level--;
+      ietag(_tag);
+    }
+
   public:
-  ///\e
-  
-  ///\e
-  ///
-    ContTag(XmlWriter &_ix,const std::string &_t) :
-      ix(_ix), _tag(_t)
-    {
-      ix.tag(_tag);
-    }
-    ~ContTag() { ix.etag(_tag);}
-  };
-
-  class LineTag
-  {
-    XmlWriter &ix;
-    const std::string _tag;
-  public:
-    ///\e
+
+    void indent() 
+    {
+      if(level>=0) indent(level);
+      else level=0;
+    }
+  
+    ///\e
+  
+    ///\e
+    ///
+    class ContTag
+    {
+      XmlWriter &ix;
+      const std::string _tag;
+    public:
+      ///\e
+  
+      ///\e
+      ///
+      ContTag(XmlWriter &_ix,const std::string &_t) :
+	ix(_ix), _tag(_t)
+      {
+	ix.tag(_tag);
+      }
+      ~ContTag() { ix.etag(_tag);}
+    };
+
+    class LineTag
+    {
+      XmlWriter &ix;
+      const std::string _tag;
+    public:
+      ///\e
     
-    ///\e
-    ///
-    LineTag(XmlWriter &_ix,const std::string &_t) :
-      ix(_ix), _tag(_t)
-    {
-      ix.itag(_tag);
-    }
-    ~LineTag() { ix.etag(_tag);}
-  };
-
-  ///\e
-  
-  ///\e
-  ///
-  class Tag
-  {
-    XmlWriter &ix;
-    const std::string _tag;
-  public:
-    ///\e
-  
-    ///\e
-    ///
-    Tag(XmlWriter &_ix,const std::string &_t) :
-      ix(_ix), _tag(_t)
-    {
-      ix.beginTag(_tag);
-    }
-    ~Tag() { 
-      ix.endTag(_tag);
-    }
-  };
+      ///\e
+      ///
+      LineTag(XmlWriter &_ix,const std::string &_t) :
+	ix(_ix), _tag(_t)
+      {
+	ix.itag(_tag);
+      }
+      ~LineTag() { ix.etag(_tag);}
+    };
+
+    ///\e
+  
+    ///\e
+    ///
+    class Tag
+    {
+      XmlWriter &ix;
+      const std::string _tag;
+    public:
+      ///\e
+  
+      ///\e
+      ///
+      Tag(XmlWriter &_ix,const std::string &_t) :
+	ix(_ix), _tag(_t)
+      {
+	ix.beginTag(_tag);
+      }
+      ~Tag() { 
+	ix.endTag(_tag);
+      }
+    };
       
-  ///\e
-  
-  ///\e
-  ///
-  XmlWriter(std::ostream& _os) : os(_os),level(-1) {}
-  ~XmlWriter() { os<< std::endl; }
-  
-  XmlWriter &operator()(int v) 
-  { 
-    if(!(os << v)) throw (std::ios::failure ("data format error"));
-    return *this;
-  }
-  XmlWriter &operator()(const std::string &_tag,int v) 
-  { 
-    LineTag t(*this,_tag);
-    if(!(os << v)) throw (std::ios::failure ("data format error"));
-    return *this;
-  }
-  XmlWriter &operator()(const std::string &_tag,double v) 
-  {
-    LineTag t(*this,_tag);
-    if(os << v) throw (std::ios::failure ("data format error"));
-    return *this;
-  }
-  XmlWriter &operator()(double v) 
-  {
-    os << v;
-    return *this;
-  }
-  XmlWriter &operator()(const std::string &v)
-  {
-    for(std::string::const_iterator i=v.begin();i!=v.end();++i)
-      switch(*i) {
-      case '\\':
-	os << "\\\\";
-	break;
-      case '<':
-	os << "\\<";
-	break;
-      case '&':
-	os << "\\&";
-	break;
-      case '\n':
-	os << "\\n";
-	break;
-      default:
-	os<<*i;
-	break;
-      }
-    return *this;
-  }
-  XmlWriter &operator()(const std::string &_tag,const std::string &v)
-  {
-    LineTag t(*this,_tag);
-    (*this)(v);
-    return *this;
-  }
-  ///\e
-  
-  ///\e
-  ///
-  template<class V>
-  XmlWriter &operator()(const std::string &_tag,const V &v)
-  {
-    Tag t(*this,_tag);
-    out(*this,v);
-    return *this;
-  }
-  ///\e
-  
-  ///\e
-  ///
-  template<class V>
-  XmlWriter &operator()(const V &v)
-  {
-    out(*this,v);
-    return *this;
-  }
-};
-
-//////////////////////////////////////////////////////////////////////
-
-class XmlReader 
-{
-  std::istream& is;
-  
-  std::string next_tag;
-  void skipWhiteSpaces()
-  {
-    char c;
-    while (is.get(c) && std::isspace(c,is.getloc()));
-    is.unget();
-  }
-protected:
-  ///\e
-  
-  ///\e
-  ///
-  void useTag() {next_tag.clear();}
-  
-  void useTag(const std::string &_tag) {
-    if(nextTag()==_tag) useTag();
-    else throw (std::ios::failure ("data format error"));
-  }
-public:
-  ///\e
-  
-  ///\e
-  ///
-  const std::string &nextTag() 
-  {
-    if(next_tag.empty()) {
-      char c;
-      skipWhiteSpaces();
-      if(!is.get(c) || c!='<')
-	throw (std::ios::failure ("data format error"));
-      next_tag.clear();
-      while (is.get(c) && c!='>') next_tag.push_back(c);
-      if(c!='>')
-	throw (std::ios::failure ("data format error"));
-    }
-    return next_tag;
-  }
-  
-  ///\e
-  
-  ///\e
-  ///
-  class Tag
-  {
-    XmlReader &ix;
-    const std::string tag;
-  public:
-    ///\e
-    
-    ///\e
-    ///
-    Tag(XmlReader &_ix,const std::string &_tag) :
-      ix(_ix), tag(_tag)
-    {
-      ix.useTag(_tag);
-    }
-    ~Tag() {
-      if(!std::uncaught_exception()) 
-	ix.useTag('/'+tag);
-    }
-  };
-
-  ///\e
-  
-  ///\e
-  ///
-  XmlReader(std::istream& _is) : is(_is) {}
-  
-  int operator()(const std::string &tag,int &v)
-  { 
-    Tag t(*this,tag);
-    if(!(is >> v)) throw (std::ios::failure ("data format error"));
-    return v;
-  }
-  double operator()(const std::string &tag,double &v) 
-  {
-    Tag t(*this,tag);
-    if(!(is >> v)) throw (std::ios::failure ("data format error"));
-    return v;
-  }
-  std::string &operator()(const std::string &tag,std::string &v)
-  {
-    Tag t(*this,tag);
-    v.clear();
-    char c;
-    while (is.get(c) && c!='<')
-      if(c=='\\')
-	if(!is.get(c)) throw (std::ios::failure ("data format error"));
-	else switch(c) {
-	case 'n':
-	  v.push_back('\n');
+    ///\e
+  
+    ///\e
+    ///
+    XmlWriter(std::ostream& _os) : os(_os),level(-1) {}
+    ~XmlWriter() { os<< std::endl; }
+  
+    XmlWriter &operator()(int v) 
+    { 
+      os << v;
+      return *this;
+    }
+    XmlWriter &operator()(const std::string &_tag,int v) 
+    { 
+      LineTag t(*this,_tag);
+      (*this)(v);
+      return *this;
+    }
+    XmlWriter &operator()(double v) 
+    {
+      os << v;
+      return *this;
+    }
+    XmlWriter &operator()(const std::string &_tag,double v) 
+    {
+      LineTag t(*this,_tag);
+      (*this)(v);
+      return *this;
+    }
+    XmlWriter &operator()(const std::string &v)
+    {
+      for(std::string::const_iterator i=v.begin();i!=v.end();++i)
+	switch(*i) {
+	case '\\':
+	  os << "\\\\";
+	  break;
+	case '<':
+	  os << "\\<";
+	  break;
+	case '&':
+	  os << "\\&";
+	  break;
+	case '\n':
+	  os << "\\n";
 	  break;
 	default:
-	  v.push_back(c);
+	  os<<*i;
 	  break;
 	}
-      else v.push_back(c);
-    if(c!='<')
-	throw (std::ios::failure ("data format error"));
-    is.unget();
-    return v;
-  }
-  ///\e
-  
-  ///\e
-  ///
-  template<class V>
-  V &operator()(const std::string &tag,V &v)
-  {
-    Tag t(*this,tag);
-    in(*this,v);
-    return v;
-  }
-  ///\e
-  
-  ///\e
-  ///
-  template<class V>
-  V &operator()(V &v)
-  {
-    in(*this,v);
-    return v;
-  }
-  ///\e
-  
-  ///\e
-  ///
-  template<class V>
-  V load(const std::string &tag)
-  {
-    Tag t(*this,tag);
-    V v;
-    (*this)(tag,v);
-    return v;
-  }
-};
-
-//////////////////////////////////////////////////////////////////////
-
-template<class A,class B>
-void out(XmlWriter &i,const std::pair<A,B> &v)
-{
-  i("first",v.first);
-  i("second",v.second);
+      return *this;
+    }
+    XmlWriter &operator()(const std::string &_tag,const std::string &v)
+    {
+      LineTag t(*this,_tag);
+      (*this)(v);
+      return *this;
+    }
+    ///\e
+  
+    ///\e
+    ///
+    template<class V>
+    XmlWriter &operator()(const std::string &_tag,const V &v)
+    {
+      Tag t(*this,_tag);
+      out(*this,v);
+      return *this;
+    }
+    ///\e
+  
+    ///\e
+    ///
+    template<class V>
+    XmlWriter &operator()(const V &v)
+    {
+      out(*this,v);
+      return *this;
+    }
+  };
+
+  //////////////////////////////////////////////////////////////////////
+
+  class XmlReader 
+  {
+    std::istream& is;
+    std::string next_tag;
+    int line_number;
+
+    void skipWhiteSpaces()
+    {
+      char c;
+      while (is.get(c) && std::isspace(c,is.getloc())) if(c=='\n') line_number++;
+      is.unget();
+    }
+  protected:
+    ///\e
+  
+    ///\e
+    ///
+    void useTag() {next_tag.clear();}
+  
+    void useTag(const std::string &_tag) {
+      if(nextTag()==_tag) useTag();
+      else throw DataFormatError("",line_number,"Unexpected token name");
+    }
+  public:
+    ///\e
+  
+    ///\e
+    ///
+    const std::string &nextTag() 
+    {
+      if(next_tag.empty()) {
+	char c;
+	skipWhiteSpaces();
+	if(!is.get(c) || c!='<')
+	  throw DataFormatError("",line_number,"Bad token");
+	next_tag.clear();
+	while (is.get(c) && c!='>') next_tag.push_back(c);
+	if(c!='>')
+	  throw DataFormatError("",line_number,"Bad token");
+      }
+      return next_tag;
+    }
+  
+    ///\e
+  
+    ///\e
+    ///
+    class Tag
+    {
+      XmlReader &ix;
+      const std::string tag;
+    public:
+      ///\e
+    
+      ///\e
+      ///
+      Tag(XmlReader &_ix,const std::string &_tag) :
+	ix(_ix), tag(_tag)
+      {
+	ix.useTag(_tag);
+      }
+      ~Tag() {
+	if(!std::uncaught_exception()) 
+	  ix.useTag('/'+tag);
+      }
+    };
+
+    ///\e
+  
+    ///\e
+    ///
+    XmlReader(std::istream& _is) : is(_is), line_number(1) {}
+  
+    int operator()(const std::string &tag,int &v)
+    { 
+      Tag t(*this,tag);
+      skipWhiteSpaces();
+      if(!(is >> v)) throw DataFormatError("",line_number,"Not an 'int'");
+      return v;
+    }
+    double operator()(const std::string &tag,double &v) 
+    {
+      Tag t(*this,tag);
+      skipWhiteSpaces();
+      if(!(is >> v))
+	throw DataFormatError("",line_number,"Not a 'double'");
+      return v;
+    }
+    std::string &operator()(const std::string &tag,std::string &v)
+    {
+      Tag t(*this,tag);
+      v.clear();
+      char c;
+      while (is.get(c) && c!='<')
+	if(c=='\\')
+	  if(!is.get(c))
+	    throw DataFormatError("",line_number,"Bad string");
+	  else switch(c) {
+	  case 'n':
+	    v.push_back('\n');
+	    break;
+	  default:
+	    v.push_back(c);
+	    break;
+	  }
+	else {
+	  if(c=='\n') line_number++;
+	  v.push_back(c);
+	}
+      if(c!='<')
+	throw DataFormatError("",line_number,"Unexpected eof");
+      is.unget();
+      return v;
+    }
+    ///\e
+  
+    ///\e
+    ///
+    template<class V>
+    V &operator()(const std::string &tag,V &v)
+    {
+      Tag t(*this,tag);
+      in(*this,v);
+      return v;
+    }
+    ///\e
+  
+    ///\e
+    ///
+    template<class V>
+    V &operator()(V &v)
+    {
+      in(*this,v);
+      return v;
+    }
+    ///\e
+  
+    ///\e
+    ///
+    template<class V>
+    V load(const std::string &tag)
+    {
+      Tag t(*this,tag);
+      V v;
+      (*this)(tag,v);
+      return v;
+    }
+  };
+
+  //////////////////////////////////////////////////////////////////////
+
+  template<class A>
+  void out(XmlWriter &x,const std::auto_ptr<A> &v)
+  {
+    x(*v);
+  }
+
+  template<class A>
+  void in(XmlReader &x,std::auto_ptr<A> &v)
+  {
+    v=new A;
+    x(*v);
+  }
+
+  //////////////////////////////
+
+  template<class A,class B>
+  void out(XmlWriter &x,const std::pair<A,B> &v)
+  {
+    x("first",v.first);
+    x("second",v.second);
+  }
+
+  template<class A,class B>
+  void in(XmlReader &x,std::pair<A,B> &v)
+  {
+    x("first",v.first);
+    x("second",v.second);
+  }
+
+  //////////////////////////////
+
+  template<class T>
+  void out(XmlWriter &x,const std::list<T> &v)
+  {
+    for(typename std::list<T>::const_iterator it=v.begin();
+	it!=v.end();++it) x("item",*it);
+  }
+
+  template<class T>
+  void in(XmlReader &x,std::list<T> &v)
+  {
+    while(x.nextTag()=="item")
+      {
+	v.push_back(T());
+	x("item",v.back());
+      }
+  }
+
+  //////////////////////////////
+
+  template<class T>
+  void out(XmlWriter &x,const std::vector<T> &v)
+  {
+    for(typename std::vector<T>::const_iterator it=v.begin();
+	it!=v.end();++it) x("item",*it);
+  }
+
+  template<class T>
+  void in(XmlReader &x,std::vector<T> &v)
+  {
+    while(x.nextTag()=="item")
+      {
+	v.push_back(T());
+	x("item",v.back());      
+      }
+  }
+
+  //////////////////////////////
+
+  template<class K,class V>
+  void out(XmlWriter &x,const std::map<K,V> &v)
+  {
+    for(typename std::map<K,V>::const_iterator it=v.begin();
+	it!=v.end();++it) x("item",*it);
+  }
+
+  template<class K,class V>
+  void in(XmlReader &x,std::map<K,V> &v)
+  {
+    while(x.nextTag()=="item")
+      {
+	typename std::map<K,V>::value_type it;
+	x("item",it);
+	v.insert(it);
+      }
+  }
+
+  //////////////////////////////
+
+  template<class T>
+  void out(XmlWriter &x,const lemon::xy<T> &v)
+  {
+    //   x("x",v.x);
+    //   x("y",v.y);
+    { XmlWriter::LineTag t(x,"x"); x(v.x); }
+    { XmlWriter::ContTag t(x,"y"); x(v.y); }
+  }
+
+  template<class T>
+  void in(XmlReader &x,lemon::xy<T> &v)
+  {
+    x("x",v.x);
+    x("y",v.y);
+  }
+
+  //////////////////////////////
+
+  template<class T>
+  void out(XmlWriter &x,const lemon::BoundingBox<T> &v)
+  {
+    if(!v.empty()) {
+      x("point",v.bottomLeft());
+      if(v.bottomLeft()!=v.topRight()) x("point",v.topRight());
+    }
+  }
+
+  template<class T>
+  void in(XmlReader &x,lemon::BoundingBox<T> &v)
+  {
+    v.clear();
+    while(x.nextTag()=="point") {
+      lemon::xy<T> co;
+      x("point",co);
+      v.add(co);
+    }
+  }
+  
 }
-
-template<class A,class B>
-void in(XmlReader &i,std::pair<A,B> &v)
-{
-  i("first",v.first);
-  i("second",v.second);
-}
-
-//////////////////////////////
-
-template<class T>
-void out(XmlWriter &i,const std::list<T> &v)
-{
-  for(typename std::list<T>::const_iterator it=v.begin();
-      it!=v.end();++it) i("item",*it);
-}
-
-template<class T>
-void in(XmlReader &i,std::list<T> &v)
-{
-  while(i.nextTag()=="item")
-    {
-      v.push_back(T());
-      i("item",v.back());
-    }
-}
-
-//////////////////////////////
-
-template<class T>
-void out(XmlWriter &i,const std::vector<T> &v)
-{
-  for(typename std::vector<T>::const_iterator it=v.begin();
-      it!=v.end();++it) i("item",*it);
-}
-
-template<class T>
-void in(XmlReader &i,std::vector<T> &v)
-{
-  while(i.nextTag()=="item")
-    {
-      v.push_back(T());
-      i("item",v.back());      
-    }
-}
-
-//////////////////////////////
-
-template<class K,class V>
-void out(XmlWriter &i,const std::map<K,V> &v)
-{
-  for(typename std::map<K,V>::const_iterator it=v.begin();
-      it!=v.end();++it) i("item",*it);
-}
-
-template<class K,class V>
-void in(XmlReader &i,std::map<K,V> &v)
-{
-  while(i.nextTag()=="item")
-    {
-      typename std::map<K,V>::value_type it;
-      i("item",it);
-      v.insert(it);
-    }
-}
-
-//////////////////////////////
-
-template<class T>
-void out(XmlWriter &i,const lemon::xy<T> &v)
-{
-//   i("x",v.x);
-//   i("y",v.y);
-  { XmlWriter::LineTag t(i,"x"); i(v.x); }
-  { XmlWriter::ContTag t(i,"y"); i(v.y); }
-}
-
-template<class T>
-void in(XmlReader &i,lemon::xy<T> &v)
-{
-  i("x",v.x);
-  i("y",v.y);
-}
-
-//////////////////////////////
-
-template<class T>
-void out(XmlWriter &i,const lemon::BoundingBox<T> &v)
-{
-  if(!v.empty()) {
-    i("point",v.bottomLeft());
-    if(v.bottomLeft()!=v.topRight()) i("point",v.topRight());
-  }
-}
-
-template<class T>
-void in(XmlReader &i,lemon::BoundingBox<T> &v)
-{
-  v.clear();
-  while(i.nextTag()=="point") {
-    lemon::xy<T> co;
-    i("point",co);
-    v+=co;
-  }
-}
