lemon/lemon_reader.h
author athos
Thu, 26 May 2005 15:33:16 +0000
changeset 1438 826bdac3525a
parent 1429 4283998fb2be
child 1476 182da222fceb
permissions -rw-r--r--
Some documentation got revised.
deba@1408
     1
/* -*- C++ -*-
ladanyi@1435
     2
 * lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library
deba@1408
     3
 *
deba@1408
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1408
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1408
     6
 *
deba@1408
     7
 * Permission to use, modify and distribute this software is granted
deba@1408
     8
 * provided that this copyright notice appears in all copies. For
deba@1408
     9
 * precise terms see the accompanying LICENSE file.
deba@1408
    10
 *
deba@1408
    11
 * This software is provided "AS IS" with no warranty of any kind,
deba@1408
    12
 * express or implied, and with no claim as to its suitability for any
deba@1408
    13
 * purpose.
deba@1408
    14
 *
deba@1408
    15
 */
deba@1408
    16
deba@1408
    17
///\ingroup io_group
deba@1408
    18
///\file
deba@1408
    19
///\brief Lemon Format reader.
deba@1408
    20
deba@1421
    21
deba@1408
    22
#ifndef LEMON_LEMON_READER_H
deba@1408
    23
#define LEMON_LEMON_READER_H
deba@1408
    24
deba@1421
    25
deba@1408
    26
#include <iostream>
deba@1408
    27
#include <fstream>
deba@1408
    28
#include <string>
deba@1408
    29
#include <vector>
deba@1408
    30
#include <algorithm>
deba@1408
    31
#include <map>
deba@1408
    32
#include <memory>
deba@1408
    33
deba@1408
    34
#include <lemon/error.h>
deba@1421
    35
#include <lemon/graph_utils.h>
deba@1421
    36
#include <lemon/utility.h>
deba@1409
    37
#include <lemon/bits/item_reader.h>
deba@1408
    38
deba@1408
    39
deba@1408
    40
namespace lemon {
deba@1408
    41
deba@1421
    42
  namespace _reader_bits {
deba@1421
    43
  
deba@1421
    44
    template <typename T>
deba@1421
    45
    bool operator<(T, T) {
deba@1421
    46
      throw DataFormatError("Id is not comparable");
deba@1421
    47
    }
deba@1421
    48
deba@1421
    49
    template <typename T>
deba@1421
    50
    struct Less {
deba@1421
    51
      bool operator()(const T& p, const T& q) const {
deba@1421
    52
	return p < q;
deba@1421
    53
      }
deba@1421
    54
    };
deba@1421
    55
deba@1421
    56
    template <typename M1, typename M2>
deba@1421
    57
    class WriteComposeMap {
deba@1421
    58
    public:
deba@1421
    59
      typedef True NeedCopy;
deba@1421
    60
      
deba@1421
    61
      typedef typename M2::Key Key;
deba@1421
    62
      typedef typename M1::Value Value;
deba@1421
    63
deba@1421
    64
      WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2) 
deba@1421
    65
	: m1(_m1), m2(_m2) {}
deba@1421
    66
      
deba@1421
    67
      void set(const Key& key, const Value& value) {
deba@1421
    68
	m1.set(m2[key], value);
deba@1421
    69
      }
deba@1421
    70
deba@1421
    71
    private:
deba@1421
    72
      
deba@1421
    73
      typename SmartReference<M1>::Type m1;
deba@1421
    74
      typename SmartConstReference<M2>::Type m2;
deba@1421
    75
      
deba@1421
    76
    };
deba@1421
    77
deba@1421
    78
    template <typename M1, typename M2>
deba@1421
    79
    WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) {
deba@1421
    80
      return WriteComposeMap<M1, M2>(m1, m2);
deba@1421
    81
    }
deba@1421
    82
deba@1421
    83
    template <typename M1, typename M2>
deba@1421
    84
    WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) {
deba@1421
    85
      return WriteComposeMap<M1, M2>(m1, m2);
deba@1421
    86
    }
deba@1421
    87
  
deba@1421
    88
  }
deba@1421
    89
deba@1409
    90
  /// \ingroup io_group
deba@1408
    91
  /// \brief Lemon Format reader class.
deba@1408
    92
  /// 
deba@1409
    93
  /// The Lemon Format contains several sections. We do not want to
deba@1409
    94
  /// determine what sections are in a lemon file we give only a framework
deba@1409
    95
  /// to read a section oriented format.
deba@1409
    96
  ///
deba@1409
    97
  /// In the Lemon Format each section starts with a line contains a \c \@
deba@1409
    98
  /// character on the first not white space position. This line is the
deba@1409
    99
  /// header line of the section. Each next lines belong to this section
deba@1409
   100
  /// while it does not starts with \c \@ character. This line can start a 
deba@1409
   101
  /// new section or if it can close the file with the \c \@end line.
deba@1427
   102
  /// The file format ignore the empty and comment lines. The line is
deba@1427
   103
  /// comment line if it starts with a \c # character. 
deba@1409
   104
  ///
deba@1409
   105
  /// The framework provides an abstract LemonReader::SectionReader class
deba@1409
   106
  /// what defines the interface of a SectionReader. The SectionReader
deba@1409
   107
  /// has the \c header() member function what get a header line string and
deba@1409
   108
  /// decides if it want to process the next section. Several SectionReaders
deba@1409
   109
  /// can be attached to an LemonReader and the first attached what can
deba@1409
   110
  /// process the section will be used. Its \c read() member will called
deba@1427
   111
  /// with a stream contains the section. From this stream the empty and
deba@1427
   112
  /// comment lines are filtered out.
deba@1409
   113
  ///
deba@1409
   114
  /// \relates GraphReader
deba@1409
   115
  /// \relates NodeSetReader
deba@1409
   116
  /// \relates EdgeSetReader
deba@1409
   117
  /// \relates NodesReader
deba@1409
   118
  /// \relates EdgesReader
deba@1409
   119
  /// \relates AttributeReader
deba@1408
   120
  class LemonReader {
deba@1408
   121
  private:
deba@1408
   122
    
deba@1408
   123
    class FilterStreamBuf : public std::streambuf {
deba@1408
   124
    public:
deba@1408
   125
deba@1408
   126
      typedef std::streambuf Parent;
deba@1408
   127
      typedef Parent::char_type char_type;
deba@1408
   128
      FilterStreamBuf(std::istream& is, int& num) 
deba@1408
   129
	: _is(is), _base(0), _eptr(0), 
deba@1408
   130
	  _num(num), skip_state(after_endl) {}
deba@1408
   131
deba@1408
   132
    protected:
deba@1408
   133
deba@1408
   134
      enum skip_state_type {
deba@1408
   135
	no_skip,
deba@1408
   136
	after_endl,
deba@1427
   137
	comment_line
deba@1408
   138
      };
deba@1408
   139
deba@1408
   140
      char_type small_buf[1];
deba@1408
   141
deba@1408
   142
deba@1408
   143
      std::istream& _is;
deba@1408
   144
deba@1408
   145
      char_type* _base;
deba@1408
   146
      char_type* _eptr;
deba@1408
   147
deba@1408
   148
      int& _num;
deba@1408
   149
deba@1408
   150
      skip_state_type skip_state;
deba@1408
   151
deba@1408
   152
deba@1408
   153
      char_type* base() { return _base; }
deba@1408
   154
deba@1408
   155
      char_type* eptr() { return _eptr; }
deba@1408
   156
deba@1408
   157
      int blen() { return _eptr - _base; }
deba@1408
   158
deba@1408
   159
      void setb(char_type* buf, int len) {
deba@1408
   160
	_base = buf;
deba@1408
   161
	_eptr = buf + len;
deba@1408
   162
      }
deba@1408
   163
  
deba@1408
   164
      virtual std::streambuf* setbuf(char *buf, int len) {
deba@1408
   165
	if (base()) return 0;
deba@1408
   166
	if (buf != 0 && len >= (int)sizeof(small_buf)) {
deba@1408
   167
	  setb(buf, len);
deba@1408
   168
	} else {
deba@1408
   169
	  setb(small_buf, sizeof(small_buf));
deba@1408
   170
	}
deba@1408
   171
	setg(0, 0, 0);
deba@1408
   172
	return this;
deba@1408
   173
      }
deba@1408
   174
deba@1408
   175
      bool put_char(char c) {
deba@1408
   176
	switch (skip_state) {
deba@1408
   177
	case no_skip:
deba@1408
   178
	  switch (c) {
deba@1408
   179
	  case '\n': 
deba@1408
   180
	    skip_state = after_endl;
deba@1408
   181
	    return true;
deba@1408
   182
	  default:
deba@1408
   183
	    return true;
deba@1408
   184
	  }
deba@1408
   185
	case after_endl:
deba@1408
   186
	  switch (c) {
deba@1408
   187
	  case '@':
deba@1408
   188
	    return false;
deba@1408
   189
	  case '\n': 
deba@1408
   190
	    return false;
deba@1408
   191
	  case '#':
deba@1427
   192
	    skip_state = comment_line;
deba@1408
   193
	    return false;
deba@1408
   194
	  default:
deba@1408
   195
	    if (!isspace(c)) {
deba@1408
   196
	      skip_state = no_skip;
deba@1408
   197
	      return true;
deba@1408
   198
	    } else {
deba@1408
   199
	      return false;
deba@1408
   200
	    }
deba@1408
   201
	  }
deba@1408
   202
	  break;
deba@1427
   203
	case comment_line:
deba@1408
   204
	  switch (c) {
deba@1408
   205
	  case '\n': 
deba@1408
   206
	    skip_state = after_endl;
deba@1408
   207
	    return false;
deba@1408
   208
	  default:
deba@1408
   209
	    return false;
deba@1408
   210
	  }
deba@1408
   211
	}
deba@1408
   212
	return false;
deba@1408
   213
      }
deba@1408
   214
deba@1408
   215
      virtual int underflow() {
deba@1408
   216
	char c;
deba@1408
   217
	if (_is.read(&c, 1)) {
deba@1408
   218
	  _is.putback(c);
deba@1408
   219
	  if (c == '@') {
deba@1408
   220
	    return EOF;
deba@1408
   221
	  }
deba@1408
   222
	} else {
deba@1408
   223
	  return EOF;
deba@1408
   224
	}
deba@1408
   225
	char_type *ptr;
deba@1408
   226
	for (ptr = base(); ptr != eptr(); ++ptr) {
deba@1408
   227
	  if (_is.read(&c, 1)) {
deba@1408
   228
	    if (c == '\n') ++_num;
deba@1408
   229
	    if (put_char(c)) {
deba@1408
   230
	      *ptr = c;
deba@1408
   231
	    } else {
deba@1408
   232
	      if (skip_state == after_endl && c == '@') {
deba@1408
   233
		_is.putback('@');
deba@1408
   234
		break;
deba@1408
   235
	      }
deba@1408
   236
	      --ptr;
deba@1408
   237
	    }
deba@1408
   238
	  } else {
deba@1408
   239
	    break;
deba@1408
   240
	  }
deba@1408
   241
	}
deba@1408
   242
	setg(base(), base(), ptr);
deba@1408
   243
	return *base();
deba@1408
   244
      }
deba@1408
   245
deba@1408
   246
      virtual int sync() {
deba@1408
   247
	return EOF;
deba@1408
   248
      }
deba@1408
   249
    };
deba@1408
   250
deba@1408
   251
  public:
deba@1408
   252
deba@1409
   253
    /// \brief Abstract base class for reading a section.
deba@1409
   254
    ///
deba@1409
   255
    /// This class has an \c header() member function what get a 
deba@1409
   256
    /// header line string and decides if it want to process the next 
deba@1409
   257
    /// section. Several SectionReaders can be attached to an LemonReader 
deba@1409
   258
    /// and the first attached what can process the section will be used. 
deba@1409
   259
    /// Its \c read() member will called with a stream contains the section. 
deba@1409
   260
    /// From this stream the empty lines and comments are filtered out.
deba@1408
   261
    class SectionReader {
deba@1409
   262
      friend class LemonReader;
deba@1409
   263
    protected:
deba@1409
   264
      /// \brief Constructor for SectionReader.
deba@1409
   265
      ///
deba@1409
   266
      /// Constructor for SectionReader. It attach this reader to
deba@1409
   267
      /// the given LemonReader.
deba@1409
   268
      SectionReader(LemonReader& reader) {
deba@1409
   269
	reader.attach(*this);
deba@1409
   270
      }
deba@1409
   271
deba@1409
   272
      /// \brief Gives back true when the SectionReader can process 
deba@1409
   273
      /// the section with the given header line.
deba@1409
   274
      ///
deba@1409
   275
      /// It gives back true when the SectionReader can process
deba@1409
   276
      /// the section with the given header line.
deba@1408
   277
      virtual bool header(const std::string& line) = 0;
deba@1409
   278
deba@1409
   279
      /// \brief Reader function of the section.
deba@1409
   280
      ///
deba@1409
   281
      /// It reads the content of the section.
deba@1408
   282
      virtual void read(std::istream& is) = 0;
deba@1408
   283
    };
deba@1408
   284
deba@1409
   285
    /// \brief Constructor for LemonReader.
deba@1409
   286
    ///
deba@1409
   287
    /// Constructor for LemonReader which reads from the given stream.
deba@1408
   288
    LemonReader(std::istream& _is) 
deba@1408
   289
      : is(&_is), own_is(false) {}
deba@1408
   290
deba@1409
   291
    /// \brief Constructor for LemonReader.
deba@1409
   292
    ///
deba@1409
   293
    /// Constructor for LemonReader which reads from the given file.
deba@1408
   294
    LemonReader(const std::string& filename) 
deba@1408
   295
      : is(0), own_is(true) {
deba@1408
   296
      is = new std::ifstream(filename.c_str());
deba@1408
   297
    }
deba@1408
   298
deba@1409
   299
    /// \brief Desctructor for LemonReader.
deba@1409
   300
    ///
deba@1409
   301
    /// Desctructor for LemonReader.
deba@1408
   302
    ~LemonReader() {
deba@1408
   303
      if (own_is) {
deba@1408
   304
	delete is;
deba@1408
   305
      }
deba@1408
   306
    }
deba@1408
   307
deba@1408
   308
  private:
deba@1408
   309
    LemonReader(const LemonReader&);
deba@1408
   310
    void operator=(const LemonReader&);
deba@1408
   311
deba@1408
   312
    void attach(SectionReader& reader) {
deba@1408
   313
      readers.push_back(&reader);
deba@1408
   314
    }
deba@1408
   315
deba@1409
   316
  public:
deba@1409
   317
    /// \brief Executes the LemonReader.
deba@1409
   318
    /// 
deba@1409
   319
    /// It executes the LemonReader.
deba@1408
   320
    void run() {
deba@1408
   321
      int line_num = 0;
deba@1408
   322
      std::string line;
deba@1408
   323
      try {
deba@1408
   324
	while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
deba@1408
   325
	  SectionReaders::iterator it;
deba@1408
   326
	  for (it = readers.begin(); it != readers.end(); ++it) {
deba@1408
   327
	    if ((*it)->header(line)) {
deba@1408
   328
	      char buf[2048];
deba@1408
   329
	      FilterStreamBuf buffer(*is, line_num);
deba@1408
   330
	      buffer.pubsetbuf(buf, sizeof(buf));
deba@1408
   331
	      std::istream is(&buffer);
deba@1408
   332
	      (*it)->read(is);
deba@1408
   333
	      break;
deba@1408
   334
	    }
deba@1408
   335
	  }
deba@1408
   336
	}
deba@1408
   337
      } catch (DataFormatError& error) {
deba@1408
   338
	error.line(line_num);
deba@1408
   339
	throw error;
deba@1408
   340
      }	
deba@1408
   341
    }
