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