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