deba@1408
   342
deba@1408
   343
deba@1408
   344
  private:
deba@1408
   345
deba@1408
   346
    std::istream* is;
deba@1408
   347
    bool own_is;
deba@1408
   348
deba@1408
   349
    typedef std::vector<SectionReader*> SectionReaders;
deba@1408
   350
    SectionReaders readers;
deba@1408
   351
deba@1408
   352
  };
deba@1408
   353
deba@1409
   354
  /// \brief Helper class for implementing the common SectionReaders.
deba@1409
   355
  ///
deba@1409
   356
  /// Helper class for implementing the common SectionReaders.
deba@1409
   357
  class CommonSectionReaderBase : public LemonReader::SectionReader {
deba@1409
   358
    typedef LemonReader::SectionReader Parent;
deba@1409
   359
  protected:
deba@1409
   360
    
deba@1409
   361
    /// \brief Constructor for CommonSectionReaderBase.
deba@1409
   362
    ///
deba@1409
   363
    /// Constructor for CommonSectionReaderBase. It attach this reader to
deba@1409
   364
    /// the given LemonReader.
deba@1409
   365
    CommonSectionReaderBase(LemonReader& _reader) 
deba@1409
   366
      : Parent(_reader) {}
deba@1408
   367
deba@1408
   368
    template <typename _Item>
deba@1408
   369
    class ReaderBase;
deba@1408
   370
    
deba@1408
   371
    template <typename _Item>
deba@1408
   372
    class InverterBase : public ReaderBase<_Item> {
deba@1408
   373
    public:
deba@1408
   374
      typedef _Item Item;
deba@1408
   375
      virtual void read(std::istream&, const Item&) = 0;
deba@1408
   376
      virtual Item read(std::istream&) const = 0;
deba@1408
   377
deba@1408
   378
      virtual InverterBase<_Item>* getInverter() {
deba@1408
   379
	return this;
deba@1408
   380
      }
deba@1408
   381
    };
deba@1408
   382
deba@1408
   383
    template <typename _Item, typename _Map, typename _Reader>
deba@1408
   384
    class MapReaderInverter : public InverterBase<_Item> {
deba@1408
   385
    public:
deba@1408
   386
      typedef _Item Item;
deba@1408
   387
      typedef _Reader Reader;
deba@1408
   388
      typedef typename Reader::Value Value;
deba@1408
   389
      typedef _Map Map;
deba@1424
   390
      typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
deba@1408
   391
deba@1421
   392
      typename SmartReference<Map>::Type map;
deba@1408
   393
      Reader reader;
deba@1408
   394
      Inverse inverse;
deba@1408
   395
deba@1421
   396
      MapReaderInverter(typename SmartParameter<Map>::Type _map,
deba@1421
   397
			const Reader& _reader) 
deba@1408
   398
	: map(_map), reader(_reader) {}
deba@1408
   399
deba@1408
   400
      virtual ~MapReaderInverter() {}
deba@1408
   401
deba@1408
   402
      virtual void read(std::istream& is, const Item& item) {
deba@1408
   403
	Value value;
deba@1408
   404
	reader.read(is, value);
deba@1408
   405
	map.set(item, value);
deba@1408
   406
	typename Inverse::iterator it = inverse.find(value);
deba@1408
   407
	if (it == inverse.end()) {
deba@1408
   408
	  inverse.insert(std::make_pair(value, item));
deba@1408
   409
	} else {
deba@1408
   410
	  throw DataFormatError("Multiple ID occurence");
deba@1408
   411
	}
deba@1408
   412
      }
deba@1408
   413
deba@1408
   414
      virtual Item read(std::istream& is) const {
deba@1408
   415
	Value value;
deba@1408
   416
	reader.read(is, value);	
deba@1408
   417
	typename Inverse::const_iterator it = inverse.find(value);
deba@1408
   418
	if (it != inverse.end()) {
deba@1408
   419
	  return it->second;
deba@1408
   420
	} else {
deba@1408
   421
	  throw DataFormatError("Invalid ID error");
deba@1408
   422
	}
deba@1408
   423
      }      
deba@1408
   424
    };
deba@1408
   425
deba@1408
   426
    template <typename _Item, typename _Reader>
deba@1408
   427
    class SkipReaderInverter : public InverterBase<_Item> {
deba@1408
   428
    public:
deba@1408
   429
      typedef _Item Item;
deba@1408
   430
      typedef _Reader Reader;
deba@1408
   431
      typedef typename Reader::Value Value;
deba@1424
   432
      typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
deba@1408
   433
deba@1408
   434
      Reader reader;
deba@1408
   435
deba@1408
   436
      SkipReaderInverter(const Reader& _reader) 
deba@1408
   437
	: reader(_reader) {}
deba@1408
   438
deba@1408
   439
      virtual ~SkipReaderInverter() {}
deba@1408
   440
deba@1408
   441
      virtual void read(std::istream& is, const Item& item) {
deba@1408
   442
	Value value;
deba@1408
   443
	reader.read(is, value);
deba@1408
   444
	typename Inverse::iterator it = inverse.find(value);
deba@1408
   445
	if (it == inverse.end()) {
deba@1408
   446
	  inverse.insert(std::make_pair(value, item));
deba@1408
   447
	} else {
deba@1408
   448
	  throw DataFormatError("Multiple ID occurence error");
deba@1408
   449
	}
deba@1408
   450
      }
deba@1408
   451
deba@1408
   452
      virtual Item read(std::istream& is) const {
deba@1408
   453
	Value value;
deba@1408
   454
	reader.read(is, value);	
deba@1408
   455
	typename Inverse::const_iterator it = inverse.find(value);
deba@1408
   456
	if (it != inverse.end()) {
deba@1408
   457
	  return it->second;
deba@1408
   458
	} else {
deba@1408
   459
	  throw DataFormatError("Invalid ID error");
deba@1408
   460
	}
deba@1408
   461
      }
deba@1408
   462
deba@1408
   463
    private:
deba@1408
   464
      Inverse inverse;
deba@1408
   465
    };
deba@1408
   466
deba@1408
   467
    template <typename _Item>    
deba@1408
   468
    class ReaderBase {
deba@1408
   469
    public:
deba@1408
   470
      typedef _Item Item;
deba@1408
   471
deba@1408
   472
      virtual ~ReaderBase() {}
deba@1408
   473
deba@1408
   474
      virtual void read(std::istream& is, const Item& item) = 0;
deba@1408
   475
      virtual InverterBase<_Item>* getInverter() = 0;
deba@1408
   476
    };
deba@1408
   477
deba@1408
   478
    template <typename _Item, typename _Map, typename _Reader>
deba@1408
   479
    class MapReader : public ReaderBase<_Item> {
deba@1408
   480
    public:
deba@1408
   481
      typedef _Map Map;
deba@1408
   482
      typedef _Reader Reader;
deba@1408
   483
      typedef typename Reader::Value Value;
deba@1408
   484
      typedef _Item Item;
deba@1408
   485
      
deba@1421
   486
      typename SmartReference<Map>::Type map;
deba@1408
   487
      Reader reader;
deba@1408
   488
deba@1421
   489
      MapReader(typename SmartParameter<Map>::Type _map, 
deba@1421
   490
		const Reader& _reader) 
deba@1408
   491
	: map(_map), reader(_reader) {}
deba@1408
   492
deba@1408
   493
      virtual ~MapReader() {}
deba@1408
   494
deba@1408
   495
      virtual void read(std::istream& is, const Item& item) {
deba@1408
   496
	Value value;
deba@1408
   497
	reader.read(is, value);
deba@1408
   498
	map.set(item, value);
deba@1408
   499
      }
deba@1408
   500
deba@1408
   501
      virtual InverterBase<_Item>* getInverter() {
deba@1408
   502
	return new MapReaderInverter<Item, Map, Reader>(map, reader);
deba@1408
   503
      }
deba@1408
   504
    };
deba@1408
   505
deba@1408
   506
deba@1408
   507
    template <typename _Item, typename _Reader>
deba@1408
   508
    class SkipReader : public ReaderBase<_Item> {
deba@1408
   509
    public:
deba@1408
   510
      typedef _Reader Reader;
deba@1408
   511
      typedef typename Reader::Value Value;
deba@1408
   512
      typedef _Item Item;
deba@1408
   513
deba@1408
   514
      Reader reader;
deba@1408
   515
      SkipReader(const Reader& _reader) : reader(_reader) {}
deba@1408
   516
deba@1408
   517
      virtual ~SkipReader() {}
deba@1408
   518
deba@1408
   519
      virtual void read(std::istream& is, const Item&) {
deba@1408
   520
	Value value;
deba@1408
   521
	reader.read(is, value);
deba@1408
   522
      }      
deba@1408
   523
deba@1408
   524
      virtual InverterBase<Item>* getInverter() {
deba@1408
   525
	return new SkipReaderInverter<Item, Reader>(reader);
deba@1408
   526
      }
deba@1408
   527
    };
deba@1408
   528
deba@1408
   529
    template <typename _Item>
deba@1409
   530
    class IdReaderBase {
deba@1408
   531
    public:
deba@1408
   532
      typedef _Item Item;
deba@1409
   533
      virtual Item read(std::istream& is) const = 0;
deba@1408
   534
    };
deba@1408
   535
deba@1409
   536
    template <typename _Item, typename _BoxedIdReader>
deba@1409
   537
    class IdReader : public IdReaderBase<_Item> {
deba@1408
   538
    public:
deba@1408
   539
      typedef _Item Item;
deba@1409
   540
      typedef _BoxedIdReader BoxedIdReader;
deba@1409
   541
      
deba@1409
   542
      const BoxedIdReader& boxedIdReader;
deba@1408
   543
deba@1409
   544
      IdReader(const BoxedIdReader& _boxedIdReader) 
deba@1409
   545
	: boxedIdReader(_boxedIdReader) {}
deba@1408
   546
deba@1409
   547
      virtual Item read(std::istream& is) const {
deba@1429
   548
	return boxedIdReader.readId(is, Item());
deba@1408
   549
      }
deba@1408
   550
    };
deba@1408
   551
deba@1408
   552
    class ValueReaderBase {
deba@1408
   553
    public:
deba@1408
   554
      virtual void read(std::istream&) {};
deba@1408
   555
    };
deba@1408
   556
deba@1408
   557
    template <typename _Value, typename _Reader>
deba@1408
   558
    class ValueReader : public ValueReaderBase {
deba@1408
   559
    public:
deba@1408
   560
      typedef _Value Value;
deba@1408
   561
      typedef _Reader Reader;
deba@1408
   562
deba@1408
   563
      ValueReader(Value& _value, const Reader& _reader)
deba@1408
   564
 	: value(_value), reader(_reader) {}
deba@1408
   565
deba@1408
   566
      virtual void read(std::istream& is) {
deba@1408
   567
	reader.read(is, value);
deba@1408
   568
      }
deba@1408
   569
    private:
deba@1408
   570
      Value& value;
deba@1408
   571
      Reader reader;
deba@1408
   572
    };
deba@1408
   573
    
deba@1408
   574
  };
