xml.h
branchgui
changeset 23 d0e4ac77bafe
child 39 959c499e3b65
equal deleted inserted replaced
-1:000000000000 0:0a9acc404153
       
     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 }