xml.h
author ladanyi
Fri, 29 Jul 2005 12:30:28 +0000
branchgui
changeset 54 9128e364fb19
parent 2 358b707800b8
child 83 6c0db51a1d99
permissions -rw-r--r--
small fix
alpar@2
     1
/* -*- C++ -*- */
alpar@2
     2
alpar@2
     3
#include <iostream>
alpar@2
     4
#include <string>
alpar@2
     5
#include <vector>
alpar@2
     6
#include <list>
alpar@2
     7
#include <map>
alpar@39
     8
#include <lemon/error.h>
alpar@2
     9
#include <lemon/xy.h>
alpar@2
    10
alpar@39
    11
namespace lemon {
alpar@2
    12
alpar@39
    13
  class XmlWriter 
alpar@39
    14
  {
alpar@39
    15
    std::ostream& os;
alpar@39
    16
    int level;
alpar@2
    17
alpar@39
    18
  protected:
alpar@39
    19
    void indent(int level) {
alpar@39
    20
      os << std::endl;
alpar@39
    21
      for(int i=0;i<level;i++) os << ' ';
alpar@39
    22
    }
alpar@39
    23
    void tag(const std::string &_tag) {
alpar@39
    24
      os << '<' << _tag << '>';
alpar@39
    25
    }
alpar@39
    26
    void etag(const std::string &_tag) {
alpar@39
    27
      os << "</" << _tag << '>';
alpar@39
    28
    }
alpar@39
    29
    void itag(const std::string &_tag) { indent();tag(_tag); }
alpar@39
    30
    void ietag(const std::string &_tag) { indent();etag(_tag); }
alpar@2
    31
alpar@39
    32
    void beginTag(const std::string &_tag) {
alpar@39
    33
      itag(_tag);
alpar@39
    34
      level++;
alpar@39
    35
    }
alpar@39
    36
    void endTag(const std::string &_tag) {
alpar@39
    37
      level--;
alpar@39
    38
      ietag(_tag);
alpar@39
    39
    }
alpar@2
    40
alpar@39
    41
  public:
alpar@39
    42
alpar@39
    43
    void indent() 
alpar@39
    44
    {
alpar@39
    45
      if(level>=0) indent(level);
alpar@39
    46
      else level=0;
alpar@39
    47
    }
alpar@2
    48
  
alpar@39
    49
    ///\e
alpar@2
    50
  
alpar@39
    51
    ///\e
alpar@39
    52
    ///
alpar@39
    53
    class ContTag
alpar@39
    54
    {
alpar@39
    55
      XmlWriter &ix;
alpar@39
    56
      const std::string _tag;
alpar@39
    57
    public:
alpar@39
    58
      ///\e
alpar@2
    59
  
alpar@39
    60
      ///\e
alpar@39
    61
      ///
alpar@39
    62
      ContTag(XmlWriter &_ix,const std::string &_t) :
alpar@39
    63
	ix(_ix), _tag(_t)
alpar@39
    64
      {
alpar@39
    65
	ix.tag(_tag);
alpar@39
    66
      }
alpar@39
    67
      ~ContTag() { ix.etag(_tag);}
alpar@39
    68
    };
alpar@39
    69
alpar@39
    70
    class LineTag
alpar@2
    71
    {
alpar@39
    72
      XmlWriter &ix;
alpar@39
    73
      const std::string _tag;
alpar@39
    74
    public:
alpar@39
    75
      ///\e
alpar@39
    76
    
alpar@39
    77
      ///\e
alpar@39
    78
      ///
alpar@39
    79
      LineTag(XmlWriter &_ix,const std::string &_t) :
alpar@39
    80
	ix(_ix), _tag(_t)
alpar@39
    81
      {
alpar@39
    82
	ix.itag(_tag);
alpar@39
    83
      }
alpar@39
    84
      ~LineTag() { ix.etag(_tag);}
alpar@39
    85
    };
alpar@39
    86
alpar@39
    87
    ///\e
alpar@39
    88
  
alpar@39
    89
    ///\e
alpar@39
    90
    ///
alpar@39
    91
    class Tag
alpar@39
    92
    {
alpar@39
    93
      XmlWriter &ix;
alpar@39
    94
      const std::string _tag;
alpar@39
    95
    public:
alpar@39
    96
      ///\e
alpar@39
    97
  
alpar@39
    98
      ///\e
alpar@39
    99
      ///
alpar@39
   100
      Tag(XmlWriter &_ix,const std::string &_t) :
alpar@39
   101
	ix(_ix), _tag(_t)
alpar@39
   102
      {
alpar@39
   103
	ix.beginTag(_tag);
alpar@39
   104
      }
alpar@39
   105
      ~Tag() { 
alpar@39
   106
	ix.endTag(_tag);
alpar@39
   107
      }
alpar@39
   108
    };
alpar@39
   109
      
alpar@39
   110
    ///\e
alpar@39
   111
  
alpar@39
   112
    ///\e
alpar@39
   113
    ///
alpar@39
   114
    XmlWriter(std::ostream& _os) : os(_os),level(-1) {}
alpar@39
   115
    ~XmlWriter() { os<< std::endl; }
alpar@39
   116
  
alpar@39
   117
    XmlWriter &operator()(int v) 
alpar@39
   118
    { 
alpar@39
   119
      os << v;
alpar@39
   120
      return *this;
alpar@2
   121
    }
alpar@39
   122
    XmlWriter &operator()(const std::string &_tag,int v) 
alpar@39
   123
    { 
alpar@39
   124
      LineTag t(*this,_tag);
alpar@39
   125
      (*this)(v);
alpar@39
   126
      return *this;
alpar@39
   127
    }
alpar@39
   128
    XmlWriter &operator()(double v) 
alpar@39
   129
    {
alpar@39
   130
      os << v;
alpar@39
   131
      return *this;
alpar@39
   132
    }
alpar@39
   133
    XmlWriter &operator()(const std::string &_tag,double v) 
alpar@39
   134
    {
alpar@39
   135
      LineTag t(*this,_tag);
alpar@39
   136
      (*this)(v);
alpar@39
   137
      return *this;
alpar@39
   138
    }
alpar@39
   139
    XmlWriter &operator()(const std::string &v)
alpar@39
   140
    {
alpar@39
   141
      for(std::string::const_iterator i=v.begin();i!=v.end();++i)
alpar@39
   142
	switch(*i) {
alpar@39
   143
	case '\\':
alpar@39
   144
	  os << "\\\\";
alpar@39
   145
	  break;
alpar@39
   146
	case '<':
alpar@39
   147
	  os << "\\<";
alpar@39
   148
	  break;
alpar@39
   149
	case '&':
alpar@39
   150
	  os << "\\&";
alpar@39
   151
	  break;
alpar@39
   152
	case '\n':
alpar@39
   153
	  os << "\\n";
alpar@39
   154
	  break;
alpar@39
   155
	default:
alpar@39
   156
	  os<<*i;
alpar@39
   157
	  break;
alpar@39
   158
	}
alpar@39
   159
      return *this;
alpar@39
   160
    }
alpar@39
   161
    XmlWriter &operator()(const std::string &_tag,const std::string &v)
alpar@39
   162
    {
alpar@39
   163
      LineTag t(*this,_tag);
alpar@39
   164
      (*this)(v);
alpar@39
   165
      return *this;
alpar@39
   166
    }
alpar@39
   167
    ///\e
alpar@39
   168
  
alpar@39
   169
    ///\e
alpar@39
   170
    ///
alpar@39
   171
    template<class V>
alpar@39
   172
    XmlWriter &operator()(const std::string &_tag,const V &v)
alpar@39
   173
    {
alpar@39
   174
      Tag t(*this,_tag);
alpar@39
   175
      out(*this,v);
alpar@39
   176
      return *this;
alpar@39
   177
    }
alpar@39
   178
    ///\e
alpar@39
   179
  
alpar@39
   180
    ///\e
alpar@39
   181
    ///
alpar@39
   182
    template<class V>
alpar@39
   183
    XmlWriter &operator()(const V &v)
alpar@39
   184
    {
alpar@39
   185
      out(*this,v);
alpar@39
   186
      return *this;
alpar@39
   187
    }
alpar@2
   188
  };
alpar@2
   189
alpar@39
   190
  //////////////////////////////////////////////////////////////////////
alpar@39
   191
alpar@39
   192
  class XmlReader 
alpar@2
   193
  {
alpar@39
   194
    std::istream& is;
alpar@39
   195
    std::string next_tag;
alpar@39
   196
    int line_number;
alpar@39
   197
alpar@39
   198
    void skipWhiteSpaces()
alpar@39
   199
    {
alpar@39
   200
      char c;
alpar@39
   201
      while (is.get(c) && std::isspace(c,is.getloc())) if(c=='\n') line_number++;
alpar@39
   202
      is.unget();
alpar@39
   203
    }
alpar@39
   204
  protected:
alpar@2
   205
    ///\e
alpar@39
   206
  
alpar@2
   207
    ///\e
alpar@2
   208
    ///
alpar@39
   209
    void useTag() {next_tag.clear();}
alpar@39
   210
  
alpar@39
   211
    void useTag(const std::string &_tag) {
alpar@39
   212
      if(nextTag()==_tag) useTag();
alpar@39
   213
      else throw DataFormatError("",line_number,"Unexpected token name");
alpar@2
   214
    }
alpar@2
   215
  public:
alpar@2
   216
    ///\e
alpar@2
   217
  
alpar@2
   218
    ///\e
alpar@2
   219
    ///
alpar@39
   220
    const std::string &nextTag() 
alpar@2
   221
    {
alpar@39
   222
      if(next_tag.empty()) {
alpar@39
   223
	char c;
alpar@39
   224
	skipWhiteSpaces();
alpar@39
   225
	if(!is.get(c) || c!='<')
alpar@39
   226
	  throw DataFormatError("",line_number,"Bad token");
alpar@39
   227
	next_tag.clear();
alpar@39
   228
	while (is.get(c) && c!='>') next_tag.push_back(c);
alpar@39
   229
	if(c!='>')
alpar@39
   230
	  throw DataFormatError("",line_number,"Bad token");
alpar@39
   231
      }
alpar@39
   232
      return next_tag;
alpar@2
   233
    }
alpar@2
   234
  
alpar@39
   235
    ///\e
alpar@2
   236
  
alpar@2
   237
    ///\e
alpar@2
   238
    ///
alpar@39
   239
    class Tag
alpar@2
   240
    {
alpar@39
   241
      XmlReader &ix;
alpar@39
   242
      const std::string tag;
alpar@39
   243
    public:
alpar@39
   244
      ///\e
alpar@39
   245
    
alpar@39
   246
      ///\e
alpar@39
   247
      ///
alpar@39
   248
      Tag(XmlReader &_ix,const std::string &_tag) :
alpar@39
   249
	ix(_ix), tag(_tag)
alpar@39
   250
      {
alpar@39
   251
	ix.useTag(_tag);
alpar@39
   252
      }
alpar@39
   253
      ~Tag() {
alpar@39
   254
	if(!std::uncaught_exception()) 
alpar@39
   255
	  ix.useTag('/'+tag);
alpar@39
   256
      }
alpar@39
   257
    };
alpar@39
   258
alpar@39
   259
    ///\e
alpar@39
   260
  
alpar@39
   261
    ///\e
alpar@39
   262
    ///
alpar@39
   263
    XmlReader(std::istream& _is) : is(_is), line_number(1) {}
alpar@39
   264
  
alpar@39
   265
    int operator()(const std::string &tag,int &v)
alpar@39
   266
    { 
alpar@39
   267
      Tag t(*this,tag);
alpar@39
   268
      skipWhiteSpaces();
alpar@39
   269
      if(!(is >> v)) throw DataFormatError("",line_number,"Not an 'int'");
alpar@39
   270
      return v;
alpar@2
   271
    }
alpar@39
   272
    double operator()(const std::string &tag,double &v) 
alpar@39
   273
    {
alpar@39
   274
      Tag t(*this,tag);
alpar@39
   275
      skipWhiteSpaces();
alpar@39
   276
      if(!(is >> v))
alpar@39
   277
	throw DataFormatError("",line_number,"Not a 'double'");
alpar@39
   278
      return v;
alpar@39
   279
    }
alpar@39
   280
    std::string &operator()(const std::string &tag,std::string &v)
alpar@39
   281
    {
alpar@39
   282
      Tag t(*this,tag);
alpar@39
   283
      v.clear();
alpar@39
   284
      char c;
alpar@39
   285
      while (is.get(c) && c!='<')
alpar@39
   286
	if(c=='\\')
alpar@39
   287
	  if(!is.get(c))
alpar@39
   288
	    throw DataFormatError("",line_number,"Bad string");
alpar@39
   289
	  else switch(c) {
alpar@39
   290
	  case 'n':
alpar@39
   291
	    v.push_back('\n');
alpar@39
   292
	    break;
alpar@39
   293
	  default:
alpar@39
   294
	    v.push_back(c);
alpar@39
   295
	    break;
alpar@39
   296
	  }
alpar@39
   297
	else {
alpar@39
   298
	  if(c=='\n') line_number++;
alpar@39
   299
	  v.push_back(c);
alpar@39
   300
	}
alpar@39
   301
      if(c!='<')
alpar@39
   302
	throw DataFormatError("",line_number,"Unexpected eof");
alpar@39
   303
      is.unget();
alpar@39
   304
      return v;
alpar@39
   305
    }
alpar@39
   306
    ///\e
alpar@39
   307
  
alpar@39
   308
    ///\e
alpar@39
   309
    ///
alpar@39
   310
    template<class V>
alpar@39
   311
    V &operator()(const std::string &tag,V &v)
alpar@39
   312
    {
alpar@39
   313
      Tag t(*this,tag);
alpar@39
   314
      in(*this,v);
alpar@39
   315
      return v;
alpar@39
   316
    }
alpar@39
   317
    ///\e
alpar@39
   318
  
alpar@39
   319
    ///\e
alpar@39
   320
    ///
alpar@39
   321
    template<class V>
alpar@39
   322
    V &operator()(V &v)
alpar@39
   323
    {
alpar@39
   324
      in(*this,v);
alpar@39
   325
      return v;
alpar@39
   326
    }
alpar@39
   327
    ///\e
alpar@39
   328
  
alpar@39
   329
    ///\e
alpar@39
   330
    ///
alpar@39
   331
    template<class V>
alpar@39
   332
    V load(const std::string &tag)
alpar@39
   333
    {
alpar@39
   334
      Tag t(*this,tag);
alpar@39
   335
      V v;
alpar@39
   336
      (*this)(tag,v);
alpar@39
   337
      return v;
alpar@2
   338
    }
alpar@2
   339
  };
alpar@2
   340
alpar@39
   341
  //////////////////////////////////////////////////////////////////////
alpar@39
   342
alpar@39
   343
  template<class A>
alpar@39
   344
  void out(XmlWriter &x,const std::auto_ptr<A> &v)
alpar@39
   345
  {
alpar@39
   346
    x(*v);
alpar@39
   347
  }
alpar@39
   348
alpar@39
   349
  template<class A>
alpar@39
   350
  void in(XmlReader &x,std::auto_ptr<A> &v)
alpar@39
   351
  {
alpar@39
   352
    v=new A;
alpar@39
   353
    x(*v);
alpar@39
   354
  }
alpar@39
   355
alpar@39
   356
  //////////////////////////////
alpar@39
   357
alpar@39
   358
  template<class A,class B>
alpar@39
   359
  void out(XmlWriter &x,const std::pair<A,B> &v)
alpar@39
   360
  {
alpar@39
   361
    x("first",v.first);
alpar@39
   362
    x("second",v.second);
alpar@39
   363
  }
alpar@39
   364
alpar@39
   365
  template<class A,class B>
alpar@39
   366
  void in(XmlReader &x,std::pair<A,B> &v)
alpar@39
   367
  {
alpar@39
   368
    x("first",v.first);
alpar@39
   369
    x("second",v.second);
alpar@39
   370
  }
alpar@39
   371
alpar@39
   372
  //////////////////////////////
alpar@39
   373
alpar@39
   374
  template<class T>
alpar@39
   375
  void out(XmlWriter &x,const std::list<T> &v)
alpar@39
   376
  {
alpar@39
   377
    for(typename std::list<T>::const_iterator it=v.begin();
alpar@39
   378
	it!=v.end();++it) x("item",*it);
alpar@39
   379
  }
alpar@39
   380
alpar@39
   381
  template<class T>
alpar@39
   382
  void in(XmlReader &x,std::list<T> &v)
alpar@39
   383
  {
alpar@39
   384
    while(x.nextTag()=="item")
alpar@39
   385
      {
alpar@39
   386
	v.push_back(T());
alpar@39
   387
	x("item",v.back());
alpar@39
   388
      }
alpar@39
   389
  }
alpar@39
   390
alpar@39
   391
  //////////////////////////////
alpar@39
   392
alpar@39
   393
  template<class T>
alpar@39
   394
  void out(XmlWriter &x,const std::vector<T> &v)
alpar@39
   395
  {
alpar@39
   396
    for(typename std::vector<T>::const_iterator it=v.begin();
alpar@39
   397
	it!=v.end();++it) x("item",*it);
alpar@39
   398
  }
alpar@39
   399
alpar@39
   400
  template<class T>
alpar@39
   401
  void in(XmlReader &x,std::vector<T> &v)
alpar@39
   402
  {
alpar@39
   403
    while(x.nextTag()=="item")
alpar@39
   404
      {
alpar@39
   405
	v.push_back(T());
alpar@39
   406
	x("item",v.back());      
alpar@39
   407
      }
alpar@39
   408
  }
alpar@39
   409
alpar@39
   410
  //////////////////////////////
alpar@39
   411
alpar@39
   412
  template<class K,class V>
alpar@39
   413
  void out(XmlWriter &x,const std::map<K,V> &v)
alpar@39
   414
  {
alpar@39
   415
    for(typename std::map<K,V>::const_iterator it=v.begin();
alpar@39
   416
	it!=v.end();++it) x("item",*it);
alpar@39
   417
  }
alpar@39
   418
alpar@39
   419
  template<class K,class V>
alpar@39
   420
  void in(XmlReader &x,std::map<K,V> &v)
alpar@39
   421
  {
alpar@39
   422
    while(x.nextTag()=="item")
alpar@39
   423
      {
alpar@39
   424
	typename std::map<K,V>::value_type it;
alpar@39
   425
	x("item",it);
alpar@39
   426
	v.insert(it);
alpar@39
   427
      }
alpar@39
   428
  }
alpar@39
   429
alpar@39
   430
  //////////////////////////////
alpar@39
   431
alpar@39
   432
  template<class T>
alpar@39
   433
  void out(XmlWriter &x,const lemon::xy<T> &v)
alpar@39
   434
  {
alpar@39
   435
    //   x("x",v.x);
alpar@39
   436
    //   x("y",v.y);
alpar@39
   437
    { XmlWriter::LineTag t(x,"x"); x(v.x); }
alpar@39
   438
    { XmlWriter::ContTag t(x,"y"); x(v.y); }
alpar@39
   439
  }
alpar@39
   440
alpar@39
   441
  template<class T>
alpar@39
   442
  void in(XmlReader &x,lemon::xy<T> &v)
alpar@39
   443
  {
alpar@39
   444
    x("x",v.x);
alpar@39
   445
    x("y",v.y);
alpar@39
   446
  }
alpar@39
   447
alpar@39
   448
  //////////////////////////////
alpar@39
   449
alpar@39
   450
  template<class T>
alpar@39
   451
  void out(XmlWriter &x,const lemon::BoundingBox<T> &v)
alpar@39
   452
  {
alpar@39
   453
    if(!v.empty()) {
alpar@39
   454
      x("point",v.bottomLeft());
alpar@39
   455
      if(v.bottomLeft()!=v.topRight()) x("point",v.topRight());
alpar@39
   456
    }
alpar@39
   457
  }
alpar@39
   458
alpar@39
   459
  template<class T>
alpar@39
   460
  void in(XmlReader &x,lemon::BoundingBox<T> &v)
alpar@39
   461
  {
alpar@39
   462
    v.clear();
alpar@39
   463
    while(x.nextTag()=="point") {
alpar@39
   464
      lemon::xy<T> co;
alpar@39
   465
      x("point",co);
alpar@39
   466
      v.add(co);
alpar@39
   467
    }
alpar@39
   468
  }
alpar@2
   469
  
alpar@2
   470
}