deba@1408
   575
deba@1409
   576
  /// \ingroup io_group
deba@1409
   577
  /// \brief SectionReader for reading a graph's nodeset.
deba@1409
   578
  ///
deba@1409
   579
  /// The lemon format can store multiple graph nodesets with several maps.
deba@1409
   580
  /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
deba@1409
   581
  /// \c nodeset_id may be empty.
deba@1409
   582
  ///
deba@1409
   583
  /// The first line of the section contains the names of the maps separated
deba@1409
   584
  /// with white spaces. Each next lines describes a node in the nodeset, and
deba@1409
   585
  /// contains the mapped values for each map.
deba@1409
   586
  ///
deba@1409
   587
  /// If the nodeset contains an \c "id" named map then it will be regarded
deba@1409
   588
  /// as id map. This map should contain only unique values and when the 
deba@1409
   589
  /// \c readId() member will read a value from the given stream it will
deba@1409
   590
  /// give back that node which is mapped to this value.
deba@1409
   591
  ///
deba@1409
   592
  /// \relates LemonReader
deba@1408
   593
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@1408
   594
  class NodeSetReader : public CommonSectionReaderBase {
deba@1408
   595
    typedef CommonSectionReaderBase Parent;
deba@1408
   596
  public:
deba@1408
   597
deba@1408
   598
    typedef _Graph Graph;
deba@1408
   599
    typedef _Traits Traits;
deba@1429
   600
    typedef typename Graph::Node Node;
deba@1408
   601
    typedef typename Traits::Skipper DefaultSkipper;
deba@1408
   602
deba@1409
   603
    /// \brief Constructor.
deba@1409
   604
    ///
deba@1409
   605
    /// Constructor for NodeSetReader. It creates the NodeSetReader and
deba@1409
   606
    /// attach it into the given LemonReader. The nodeset reader will
deba@1409
   607
    /// add the readed nodes to the given Graph. The reader will read
deba@1409
   608
    /// the section when the \c section_id and the \c _id are the same. 
deba@1421
   609
    NodeSetReader(LemonReader& _reader, 
deba@1421
   610
		  typename SmartParameter<Graph>::Type _graph, 
deba@1408
   611
		  const std::string& _id = std::string(),
deba@1409
   612
		  const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1409
   613
      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} 
deba@1408
   614
deba@1409
   615
deba@1409
   616
    /// \brief Destructor.
deba@1409
   617
    ///
deba@1409
   618
    /// Destructor for NodeSetReader.
deba@1408
   619
    virtual ~NodeSetReader() {
deba@1408
   620
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1408
   621
	   it != readers.end(); ++it) {
deba@1408
   622
	delete it->second;
deba@1408
   623
      }
deba@1408
   624
    }
deba@1408
   625
deba@1408
   626
  private:
deba@1408
   627
    NodeSetReader(const NodeSetReader&);
deba@1408
   628
    void operator=(const NodeSetReader&);
deba@1408
   629
  
deba@1408
   630
  public:
deba@1408
   631
deba@1408
   632
    /// \brief Add a new node map reader command for the reader.
deba@1408
   633
    ///
deba@1408
   634
    /// Add a new node map reader command for the reader.
deba@1408
   635
    template <typename Map>
deba@1421
   636
    NodeSetReader& readNodeMap(std::string name, Map& map) {
deba@1421
   637
      return _readMap<
deba@1421
   638
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
   639
	typename SmartParameter<Map>::Type>(name, map);
deba@1421
   640
    }
deba@1421
   641
deba@1421
   642
    template <typename Map>
deba@1421
   643
    NodeSetReader& readNodeMap(std::string name, const Map& map) {
deba@1421
   644
      return _readMap<
deba@1421
   645
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
   646
	typename SmartParameter<Map>::Type>(name, map);
deba@1408
   647
    }
deba@1408
   648
deba@1408
   649
    /// \brief Add a new node map reader command for the reader.
deba@1408
   650
    ///
deba@1408
   651
    /// Add a new node map reader command for the reader.
deba@1408
   652
    template <typename Reader, typename Map>
deba@1421
   653
    NodeSetReader& readNodeMap(std::string name, Map& map, 
deba@1421
   654
			       const Reader& reader = Reader()) {
deba@1429
   655
      return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
deba@1429
   656
	(name, map, reader);
deba@1421
   657
    }
deba@1421
   658
deba@1421
   659
    template <typename Reader, typename Map>
deba@1421
   660
    NodeSetReader& readNodeMap(std::string name, const Map& map, 
deba@1421
   661
			       const Reader& reader = Reader()) {
deba@1429
   662
      return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
deba@1429
   663
	(name, map, reader);
deba@1421
   664
    }
deba@1421
   665
deba@1421
   666
  private:
deba@1421
   667
deba@1421
   668
    template <typename Reader, typename Map, typename MapParameter>
deba@1421
   669
    NodeSetReader& _readMap(std::string name, MapParameter map, 
deba@1421
   670
			    const Reader& reader = Reader()) {
deba@1408
   671
      if (readers.find(name) != readers.end()) {
deba@1408
   672
	ErrorMessage msg;
deba@1408
   673
	msg << "Multiple read rule for node map: " << name;
deba@1408
   674
	throw IOParameterError(msg.message());
deba@1408
   675
      }
deba@1408
   676
      readers.insert(
deba@1429
   677
	make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
deba@1408
   678
      return *this;
deba@1408
   679
    }
deba@1408
   680
deba@1421
   681
  public:
deba@1421
   682
deba@1408
   683
    /// \brief Add a new node map skipper command for the reader.
deba@1408
   684
    ///
deba@1408
   685
    /// Add a new node map skipper command for the reader.
deba@1408
   686
    template <typename Reader>
deba@1421
   687
    NodeSetReader& skipNodeMap(std::string name, 
deba@1408
   688
			   const Reader& reader = Reader()) {
deba@1408
   689
      if (readers.find(name) != readers.end()) {
deba@1408
   690
	ErrorMessage msg;
deba@1408
   691
	msg << "Multiple read rule for node map: " << name;
deba@1408
   692
	throw IOParameterError(msg.message());
deba@1408
   693
      }
deba@1429
   694
      readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
deba@1408
   695
      return *this;
deba@1408
   696
    }
deba@1408
   697
deba@1409
   698
  protected:
deba@1409
   699
deba@1409
   700
    /// \brief Gives back true when the SectionReader can process 
deba@1409
   701
    /// the section with the given header line.
deba@1409
   702
    ///
deba@1421
   703
    /// It gives back true when the header line starts with \c \@nodeset,
deba@1409
   704
    /// and the header line's id and the nodeset's id are the same.
deba@1408
   705
    virtual bool header(const std::string& line) {
deba@1408
   706
      std::istringstream ls(line);
deba@1408
   707
      std::string command;
deba@1408
   708
      std::string name;
deba@1408
   709
      ls >> command >> name;
deba@1408
   710
      return command == "@nodeset" && name == id;
deba@1408
   711
    }
deba@1408
   712
deba@1409
   713
    /// \brief Reader function of the section.
deba@1409
   714
    ///
deba@1409
   715
    /// It reads the content of the section.
deba@1408
   716
    virtual void read(std::istream& is) {
deba@1429
   717
      std::vector<ReaderBase<Node>* > index;
deba@1408
   718
      std::string line;
deba@1408
   719
deba@1408
   720
      getline(is, line);
deba@1408
   721
      std::istringstream ls(line);	
deba@1408
   722
      while (ls >> id) {
deba@1408
   723
	typename MapReaders::iterator it = readers.find(id);
deba@1408
   724
	if (it != readers.end()) {
deba@1408
   725
	  index.push_back(it->second);
deba@1408
   726
	} else {
deba@1408
   727
	  index.push_back(&skipper);
deba@1408
   728
	}
deba@1408
   729
	if (id == "id" && inverter.get() == 0) {
deba@1408
   730
	  inverter.reset(index.back()->getInverter());
deba@1408
   731
	  index.back() = inverter.get();
deba@1408
   732
	}
deba@1408
   733
      }
deba@1408
   734
      while (getline(is, line)) {	
deba@1429
   735
	Node node = graph.addNode();
deba@1408
   736
	std::istringstream ls(line);
deba@1408
   737
	for (int i = 0; i < (int)index.size(); ++i) {
deba@1408
   738
	  index[i]->read(ls, node);
deba@1408
   739
	}
deba@1408
   740
      }
deba@1408
   741
    }
deba@1408
   742
deba@1409
   743
  public:
deba@1409
   744
deba@1409
   745
    /// \brief Returns true if the nodeset can give back the node by its id.
deba@1409
   746
    ///
deba@1409
   747
    /// Returns true if the nodeset can give back the node by its id.
deba@1409
   748
    /// It is possible only if an "id" named map was read.
deba@1409
   749
    bool isIdReader() const {
deba@1408
   750
      return inverter.get() != 0;
deba@1408
   751
    }
deba@1408
   752
deba@1409
   753
    /// \brief Gives back the node by its id.
deba@1409
   754
    ///
deba@1409
   755
    /// It reads an id from the stream and gives back which node belongs to
deba@1409
   756
    /// it. It is possible only if there was read an "id" named map.
deba@1429
   757
    Node readId(std::istream& is, Node = Node()) const {
deba@1408
   758
      return inverter->read(is);
deba@1408
   759
    } 
deba@1408
   760
deba@1408
   761
  private:
deba@1408
   762
deba@1429
   763
    typedef std::map<std::string, ReaderBase<Node>*> MapReaders;
deba@1408
   764
    MapReaders readers;
deba@1408
   765
   
deba@1421
   766
    typename SmartReference<Graph>::Type graph;   
deba@1408
   767
    std::string id;
deba@1429
   768
    SkipReader<Node, DefaultSkipper> skipper;
deba@1408
   769
deba@1429
   770
    std::auto_ptr<InverterBase<Node> > inverter;
deba@1408
   771
  };
deba@1408
   772
deba@1409
   773
  /// \ingroup io_group
deba@1409
   774
  /// \brief SectionReader for reading a graph's edgeset.
deba@1409
   775
  ///
deba@1409
   776
  /// The lemon format can store multiple graph edgesets with several maps.
deba@1409
   777
  /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
deba@1409
   778
  /// \c edgeset_id may be empty.
deba@1409
   779
  ///
deba@1409
   780
  /// The first line of the section contains the names of the maps separated
deba@1421
   781
  /// with white spaces. Each next lines describes an edge in the edgeset. The
deba@1421
   782
  /// line contains the source and the target nodes' id and the mapped 
deba@1421
   783
  /// values for each map.
deba@1409
   784
  ///
deba@1409
   785
  /// If the edgeset contains an \c "id" named map then it will be regarded
deba@1409
   786
  /// as id map. This map should contain only unique values and when the 
deba@1409
   787
  /// \c readId() member will read a value from the given stream it will
deba@1409
   788
  /// give back that edge which is mapped to this value.
deba@1409
   789
  ///
