COIN-OR::LEMON - Graph Library

Changeset 1735:41e96cd91d6d in lemon-0.x for gui/xml.h


Ignore:
Timestamp:
10/24/05 10:11:21 (18 years ago)
Author:
Alpar Juttner
Branch:
default
Phase:
public
Convert:
svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@2262
Message:

New version of XML reader/writer.
Now, there are only a single XmlIo? class both for reading and writing.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • gui/xml.h

    r1588 r1735  
    1 /* -*- C++ -*- */
     1/* -*- C++ -*-
     2 * gui/xml.h - Part of LEMON, a generic C++ optimization library
     3 *
     4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
     6 *
     7 * Permission to use, modify and distribute this software is granted
     8 * provided that this copyright notice appears in all copies. For
     9 * precise terms see the accompanying LICENSE file.
     10 *
     11 * This software is provided "AS IS" with no warranty of any kind,
     12 * express or implied, and with no claim as to its suitability for any
     13 * purpose.
     14 *
     15 */
    216
    317#include <iostream>
     
    1125namespace lemon {
    1226
    13   class XmlWriter
    14   {
     27  class XmlIo
     28  {
     29    bool _writeMode;
     30  public:
     31    ///Check if XmlIo is in write mode.
     32    bool write() { return _writeMode;}
     33    ///Check if XmlIo is in read mode.
     34    bool read() { return !_writeMode;}
     35
    1536    std::ostream& os;
    1637    int level;
    17 
     38   
    1839  protected:
    1940    void indent(int level) {
     
    4061
    4162  public:
    42 
    43     void indent()
    44     {
    45       if(level>=0) indent(level);
    46       else level=0;
    47     }
    48  
    49     ///\e
    50  
    51     ///\e
    52     ///
     63    ///Indent the line according to its level.
     64
     65    ///\warning It can only be used in write mode.
     66    ///
     67    void indent()
     68    {
     69      if(write())
     70        if(level>=0) indent(level);
     71        else level=0;
     72      else throw LogicError(); 
     73    }
     74 
     75    ///Read/write a tag
     76 
     77    ///Read/write a tag.
     78    ///In write mode it does not start a new line.
    5379    class ContTag
    5480    {
    55       XmlWriter &ix;
     81      XmlIo &ix;
    5682      const std::string _tag;
    5783    public:
     
    6086      ///\e
    6187      ///
    62       ContTag(XmlWriter &_ix,const std::string &_t) :
     88      ContTag(XmlIo &_ix,const std::string &_t) :
    6389        ix(_ix), _tag(_t)
    6490      {
    65         ix.tag(_tag);
    66       }
    67       ~ContTag() { ix.etag(_tag);}
     91        if(ix.write()) ix.tag(_tag);
     92        else ix.useTag(_tag);
     93      }
     94      ~ContTag() {
     95        if(ix.write()) ix.etag(_tag);
     96        else if(!std::uncaught_exception()) ix.useTag('/'+_tag);     
     97      }
    6898    };
    6999
     100    ///Read/write a tag
     101 
     102    ///Read/write a tag.
     103    ///The whole <foo> ... </foo> will be places in a single line.
    70104    class LineTag
    71105    {
    72       XmlWriter &ix;
     106      XmlIo &ix;
    73107      const std::string _tag;
    74108    public:
     
    77111      ///\e
    78112      ///
    79       LineTag(XmlWriter &_ix,const std::string &_t) :
     113      LineTag(XmlIo &_ix,const std::string &_t) :
    80114        ix(_ix), _tag(_t)
    81115      {
    82         ix.itag(_tag);
    83       }
    84       ~LineTag() { ix.etag(_tag);}
     116        if(ix.write()) ix.itag(_tag);
     117        else ix.useTag(_tag);
     118      }
     119      ~LineTag() {
     120        if(ix.write()) ix.etag(_tag);
     121        else if(!std::uncaught_exception()) ix.useTag('/'+_tag);
     122      }
    85123    };
    86124
    87     ///\e
    88  
    89     ///\e
     125    ///Read/write a tag
     126 
     127    ///Read/write a tag.
    90128    ///
    91129    class Tag
    92130    {
    93       XmlWriter &ix;
     131      XmlIo &ix;
    94132      const std::string _tag;
    95133    public:
     
    98136      ///\e
    99137      ///
    100       Tag(XmlWriter &_ix,const std::string &_t) :
     138      Tag(XmlIo &_ix,const std::string &_t) :
    101139        ix(_ix), _tag(_t)
    102140      {
    103         ix.beginTag(_tag);
    104       }
    105       ~Tag() {
    106         ix.endTag(_tag);
     141        if(ix.write()) ix.beginTag(_tag);
     142        else ix.useTag(_tag);
     143      }
     144      ~Tag() {
     145        if(ix.write()) ix.endTag(_tag);
     146        else if(!std::uncaught_exception()) ix.useTag('/'+_tag);
    107147      }
    108148    };
    109      
    110     ///\e
    111  
    112     ///\e
    113     ///
    114     XmlWriter(std::ostream& _os) : os(_os),level(-1) {}
    115     ~XmlWriter() { os<< std::endl; }
    116  
    117     XmlWriter &operator()(int v)
     149
     150  private:
     151    std::istream& is;
     152    std::string next_tag;
     153    int line_number;
     154
     155    void skipWhiteSpaces()
     156    {
     157      if(write()) throw LogicError();
     158      {
     159        char c;
     160        while (is.get(c) && std::isspace(c,is.getloc()))
     161          if(c=='\n') line_number++;
     162        is.unget();
     163      }
     164    }
     165  protected:
     166    /// Use the next tag.
     167
     168    ///\e
     169    ///
     170    void useTag() {next_tag.clear();}
     171 
     172    ///Use the next tag and check if it is equal with \c _tag
     173 
     174    ///\e
     175    ///
     176    void useTag(const std::string &_tag) {
     177      if(nextTag()==_tag) useTag();
     178      else throw DataFormatError("",line_number,"Unexpected token name");
     179    }
     180  public:
     181    ///Return the next tag (if a tag follows on the stream).
     182 
     183    ///\warning It can only be used in read mode.
     184    ///
     185    const std::string &nextTag()
     186    {
     187      if(write()) throw LogicError();
     188      else if(next_tag.empty()) {
     189        char c;
     190        skipWhiteSpaces();
     191        if(!is.get(c) || c!='<')
     192          throw DataFormatError("",line_number,"Bad format");
     193        next_tag.clear();
     194        while (is.get(c) && c!='>') next_tag.push_back(c);
     195        if(c!='>')
     196          throw DataFormatError("",line_number,"Bad format");
     197      }
     198      return next_tag;
     199    }
     200
     201    /**********************************************************************/
     202
     203
     204    ///\e
     205 
     206    ///\e
     207    ///
     208    XmlIo(std::ostream& _os) : _writeMode(true), os(_os),
     209                               level(-1),
     210                               is(*(std::istream*)(NULL)) {}
     211    ///\e
     212    ///
     213    XmlIo(std::istream& _is) : _writeMode(false),
     214                               os(*(std::ostream*)(NULL)), is(_is),
     215                               line_number(1) {}
     216
     217    ~XmlIo() { if(write()) os<< std::endl; }
     218 
     219
     220
     221    XmlIo &operator()(const int &v)
    118222    {
    119       os << v;
    120       return *this;
    121     }
    122     XmlWriter &operator()(const std::string &_tag,int v)
     223      if(write()) os << v;
     224      else {
     225        skipWhiteSpaces();
     226        if(!(is >> const_cast<int &>(v)))
     227          throw DataFormatError("",line_number,"Not an 'int'");
     228      }
     229      return *this;
     230    }
     231    XmlIo &operator()(const double &v)
     232    {
     233      if(write()) os << v;
     234      else {
     235        skipWhiteSpaces();
     236        if(!(is >> const_cast<double &>(v)))
     237          throw DataFormatError("",line_number,"Not an 'double'");
     238      }
     239      return *this;
     240    }
     241    XmlIo &operator()(const std::string &v)
     242    {
     243      if(write())
     244        for(std::string::const_iterator i=v.begin();i!=v.end();++i)
     245          switch(*i) {
     246          case '\\':
     247            os << "\\\\";
     248            break;
     249          case '<':
     250            os << "\\<";
     251            break;
     252          case '&':
     253            os << "\\&";
     254            break;
     255          case '\n':
     256            os << "\\n";
     257            break;
     258          default:
     259            os<<*i;
     260            break;
     261          }
     262      else {
     263        std::string &w = const_cast<std::string &>(v);
     264        w.clear();
     265        char c;
     266        while (is.get(c) && c!='<')
     267          if(c=='\\')
     268            if(!is.get(c))
     269              throw DataFormatError("",line_number,"Bad string");
     270            else switch(c) {
     271            case 'n':
     272              w.push_back('\n');
     273              break;
     274            default:
     275              w.push_back(c);
     276              break;
     277            }
     278          else {
     279            if(c=='\n') line_number++;
     280            w.push_back(c);
     281          }
     282        if(c!='<')
     283          throw DataFormatError("",line_number,"Unexpected eof");
     284        is.unget();
     285      }
     286      return *this;
     287    }
     288
     289
     290    XmlIo &operator()(const std::string &_tag,const int &v)
    123291    {
    124292      LineTag t(*this,_tag);
     
    126294      return *this;
    127295    }
    128     XmlWriter &operator()(double v)
    129     {
    130       os << v;
    131       return *this;
    132     }
    133     XmlWriter &operator()(const std::string &_tag,double v)
     296    XmlIo &operator()(const std::string &_tag,const double &v)
    134297    {
    135298      LineTag t(*this,_tag);
     
    137300      return *this;
    138301    }
    139     XmlWriter &operator()(const std::string &v)
    140     {
    141       for(std::string::const_iterator i=v.begin();i!=v.end();++i)
    142         switch(*i) {
    143         case '\\':
    144           os << "\\\\";
    145           break;
    146         case '<':
    147           os << "\\<";
    148           break;
    149         case '&':
    150           os << "\\&";
    151           break;
    152         case '\n':
    153           os << "\\n";
    154           break;
    155         default:
    156           os<<*i;
    157           break;
    158         }
    159       return *this;
    160     }
    161     XmlWriter &operator()(const std::string &_tag,const std::string &v)
     302    XmlIo &operator()(const std::string &_tag,const std::string &v)
    162303    {
    163304      LineTag t(*this,_tag);
     
    170311    ///
    171312    template<class V>
    172     XmlWriter &operator()(const std::string &_tag,const V &v)
     313    XmlIo &operator()(const std::string &_tag,const V &v)
    173314    {
    174315      Tag t(*this,_tag);
    175       out(*this,v);
     316      xml(*this,const_cast<V &>(v));
    176317      return *this;
    177318    }
     
    181322    ///
    182323    template<class V>
    183     XmlWriter &operator()(const V &v)
    184     {
    185       out(*this,v);
    186       return *this;
    187     }
    188   };
     324    XmlIo &operator()(const V &v)
     325    {
     326      xml(*this,const_cast<V &>(v));
     327      return *this;
     328    }
     329    };
    189330
    190331  //////////////////////////////////////////////////////////////////////
    191 
    192   class XmlReader
    193   {
    194     std::istream& is;
    195     std::string next_tag;
    196     int line_number;
    197 
    198     void skipWhiteSpaces()
    199     {
    200       char c;
    201       while (is.get(c) && std::isspace(c,is.getloc())) if(c=='\n') line_number++;
    202       is.unget();
    203     }
    204   protected:
    205     ///\e
    206  
    207     ///\e
    208     ///
    209     void useTag() {next_tag.clear();}
    210  
    211     void useTag(const std::string &_tag) {
    212       if(nextTag()==_tag) useTag();
    213       else throw DataFormatError("",line_number,"Unexpected token name");
    214     }
    215   public:
    216     ///\e
    217  
    218     ///\e
    219     ///
    220     const std::string &nextTag()
    221     {
    222       if(next_tag.empty()) {
    223         char c;
    224         skipWhiteSpaces();
    225         if(!is.get(c) || c!='<')
    226           throw DataFormatError("",line_number,"Bad token");
    227         next_tag.clear();
    228         while (is.get(c) && c!='>') next_tag.push_back(c);
    229         if(c!='>')
    230           throw DataFormatError("",line_number,"Bad token");
    231       }
    232       return next_tag;
    233     }
    234  
    235     ///\e
    236  
    237     ///\e
    238     ///
    239     class Tag
    240     {
    241       XmlReader &ix;
    242       const std::string tag;
    243     public:
    244       ///\e
    245    
    246       ///\e
    247       ///
    248       Tag(XmlReader &_ix,const std::string &_tag) :
    249         ix(_ix), tag(_tag)
    250       {
    251         ix.useTag(_tag);
    252       }
    253       ~Tag() {
    254         if(!std::uncaught_exception())
    255           ix.useTag('/'+tag);
    256       }
    257     };
    258 
    259     ///\e
    260  
    261     ///\e
    262     ///
    263     XmlReader(std::istream& _is) : is(_is), line_number(1) {}
    264  
    265     int operator()(const std::string &tag,int &v)
    266     {
    267       Tag t(*this,tag);
    268       skipWhiteSpaces();
    269       if(!(is >> v)) throw DataFormatError("",line_number,"Not an 'int'");
    270       return v;
    271     }
    272     double operator()(const std::string &tag,double &v)
    273     {
    274       Tag t(*this,tag);
    275       skipWhiteSpaces();
    276       if(!(is >> v))
    277         throw DataFormatError("",line_number,"Not a 'double'");
    278       return v;
    279     }
    280     std::string &operator()(const std::string &tag,std::string &v)
    281     {
    282       Tag t(*this,tag);
    283       v.clear();
    284       char c;
    285       while (is.get(c) && c!='<')
    286         if(c=='\\')
    287           if(!is.get(c))
    288             throw DataFormatError("",line_number,"Bad string");
    289           else switch(c) {
    290           case 'n':
    291             v.push_back('\n');
    292             break;
    293           default:
    294             v.push_back(c);
    295             break;
    296           }
    297         else {
    298           if(c=='\n') line_number++;
    299           v.push_back(c);
    300         }
    301       if(c!='<')
    302         throw DataFormatError("",line_number,"Unexpected eof");
    303       is.unget();
    304       return v;
    305     }
    306     ///\e
    307  
    308     ///\e
    309     ///
    310     template<class V>
    311     V &operator()(const std::string &tag,V &v)
    312     {
    313       Tag t(*this,tag);
    314       in(*this,v);
    315       return v;
    316     }
    317     ///\e
    318  
    319     ///\e
    320     ///
    321     template<class V>
    322     V &operator()(V &v)
    323     {
    324       in(*this,v);
    325       return v;
    326     }
    327     ///\e
    328  
    329     ///\e
    330     ///
    331     template<class V>
    332     V load(const std::string &tag)
    333     {
    334       Tag t(*this,tag);
    335       V v;
    336       (*this)(tag,v);
    337       return v;
    338     }
    339   };
    340 
    341332  //////////////////////////////////////////////////////////////////////
    342333
     334  ///\e
     335 
     336  ///\relates XmlIo
     337  ///
    343338  template<class A>
    344   void out(XmlWriter &x,const std::auto_ptr<A> &v)
    345   {
     339  void xml(XmlIo &x,std::auto_ptr<A> &v)
     340  {
     341    if(x.write()) v=new A;
    346342    x(*v);
    347343  }
    348 
    349   template<class A>
    350   void in(XmlReader &x,std::auto_ptr<A> &v)
    351   {
    352     v=new A;
    353     x(*v);
    354   }
    355 
    356   //////////////////////////////
    357 
     344 
     345  ///\e
     346 
     347  ///\relates XmlIo
     348  ///
    358349  template<class A,class B>
    359   void out(XmlWriter &x,const std::pair<A,B> &v)
     350  void xml(XmlIo &x,std::pair<A,B> &v)
    360351  {
    361352    x("first",v.first);
     
    363354  }
    364355
    365   template<class A,class B>
    366   void in(XmlReader &x,std::pair<A,B> &v)
    367   {
    368     x("first",v.first);
    369     x("second",v.second);
    370   }
    371 
    372   //////////////////////////////
    373 
     356  ///\e
     357 
     358  ///\relates XmlIo
     359  ///
    374360  template<class T>
    375   void out(XmlWriter &x,const std::list<T> &v)
    376   {
    377     for(typename std::list<T>::const_iterator it=v.begin();
    378         it!=v.end();++it) x("item",*it);
    379   }
    380 
    381   template<class T>
    382   void in(XmlReader &x,std::list<T> &v)
    383   {
    384     while(x.nextTag()=="item")
     361  void xml(XmlIo &x,std::list<T> &v)
     362  {
     363    if(x.write())
     364      for(typename std::list<T>::const_iterator it=v.begin();
     365          it!=v.end();++it) x("item",*it);
     366    else while(x.nextTag()=="item")
    385367      {
    386368        v.push_back(T());
     
    388370      }
    389371  }
    390 
    391   //////////////////////////////
    392 
     372  ///\e
     373 
     374  ///\relates XmlIo
     375  ///
    393376  template<class T>
    394   void out(XmlWriter &x,const std::vector<T> &v)
    395   {
    396     for(typename std::vector<T>::const_iterator it=v.begin();
    397         it!=v.end();++it) x("item",*it);
    398   }
    399 
    400   template<class T>
    401   void in(XmlReader &x,std::vector<T> &v)
    402   {
    403     while(x.nextTag()=="item")
     377  void xml(XmlIo &x,std::vector<T> &v)
     378  {
     379    if(x.write())
     380      for(typename std::vector<T>::const_iterator it=v.begin();
     381          it!=v.end();++it) x("item",*it);
     382    else while(x.nextTag()=="item")
    404383      {
    405384        v.push_back(T());
     
    408387  }
    409388
    410   //////////////////////////////
    411 
     389  ///\e
     390 
     391  ///\relates XmlIo
     392  ///
    412393  template<class K,class V>
    413   void out(XmlWriter &x,const std::map<K,V> &v)
    414   {
    415     for(typename std::map<K,V>::const_iterator it=v.begin();
    416         it!=v.end();++it) x("item",*it);
    417   }
    418 
    419   template<class K,class V>
    420   void in(XmlReader &x,std::map<K,V> &v)
    421   {
    422     while(x.nextTag()=="item")
     394  void xml(XmlIo &x,std::map<K,V> &v)
     395  {
     396    if(x.write())
     397      for(typename std::map<K,V>::const_iterator it=v.begin();
     398          it!=v.end();++it) x("item",*it);
     399    else while(x.nextTag()=="item")
    423400      {
    424401        typename std::map<K,V>::value_type it;
     
    428405  }
    429406
    430   //////////////////////////////
    431 
     407  ///\e
     408 
     409  ///\relates XmlIo
     410  ///
    432411  template<class T>
    433   void out(XmlWriter &x,const lemon::xy<T> &v)
    434   {
    435     //   x("x",v.x);
    436     //   x("y",v.y);
    437     { XmlWriter::LineTag t(x,"x"); x(v.x); }
    438     { XmlWriter::ContTag t(x,"y"); x(v.y); }
    439   }
    440 
     412  void xml(XmlIo &x,lemon::xy<T> &v)
     413  {
     414    { XmlIo::LineTag t(x,"x"); x(v.x); }
     415    { XmlIo::ContTag t(x,"y"); x(v.y); }
     416  }
     417
     418  ///\e
     419 
     420  ///\relates XmlIo
     421  ///
    441422  template<class T>
    442   void in(XmlReader &x,lemon::xy<T> &v)
    443   {
    444     x("x",v.x);
    445     x("y",v.y);
    446   }
    447 
    448   //////////////////////////////
    449 
    450   template<class T>
    451   void out(XmlWriter &x,const lemon::BoundingBox<T> &v)
    452   {
    453     if(!v.empty()) {
    454       x("point",v.bottomLeft());
    455       if(v.bottomLeft()!=v.topRight()) x("point",v.topRight());
    456     }
    457   }
    458 
    459   template<class T>
    460   void in(XmlReader &x,lemon::BoundingBox<T> &v)
    461   {
    462     v.clear();
    463     while(x.nextTag()=="point") {
    464       lemon::xy<T> co;
    465       x("point",co);
    466       v.add(co);
     423  void xml(XmlIo &x,lemon::BoundingBox<T> &v)
     424  {
     425    if(x.write()) {
     426      if(!v.empty()) {
     427        x("point",v.bottomLeft());
     428        if(v.bottomLeft()!=v.topRight()) x("point",v.topRight());
     429      }
     430    }
     431    else {
     432      v.clear();
     433      while(x.nextTag()=="point") {
     434        lemon::xy<T> co;
     435        x("point",co);
     436        v.add(co);
     437      }
    467438    }
    468439  }
    469440 
    470441}
     442
Note: See TracChangeset for help on using the changeset viewer.