gui/xml.h
author ladanyi
Tue, 14 Jun 2005 09:42:46 +0000
changeset 1480 268c2b5d8971
parent 1428 9ba88ddc629c
child 1588 b79bcba43661
permissions -rw-r--r--
distribute the LICENSE file too
     1 /* -*- C++ -*- */
     2 
     3 #include <iostream>
     4 #include <string>
     5 #include <vector>
     6 #include <list>
     7 #include <map>
     8 #include <lemon/xy.h>
     9 
    10 class XmlWriter 
    11 {
    12   std::ostream& os;
    13   int level;
    14 
    15 protected:
    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 
    38 public:
    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 
   189 class 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   }
   200 protected:
   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   }
   211 public:
   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 
   332 template<class A,class B>
   333 void out(XmlWriter &i,const std::pair<A,B> &v)
   334 {
   335   i("first",v.first);
   336   i("second",v.second);
   337 }
   338 
   339 template<class A,class B>
   340 void in(XmlReader &i,std::pair<A,B> &v)
   341 {
   342   i("first",v.first);
   343   i("second",v.second);
   344 }
   345 
   346 //////////////////////////////
   347 
   348 template<class T>
   349 void 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 
   355 template<class T>
   356 void 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 
   367 template<class T>
   368 void 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 
   374 template<class T>
   375 void 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 
   386 template<class K,class V>
   387 void 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 
   393 template<class K,class V>
   394 void 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 
   406 template<class T>
   407 void 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 
   415 template<class T>
   416 void in(XmlReader &i,lemon::xy<T> &v)
   417 {
   418   i("x",v.x);
   419   i("y",v.y);
   420 }
   421 
   422 //////////////////////////////
   423 
   424 template<class T>
   425 void 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 
   433 template<class T>
   434 void 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 }