deba@1409
   790
  /// The edgeset reader needs a node id reader to identify which nodes
deba@1409
   791
  /// have to be connected. If a NodeSetReader reads an "id" named map,
deba@1409
   792
  /// it will be able to resolve the nodes by ids.
deba@1409
   793
  ///
deba@1409
   794
  /// \relates LemonReader
deba@1408
   795
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@1408
   796
  class EdgeSetReader : public CommonSectionReaderBase {
deba@1408
   797
    typedef CommonSectionReaderBase Parent;
deba@1408
   798
  public:
deba@1408
   799
deba@1408
   800
    typedef _Graph Graph;
deba@1408
   801
    typedef _Traits Traits;
deba@1429
   802
    typedef typename Graph::Node Node;
deba@1429
   803
    typedef typename Graph::Edge Edge;
deba@1408
   804
    typedef typename Traits::Skipper DefaultSkipper;
deba@1408
   805
deba@1409
   806
    /// \brief Constructor.
deba@1409
   807
    ///
deba@1409
   808
    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
deba@1409
   809
    /// attach it into the given LemonReader. The edgeset reader will
deba@1409
   810
    /// add the readed edges to the given Graph. It will use the given
deba@1409
   811
    /// node id reader to read the source and target nodes of the edges.
deba@1409
   812
    /// The reader will read the section only if the \c _id and the 
deba@1409
   813
    /// \c edgset_id are the same. 
deba@1409
   814
    template <typename NodeIdReader>
deba@1421
   815
    EdgeSetReader(LemonReader& _reader, 
deba@1421
   816
		  typename SmartParameter<Graph>::Type _graph, 
deba@1409
   817
		  const NodeIdReader& _nodeIdReader, 
deba@1408
   818
		  const std::string& _id = std::string(),
deba@1409
   819
		  const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1409
   820
      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
deba@1429
   821
	nodeIdReader(new IdReader<Node, NodeIdReader>(_nodeIdReader)) {} 
deba@1408
   822
deba@1409
   823
    /// \brief Destructor.
deba@1409
   824
    ///
deba@1409
   825
    /// Destructor for EdgeSetReader.
deba@1408
   826
    virtual ~EdgeSetReader() {
deba@1408
   827
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1408
   828
	   it != readers.end(); ++it) {
deba@1408
   829
	delete it->second;
deba@1408
   830
      }
deba@1408
   831
    }
deba@1408
   832
deba@1408
   833
  private:
deba@1408
   834
    EdgeSetReader(const EdgeSetReader&);
deba@1408
   835
    void operator=(const EdgeSetReader&);
deba@1408
   836
deba@1408
   837
  public:
deba@1408
   838
deba@1409
   839
    /// \brief Add a new edge map reader command for the reader.
deba@1408
   840
    ///
deba@1409
   841
    /// Add a new edge map reader command for the reader.
deba@1408
   842
    template <typename Map>
deba@1421
   843
    EdgeSetReader& readEdgeMap(std::string name, Map& map) {
deba@1421
   844
      return _readMap<
deba@1421
   845
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
   846
	typename SmartParameter<Map>::Type>(name, map);
deba@1421
   847
    }
deba@1421
   848
deba@1421
   849
    template <typename Map>
deba@1421
   850
    EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
deba@1421
   851
      return _readMap<
deba@1421
   852
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
   853
	typename SmartParameter<Map>::Type>(name, map);
deba@1408
   854
    }
deba@1408
   855
deba@1409
   856
    /// \brief Add a new edge map reader command for the reader.
deba@1408
   857
    ///
deba@1409
   858
    /// Add a new edge map reader command for the reader.
deba@1408
   859
    template <typename Reader, typename Map>
deba@1421
   860
    EdgeSetReader& readEdgeMap(std::string name, Map& map, 
deba@1421
   861
			   const Reader& reader = Reader()) {
deba@1429
   862
      return _readMap<Reader, Map,
deba@1421
   863
	typename SmartParameter<Map>::Type>(name, map, reader);
deba@1421
   864
    }
deba@1421
   865
deba@1421
   866
    template <typename Reader, typename Map>
deba@1421
   867
    EdgeSetReader& readEdgeMap(std::string name, const Map& map, 
deba@1421
   868
			       const Reader& reader = Reader()) {
deba@1429
   869
      return _readMap<Reader, Map,
deba@1421
   870
	typename SmartParameter<Map>::Type>(name, map, reader);
deba@1421
   871
    }
deba@1421
   872
deba@1421
   873
  private:
deba@1421
   874
deba@1421
   875
    template <typename Reader, typename Map, typename MapParameter>
deba@1421
   876
    EdgeSetReader& _readMap(std::string name, MapParameter map, 
deba@1421
   877
			    const Reader& reader = Reader()) {
deba@1408
   878
      if (readers.find(name) != readers.end()) {
deba@1408
   879
	ErrorMessage msg;
deba@1408
   880
	msg << "Multiple read rule for edge map: " << name;
deba@1408
   881
	throw IOParameterError(msg.message());
deba@1408
   882
      }
deba@1408
   883
      readers.insert(
deba@1429
   884
	make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
deba@1408
   885
      return *this;
deba@1408
   886
    }
deba@1408
   887
deba@1421
   888
  public:
deba@1421
   889
deba@1409
   890
    /// \brief Add a new edge map skipper command for the reader.
deba@1408
   891
    ///
deba@1409
   892
    /// Add a new edge map skipper command for the reader.
deba@1408
   893
    template <typename Reader>
deba@1421
   894
    EdgeSetReader& skipEdgeMap(std::string name, 
deba@1421
   895
			       const Reader& reader = Reader()) {
deba@1408
   896
      if (readers.find(name) != readers.end()) {
deba@1408
   897
	ErrorMessage msg;
deba@1421
   898
	msg << "Multiple read rule for edge map: " << name;
deba@1408
   899
	throw IOParameterError(msg.message());
deba@1408
   900
      }
deba@1429
   901
      readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
deba@1408
   902
      return *this;
deba@1408
   903
    }
deba@1408
   904
deba@1409
   905
  protected:
deba@1409
   906
deba@1409
   907
    /// \brief Gives back true when the SectionReader can process 
deba@1409
   908
    /// the section with the given header line.
deba@1409
   909
    ///
deba@1421
   910
    /// It gives back true when the header line starts with \c \@edgeset,
deba@1409
   911
    /// and the header line's id and the edgeset's id are the same.
deba@1408
   912
    virtual bool header(const std::string& line) {
deba@1408
   913
      std::istringstream ls(line);
deba@1408
   914
      std::string command;
deba@1408
   915
      std::string name;
deba@1408
   916
      ls >> command >> name;
deba@1408
   917
      return command == "@edgeset" && name == id;
deba@1408
   918
    }
deba@1408
   919
deba@1409
   920
    /// \brief Reader function of the section.
deba@1409
   921
    ///
deba@1409
   922
    /// It reads the content of the section.
deba@1408
   923
    virtual void read(std::istream& is) {
deba@1429
   924
      std::vector<ReaderBase<Edge>* > index;
deba@1408
   925
      std::string line;
deba@1408
   926
deba@1408
   927
      getline(is, line);
deba@1408
   928
      std::istringstream ls(line);	
deba@1408
   929
      while (ls >> id) {
deba@1408
   930
	typename MapReaders::iterator it = readers.find(id);
deba@1408
   931
	if (it != readers.end()) {
deba@1408
   932
	  index.push_back(it->second);
deba@1408
   933
	} else {
deba@1408
   934
	  index.push_back(&skipper);
deba@1408
   935
	}
deba@1408
   936
	if (id == "id" && inverter.get() == 0) {
deba@1408
   937
	  inverter.reset(index.back()->getInverter());
deba@1408
   938
	  index.back() = inverter.get();
deba@1408
   939
	}
deba@1408
   940
      }
deba@1408
   941
      while (getline(is, line)) {	
deba@1408
   942
	std::istringstream ls(line);
deba@1429
   943
	Node from = nodeIdReader->read(ls);
deba@1429
   944
	Node to = nodeIdReader->read(ls);
deba@1429
   945
	Edge edge = graph.addEdge(from, to);
deba@1408
   946
	for (int i = 0; i < (int)index.size(); ++i) {
deba@1408
   947
	  index[i]->read(ls, edge);
deba@1408
   948
	}
deba@1408
   949
      }
deba@1408
   950
    }
deba@1408
   951
deba@1409
   952
  public:
deba@1409
   953
deba@1409
   954
    /// \brief Returns true if the edgeset can give back the edge by its id.
deba@1409
   955
    ///
deba@1409
   956
    /// Returns true if the edgeset can give back the edge by its id.
deba@1409
   957
    /// It is possible only if an "id" named map was read.
deba@1409
   958
    bool isIdReader() const {
deba@1408
   959
      return inverter.get() != 0;
deba@1408
   960
    }
deba@1408
   961
deba@1409
   962
    /// \brief Gives back the edge by its id.
deba@1409
   963
    ///
deba@1409
   964
    /// It reads an id from the stream and gives back which edge belongs to
deba@1409
   965
    /// it. It is possible only if there was read an "id" named map.
deba@1429
   966
    Edge readId(std::istream& is, Edge = Edge()) const {
deba@1408
   967
      return inverter->read(is);
deba@1408
   968
    } 
deba@1408
   969
deba@1408
   970
  private:
deba@1408
   971
deba@1429
   972
    typedef std::map<std::string, ReaderBase<Edge>*> MapReaders;
deba@1408
   973
    MapReaders readers;
deba@1408
   974
   
deba@1421
   975
    typename SmartReference<Graph>::Type graph;   
deba@1421
   976
    std::string id;
deba@1429
   977
    SkipReader<Edge, DefaultSkipper> skipper;
deba@1421
   978
deba@1429
   979
    std::auto_ptr<InverterBase<Edge> > inverter;
deba@1429
   980
    std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
deba@1421
   981
  };
deba@1421
   982
deba@1421
   983
  /// \ingroup io_group
deba@1421
   984
  /// \brief SectionReader for reading a undirected graph's edgeset.
deba@1421
   985
  ///
deba@1421
   986
  /// The lemon format can store multiple undirected edgesets with several 
deba@1421
   987
  /// maps. The undirected edgeset section's header line is \c \@undiredgeset 
deba@1421
   988
  /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
deba@1421
   989
  ///
deba@1421
   990
  /// The first line of the section contains the names of the maps separated
deba@1421
   991
  /// with white spaces. Each next lines describes an edge in the edgeset. The
deba@1421
   992
  /// line contains the connected nodes' id and the mapped values for each map.
deba@1421
   993
  ///
deba@1421
   994
  /// The section can handle the directed as a syntactical sugar. Two
deba@1421
   995
  /// undirected edge map describes one directed edge map. This two maps
deba@1421
   996
  /// are the forward map and the backward map and the names of this map
deba@1421
   997
  /// is near the same just with a prefix \c '+' or \c '-' character 
deba@1421
   998
  /// difference.
deba@1421
   999
  ///
deba@1421
  1000
  /// If the edgeset contains an \c "id" named map then it will be regarded
deba@1421
  1001
  /// as id map. This map should contain only unique values and when the 
deba@1421
  1002
  /// \c readId() member will read a value from the given stream it will
deba@1421
  1003
  /// give back that undiricted edge which is mapped to this value.
deba@1421
  1004
  ///
deba@1421
  1005
  /// The undirected edgeset reader needs a node id reader to identify which 
deba@1421
  1006
  /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
deba@1421
  1007
  /// it will be able to resolve the nodes by ids.
deba@1421
  1008
  ///
deba@1421
  1009
  /// \relates LemonReader
