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