deba@1421
  1010
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@1421
  1011
  class UndirEdgeSetReader : public CommonSectionReaderBase {
deba@1421
  1012
    typedef CommonSectionReaderBase Parent;
deba@1421
  1013
  public:
deba@1421
  1014
deba@1421
  1015
    typedef _Graph Graph;
deba@1421
  1016
    typedef _Traits Traits;
deba@1429
  1017
    typedef typename Graph::Node Node;
deba@1429
  1018
    typedef typename Graph::Edge Edge;
deba@1429
  1019
    typedef typename Graph::UndirEdge UndirEdge;
deba@1421
  1020
    typedef typename Traits::Skipper DefaultSkipper;
deba@1421
  1021
deba@1421
  1022
    /// \brief Constructor.
deba@1421
  1023
    ///
deba@1421
  1024
    /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader 
deba@1421
  1025
    /// and attach it into the given LemonReader. The undirected edgeset 
deba@1421
  1026
    /// reader will add the readed undirected edges to the given Graph. It 
deba@1421
  1027
    /// will use the given node id reader to read the source and target 
deba@1421
  1028
    /// nodes of the edges. The reader will read the section only if the 
deba@1421
  1029
    /// \c _id and the \c undiredgset_id are the same. 
deba@1421
  1030
    template <typename NodeIdReader>
deba@1421
  1031
    UndirEdgeSetReader(LemonReader& _reader, 
deba@1421
  1032
		       typename SmartParameter<Graph>::Type _graph, 
deba@1421
  1033
		       const NodeIdReader& _nodeIdReader, 
deba@1421
  1034
		       const std::string& _id = std::string(),
deba@1421
  1035
		       const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1421
  1036
      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
deba@1429
  1037
	nodeIdReader(new IdReader<Node, NodeIdReader>(_nodeIdReader)) {} 
deba@1421
  1038
deba@1421
  1039
    /// \brief Destructor.
deba@1421
  1040
    ///
deba@1421
  1041
    /// Destructor for UndirEdgeSetReader.
deba@1421
  1042
    virtual ~UndirEdgeSetReader() {
deba@1421
  1043
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1421
  1044
	   it != readers.end(); ++it) {
deba@1421
  1045
	delete it->second;
deba@1421
  1046
      }
deba@1421
  1047
    }
deba@1421
  1048
deba@1421
  1049
  private:
deba@1421
  1050
    UndirEdgeSetReader(const UndirEdgeSetReader&);
deba@1421
  1051
    void operator=(const UndirEdgeSetReader&);
deba@1421
  1052
deba@1421
  1053
  public:
deba@1421
  1054
deba@1421
  1055
    /// \brief Add a new undirected edge map reader command for the reader.
deba@1421
  1056
    ///
deba@1421
  1057
    /// Add a new edge undirected map reader command for the reader.
deba@1421
  1058
    template <typename Map>
deba@1421
  1059
    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
deba@1421
  1060
      return _readMap<
deba@1421
  1061
	typename Traits::template Reader<typename Map::Value>, Map, 
deba@1421
  1062
	typename SmartParameter<Map>::Type>(name, map);
deba@1421
  1063
    }
deba@1421
  1064
deba@1421
  1065
    template <typename Map>
deba@1421
  1066
    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
deba@1421
  1067
      return _readMap<
deba@1421
  1068
	typename Traits::template Reader<typename Map::Value>, Map, 
deba@1421
  1069
	typename SmartParameter<Map>::Type>(name, map);
deba@1421
  1070
    }
deba@1421
  1071
deba@1421
  1072
    /// \brief Add a new undirected edge map reader command for the reader.
deba@1421
  1073
    ///
deba@1421
  1074
    /// Add a new edge undirected map reader command for the reader.
deba@1421
  1075
    template <typename Reader, typename Map>
deba@1421
  1076
    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map, 
deba@1421
  1077
					 const Reader& reader = Reader()) {
deba@1421
  1078
      return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
deba@1421
  1079
	(name, map, reader);
deba@1421
  1080
    }
deba@1421
  1081
deba@1421
  1082
    template <typename Reader, typename Map>
deba@1421
  1083
    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map, 
deba@1421
  1084
					 const Reader& reader = Reader()) {
deba@1421
  1085
      return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
deba@1421
  1086
	(name, map, reader);
deba@1421
  1087
    }
deba@1421
  1088
deba@1421
  1089
  private:
deba@1421
  1090
deba@1421
  1091
    template <typename Reader, typename Map, typename MapParameter>
deba@1421
  1092
    UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
deba@1421
  1093
				 const Reader& reader = Reader()) {
deba@1421
  1094
      if (readers.find(name) != readers.end()) {
deba@1421
  1095
	ErrorMessage msg;
deba@1421
  1096
	msg << "Multiple read rule for edge map: " << name;
deba@1421
  1097
	throw IOParameterError(msg.message());
deba@1421
  1098
      }
deba@1421
  1099
      readers.insert(
deba@1429
  1100
	make_pair(name, new MapReader<UndirEdge, Map, Reader>(map, reader)));
deba@1421
  1101
      return *this;
deba@1421
  1102
    }
deba@1421
  1103
deba@1421
  1104
  public:
deba@1421
  1105
deba@1421
  1106
    /// \brief Add a new undirected edge map skipper command for the reader.
deba@1421
  1107
    ///
deba@1421
  1108
    /// Add a new undirected edge map skipper command for the reader.
deba@1421
  1109
    template <typename Reader>
deba@1421
  1110
    UndirEdgeSetReader& skipUndirEdgeMap(std::string name, 
deba@1421
  1111
					 const Reader& reader = Reader()) {
deba@1421
  1112
      if (readers.find(name) != readers.end()) {
deba@1421
  1113
	ErrorMessage msg;
deba@1421
  1114
	msg << "Multiple read rule for node map: " << name;
deba@1421
  1115
	throw IOParameterError(msg.message());
deba@1421
  1116
      }
deba@1429
  1117
      readers.insert(make_pair(name, 
deba@1429
  1118
			       new SkipReader<UndirEdge, Reader>(reader)));
deba@1421
  1119
      return *this;
deba@1421
  1120
    }
deba@1421
  1121
deba@1421
  1122
    /// \brief Add a new directed edge map reader command for the reader.
deba@1421
  1123
    ///
deba@1421
  1124
    /// Add a new directed edge map reader command for the reader.
deba@1421
  1125
    template <typename Map>
deba@1421
  1126
    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
deba@1421
  1127
      return _readDirMap<
deba@1421
  1128
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
  1129
	typename SmartParameter<Map>::Type>(name, map);
deba@1421
  1130
    }
deba@1421
  1131
deba@1421
  1132
    template <typename Map>
deba@1421
  1133
    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
deba@1421
  1134
      return _readDirMap<
deba@1421
  1135
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
  1136
	typename SmartParameter<Map>::Type>(name, map);
deba@1421
  1137
    }
deba@1421
  1138
deba@1421
  1139
    /// \brief Add a new directed edge map reader command for the reader.
deba@1421
  1140
    ///
deba@1421
  1141
    /// Add a new directed edge map reader command for the reader.
deba@1421
  1142
    template <typename Reader, typename Map>
deba@1421
  1143
    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map, 
deba@1421
  1144
				    const Reader& reader = Reader()) {
deba@1421
  1145
      return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
deba@1421
  1146
	(name, map, reader);
deba@1421
  1147
    }
deba@1421
  1148
deba@1421
  1149
    template <typename Reader, typename Map>
deba@1421
  1150
    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map, 
deba@1421
  1151
				    const Reader& reader = Reader()) {
deba@1421
  1152
      return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
deba@1421
  1153
	(name, map, reader);
deba@1421
  1154
    }
deba@1421
  1155
deba@1421
  1156
  private:
deba@1421
  1157
deba@1421
  1158
    template <typename Reader, typename Map, typename MapParameter>
deba@1421
  1159
    UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
deba@1421
  1160
				    const Reader& reader = Reader()) {
deba@1421
  1161
      readMap("+" + name, 
deba@1421
  1162
	      _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
deba@1421
  1163
      readMap("-" + name, 
deba@1421
  1164
	      _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
deba@1421
  1165
      return *this;      
deba@1421
  1166
    }
deba@1421
  1167
deba@1421
  1168
  public:
deba@1421
  1169
deba@1421
  1170
    /// \brief Add a new directed edge map skipper command for the reader.
deba@1421
  1171
    ///
deba@1421
  1172
    /// Add a new directed edge map skipper command for the reader.
deba@1421
  1173
    template <typename Reader>
deba@1421
  1174
    UndirEdgeSetReader& skipEdgeMap(std::string name, 
deba@1421
  1175
				    const Reader& reader = Reader()) {
deba@1421
  1176
      skipMap("+" + name, reader);
deba@1421
  1177
      skipMap("-" + name, reader);
deba@1421
  1178
      return *this;
deba@1421
  1179
    }
deba@1421
  1180
deba@1421
  1181
  protected:
deba@1421
  1182
deba@1421
  1183
    /// \brief Gives back true when the SectionReader can process 
deba@1421
  1184
    /// the section with the given header line.
deba@1421
  1185
    ///
deba@1421
  1186
    /// It gives back true when the header line starts with \c \@undiredgeset,
deba@1421
  1187
    /// and the header line's id and the edgeset's id are the same.
deba@1421
  1188
    virtual bool header(const std::string& line) {
deba@1421
  1189
      std::istringstream ls(line);
deba@1421
  1190
      std::string command;
deba@1421
  1191
      std::string name;
deba@1421
  1192
      ls >> command >> name;
deba@1421
  1193
      return command == "@undiredgeset" && name == id;
deba@1421
  1194
    }
deba@1421
  1195
deba@1421
  1196
    /// \brief Reader function of the section.
deba@1421
  1197
    ///
deba@1421
  1198
    /// It reads the content of the section.
deba@1421
  1199
    virtual void read(std::istream& is) {
deba@1429
  1200
      std::vector<ReaderBase<UndirEdge>* > index;
deba@1421
  1201
      std::string line;
deba@1421
  1202
deba@1421
  1203
      getline(is, line);
deba@1421
  1204
      std::istringstream ls(line);	
deba@1421
  1205
      while (ls >> id) {
deba@1421
  1206
	typename MapReaders::iterator it = readers.find(id);
deba@1421
  1207
	if (it != readers.end()) {
deba@1421
  1208
	  index.push_back(it->second);
deba@1421
  1209
	} else {
deba@1421
  1210
	  index.push_back(&skipper);
deba@1421
  1211
	}
deba@1421
  1212
	if (id == "id" && inverter.get() == 0) {
deba@1421
  1213
	  inverter.reset(index.back()->getInverter());
deba@1421
  1214
	  index.back() = inverter.get();
deba@1421
  1215
	}
deba@1421
  1216
      }
deba@1421
  1217
      while (getline(is, line)) {	
deba@1421
  1218
	std::istringstream ls(line);
deba@1429
  1219
	Node from = nodeIdReader->read(ls);
deba@1429
  1220
	Node to = nodeIdReader->read(ls);
deba@1429
  1221
	UndirEdge edge = graph.addEdge(from, to);
deba@1421
  1222
	for (int i = 0; i < (int)index.size(); ++i) {
deba@1421
  1223
	  index[i]->read(ls, edge);
deba@1421
  1224
	}
deba@1421
  1225
      }
deba@1421
  1226
    }
deba@1421
  1227
deba@1421
  1228
  public:
deba@1421
  1229
deba@1421
  1230
    /// \brief Returns true if the edgeset can give back the edge by its id.
deba@1421
  1231
    ///
deba@1421
  1232
    /// Returns true if the edgeset can give back the undirected edge by its 
deba@1421
  1233
    /// id. It is possible only if an "id" named map was read.
deba@1421
  1234
    bool isIdReader() const {
deba@1421
  1235
      return inverter.get() != 0;
deba@1421
  1236
    }
deba@1421
  1237
deba@1421
  1238
    /// \brief Gives back the undirected edge by its id.
deba@1421
  1239
    ///
deba@1421
  1240
    /// It reads an id from the stream and gives back which undirected edge 
deba@1421
  1241
    /// belongs to it. It is possible only if there was read an "id" named map.
deba@1429
  1242
    UndirEdge readId(std::istream& is, UndirEdge = UndirEdge()) const {
deba@1421
  1243
      return inverter->read(is);
deba@1421
  1244
    } 
deba@1421
  1245
deba@1429
  1246
    /// \brief Gives back the directed edge by its id.
deba@1429
  1247
    ///
deba@1429
  1248
    /// It reads an id from the stream and gives back which directed edge 
deba@1429
  1249
    /// belongs to it. The directed edge id is the \c '+' or \c '-' character
deba@1429
  1250
    /// and the undirected edge id. It is possible only if there was read 
deba@1429
  1251
    /// an "id" named map.
deba@1429
  1252
    Edge readId(std::istream& is, Edge = Edge()) const {
deba@1429
  1253
      char c;
deba@1429
  1254
      is >> c;
deba@1429
  1255
      UndirEdge undirEdge = inverter->read(is);
deba@1429
  1256
      if (c == '+') {
deba@1429
  1257
	return graph.edgeWithSource(undirEdge, graph.source(undirEdge));
deba@1429
  1258
      } else if (c == '-') {
deba@1429
  1259
	return graph.edgeWithSource(undirEdge, graph.target(undirEdge));
deba@1429
  1260
      } else {
deba@1429
  1261
	throw DataFormatError("Wrong id format for edge "
deba@1429
  1262
			      "in undirected edgeset");
deba@1429
  1263
      }
deba@1429
  1264
    } 
deba@1429
  1265
deba@1421
  1266
  private:
deba@1421
  1267
deba@1429
  1268
    typedef std::map<std::string, ReaderBase<UndirEdge>*> MapReaders;
deba@1421
  1269
    MapReaders readers;
deba@1421
  1270
   
deba@1421
  1271
    typename SmartReference<Graph>::Type graph;   
deba@1408
  1272
    std::string id;
deba@1429
  1273
    SkipReader<UndirEdge, DefaultSkipper> skipper;
deba@1408
  1274
deba@1429
  1275
    std::auto_ptr<InverterBase<UndirEdge> > inverter;
deba@1429
  1276
    std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
deba@1408
  1277
  };
deba@1408
  1278
deba@1409
  1279
  /// \ingroup io_group
deba@1409
  1280
  /// \brief SectionReader for reading labeled nodes.
deba@1409
  1281
  ///
deba@1409
  1282
  /// The nodes section's header line is \c \@nodes \c nodes_id, but the
deba@1409
  1283
  /// \c nodes_id may be empty.
deba@1409
  1284
  ///
deba@1409
  1285
  /// Each line in the section contains the name of the node 
deba@1409
  1286
  /// and then the node id. 
deba@1409
  1287
  ///
deba@1409
  1288
  /// \relates LemonReader
deba@1409
  1289
  template <typename _Graph>
deba@1409
  1290
  class NodeReader : public CommonSectionReaderBase {
deba@1409
  1291
    typedef CommonSectionReaderBase Parent;
deba@1409
  1292
    typedef _Graph Graph;
deba@1429
  1293
    typedef typename Graph::Node Node;
deba@1409
  1294
  public:
deba@1409
  1295
    
deba@1409
  1296
    /// \brief Constructor.
deba@1409
  1297
    ///
deba@1409
  1298
    /// Constructor for NodeReader. It creates the NodeReader and
deba@1409
  1299
    /// attach it into the given LemonReader. It will use the given
deba@1409
  1300
    /// node id reader to give back the nodes. The reader will read the 
deba@1409
  1301
    /// section only if the \c _id and the \c nodes_id are the same. 
deba@1409
  1302
    template <typename _IdReader>
deba@1409
  1303
    NodeReader(LemonReader& _reader, const _IdReader& _idReader, 
deba@1409
  1304
	       const std::string& _id = std::string()) 
deba@1409
  1305
      : Parent(_reader), id(_id), 
deba@1409
  1306
	idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {} 
deba@1408
  1307
deba@1409
  1308
    /// \brief Destructor.
deba@1409
  1309
    ///
deba@1409
  1310
    /// Destructor for NodeReader.
deba@1409
  1311
    virtual ~NodeReader() {}
deba@1409
  1312
deba@1409
  1313
  private:
deba@1409
  1314
    NodeReader(const NodeReader&);
deba@1409
  1315
    void operator=(const NodeReader&);
deba@1409
  1316
deba@1409
  1317
  public:
deba@1409
  1318
deba@1409
  1319
    /// \brief Add a node reader command for the NodeReader.
deba@1409
  1320
    ///
deba@1409
  1321
    /// Add a node reader command for the NodeReader.
deba@1429
  1322
    void readNode(const std::string& name, Node& item) {
deba@1409
  1323
      if (readers.find(name) != readers.end()) {
deba@1409
  1324
	ErrorMessage msg;
deba@1409
  1325
	msg << "Multiple read rule for node: " << name;
deba@1409
  1326
	throw IOParameterError(msg.message());
deba@1409
  1327
      }
deba@1409
  1328
      readers.insert(make_pair(name, &item));
deba@1409
  1329
    }
deba@1409
  1330
deba@1409
  1331
  protected:
deba@1409
  1332
deba@1409
  1333
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  1334
    /// the section with the given header line.
deba@1409
  1335
    ///
deba@1421
  1336
    /// It gives back true when the header line start with \c \@nodes,
deba@1409
  1337
    /// and the header line's id and the reader's id are the same.
deba@1409
  1338
    virtual bool header(const std::string& line) {
deba@1409
  1339
      std::istringstream ls(line);
deba@1409
  1340
      std::string command;
deba@1409
  1341
      std::string name;
deba@1409
  1342
      ls >> command >> name;
deba@1409
  1343
      return command == "@nodes" && name == id;
deba@1409
  1344
    }
deba@1409
  1345
deba@1409
  1346
    /// \brief Reader function of the section.
deba@1409
  1347
    ///
deba@1409
  1348
    /// It reads the content of the section.
deba@1409
  1349
    virtual void read(std::istream& is) {
deba@1409
  1350
      std::string line;
deba@1409
  1351
      while (getline(is, line)) {
deba@1409
  1352
	std::istringstream ls(line);
deba@1409
  1353
	std::string id;
deba@1409
  1354
	ls >> id;
deba@1429
  1355
	typename NodeReaders::iterator it = readers.find(id);
deba@1409
  1356
	if (it != readers.end()) {
deba@1409
  1357
	  *(it->second) = idReader->read(ls); 
deba@1409
  1358
	}	
deba@1409
  1359
      }
deba@1409
  1360
    }
deba@1409
  1361
    
deba@1409
  1362
  private:
deba@1409
  1363
deba@1409
  1364
    std::string id;
deba@1409
  1365
deba@1429
  1366
    typedef std::map<std::string, Node*> NodeReaders;
deba@1429
  1367
    NodeReaders readers;
deba@1429
  1368
    std::auto_ptr<IdReaderBase<Node> > idReader;
deba@1409
  1369
  };
deba@1409
  1370
deba@1409
  1371
  /// \ingroup io_group
deba@1409
  1372
  /// \brief SectionReader for reading labeled edges.
deba@1409
  1373
  ///
deba@1409
  1374
  /// The edges section's header line is \c \@edges \c edges_id, but the
deba@1409
  1375
  /// \c edges_id may be empty.
deba@1409
  1376
  ///
deba@1409
  1377
  /// Each line in the section contains the name of the edge 
deba@1409
  1378
  /// and then the edge id. 
deba@1409
  1379
  ///
deba@1409
  1380
  /// \relates LemonReader
deba@1409
  1381
  template <typename _Graph>
deba@1409
  1382
  class EdgeReader : public CommonSectionReaderBase {
deba@1409
  1383
    typedef CommonSectionReaderBase Parent;
deba@1409
  1384
    typedef _Graph Graph;
deba@1429
  1385
    typedef typename Graph::Edge Edge;
deba@1409
  1386
  public:
deba@1409
  1387
    
deba@1409
  1388
    /// \brief Constructor.
deba@1409
  1389
    ///
deba@1409
  1390
    /// Constructor for EdgeReader. It creates the EdgeReader and
deba@1409
  1391
    /// attach it into the given LemonReader. It will use the given
deba@1409
  1392
    /// edge id reader to give back the edges. The reader will read the 
deba@1421
  1393
    /// section only if the \c _id and the \c edges_id are the same. 
deba@1409
  1394
    template <typename _IdReader>
deba@1409
  1395
    EdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
deba@1409
  1396
	       const std::string& _id = std::string()) 
deba@1409
  1397
      : Parent(_reader), id(_id), 
deba@1409
  1398
	idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {} 
deba@1409
  1399
deba@1409
  1400
    /// \brief Destructor.
deba@1409
  1401
    ///
deba@1409
  1402
    /// Destructor for EdgeReader.
deba@1409
  1403
    virtual ~EdgeReader() {}
deba@1409
  1404
  private:
deba@1409
  1405
    EdgeReader(const EdgeReader&);
deba@1409
  1406
    void operator=(const EdgeReader&);
deba@1409
  1407
deba@1409
  1408
  public:
deba@1409
  1409
deba@1409
  1410
    /// \brief Add an edge reader command for the EdgeReader.
deba@1409
  1411
    ///
deba@1409
  1412
    /// Add an edge reader command for the EdgeReader.
deba@1429
  1413
    void readEdge(const std::string& name, Edge& item) {
deba@1409
  1414
      if (readers.find(name) != readers.end()) {
deba@1409
  1415
	ErrorMessage msg;
deba@1409
  1416
	msg << "Multiple read rule for edge: " << name;
deba@1409
  1417
	throw IOParameterError(msg.message());
deba@1409
  1418
      }
deba@1409
  1419
      readers.insert(make_pair(name, &item));
deba@1409
  1420
    }
deba@1409
  1421
deba@1409
  1422
  protected:
deba@1409
  1423
deba@1409
  1424
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  1425
    /// the section with the given header line.
deba@1409
  1426
    ///
deba@1421
  1427
    /// It gives back true when the header line start with \c \@edges,
deba@1421
  1428
    /// and the header line's id and the reader's id are the same.
deba@1421
  1429
    virtual bool header(const std::string& line) {
deba@1421
  1430
      std::istringstream ls(line);
deba@1421
  1431
      std::string command;
deba@1421
  1432
      std::string name;
deba@1421
  1433
      ls >> command >> name;
deba@1421
  1434
      return command == "@edges" && name == id;
deba@1421
  1435
    }
deba@1421
  1436
deba@1421
  1437
    /// \brief Reader function of the section.
deba@1421
  1438
    ///
deba@1421
  1439
    /// It reads the content of the section.
deba@1421
  1440
    virtual void read(std::istream& is) {
deba@1421
  1441
      std::string line;
deba@1421
  1442
      while (getline(is, line)) {
deba@1421
  1443
	std::istringstream ls(line);
deba@1421
  1444
	std::string id;
deba@1421
  1445
	ls >> id;
deba@1429
  1446
	typename EdgeReaders::iterator it = readers.find(id);
deba@1421
  1447
	if (it != readers.end()) {
deba@1421
  1448
	  *(it->second) = idReader->read(ls); 
deba@1421
  1449
	}	
deba@1421
  1450
      }
deba@1421
  1451
    }
deba@1421
  1452
    
deba@1421
  1453
  private:
deba@1421
  1454
deba@1421
  1455
    std::string id;
deba@1421
  1456
deba@1429
  1457
    typedef std::map<std::string, Edge*> EdgeReaders;
deba@1429
  1458
    EdgeReaders readers;
deba@1429
  1459
    std::auto_ptr<IdReaderBase<Edge> > idReader;
deba@1421
  1460
  };
deba@1421
  1461
deba@1421
  1462
  /// \ingroup io_group
deba@1421
  1463
  /// \brief SectionReader for reading labeled undirected edges.
deba@1421
  1464
  ///
deba@1421
  1465
  /// The undirected edges section's header line is \c \@undiredges 
deba@1421
  1466
  /// \c undiredges_id, but the \c undiredges_id may be empty.
deba@1421
  1467
  ///
deba@1421
  1468
  /// Each line in the section contains the name of the undirected edge 
deba@1421
  1469
  /// and then the undirected edge id. 
deba@1421
  1470
  ///
deba@1421
  1471
  /// \relates LemonReader
deba@1421
  1472
  template <typename _Graph>
deba@1421
  1473
  class UndirEdgeReader : public CommonSectionReaderBase {
deba@1421
  1474
    typedef CommonSectionReaderBase Parent;
deba@1421
  1475
    typedef _Graph Graph;
deba@1429
  1476
    typedef typename Graph::Edge Edge;
deba@1429
  1477
    typedef typename Graph::UndirEdge UndirEdge;
deba@1421
  1478
  public:
deba@1421
  1479
    
deba@1421
  1480
    /// \brief Constructor.
deba@1421
  1481
    ///
deba@1421
  1482
    /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
deba@1421
  1483
    /// attach it into the given LemonReader. It will use the given
deba@1421
  1484
    /// undirected edge id reader to give back the edges. The reader will 
deba@1421
  1485
    /// read the section only if the \c _id and the \c undiredges_id are 
deba@1421
  1486
    /// the same. 
deba@1421
  1487
    template <typename _IdReader>
deba@1421
  1488
    UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
deba@1421
  1489
	       const std::string& _id = std::string()) 
deba@1421
  1490
      : Parent(_reader), id(_id), 
deba@1429
  1491
	undirEdgeIdReader(new IdReader<UndirEdge, _IdReader>(_idReader)),
deba@1429
  1492
	edgeIdReader(new IdReader<Edge, _IdReader>(_idReader))
deba@1421
  1493
    {} 
deba@1421
  1494
deba@1421
  1495
    /// \brief Destructor.
deba@1421
  1496
    ///
deba@1421
  1497
    /// Destructor for UndirEdgeReader.
deba@1421
  1498
    virtual ~UndirEdgeReader() {}
deba@1421
  1499
  private:
deba@1421
  1500
    UndirEdgeReader(const UndirEdgeReader&);
deba@1421
  1501
    void operator=(const UndirEdgeReader&);
deba@1421
  1502
deba@1421
  1503
  public:
deba@1421
  1504
deba@1421
  1505
    /// \brief Add an undirected edge reader command for the UndirEdgeReader.
deba@1421
  1506
    ///
deba@1421
  1507
    /// Add an undirected edge reader command for the UndirEdgeReader.
deba@1429
  1508
    void readUndirEdge(const std::string& name, UndirEdge& item) {
deba@1429
  1509
      if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) {
deba@1429
  1510
	ErrorMessage msg;
deba@1429
  1511
	msg << "Multiple read rule for undirected edge: " << name;
deba@1429
  1512
	throw IOParameterError(msg.message());
deba@1429
  1513
      }
deba@1429
  1514
      undirEdgeReaders.insert(make_pair(name, &item));
deba@1429
  1515
    }
deba@1429
  1516
deba@1429
  1517
    /// \brief Add an edge reader command for the UndirEdgeReader.
deba@1429
  1518
    ///
deba@1429
  1519
    /// Add an edge reader command for the UndirEdgeReader.
deba@1429
  1520
    void readEdge(const std::string& name, Edge& item) {
deba@1429
  1521
      if (edgeReaders.find(name) != edgeReaders.end()) {
deba@1421
  1522
	ErrorMessage msg;
deba@1421
  1523
	msg << "Multiple read rule for edge: " << name;
deba@1421
  1524
	throw IOParameterError(msg.message());
deba@1421
  1525
      }
deba@1429
  1526
      edgeReaders.insert(make_pair(name, &item));
deba@1421
  1527
    }
deba@1421
  1528
deba@1421
  1529
  protected:
deba@1421
  1530
deba@1421
  1531
    /// \brief Gives back true when the SectionReader can process 
deba@1421
  1532
    /// the section with the given header line.
deba@1421
  1533
    ///
deba@1421
  1534
    /// It gives back true when the header line start with \c \@edges,
deba@1409
  1535
    /// and the header line's id and the reader's id are the same.
deba@1409
  1536
    virtual bool header(const std::string& line) {
deba@1409
  1537
      std::istringstream ls(line);
deba@1409
  1538
      std::string command;
deba@1409
  1539
      std::string name;
deba@1409
  1540
      ls >> command >> name;
deba@1429
  1541
      return command == "@undiredges" && name == id;
deba@1409
  1542
    }
deba@1409
  1543
deba@1409
  1544
    /// \brief Reader function of the section.
deba@1409
  1545
    ///
deba@1409
  1546
    /// It reads the content of the section.
deba@1409
  1547
    virtual void read(std::istream& is) {
deba@1409
  1548
      std::string line;
deba@1409
  1549
      while (getline(is, line)) {
deba@1409
  1550
	std::istringstream ls(line);
deba@1409
  1551
	std::string id;
deba@1409
  1552
	ls >> id;
deba@1429
  1553
	{
deba@1429
  1554
	  typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id);
deba@1429
  1555
	  if (it != undirEdgeReaders.end()) {
deba@1429
  1556
	    *(it->second) = undirEdgeIdReader->read(ls); 
deba@1429
  1557
	    break;
deba@1429
  1558
	  }	
deba@1429
  1559
	} {
deba@1429
  1560
	  typename EdgeReaders::iterator it = edgeReaders.find(id);
deba@1429
  1561
	  if (it != edgeReaders.end()) {
deba@1429
  1562
	    *(it->second) = edgeIdReader->read(ls); 
deba@1429
  1563
	    break;
deba@1429
  1564
	  }	
deba@1429
  1565
	}
deba@1409
  1566
      }
deba@1409
  1567
    }
deba@1409
  1568
    
deba@1409
  1569
  private:
deba@1409
  1570
deba@1409
  1571
    std::string id;
deba@1409
  1572
deba@1429
  1573
    typedef std::map<std::string, UndirEdge*> UndirEdgeReaders;
deba@1429
  1574
    UndirEdgeReaders undirEdgeReaders;
deba@1429
  1575
    std::auto_ptr<IdReaderBase<UndirEdge> > undirEdgeIdReader;
deba@1429
  1576
deba@1429
  1577
    typedef std::map<std::string, Edge*> EdgeReaders;
deba@1429
  1578
    EdgeReaders edgeReaders;
deba@1429
  1579
    std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
deba@1409
  1580
  };
deba@1409
  1581
deba@1409
  1582
  /// \ingroup io_group
deba@1409
  1583
  /// \brief SectionReader for attributes.
deba@1409
  1584
  ///
deba@1409
  1585
  /// The lemon format can store multiple attribute set. Each set has
deba@1409
  1586
  /// the header line \c \@attributes \c attributeset_id, but the 
deba@1409
  1587
  /// attributeset_id may be empty.
deba@1409
  1588
  ///
deba@1409
  1589
  /// The attributeset section contains several lines. Each of them starts
deba@1409
  1590
  /// with an attribute and then a the value for the id.
deba@1409
  1591
  ///
deba@1409
  1592
  /// \relates LemonReader
deba@1408
  1593
  template <typename _Traits = DefaultReaderTraits>
deba@1408
  1594
  class AttributeReader : public CommonSectionReaderBase {
deba@1408
  1595
    typedef CommonSectionReaderBase Parent;
deba@1408
  1596
    typedef _Traits Traits; 
deba@1408
  1597
  public:
deba@1409
  1598
    /// \brief Constructor.
deba@1409
  1599
    ///
deba@1409
  1600
    /// Constructor for AttributeReader. It creates the AttributeReader and
deba@1409
  1601
    /// attach it into the given LemonReader. The reader process a section
deba@1409
  1602
    /// only if the \c section_id and the \c _id are the same.
deba@1408
  1603
    AttributeReader(LemonReader& _reader, 
deba@1409
  1604
		    const std::string& _id = std::string()) 
deba@1409
  1605
      : Parent(_reader), id(_id) {}
deba@1408
  1606
deba@1409
  1607
    /// \brief Destructor.
deba@1409
  1608
    ///
deba@1409
  1609
    /// Destructor for AttributeReader.
deba@1408
  1610
    virtual ~AttributeReader() {
deba@1408
  1611
      for (typename Readers::iterator it = readers.begin(); 
deba@1408
  1612
	   it != readers.end(); ++it) {
deba@1408
  1613
	delete it->second;
deba@1408
  1614
      }
deba@1408
  1615
    }
deba@1408
  1616
deba@1408
  1617
  private:
deba@1408
  1618
    AttributeReader(const AttributeReader&);
deba@1408
  1619
    void operator=(AttributeReader&);
deba@1408
  1620
deba@1408
  1621
  public:
deba@1409
  1622
    /// \brief Add an attribute reader command for the reader.
deba@1409
  1623
    ///
deba@1409
  1624
    /// Add an attribute reader command for the reader.
deba@1408
  1625
    template <typename Value>
deba@1408
  1626
    AttributeReader& readAttribute(const std::string& id, Value& value) {
deba@1408
  1627
      return readAttribute<typename Traits::template Reader<Value> >
deba@1408
  1628
	(id, value);
deba@1408
  1629
    }
deba@1408
  1630
deba@1409
  1631
    /// \brief Add an attribute reader command for the reader.
deba@1409
  1632
    ///
deba@1409
  1633
    /// Add an attribute reader command for the reader.
deba@1408
  1634
    template <typename Reader, typename Value>
deba@1408
  1635
    AttributeReader& readAttribute(const std::string& name, Value& value,
deba@1408
  1636
				   const Reader& reader = Reader()) {
deba@1408
  1637
      if (readers.find(name) != readers.end()) {
deba@1408
  1638
	ErrorMessage msg;
deba@1408
  1639
	msg << "Multiple read rule for attribute: " << name;
deba@1408
  1640
	throw IOParameterError(msg.message());
deba@1408
  1641
      }
deba@1408
  1642
      readers.insert(make_pair(name, new ValueReader<Value, Reader>
deba@1408
  1643
      			       (value, reader)));
deba@1408
  1644
      return *this;
deba@1408
  1645
    }
deba@1408
  1646
deba@1409
  1647
  protected:
deba@1409
  1648
deba@1409
  1649
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  1650
    /// the section with the given header line.
deba@1409
  1651
    ///
deba@1421
  1652
    /// It gives back true when the header line start with \c \@attributes,
deba@1409
  1653
    /// and the header line's id and the attributeset's id are the same.
deba@1408
  1654
    bool header(const std::string& line) {
deba@1408
  1655
      std::istringstream ls(line);
deba@1408
  1656
      std::string command;
deba@1408
  1657
      std::string name;
deba@1408
  1658
      ls >> command >> name;
deba@1408
  1659
      return command == "@attributes" && name == id;
deba@1408
  1660
    }
deba@1408
  1661
deba@1409
  1662
    /// \brief Reader function of the section.
deba@1409
  1663
    ///
deba@1409
  1664
    /// It reads the content of the section.
deba@1408
  1665
    void read(std::istream& is) {
deba@1408
  1666
      std::string line;
deba@1408
  1667
      while (getline(is, line)) {
deba@1408
  1668
	std::istringstream ls(line);
deba@1408
  1669
	std::string id;
deba@1408
  1670
	ls >> id;
deba@1408
  1671
	typename Readers::iterator it = readers.find(id);
deba@1408
  1672
	if (it != readers.end()) {
deba@1408
  1673
	  it->second->read(ls);
deba@1408
  1674
	}
deba@1408
  1675
      }
deba@1408
  1676
    }    
deba@1408
  1677
deba@1408
  1678
  private:
deba@1408
  1679
    std::string id;
deba@1408
  1680
deba@1408
  1681
    typedef std::map<std::string, ValueReaderBase*> Readers;
deba@1409
  1682
    Readers readers;  
deba@1408
  1683
  };
deba@1408
  1684
deba@1423
  1685
  /// \ingroup io_group
deba@1423
  1686
  /// \brief SectionReader for retrieve what is in the file.
deba@1423
  1687
  ///
deba@1423
  1688
  /// SectionReader for retrieve what is in the file. If you want
deba@1423
  1689
  /// to know which sections, maps and items are in the file
deba@1423
  1690
  /// use the next code:
deba@1423
  1691
  /// \code
deba@1423
  1692
  /// LemonReader reader("input.lgf");
deba@1423
  1693
  /// ContentReader content(reader);
deba@1423
  1694
  /// reader.run();
deba@1423
  1695
  /// \endcode
deba@1423
  1696
  class ContentReader : public LemonReader::SectionReader {
deba@1423
  1697
    typedef LemonReader::SectionReader Parent;
deba@1423
  1698
  public:
deba@1423
  1699
    /// \brief Constructor.
deba@1423
  1700
    ///
deba@1423
  1701
    /// Constructor for
deba@1423
  1702
    ContentReader(LemonReader& _reader) : Parent(_reader) {}
deba@1423
  1703
deba@1423
  1704
    /// \brief Desctructor.
deba@1423
  1705
    ///
deba@1423
  1706
    /// Desctructor.
deba@1423
  1707
    virtual ~ContentReader() {}
deba@1423
  1708
deba@1423
  1709
    /// \brief Gives back how many nodesets are in the file.
deba@1423
  1710
    ///
deba@1423
  1711
    /// Gives back how many nodesets are in the file.
deba@1423
  1712
    int nodeSetNum() const {
deba@1423
  1713
      return nodesets.size();
deba@1423
  1714
    }
deba@1423
  1715
deba@1423
  1716
    /// \brief Gives back the name of nodeset on the indiced position.
deba@1423
  1717
    ///
deba@1423
  1718
    /// Gives back the name of nodeset on the indiced position.
deba@1423
  1719
    std::string nodeSetName(int index) const {
deba@1423
  1720
      return nodesets[index].name;
deba@1423
  1721
    }
deba@1423
  1722
deba@1423
  1723
    /// \brief Gives back the map names of nodeset on the indiced position.
deba@1423
  1724
    ///
deba@1423
  1725
    /// Gives back the map names of nodeset on the indiced position.
deba@1423
  1726
    const std::vector<std::string>& nodeSetMaps(int index) const {
deba@1423
  1727
      return nodesets[index].items;
deba@1423
  1728
    }
deba@1423
  1729
deba@1423
  1730
    /// \brief Gives back how many edgesets are in the file.
deba@1423
  1731
    ///
deba@1423
  1732
    /// Gives back how many edgesets are in the file.
deba@1423
  1733
    int edgeSetNum() const {
deba@1423
  1734
      return edgesets.size();
deba@1423
  1735
    }
deba@1423
  1736
deba@1423
  1737
    /// \brief Gives back the name of edgeset on the indiced position.
deba@1423
  1738
    ///
deba@1423
  1739
    /// Gives back the name of edgeset on the indiced position.
deba@1423
  1740
    std::string edgeSetName(int index) const {
deba@1423
  1741
      return edgesets[index].name;
deba@1423
  1742
    }
deba@1423
  1743
deba@1423
  1744
    /// \brief Gives back the map names of edgeset on the indiced position.
deba@1423
  1745
    ///
deba@1423
  1746
    /// Gives back the map names of edgeset on the indiced position.
deba@1423
  1747
    const std::vector<std::string>& edgeSetMaps(int index) const {
deba@1423
  1748
      return edgesets[index].items;
deba@1423
  1749
    }
deba@1423
  1750
deba@1423
  1751
    /// \brief Gives back how many undirected edgesets are in the file.
deba@1423
  1752
    ///
deba@1423
  1753
    /// Gives back how many undirected edgesets are in the file.
deba@1423
  1754
    int undirEdgeSetNum() const {
deba@1423
  1755
      return undiredgesets.size();
deba@1423
  1756
    }
deba@1423
  1757
deba@1423
  1758
    /// \brief Gives back the name of undirected edgeset on the indiced 
deba@1423
  1759
    /// position.
deba@1423
  1760
    ///
deba@1423
  1761
    /// Gives back the name of undirected edgeset on the indiced position.
deba@1423
  1762
    std::string undirEdgeSetName(int index) const {
deba@1423
  1763
      return undiredgesets[index].name;
deba@1423
  1764
    }
deba@1423
  1765
deba@1423
  1766
    /// \brief Gives back the map names of undirected edgeset on the indiced 
deba@1423
  1767
    /// position.
deba@1423
  1768
    ///
deba@1423
  1769
    /// Gives back the map names of undirected edgeset on the indiced position.
deba@1423
  1770
    const std::vector<std::string>& undirEdgeSetMaps(int index) const {
deba@1423
  1771
      return undiredgesets[index].items;
deba@1423
  1772
    }
deba@1423
  1773
deba@1423
  1774
    /// \brief Gives back how many labeled nodes section are in the file.
deba@1423
  1775
    ///
deba@1423
  1776
    /// Gives back how many labeled nodes section are in the file.
deba@1423
  1777
    int nodesNum() const {
deba@1423
  1778
      return nodes.size();
deba@1423
  1779
    }
deba@1423
  1780
deba@1423
  1781
    /// \brief Gives back the name of labeled nodes section on the indiced 
deba@1423
  1782
    /// position.
deba@1423
  1783
    ///
deba@1423
  1784
    /// Gives back the name of labeled nodes section on the indiced position.
deba@1423
  1785
    std::string nodesName(int index) const {
deba@1423
  1786
      return nodes[index].name;
deba@1423
  1787
    }
deba@1423
  1788
deba@1423
  1789
    /// \brief Gives back the names of the labeled nodes in the indiced 
deba@1423
  1790
    /// section.
deba@1423
  1791
    ///
deba@1423
  1792
    /// Gives back the names of the labeled nodes in the indiced section.
deba@1423
  1793
    const std::vector<std::string>& nodesItems(int index) const {
deba@1423
  1794
      return nodes[index].items;
deba@1423
  1795
    }
deba@1423
  1796
deba@1423
  1797
    /// \brief Gives back how many labeled edges section are in the file.
deba@1423
  1798
    ///
deba@1423
  1799
    /// Gives back how many labeled edges section are in the file.
deba@1423
  1800
    int edgesNum() const {
deba@1423
  1801
      return edges.size();
deba@1423
  1802
    }
deba@1423
  1803
deba@1423
  1804
    /// \brief Gives back the name of labeled edges section on the indiced 
deba@1423
  1805
    /// position.
deba@1423
  1806
    ///
deba@1423
  1807
    /// Gives back the name of labeled edges section on the indiced position.
deba@1423
  1808
    std::string edgesName(int index) const {
deba@1423
  1809
      return edges[index].name;
deba@1423
  1810
    }
deba@1423
  1811
deba@1423
  1812
    /// \brief Gives back the names of the labeled edges in the indiced 
deba@1423
  1813
    /// section.
deba@1423
  1814
    ///
deba@1423
  1815
    /// Gives back the names of the labeled edges in the indiced section.
deba@1423
  1816
    const std::vector<std::string>& edgesItems(int index) const {
deba@1423
  1817
      return edges[index].items;
deba@1423
  1818
    }
deba@1423
  1819
 
deba@1423
  1820
    /// \brief Gives back how many labeled undirected edges section are 
deba@1423
  1821
    /// in the file.
deba@1423
  1822
    ///
deba@1423
  1823
    /// Gives back how many labeled undirected edges section are in the file.
deba@1423
  1824
    int undirEdgesNum() const {
deba@1423
  1825
      return undiredges.size();
deba@1423
  1826
    }
deba@1423
  1827
deba@1423
  1828
    /// \brief Gives back the name of labeled undirected edges section 
deba@1423
  1829
    /// on the indiced position.
deba@1423
  1830
    ///
deba@1423
  1831
    /// Gives back the name of labeled undirected edges section on the 
deba@1423
  1832
    /// indiced position.
deba@1423
  1833
    std::string undirEdgesName(int index) const {
deba@1423
  1834
      return undiredges[index].name;
deba@1423
  1835
    }
deba@1423
  1836
deba@1423
  1837
    /// \brief Gives back the names of the labeled undirected edges in 
deba@1423
  1838
    /// the indiced section.
deba@1423
  1839
    ///
deba@1423
  1840
    /// Gives back the names of the labeled undirected edges in the 
deba@1423
  1841
    /// indiced section.
deba@1423
  1842
    const std::vector<std::string>& undirEdgesItems(int index) const {
deba@1423
  1843
      return undiredges[index].items;
deba@1423
  1844
    }
deba@1423
  1845
deba@1423
  1846
 
deba@1423
  1847
    /// \brief Gives back how many attributes section are in the file.
deba@1423
  1848
    ///
deba@1423
  1849
    /// Gives back how many attributes section are in the file.
deba@1423
  1850
    int attributesNum() const {
deba@1423
  1851
      return attributes.size();
deba@1423
  1852
    }
deba@1423
  1853
deba@1423
  1854
    /// \brief Gives back the name of attributes section on the indiced 
deba@1423
  1855
    /// position.
deba@1423
  1856
    ///
deba@1423
  1857
    /// Gives back the name of attributes section on the indiced position.
deba@1423
  1858
    std::string attributesName(int index) const {
deba@1423
  1859
      return attributes[index].name;
deba@1423
  1860
    }
deba@1423
  1861
deba@1423
  1862
    /// \brief Gives back the names of the attributes in the indiced section.
deba@1423
  1863
    ///
deba@1423
  1864
    /// Gives back the names of the attributes in the indiced section.
deba@1423
  1865
    const std::vector<std::string>& attributesItems(int index) const {
deba@1423
  1866
      return attributes[index].items;
deba@1423
  1867
    }
deba@1423
  1868
deba@1423
  1869
    const std::vector<std::string>& otherSections() const {
deba@1423
  1870
      return sections;
deba@1423
  1871
    }
deba@1423
  1872
deba@1423
  1873
  protected:
deba@1423
  1874
    
deba@1423
  1875
    /// \brief Gives back true when the SectionReader can process 
deba@1423
  1876
    /// the section with the given header line.
deba@1423
  1877
    ///
deba@1423
  1878
    /// It gives back true when the section is common section.
deba@1423
  1879
    bool header(const std::string& line) {
deba@1423
  1880
      std::istringstream ls(line);
deba@1423
  1881
      std::string command, name;
deba@1423
  1882
      ls >> command >> name;
deba@1423
  1883
      if (command == "@nodeset") {
deba@1423
  1884
	current = command;
deba@1423
  1885
	nodesets.push_back(SectionInfo(name));
deba@1423
  1886
      } else if (command == "@edgeset") {
deba@1423
  1887
	current = command;
deba@1423
  1888
	edgesets.push_back(SectionInfo(name));
deba@1423
  1889
      } else if (command == "@undiredgeset") {
deba@1423
  1890
	current = command;
deba@1423
  1891
	undiredgesets.push_back(SectionInfo(name));
deba@1423
  1892
      } else if (command == "@nodes") {
deba@1423
  1893
	current = command;
deba@1423
  1894
	nodes.push_back(SectionInfo(name));
deba@1423
  1895
      } else if (command == "@edges") {
deba@1423
  1896
	current = command;
deba@1423
  1897
	edges.push_back(SectionInfo(name));
deba@1423
  1898
      } else if (command == "@undiredges") {
deba@1423
  1899
	current = command;
deba@1423
  1900
	undiredges.push_back(SectionInfo(name));
deba@1423
  1901
      } else if (command == "@attributes") {
deba@1423
  1902
	current = command;
deba@1423
  1903
	attributes.push_back(SectionInfo(name));
deba@1423
  1904
      } else {
deba@1423
  1905
	sections.push_back(line);
deba@1423
  1906
	return false;
deba@1423
  1907
      }
deba@1423
  1908
      return true;
deba@1423
  1909
    }
deba@1423
  1910
deba@1423
  1911
    /// \brief Retrieve the items from various sections.
deba@1423
  1912
    ///
deba@1423
  1913
    /// Retrieve the items from various sections.
deba@1423
  1914
    void read(std::istream& is) {
deba@1423
  1915
      if (current == "@nodeset") {
deba@1423
  1916
	readMapNames(is, nodesets.back().items);
deba@1423
  1917
      } else if (current == "@edgeset") {
deba@1423
  1918
	readMapNames(is, edgesets.back().items);
deba@1423
  1919
      } else if (current == "@undiredgeset") {
deba@1423
  1920
	readMapNames(is, undiredgesets.back().items);
deba@1423
  1921
      } else if (current == "@nodes") {
deba@1423
  1922
	readItemNames(is, nodes.back().items);
deba@1423
  1923
      } else if (current == "@edges") {
deba@1423
  1924
	readItemNames(is, edges.back().items);
deba@1423
  1925
      } else if (current == "@undiredges") {
deba@1423
  1926
	readItemNames(is, undiredges.back().items);
deba@1423
  1927
      } else if (current == "@attributes") {
deba@1423
  1928
	readItemNames(is, attributes.back().items);
deba@1423
  1929
      }
deba@1423
  1930
    }    
deba@1423
  1931
deba@1423
  1932
  private:
deba@1423
  1933
deba@1423
  1934
    void readMapNames(std::istream& is, std::vector<std::string>& maps) {
deba@1423
  1935
      std::string line, id;
deba@1423
  1936
      std::getline(is, line);
deba@1423
  1937
      std::istringstream ls(line);
deba@1423
  1938
      while (ls >> id) {
deba@1423
  1939
	maps.push_back(id);
deba@1423
  1940
      }
deba@1423
  1941
      while (getline(is, line));
deba@1423
  1942
    }
deba@1423
  1943
deba@1423
  1944
    void readItemNames(std::istream& is, std::vector<std::string>& maps) {
deba@1423
  1945
      std::string line, id;
deba@1423
  1946
      while (std::getline(is, line)) {
deba@1423
  1947
	std::istringstream ls(line);
deba@1423
  1948
	ls >> id;
deba@1423
  1949
	maps.push_back(id);
deba@1423
  1950
      }
deba@1423
  1951
    }
deba@1423
  1952
deba@1423
  1953
    struct SectionInfo {
deba@1423
  1954
      std::string name;
deba@1423
  1955
      std::vector<std::string> items;
deba@1423
  1956
deba@1423
  1957
      SectionInfo(const std::string& _name) : name(_name) {}
deba@1423
  1958
    };
deba@1423
  1959
deba@1423
  1960
    std::vector<SectionInfo> nodesets;
deba@1423
  1961
    std::vector<SectionInfo> edgesets;
deba@1423
  1962
    std::vector<SectionInfo> undiredgesets;
deba@1423
  1963
deba@1423
  1964
    std::vector<SectionInfo> nodes;
deba@1423
  1965
    std::vector<SectionInfo> edges;
deba@1423
  1966
    std::vector<SectionInfo> undiredges;
deba@1423
  1967
deba@1423
  1968
    std::vector<SectionInfo> attributes;
deba@1423
  1969
deba@1423
  1970
    std::vector<std::string> sections;
deba@1423
  1971
deba@1423
  1972
    std::string current;
deba@1423
  1973
deba@1423
  1974
  };
deba@1423
  1975
deba@1408
  1976
}
deba@1408
  1977
#endif