src/lemon/lemon_reader.h
author deba
Sat, 14 May 2005 17:39:37 +0000
changeset 1421 7a21e1414c38
parent 1409 d2d1f8fa187b
child 1423 78502c63f771
permissions -rw-r--r--
IO with undirected edgesets and undirected graphs.
Missing features:
InfoReader,
aliased edges in undir edgesets
deba@1408
     1
/* -*- C++ -*-
deba@1408
     2
 * src/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@1409
   102
  /// The file format ignore the empty lines and it may contain comments
deba@1409
   103
  /// started with a \c # character to the end of the line. 
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@1409
   111
  /// with a stream contains the section. From this stream the empty lines
deba@1409
   112
  /// and comments 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_comment,
deba@1408
   137
	after_endl,
deba@1408
   138
	empty_line
deba@1408
   139
      };
deba@1408
   140
deba@1408
   141
      char_type small_buf[1];
deba@1408
   142
deba@1408
   143
deba@1408
   144
      std::istream& _is;
deba@1408
   145
deba@1408
   146
      char_type* _base;
deba@1408
   147
      char_type* _eptr;
deba@1408
   148
deba@1408
   149
      int& _num;
deba@1408
   150
deba@1408
   151
      skip_state_type skip_state;
deba@1408
   152
deba@1408
   153
deba@1408
   154
      char_type* base() { return _base; }
deba@1408
   155
deba@1408
   156
      char_type* eptr() { return _eptr; }
deba@1408
   157
deba@1408
   158
      int blen() { return _eptr - _base; }
deba@1408
   159
deba@1408
   160
      void setb(char_type* buf, int len) {
deba@1408
   161
	_base = buf;
deba@1408
   162
	_eptr = buf + len;
deba@1408
   163
      }
deba@1408
   164
  
deba@1408
   165
      virtual std::streambuf* setbuf(char *buf, int len) {
deba@1408
   166
	if (base()) return 0;
deba@1408
   167
	if (buf != 0 && len >= (int)sizeof(small_buf)) {
deba@1408
   168
	  setb(buf, len);
deba@1408
   169
	} else {
deba@1408
   170
	  setb(small_buf, sizeof(small_buf));
deba@1408
   171
	}
deba@1408
   172
	setg(0, 0, 0);
deba@1408
   173
	return this;
deba@1408
   174
      }
deba@1408
   175
deba@1408
   176
      bool put_char(char c) {
deba@1408
   177
	switch (skip_state) {
deba@1408
   178
	case no_skip:
deba@1408
   179
	  switch (c) {
deba@1408
   180
	  case '\n': 
deba@1408
   181
	    skip_state = after_endl;
deba@1408
   182
	    return true;
deba@1408
   183
	  case '#':
deba@1408
   184
	    skip_state = after_comment;
deba@1408
   185
	    return false;
deba@1408
   186
	  default:
deba@1408
   187
	    return true;
deba@1408
   188
	  }
deba@1408
   189
	case after_comment:
deba@1408
   190
	  switch (c) {
deba@1408
   191
	  case '\n': 
deba@1408
   192
	    skip_state = after_endl;
deba@1408
   193
	    return true;
deba@1408
   194
	  default:
deba@1408
   195
	    return false;
deba@1408
   196
	  }        
deba@1408
   197
	case after_endl:
deba@1408
   198
	  switch (c) {
deba@1408
   199
	  case '@':
deba@1408
   200
	    return false;
deba@1408
   201
	  case '\n': 
deba@1408
   202
	    return false;
deba@1408
   203
	  case '#':
deba@1408
   204
	    skip_state = empty_line;
deba@1408
   205
	    return false;
deba@1408
   206
	  default:
deba@1408
   207
	    if (!isspace(c)) {
deba@1408
   208
	      skip_state = no_skip;
deba@1408
   209
	      return true;
deba@1408
   210
	    } else {
deba@1408
   211
	      return false;
deba@1408
   212
	    }
deba@1408
   213
	  }
deba@1408
   214
	  break;
deba@1408
   215
	case empty_line:
deba@1408
   216
	  switch (c) {
deba@1408
   217
	  case '\n': 
deba@1408
   218
	    skip_state = after_endl;
deba@1408
   219
	    return false;
deba@1408
   220
	  default:
deba@1408
   221
	    return false;
deba@1408
   222
	  }
deba@1408
   223
	}
deba@1408
   224
	return false;
deba@1408
   225
      }
deba@1408
   226
deba@1408
   227
      virtual int underflow() {
deba@1408
   228
	char c;
deba@1408
   229
	if (_is.read(&c, 1)) {
deba@1408
   230
	  _is.putback(c);
deba@1408
   231
	  if (c == '@') {
deba@1408
   232
	    return EOF;
deba@1408
   233
	  }
deba@1408
   234
	} else {
deba@1408
   235
	  return EOF;
deba@1408
   236
	}
deba@1408
   237
	char_type *ptr;
deba@1408
   238
	for (ptr = base(); ptr != eptr(); ++ptr) {
deba@1408
   239
	  if (_is.read(&c, 1)) {
deba@1408
   240
	    if (c == '\n') ++_num;
deba@1408
   241
	    if (put_char(c)) {
deba@1408
   242
	      *ptr = c;
deba@1408
   243
	    } else {
deba@1408
   244
	      if (skip_state == after_endl && c == '@') {
deba@1408
   245
		_is.putback('@');
deba@1408
   246
		break;
deba@1408
   247
	      }
deba@1408
   248
	      --ptr;
deba@1408
   249
	    }
deba@1408
   250
	  } else {
deba@1408
   251
	    break;
deba@1408
   252
	  }
deba@1408
   253
	}
deba@1408
   254
	setg(base(), base(), ptr);
deba@1408
   255
	return *base();
deba@1408
   256
      }
deba@1408
   257
deba@1408
   258
      virtual int sync() {
deba@1408
   259
	return EOF;
deba@1408
   260
      }
deba@1408
   261
    };
deba@1408
   262
deba@1408
   263
  public:
deba@1408
   264
deba@1409
   265
    /// \brief Abstract base class for reading a section.
deba@1409
   266
    ///
deba@1409
   267
    /// This class has an \c header() member function what get a 
deba@1409
   268
    /// header line string and decides if it want to process the next 
deba@1409
   269
    /// section. Several SectionReaders can be attached to an LemonReader 
deba@1409
   270
    /// and the first attached what can process the section will be used. 
deba@1409
   271
    /// Its \c read() member will called with a stream contains the section. 
deba@1409
   272
    /// From this stream the empty lines and comments are filtered out.
deba@1408
   273
    class SectionReader {
deba@1409
   274
      friend class LemonReader;
deba@1409
   275
    protected:
deba@1409
   276
      /// \brief Constructor for SectionReader.
deba@1409
   277
      ///
deba@1409
   278
      /// Constructor for SectionReader. It attach this reader to
deba@1409
   279
      /// the given LemonReader.
deba@1409
   280
      SectionReader(LemonReader& reader) {
deba@1409
   281
	reader.attach(*this);
deba@1409
   282
      }
deba@1409
   283
deba@1409
   284
      /// \brief Gives back true when the SectionReader can process 
deba@1409
   285
      /// the section with the given header line.
deba@1409
   286
      ///
deba@1409
   287
      /// It gives back true when the SectionReader can process
deba@1409
   288
      /// the section with the given header line.
deba@1408
   289
      virtual bool header(const std::string& line) = 0;
deba@1409
   290
deba@1409
   291
      /// \brief Reader function of the section.
deba@1409
   292
      ///
deba@1409
   293
      /// It reads the content of the section.
deba@1408
   294
      virtual void read(std::istream& is) = 0;
deba@1408
   295
    };
deba@1408
   296
deba@1409
   297
    /// \brief Constructor for LemonReader.
deba@1409
   298
    ///
deba@1409
   299
    /// Constructor for LemonReader which reads from the given stream.
deba@1408
   300
    LemonReader(std::istream& _is) 
deba@1408
   301
      : is(&_is), own_is(false) {}
deba@1408
   302
deba@1409
   303
    /// \brief Constructor for LemonReader.
deba@1409
   304
    ///
deba@1409
   305
    /// Constructor for LemonReader which reads from the given file.
deba@1408
   306
    LemonReader(const std::string& filename) 
deba@1408
   307
      : is(0), own_is(true) {
deba@1408
   308
      is = new std::ifstream(filename.c_str());
deba@1408
   309
    }
deba@1408
   310
deba@1409
   311
    /// \brief Desctructor for LemonReader.
deba@1409
   312
    ///
deba@1409
   313
    /// Desctructor for LemonReader.
deba@1408
   314
    ~LemonReader() {
deba@1408
   315
      if (own_is) {
deba@1408
   316
	delete is;
deba@1408
   317
      }
deba@1408
   318
    }
deba@1408
   319
deba@1408
   320
  private:
deba@1408
   321
    LemonReader(const LemonReader&);
deba@1408
   322
    void operator=(const LemonReader&);
deba@1408
   323
deba@1408
   324
    void attach(SectionReader& reader) {
deba@1408
   325
      readers.push_back(&reader);
deba@1408
   326
    }
deba@1408
   327
deba@1409
   328
  public:
deba@1409
   329
    /// \brief Executes the LemonReader.
deba@1409
   330
    /// 
deba@1409
   331
    /// It executes the LemonReader.
deba@1408
   332
    void run() {
deba@1408
   333
      int line_num = 0;
deba@1408
   334
      std::string line;
deba@1408
   335
      try {
deba@1408
   336
	while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
deba@1408
   337
	  SectionReaders::iterator it;
deba@1408
   338
	  for (it = readers.begin(); it != readers.end(); ++it) {
deba@1408
   339
	    if ((*it)->header(line)) {
deba@1408
   340
	      char buf[2048];
deba@1408
   341
	      FilterStreamBuf buffer(*is, line_num);
deba@1408
   342
	      buffer.pubsetbuf(buf, sizeof(buf));
deba@1408
   343
	      std::istream is(&buffer);
deba@1408
   344
	      (*it)->read(is);
deba@1408
   345
	      break;
deba@1408
   346
	    }
deba@1408
   347
	  }
deba@1408
   348
	}
deba@1408
   349
      } catch (DataFormatError& error) {
deba@1408
   350
	error.line(line_num);
deba@1408
   351
	throw error;
deba@1408
   352
      }	
deba@1408
   353
    }
deba@1408
   354
deba@1408
   355
deba@1408
   356
  private:
deba@1408
   357
deba@1408
   358
    std::istream* is;
deba@1408
   359
    bool own_is;
deba@1408
   360
deba@1408
   361
    typedef std::vector<SectionReader*> SectionReaders;
deba@1408
   362
    SectionReaders readers;
deba@1408
   363
deba@1408
   364
  };
deba@1408
   365
deba@1409
   366
  /// \brief Helper class for implementing the common SectionReaders.
deba@1409
   367
  ///
deba@1409
   368
  /// Helper class for implementing the common SectionReaders.
deba@1409
   369
  class CommonSectionReaderBase : public LemonReader::SectionReader {
deba@1409
   370
    typedef LemonReader::SectionReader Parent;
deba@1409
   371
  protected:
deba@1409
   372
    
deba@1409
   373
    /// \brief Constructor for CommonSectionReaderBase.
deba@1409
   374
    ///
deba@1409
   375
    /// Constructor for CommonSectionReaderBase. It attach this reader to
deba@1409
   376
    /// the given LemonReader.
deba@1409
   377
    CommonSectionReaderBase(LemonReader& _reader) 
deba@1409
   378
      : Parent(_reader) {}
deba@1408
   379
deba@1408
   380
    template <typename _Item>
deba@1408
   381
    class ReaderBase;
deba@1408
   382
    
deba@1408
   383
    template <typename _Item>
deba@1408
   384
    class InverterBase : public ReaderBase<_Item> {
deba@1408
   385
    public:
deba@1408
   386
      typedef _Item Item;
deba@1408
   387
      virtual void read(std::istream&, const Item&) = 0;
deba@1408
   388
      virtual Item read(std::istream&) const = 0;
deba@1408
   389
deba@1408
   390
      virtual InverterBase<_Item>* getInverter() {
deba@1408
   391
	return this;
deba@1408
   392
      }
deba@1408
   393
    };
deba@1408
   394
deba@1408
   395
    template <typename _Item, typename _Map, typename _Reader>
deba@1408
   396
    class MapReaderInverter : public InverterBase<_Item> {
deba@1408
   397
    public:
deba@1408
   398
      typedef _Item Item;
deba@1408
   399
      typedef _Reader Reader;
deba@1408
   400
      typedef typename Reader::Value Value;
deba@1408
   401
      typedef _Map Map;
deba@1421
   402
      typedef std::map<Value, Item, 
deba@1421
   403
		       typename _reader_bits::template Less<Value> > Inverse;
deba@1408
   404
deba@1421
   405
      typename SmartReference<Map>::Type map;
deba@1408
   406
      Reader reader;
deba@1408
   407
      Inverse inverse;
deba@1408
   408
deba@1421
   409
      MapReaderInverter(typename SmartParameter<Map>::Type _map,
deba@1421
   410
			const Reader& _reader) 
deba@1408
   411
	: map(_map), reader(_reader) {}
deba@1408
   412
deba@1408
   413
      virtual ~MapReaderInverter() {}
deba@1408
   414
deba@1408
   415
      virtual void read(std::istream& is, const Item& item) {
deba@1408
   416
	Value value;
deba@1408
   417
	reader.read(is, value);
deba@1408
   418
	map.set(item, value);
deba@1408
   419
	typename Inverse::iterator it = inverse.find(value);
deba@1408
   420
	if (it == inverse.end()) {
deba@1408
   421
	  inverse.insert(std::make_pair(value, item));
deba@1408
   422
	} else {
deba@1408
   423
	  throw DataFormatError("Multiple ID occurence");
deba@1408
   424
	}
deba@1408
   425
      }
deba@1408
   426
deba@1408
   427
      virtual Item read(std::istream& is) const {
deba@1408
   428
	Value value;
deba@1408
   429
	reader.read(is, value);	
deba@1408
   430
	typename Inverse::const_iterator it = inverse.find(value);
deba@1408
   431
	if (it != inverse.end()) {
deba@1408
   432
	  return it->second;
deba@1408
   433
	} else {
deba@1408
   434
	  throw DataFormatError("Invalid ID error");
deba@1408
   435
	}
deba@1408
   436
      }      
deba@1408
   437
    };
deba@1408
   438
deba@1408
   439
    template <typename _Item, typename _Reader>
deba@1408
   440
    class SkipReaderInverter : public InverterBase<_Item> {
deba@1408
   441
    public:
deba@1408
   442
      typedef _Item Item;
deba@1408
   443
      typedef _Reader Reader;
deba@1408
   444
      typedef typename Reader::Value Value;
deba@1421
   445
      typedef std::map<Value, Item, 
deba@1421
   446
		       typename _reader_bits::template Less<Value> > Inverse;
deba@1408
   447
deba@1408
   448
      Reader reader;
deba@1408
   449
deba@1408
   450
      SkipReaderInverter(const Reader& _reader) 
deba@1408
   451
	: reader(_reader) {}
deba@1408
   452
deba@1408
   453
      virtual ~SkipReaderInverter() {}
deba@1408
   454
deba@1408
   455
      virtual void read(std::istream& is, const Item& item) {
deba@1408
   456
	Value value;
deba@1408
   457
	reader.read(is, value);
deba@1408
   458
	typename Inverse::iterator it = inverse.find(value);
deba@1408
   459
	if (it == inverse.end()) {
deba@1408
   460
	  inverse.insert(std::make_pair(value, item));
deba@1408
   461
	} else {
deba@1408
   462
	  throw DataFormatError("Multiple ID occurence error");
deba@1408
   463
	}
deba@1408
   464
      }
deba@1408
   465
deba@1408
   466
      virtual Item read(std::istream& is) const {
deba@1408
   467
	Value value;
deba@1408
   468
	reader.read(is, value);	
deba@1408
   469
	typename Inverse::const_iterator it = inverse.find(value);
deba@1408
   470
	if (it != inverse.end()) {
deba@1408
   471
	  return it->second;
deba@1408
   472
	} else {
deba@1408
   473
	  throw DataFormatError("Invalid ID error");
deba@1408
   474
	}
deba@1408
   475
      }
deba@1408
   476
deba@1408
   477
    private:
deba@1408
   478
      Inverse inverse;
deba@1408
   479
    };
deba@1408
   480
deba@1408
   481
    template <typename _Item>    
deba@1408
   482
    class ReaderBase {
deba@1408
   483
    public:
deba@1408
   484
      typedef _Item Item;
deba@1408
   485
deba@1408
   486
      virtual ~ReaderBase() {}
deba@1408
   487
deba@1408
   488
      virtual void read(std::istream& is, const Item& item) = 0;
deba@1408
   489
      virtual InverterBase<_Item>* getInverter() = 0;
deba@1408
   490
    };
deba@1408
   491
deba@1408
   492
    template <typename _Item, typename _Map, typename _Reader>
deba@1408
   493
    class MapReader : public ReaderBase<_Item> {
deba@1408
   494
    public:
deba@1408
   495
      typedef _Map Map;
deba@1408
   496
      typedef _Reader Reader;
deba@1408
   497
      typedef typename Reader::Value Value;
deba@1408
   498
      typedef _Item Item;
deba@1408
   499
      
deba@1421
   500
      typename SmartReference<Map>::Type map;
deba@1408
   501
      Reader reader;
deba@1408
   502
deba@1421
   503
      MapReader(typename SmartParameter<Map>::Type _map, 
deba@1421
   504
		const Reader& _reader) 
deba@1408
   505
	: map(_map), reader(_reader) {}
deba@1408
   506
deba@1408
   507
      virtual ~MapReader() {}
deba@1408
   508
deba@1408
   509
      virtual void read(std::istream& is, const Item& item) {
deba@1408
   510
	Value value;
deba@1408
   511
	reader.read(is, value);
deba@1408
   512
	map.set(item, value);
deba@1408
   513
      }
deba@1408
   514
deba@1408
   515
      virtual InverterBase<_Item>* getInverter() {
deba@1408
   516
	return new MapReaderInverter<Item, Map, Reader>(map, reader);
deba@1408
   517
      }
deba@1408
   518
    };
deba@1408
   519
deba@1408
   520
deba@1408
   521
    template <typename _Item, typename _Reader>
deba@1408
   522
    class SkipReader : public ReaderBase<_Item> {
deba@1408
   523
    public:
deba@1408
   524
      typedef _Reader Reader;
deba@1408
   525
      typedef typename Reader::Value Value;
deba@1408
   526
      typedef _Item Item;
deba@1408
   527
deba@1408
   528
      Reader reader;
deba@1408
   529
      SkipReader(const Reader& _reader) : reader(_reader) {}
deba@1408
   530
deba@1408
   531
      virtual ~SkipReader() {}
deba@1408
   532
deba@1408
   533
      virtual void read(std::istream& is, const Item&) {
deba@1408
   534
	Value value;
deba@1408
   535
	reader.read(is, value);
deba@1408
   536
      }      
deba@1408
   537
deba@1408
   538
      virtual InverterBase<Item>* getInverter() {
deba@1408
   539
	return new SkipReaderInverter<Item, Reader>(reader);
deba@1408
   540
      }
deba@1408
   541
    };
deba@1408
   542
deba@1408
   543
    template <typename _Item>
deba@1409
   544
    class IdReaderBase {
deba@1408
   545
    public:
deba@1408
   546
      typedef _Item Item;
deba@1409
   547
      virtual Item read(std::istream& is) const = 0;
deba@1408
   548
    };
deba@1408
   549
deba@1409
   550
    template <typename _Item, typename _BoxedIdReader>
deba@1409
   551
    class IdReader : public IdReaderBase<_Item> {
deba@1408
   552
    public:
deba@1408
   553
      typedef _Item Item;
deba@1409
   554
      typedef _BoxedIdReader BoxedIdReader;
deba@1409
   555
      
deba@1409
   556
      const BoxedIdReader& boxedIdReader;
deba@1408
   557
deba@1409
   558
      IdReader(const BoxedIdReader& _boxedIdReader) 
deba@1409
   559
	: boxedIdReader(_boxedIdReader) {}
deba@1408
   560
deba@1409
   561
      virtual Item read(std::istream& is) const {
deba@1409
   562
	return boxedIdReader.readId(is);
deba@1408
   563
      }
deba@1408
   564
    };
deba@1408
   565
deba@1408
   566
    class ValueReaderBase {
deba@1408
   567
    public:
deba@1408
   568
      virtual void read(std::istream&) {};
deba@1408
   569
    };
deba@1408
   570
deba@1408
   571
    template <typename _Value, typename _Reader>
deba@1408
   572
    class ValueReader : public ValueReaderBase {
deba@1408
   573
    public:
deba@1408
   574
      typedef _Value Value;
deba@1408
   575
      typedef _Reader Reader;
deba@1408
   576
deba@1408
   577
      ValueReader(Value& _value, const Reader& _reader)
deba@1408
   578
 	: value(_value), reader(_reader) {}
deba@1408
   579
deba@1408
   580
      virtual void read(std::istream& is) {
deba@1408
   581
	reader.read(is, value);
deba@1408
   582
      }
deba@1408
   583
    private:
deba@1408
   584
      Value& value;
deba@1408
   585
      Reader reader;
deba@1408
   586
    };
deba@1408
   587
    
deba@1408
   588
  };
deba@1408
   589
deba@1409
   590
  /// \ingroup io_group
deba@1409
   591
  /// \brief SectionReader for reading a graph's nodeset.
deba@1409
   592
  ///
deba@1409
   593
  /// The lemon format can store multiple graph nodesets with several maps.
deba@1409
   594
  /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
deba@1409
   595
  /// \c nodeset_id may be empty.
deba@1409
   596
  ///
deba@1409
   597
  /// The first line of the section contains the names of the maps separated
deba@1409
   598
  /// with white spaces. Each next lines describes a node in the nodeset, and
deba@1409
   599
  /// contains the mapped values for each map.
deba@1409
   600
  ///
deba@1409
   601
  /// If the nodeset contains an \c "id" named map then it will be regarded
deba@1409
   602
  /// as id map. This map should contain only unique values and when the 
deba@1409
   603
  /// \c readId() member will read a value from the given stream it will
deba@1409
   604
  /// give back that node which is mapped to this value.
deba@1409
   605
  ///
deba@1409
   606
  /// \relates LemonReader
deba@1408
   607
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@1408
   608
  class NodeSetReader : public CommonSectionReaderBase {
deba@1408
   609
    typedef CommonSectionReaderBase Parent;
deba@1408
   610
  public:
deba@1408
   611
deba@1408
   612
    typedef _Graph Graph;
deba@1408
   613
    typedef _Traits Traits;
deba@1408
   614
    typedef typename Graph::Node Item;
deba@1408
   615
    typedef typename Traits::Skipper DefaultSkipper;
deba@1408
   616
deba@1409
   617
    /// \brief Constructor.
deba@1409
   618
    ///
deba@1409
   619
    /// Constructor for NodeSetReader. It creates the NodeSetReader and
deba@1409
   620
    /// attach it into the given LemonReader. The nodeset reader will
deba@1409
   621
    /// add the readed nodes to the given Graph. The reader will read
deba@1409
   622
    /// the section when the \c section_id and the \c _id are the same. 
deba@1421
   623
    NodeSetReader(LemonReader& _reader, 
deba@1421
   624
		  typename SmartParameter<Graph>::Type _graph, 
deba@1408
   625
		  const std::string& _id = std::string(),
deba@1409
   626
		  const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1409
   627
      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} 
deba@1408
   628
deba@1409
   629
deba@1409
   630
    /// \brief Destructor.
deba@1409
   631
    ///
deba@1409
   632
    /// Destructor for NodeSetReader.
deba@1408
   633
    virtual ~NodeSetReader() {
deba@1408
   634
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1408
   635
	   it != readers.end(); ++it) {
deba@1408
   636
	delete it->second;
deba@1408
   637
      }
deba@1408
   638
    }
deba@1408
   639
deba@1408
   640
  private:
deba@1408
   641
    NodeSetReader(const NodeSetReader&);
deba@1408
   642
    void operator=(const NodeSetReader&);
deba@1408
   643
  
deba@1408
   644
  public:
deba@1408
   645
deba@1408
   646
    /// \brief Add a new node map reader command for the reader.
deba@1408
   647
    ///
deba@1408
   648
    /// Add a new node map reader command for the reader.
deba@1408
   649
    template <typename Map>
deba@1421
   650
    NodeSetReader& readNodeMap(std::string name, Map& map) {
deba@1421
   651
      return _readMap<
deba@1421
   652
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
   653
	typename SmartParameter<Map>::Type>(name, map);
deba@1421
   654
    }
deba@1421
   655
deba@1421
   656
    template <typename Map>
deba@1421
   657
    NodeSetReader& readNodeMap(std::string name, const Map& map) {
deba@1421
   658
      return _readMap<
deba@1421
   659
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
   660
	typename SmartParameter<Map>::Type>(name, map);
deba@1408
   661
    }
deba@1408
   662
deba@1408
   663
    /// \brief Add a new node map reader command for the reader.
deba@1408
   664
    ///
deba@1408
   665
    /// Add a new node map reader command for the reader.
deba@1408
   666
    template <typename Reader, typename Map>
deba@1421
   667
    NodeSetReader& readNodeMap(std::string name, Map& map, 
deba@1421
   668
			       const Reader& reader = Reader()) {
deba@1421
   669
      return _readMap<
deba@1421
   670
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
   671
	typename SmartParameter<Map>::Type>(name, map, reader);
deba@1421
   672
    }
deba@1421
   673
deba@1421
   674
    template <typename Reader, typename Map>
deba@1421
   675
    NodeSetReader& readNodeMap(std::string name, const Map& map, 
deba@1421
   676
			       const Reader& reader = Reader()) {
deba@1421
   677
      return _readMap<
deba@1421
   678
	typename Traits::template Reader<typename Map::Value>, Map, 
deba@1421
   679
	typename SmartParameter<Map>::Type>(name, map, reader);
deba@1421
   680
    }
deba@1421
   681
deba@1421
   682
  private:
deba@1421
   683
deba@1421
   684
    template <typename Reader, typename Map, typename MapParameter>
deba@1421
   685
    NodeSetReader& _readMap(std::string name, MapParameter map, 
deba@1421
   686
			    const Reader& reader = Reader()) {
deba@1408
   687
      if (readers.find(name) != readers.end()) {
deba@1408
   688
	ErrorMessage msg;
deba@1408
   689
	msg << "Multiple read rule for node map: " << name;
deba@1408
   690
	throw IOParameterError(msg.message());
deba@1408
   691
      }
deba@1408
   692
      readers.insert(
deba@1408
   693
	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
deba@1408
   694
      return *this;
deba@1408
   695
    }
deba@1408
   696
deba@1421
   697
  public:
deba@1421
   698
deba@1408
   699
    /// \brief Add a new node map skipper command for the reader.
deba@1408
   700
    ///
deba@1408
   701
    /// Add a new node map skipper command for the reader.
deba@1408
   702
    template <typename Reader>
deba@1421
   703
    NodeSetReader& skipNodeMap(std::string name, 
deba@1408
   704
			   const Reader& reader = Reader()) {
deba@1408
   705
      if (readers.find(name) != readers.end()) {
deba@1408
   706
	ErrorMessage msg;
deba@1408
   707
	msg << "Multiple read rule for node map: " << name;
deba@1408
   708
	throw IOParameterError(msg.message());
deba@1408
   709
      }
deba@1408
   710
      readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
deba@1408
   711
      return *this;
deba@1408
   712
    }
deba@1408
   713
deba@1409
   714
  protected:
deba@1409
   715
deba@1409
   716
    /// \brief Gives back true when the SectionReader can process 
deba@1409
   717
    /// the section with the given header line.
deba@1409
   718
    ///
deba@1421
   719
    /// It gives back true when the header line starts with \c \@nodeset,
deba@1409
   720
    /// and the header line's id and the nodeset's id are the same.
deba@1408
   721
    virtual bool header(const std::string& line) {
deba@1408
   722
      std::istringstream ls(line);
deba@1408
   723
      std::string command;
deba@1408
   724
      std::string name;
deba@1408
   725
      ls >> command >> name;
deba@1408
   726
      return command == "@nodeset" && name == id;
deba@1408
   727
    }
deba@1408
   728
deba@1409
   729
    /// \brief Reader function of the section.
deba@1409
   730
    ///
deba@1409
   731
    /// It reads the content of the section.
deba@1408
   732
    virtual void read(std::istream& is) {
deba@1408
   733
      std::vector<ReaderBase<Item>* > index;
deba@1408
   734
      std::string line;
deba@1408
   735
deba@1408
   736
      getline(is, line);
deba@1408
   737
      std::istringstream ls(line);	
deba@1408
   738
      while (ls >> id) {
deba@1408
   739
	typename MapReaders::iterator it = readers.find(id);
deba@1408
   740
	if (it != readers.end()) {
deba@1408
   741
	  index.push_back(it->second);
deba@1408
   742
	} else {
deba@1408
   743
	  index.push_back(&skipper);
deba@1408
   744
	}
deba@1408
   745
	if (id == "id" && inverter.get() == 0) {
deba@1408
   746
	  inverter.reset(index.back()->getInverter());
deba@1408
   747
	  index.back() = inverter.get();
deba@1408
   748
	}
deba@1408
   749
      }
deba@1408
   750
      while (getline(is, line)) {	
deba@1408
   751
	typename Graph::Node node = graph.addNode();
deba@1408
   752
	std::istringstream ls(line);
deba@1408
   753
	for (int i = 0; i < (int)index.size(); ++i) {
deba@1408
   754
	  index[i]->read(ls, node);
deba@1408
   755
	}
deba@1408
   756
      }
deba@1408
   757
    }
deba@1408
   758
deba@1409
   759
  public:
deba@1409
   760
deba@1409
   761
    /// \brief Returns true if the nodeset can give back the node by its id.
deba@1409
   762
    ///
deba@1409
   763
    /// Returns true if the nodeset can give back the node by its id.
deba@1409
   764
    /// It is possible only if an "id" named map was read.
deba@1409
   765
    bool isIdReader() const {
deba@1408
   766
      return inverter.get() != 0;
deba@1408
   767
    }
deba@1408
   768
deba@1409
   769
    /// \brief Gives back the node by its id.
deba@1409
   770
    ///
deba@1409
   771
    /// It reads an id from the stream and gives back which node belongs to
deba@1409
   772
    /// it. It is possible only if there was read an "id" named map.
deba@1421
   773
    Item readId(std::istream& is) const {
deba@1408
   774
      return inverter->read(is);
deba@1408
   775
    } 
deba@1408
   776
deba@1408
   777
  private:
deba@1408
   778
deba@1408
   779
    typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
deba@1408
   780
    MapReaders readers;
deba@1408
   781
   
deba@1421
   782
    typename SmartReference<Graph>::Type graph;   
deba@1408
   783
    std::string id;
deba@1408
   784
    SkipReader<Item, DefaultSkipper> skipper;
deba@1408
   785
deba@1408
   786
    std::auto_ptr<InverterBase<Item> > inverter;
deba@1408
   787
  };
deba@1408
   788
deba@1409
   789
  /// \ingroup io_group
deba@1409
   790
  /// \brief SectionReader for reading a graph's edgeset.
deba@1409
   791
  ///
deba@1409
   792
  /// The lemon format can store multiple graph edgesets with several maps.
deba@1409
   793
  /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
deba@1409
   794
  /// \c edgeset_id may be empty.
deba@1409
   795
  ///
deba@1409
   796
  /// The first line of the section contains the names of the maps separated
deba@1421
   797
  /// with white spaces. Each next lines describes an edge in the edgeset. The
deba@1421
   798
  /// line contains the source and the target nodes' id and the mapped 
deba@1421
   799
  /// values for each map.
deba@1409
   800
  ///
deba@1409
   801
  /// If the edgeset contains an \c "id" named map then it will be regarded
deba@1409
   802
  /// as id map. This map should contain only unique values and when the 
deba@1409
   803
  /// \c readId() member will read a value from the given stream it will
deba@1409
   804
  /// give back that edge which is mapped to this value.
deba@1409
   805
  ///
deba@1409
   806
  /// The edgeset reader needs a node id reader to identify which nodes
deba@1409
   807
  /// have to be connected. If a NodeSetReader reads an "id" named map,
deba@1409
   808
  /// it will be able to resolve the nodes by ids.
deba@1409
   809
  ///
deba@1409
   810
  /// \relates LemonReader
deba@1408
   811
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@1408
   812
  class EdgeSetReader : public CommonSectionReaderBase {
deba@1408
   813
    typedef CommonSectionReaderBase Parent;
deba@1408
   814
  public:
deba@1408
   815
deba@1408
   816
    typedef _Graph Graph;
deba@1408
   817
    typedef _Traits Traits;
deba@1408
   818
    typedef typename Graph::Edge Item;
deba@1408
   819
    typedef typename Traits::Skipper DefaultSkipper;
deba@1408
   820
deba@1409
   821
    /// \brief Constructor.
deba@1409
   822
    ///
deba@1409
   823
    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
deba@1409
   824
    /// attach it into the given LemonReader. The edgeset reader will
deba@1409
   825
    /// add the readed edges to the given Graph. It will use the given
deba@1409
   826
    /// node id reader to read the source and target nodes of the edges.
deba@1409
   827
    /// The reader will read the section only if the \c _id and the 
deba@1409
   828
    /// \c edgset_id are the same. 
deba@1409
   829
    template <typename NodeIdReader>
deba@1421
   830
    EdgeSetReader(LemonReader& _reader, 
deba@1421
   831
		  typename SmartParameter<Graph>::Type _graph, 
deba@1409
   832
		  const NodeIdReader& _nodeIdReader, 
deba@1408
   833
		  const std::string& _id = std::string(),
deba@1409
   834
		  const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1409
   835
      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
deba@1409
   836
	nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
deba@1409
   837
		     (_nodeIdReader)) {} 
deba@1408
   838
deba@1409
   839
    /// \brief Destructor.
deba@1409
   840
    ///
deba@1409
   841
    /// Destructor for EdgeSetReader.
deba@1408
   842
    virtual ~EdgeSetReader() {
deba@1408
   843
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1408
   844
	   it != readers.end(); ++it) {
deba@1408
   845
	delete it->second;
deba@1408
   846
      }
deba@1408
   847
    }
deba@1408
   848
deba@1408
   849
  private:
deba@1408
   850
    EdgeSetReader(const EdgeSetReader&);
deba@1408
   851
    void operator=(const EdgeSetReader&);
deba@1408
   852
deba@1408
   853
  public:
deba@1408
   854
deba@1409
   855
    /// \brief Add a new edge map reader command for the reader.
deba@1408
   856
    ///
deba@1409
   857
    /// Add a new edge map reader command for the reader.
deba@1408
   858
    template <typename Map>
deba@1421
   859
    EdgeSetReader& readEdgeMap(std::string name, Map& map) {
deba@1421
   860
      return _readMap<
deba@1421
   861
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
   862
	typename SmartParameter<Map>::Type>(name, map);
deba@1421
   863
    }
deba@1421
   864
deba@1421
   865
    template <typename Map>
deba@1421
   866
    EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
deba@1421
   867
      return _readMap<
deba@1421
   868
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
   869
	typename SmartParameter<Map>::Type>(name, map);
deba@1408
   870
    }
deba@1408
   871
deba@1409
   872
    /// \brief Add a new edge map reader command for the reader.
deba@1408
   873
    ///
deba@1409
   874
    /// Add a new edge map reader command for the reader.
deba@1408
   875
    template <typename Reader, typename Map>
deba@1421
   876
    EdgeSetReader& readEdgeMap(std::string name, Map& map, 
deba@1421
   877
			   const Reader& reader = Reader()) {
deba@1421
   878
      return _readMap<
deba@1421
   879
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
   880
	typename SmartParameter<Map>::Type>(name, map, reader);
deba@1421
   881
    }
deba@1421
   882
deba@1421
   883
    template <typename Reader, typename Map>
deba@1421
   884
    EdgeSetReader& readEdgeMap(std::string name, const Map& map, 
deba@1421
   885
			       const Reader& reader = Reader()) {
deba@1421
   886
      return _readMap<
deba@1421
   887
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
   888
	typename SmartParameter<Map>::Type>(name, map, reader);
deba@1421
   889
    }
deba@1421
   890
deba@1421
   891
  private:
deba@1421
   892
deba@1421
   893
    template <typename Reader, typename Map, typename MapParameter>
deba@1421
   894
    EdgeSetReader& _readMap(std::string name, MapParameter map, 
deba@1421
   895
			    const Reader& reader = Reader()) {
deba@1408
   896
      if (readers.find(name) != readers.end()) {
deba@1408
   897
	ErrorMessage msg;
deba@1408
   898
	msg << "Multiple read rule for edge map: " << name;
deba@1408
   899
	throw IOParameterError(msg.message());
deba@1408
   900
      }
deba@1408
   901
      readers.insert(
deba@1408
   902
	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
deba@1408
   903
      return *this;
deba@1408
   904
    }
deba@1408
   905
deba@1421
   906
  public:
deba@1421
   907
deba@1409
   908
    /// \brief Add a new edge map skipper command for the reader.
deba@1408
   909
    ///
deba@1409
   910
    /// Add a new edge map skipper command for the reader.
deba@1408
   911
    template <typename Reader>
deba@1421
   912
    EdgeSetReader& skipEdgeMap(std::string name, 
deba@1421
   913
			       const Reader& reader = Reader()) {
deba@1408
   914
      if (readers.find(name) != readers.end()) {
deba@1408
   915
	ErrorMessage msg;
deba@1421
   916
	msg << "Multiple read rule for edge map: " << name;
deba@1408
   917
	throw IOParameterError(msg.message());
deba@1408
   918
      }
deba@1408
   919
      readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
deba@1408
   920
      return *this;
deba@1408
   921
    }
deba@1408
   922
deba@1409
   923
  protected:
deba@1409
   924
deba@1409
   925
    /// \brief Gives back true when the SectionReader can process 
deba@1409
   926
    /// the section with the given header line.
deba@1409
   927
    ///
deba@1421
   928
    /// It gives back true when the header line starts with \c \@edgeset,
deba@1409
   929
    /// and the header line's id and the edgeset's id are the same.
deba@1408
   930
    virtual bool header(const std::string& line) {
deba@1408
   931
      std::istringstream ls(line);
deba@1408
   932
      std::string command;
deba@1408
   933
      std::string name;
deba@1408
   934
      ls >> command >> name;
deba@1408
   935
      return command == "@edgeset" && name == id;
deba@1408
   936
    }
deba@1408
   937
deba@1409
   938
    /// \brief Reader function of the section.
deba@1409
   939
    ///
deba@1409
   940
    /// It reads the content of the section.
deba@1408
   941
    virtual void read(std::istream& is) {
deba@1408
   942
      std::vector<ReaderBase<Item>* > index;
deba@1408
   943
      std::string line;
deba@1408
   944
deba@1408
   945
      getline(is, line);
deba@1408
   946
      std::istringstream ls(line);	
deba@1408
   947
      while (ls >> id) {
deba@1408
   948
	typename MapReaders::iterator it = readers.find(id);
deba@1408
   949
	if (it != readers.end()) {
deba@1408
   950
	  index.push_back(it->second);
deba@1408
   951
	} else {
deba@1408
   952
	  index.push_back(&skipper);
deba@1408
   953
	}
deba@1408
   954
	if (id == "id" && inverter.get() == 0) {
deba@1408
   955
	  inverter.reset(index.back()->getInverter());
deba@1408
   956
	  index.back() = inverter.get();
deba@1408
   957
	}
deba@1408
   958
      }
deba@1408
   959
      while (getline(is, line)) {	
deba@1408
   960
	std::istringstream ls(line);
deba@1409
   961
	typename Graph::Node from = nodeIdReader->read(ls);
deba@1409
   962
	typename Graph::Node to = nodeIdReader->read(ls);
deba@1408
   963
	typename Graph::Edge edge = graph.addEdge(from, to);
deba@1408
   964
	for (int i = 0; i < (int)index.size(); ++i) {
deba@1408
   965
	  index[i]->read(ls, edge);
deba@1408
   966
	}
deba@1408
   967
      }
deba@1408
   968
    }
deba@1408
   969
deba@1409
   970
  public:
deba@1409
   971
deba@1409
   972
    /// \brief Returns true if the edgeset can give back the edge by its id.
deba@1409
   973
    ///
deba@1409
   974
    /// Returns true if the edgeset can give back the edge by its id.
deba@1409
   975
    /// It is possible only if an "id" named map was read.
deba@1409
   976
    bool isIdReader() const {
deba@1408
   977
      return inverter.get() != 0;
deba@1408
   978
    }
deba@1408
   979
deba@1409
   980
    /// \brief Gives back the edge by its id.
deba@1409
   981
    ///
deba@1409
   982
    /// It reads an id from the stream and gives back which edge belongs to
deba@1409
   983
    /// it. It is possible only if there was read an "id" named map.
deba@1421
   984
    Item readId(std::istream& is) const {
deba@1408
   985
      return inverter->read(is);
deba@1408
   986
    } 
deba@1408
   987
deba@1408
   988
  private:
deba@1408
   989
deba@1408
   990
    typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
deba@1408
   991
    MapReaders readers;
deba@1408
   992
   
deba@1421
   993
    typename SmartReference<Graph>::Type graph;   
deba@1421
   994
    std::string id;
deba@1421
   995
    SkipReader<Item, DefaultSkipper> skipper;
deba@1421
   996
deba@1421
   997
    std::auto_ptr<InverterBase<Item> > inverter;
deba@1421
   998
    std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
deba@1421
   999
  };
deba@1421
  1000
deba@1421
  1001
  /// \ingroup io_group
deba@1421
  1002
  /// \brief SectionReader for reading a undirected graph's edgeset.
deba@1421
  1003
  ///
deba@1421
  1004
  /// The lemon format can store multiple undirected edgesets with several 
deba@1421
  1005
  /// maps. The undirected edgeset section's header line is \c \@undiredgeset 
deba@1421
  1006
  /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
deba@1421
  1007
  ///
deba@1421
  1008
  /// The first line of the section contains the names of the maps separated
deba@1421
  1009
  /// with white spaces. Each next lines describes an edge in the edgeset. The
deba@1421
  1010
  /// line contains the connected nodes' id and the mapped values for each map.
deba@1421
  1011
  ///
deba@1421
  1012
  /// The section can handle the directed as a syntactical sugar. Two
deba@1421
  1013
  /// undirected edge map describes one directed edge map. This two maps
deba@1421
  1014
  /// are the forward map and the backward map and the names of this map
deba@1421
  1015
  /// is near the same just with a prefix \c '+' or \c '-' character 
deba@1421
  1016
  /// difference.
deba@1421
  1017
  ///
deba@1421
  1018
  /// If the edgeset contains an \c "id" named map then it will be regarded
deba@1421
  1019
  /// as id map. This map should contain only unique values and when the 
deba@1421
  1020
  /// \c readId() member will read a value from the given stream it will
deba@1421
  1021
  /// give back that undiricted edge which is mapped to this value.
deba@1421
  1022
  ///
deba@1421
  1023
  /// The undirected edgeset reader needs a node id reader to identify which 
deba@1421
  1024
  /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
deba@1421
  1025
  /// it will be able to resolve the nodes by ids.
deba@1421
  1026
  ///
deba@1421
  1027
  /// \relates LemonReader
deba@1421
  1028
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@1421
  1029
  class UndirEdgeSetReader : public CommonSectionReaderBase {
deba@1421
  1030
    typedef CommonSectionReaderBase Parent;
deba@1421
  1031
  public:
deba@1421
  1032
deba@1421
  1033
    typedef _Graph Graph;
deba@1421
  1034
    typedef _Traits Traits;
deba@1421
  1035
    typedef typename Graph::UndirEdge Item;
deba@1421
  1036
    typedef typename Traits::Skipper DefaultSkipper;
deba@1421
  1037
deba@1421
  1038
    /// \brief Constructor.
deba@1421
  1039
    ///
deba@1421
  1040
    /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader 
deba@1421
  1041
    /// and attach it into the given LemonReader. The undirected edgeset 
deba@1421
  1042
    /// reader will add the readed undirected edges to the given Graph. It 
deba@1421
  1043
    /// will use the given node id reader to read the source and target 
deba@1421
  1044
    /// nodes of the edges. The reader will read the section only if the 
deba@1421
  1045
    /// \c _id and the \c undiredgset_id are the same. 
deba@1421
  1046
    template <typename NodeIdReader>
deba@1421
  1047
    UndirEdgeSetReader(LemonReader& _reader, 
deba@1421
  1048
		       typename SmartParameter<Graph>::Type _graph, 
deba@1421
  1049
		       const NodeIdReader& _nodeIdReader, 
deba@1421
  1050
		       const std::string& _id = std::string(),
deba@1421
  1051
		       const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1421
  1052
      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
deba@1421
  1053
	nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
deba@1421
  1054
		     (_nodeIdReader)) {} 
deba@1421
  1055
deba@1421
  1056
    /// \brief Destructor.
deba@1421
  1057
    ///
deba@1421
  1058
    /// Destructor for UndirEdgeSetReader.
deba@1421
  1059
    virtual ~UndirEdgeSetReader() {
deba@1421
  1060
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1421
  1061
	   it != readers.end(); ++it) {
deba@1421
  1062
	delete it->second;
deba@1421
  1063
      }
deba@1421
  1064
    }
deba@1421
  1065
deba@1421
  1066
  private:
deba@1421
  1067
    UndirEdgeSetReader(const UndirEdgeSetReader&);
deba@1421
  1068
    void operator=(const UndirEdgeSetReader&);
deba@1421
  1069
deba@1421
  1070
  public:
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 Map>
deba@1421
  1076
    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
deba@1421
  1077
      return _readMap<
deba@1421
  1078
	typename Traits::template Reader<typename Map::Value>, Map, 
deba@1421
  1079
	typename SmartParameter<Map>::Type>(name, map);
deba@1421
  1080
    }
deba@1421
  1081
deba@1421
  1082
    template <typename Map>
deba@1421
  1083
    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
deba@1421
  1084
      return _readMap<
deba@1421
  1085
	typename Traits::template Reader<typename Map::Value>, Map, 
deba@1421
  1086
	typename SmartParameter<Map>::Type>(name, map);
deba@1421
  1087
    }
deba@1421
  1088
deba@1421
  1089
    /// \brief Add a new undirected edge map reader command for the reader.
deba@1421
  1090
    ///
deba@1421
  1091
    /// Add a new edge undirected map reader command for the reader.
deba@1421
  1092
    template <typename Reader, typename Map>
deba@1421
  1093
    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map, 
deba@1421
  1094
					 const Reader& reader = Reader()) {
deba@1421
  1095
      return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
deba@1421
  1096
	(name, map, reader);
deba@1421
  1097
    }
deba@1421
  1098
deba@1421
  1099
    template <typename Reader, typename Map>
deba@1421
  1100
    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map, 
deba@1421
  1101
					 const Reader& reader = Reader()) {
deba@1421
  1102
      return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
deba@1421
  1103
	(name, map, reader);
deba@1421
  1104
    }
deba@1421
  1105
deba@1421
  1106
  private:
deba@1421
  1107
deba@1421
  1108
    template <typename Reader, typename Map, typename MapParameter>
deba@1421
  1109
    UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
deba@1421
  1110
				 const Reader& reader = Reader()) {
deba@1421
  1111
      if (readers.find(name) != readers.end()) {
deba@1421
  1112
	ErrorMessage msg;
deba@1421
  1113
	msg << "Multiple read rule for edge map: " << name;
deba@1421
  1114
	throw IOParameterError(msg.message());
deba@1421
  1115
      }
deba@1421
  1116
      readers.insert(
deba@1421
  1117
	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
deba@1421
  1118
      return *this;
deba@1421
  1119
    }
deba@1421
  1120
deba@1421
  1121
  public:
deba@1421
  1122
deba@1421
  1123
    /// \brief Add a new undirected edge map skipper command for the reader.
deba@1421
  1124
    ///
deba@1421
  1125
    /// Add a new undirected edge map skipper command for the reader.
deba@1421
  1126
    template <typename Reader>
deba@1421
  1127
    UndirEdgeSetReader& skipUndirEdgeMap(std::string name, 
deba@1421
  1128
					 const Reader& reader = Reader()) {
deba@1421
  1129
      if (readers.find(name) != readers.end()) {
deba@1421
  1130
	ErrorMessage msg;
deba@1421
  1131
	msg << "Multiple read rule for node map: " << name;
deba@1421
  1132
	throw IOParameterError(msg.message());
deba@1421
  1133
      }
deba@1421
  1134
      readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
deba@1421
  1135
      return *this;
deba@1421
  1136
    }
deba@1421
  1137
deba@1421
  1138
    /// \brief Add a new directed edge map reader command for the reader.
deba@1421
  1139
    ///
deba@1421
  1140
    /// Add a new directed edge map reader command for the reader.
deba@1421
  1141
    template <typename Map>
deba@1421
  1142
    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
deba@1421
  1143
      return _readDirMap<
deba@1421
  1144
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
  1145
	typename SmartParameter<Map>::Type>(name, map);
deba@1421
  1146
    }
deba@1421
  1147
deba@1421
  1148
    template <typename Map>
deba@1421
  1149
    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
deba@1421
  1150
      return _readDirMap<
deba@1421
  1151
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1421
  1152
	typename SmartParameter<Map>::Type>(name, map);
deba@1421
  1153
    }
deba@1421
  1154
deba@1421
  1155
    /// \brief Add a new directed edge map reader command for the reader.
deba@1421
  1156
    ///
deba@1421
  1157
    /// Add a new directed edge map reader command for the reader.
deba@1421
  1158
    template <typename Reader, typename Map>
deba@1421
  1159
    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map, 
deba@1421
  1160
				    const Reader& reader = Reader()) {
deba@1421
  1161
      return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
deba@1421
  1162
	(name, map, reader);
deba@1421
  1163
    }
deba@1421
  1164
deba@1421
  1165
    template <typename Reader, typename Map>
deba@1421
  1166
    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map, 
deba@1421
  1167
				    const Reader& reader = Reader()) {
deba@1421
  1168
      return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
deba@1421
  1169
	(name, map, reader);
deba@1421
  1170
    }
deba@1421
  1171
deba@1421
  1172
  private:
deba@1421
  1173
deba@1421
  1174
    template <typename Reader, typename Map, typename MapParameter>
deba@1421
  1175
    UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
deba@1421
  1176
				    const Reader& reader = Reader()) {
deba@1421
  1177
      readMap("+" + name, 
deba@1421
  1178
	      _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
deba@1421
  1179
      readMap("-" + name, 
deba@1421
  1180
	      _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
deba@1421
  1181
      return *this;      
deba@1421
  1182
    }
deba@1421
  1183
deba@1421
  1184
  public:
deba@1421
  1185
deba@1421
  1186
    /// \brief Add a new directed edge map skipper command for the reader.
deba@1421
  1187
    ///
deba@1421
  1188
    /// Add a new directed edge map skipper command for the reader.
deba@1421
  1189
    template <typename Reader>
deba@1421
  1190
    UndirEdgeSetReader& skipEdgeMap(std::string name, 
deba@1421
  1191
				    const Reader& reader = Reader()) {
deba@1421
  1192
      skipMap("+" + name, reader);
deba@1421
  1193
      skipMap("-" + name, reader);
deba@1421
  1194
      return *this;
deba@1421
  1195
    }
deba@1421
  1196
deba@1421
  1197
  protected:
deba@1421
  1198
deba@1421
  1199
    /// \brief Gives back true when the SectionReader can process 
deba@1421
  1200
    /// the section with the given header line.
deba@1421
  1201
    ///
deba@1421
  1202
    /// It gives back true when the header line starts with \c \@undiredgeset,
deba@1421
  1203
    /// and the header line's id and the edgeset's id are the same.
deba@1421
  1204
    virtual bool header(const std::string& line) {
deba@1421
  1205
      std::istringstream ls(line);
deba@1421
  1206
      std::string command;
deba@1421
  1207
      std::string name;
deba@1421
  1208
      ls >> command >> name;
deba@1421
  1209
      return command == "@undiredgeset" && name == id;
deba@1421
  1210
    }
deba@1421
  1211
deba@1421
  1212
    /// \brief Reader function of the section.
deba@1421
  1213
    ///
deba@1421
  1214
    /// It reads the content of the section.
deba@1421
  1215
    virtual void read(std::istream& is) {
deba@1421
  1216
      std::vector<ReaderBase<Item>* > index;
deba@1421
  1217
      std::string line;
deba@1421
  1218
deba@1421
  1219
      getline(is, line);
deba@1421
  1220
      std::istringstream ls(line);	
deba@1421
  1221
      while (ls >> id) {
deba@1421
  1222
	typename MapReaders::iterator it = readers.find(id);
deba@1421
  1223
	if (it != readers.end()) {
deba@1421
  1224
	  index.push_back(it->second);
deba@1421
  1225
	} else {
deba@1421
  1226
	  index.push_back(&skipper);
deba@1421
  1227
	}
deba@1421
  1228
	if (id == "id" && inverter.get() == 0) {
deba@1421
  1229
	  inverter.reset(index.back()->getInverter());
deba@1421
  1230
	  index.back() = inverter.get();
deba@1421
  1231
	}
deba@1421
  1232
      }
deba@1421
  1233
      while (getline(is, line)) {	
deba@1421
  1234
	std::istringstream ls(line);
deba@1421
  1235
	typename Graph::Node from = nodeIdReader->read(ls);
deba@1421
  1236
	typename Graph::Node to = nodeIdReader->read(ls);
deba@1421
  1237
	typename Graph::UndirEdge edge = graph.addEdge(from, to);
deba@1421
  1238
	for (int i = 0; i < (int)index.size(); ++i) {
deba@1421
  1239
	  index[i]->read(ls, edge);
deba@1421
  1240
	}
deba@1421
  1241
      }
deba@1421
  1242
    }
deba@1421
  1243
deba@1421
  1244
  public:
deba@1421
  1245
deba@1421
  1246
    /// \brief Returns true if the edgeset can give back the edge by its id.
deba@1421
  1247
    ///
deba@1421
  1248
    /// Returns true if the edgeset can give back the undirected edge by its 
deba@1421
  1249
    /// id. It is possible only if an "id" named map was read.
deba@1421
  1250
    bool isIdReader() const {
deba@1421
  1251
      return inverter.get() != 0;
deba@1421
  1252
    }
deba@1421
  1253
deba@1421
  1254
    /// \brief Gives back the undirected edge by its id.
deba@1421
  1255
    ///
deba@1421
  1256
    /// It reads an id from the stream and gives back which undirected edge 
deba@1421
  1257
    /// belongs to it. It is possible only if there was read an "id" named map.
deba@1421
  1258
    Item readId(std::istream& is) const {
deba@1421
  1259
      return inverter->read(is);
deba@1421
  1260
    } 
deba@1421
  1261
deba@1421
  1262
  private:
deba@1421
  1263
deba@1421
  1264
    typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
deba@1421
  1265
    MapReaders readers;
deba@1421
  1266
   
deba@1421
  1267
    typename SmartReference<Graph>::Type graph;   
deba@1408
  1268
    std::string id;
deba@1408
  1269
    SkipReader<Item, DefaultSkipper> skipper;
deba@1408
  1270
deba@1408
  1271
    std::auto_ptr<InverterBase<Item> > inverter;
deba@1409
  1272
    std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
deba@1408
  1273
  };
deba@1408
  1274
deba@1409
  1275
  /// \ingroup io_group
deba@1409
  1276
  /// \brief SectionReader for reading labeled nodes.
deba@1409
  1277
  ///
deba@1409
  1278
  /// The nodes section's header line is \c \@nodes \c nodes_id, but the
deba@1409
  1279
  /// \c nodes_id may be empty.
deba@1409
  1280
  ///
deba@1409
  1281
  /// Each line in the section contains the name of the node 
deba@1409
  1282
  /// and then the node id. 
deba@1409
  1283
  ///
deba@1409
  1284
  /// \relates LemonReader
deba@1409
  1285
  template <typename _Graph>
deba@1409
  1286
  class NodeReader : public CommonSectionReaderBase {
deba@1409
  1287
    typedef CommonSectionReaderBase Parent;
deba@1409
  1288
    typedef _Graph Graph;
deba@1409
  1289
    typedef typename Graph::Node Item;
deba@1409
  1290
  public:
deba@1409
  1291
    
deba@1409
  1292
    /// \brief Constructor.
deba@1409
  1293
    ///
deba@1409
  1294
    /// Constructor for NodeReader. It creates the NodeReader and
deba@1409
  1295
    /// attach it into the given LemonReader. It will use the given
deba@1409
  1296
    /// node id reader to give back the nodes. The reader will read the 
deba@1409
  1297
    /// section only if the \c _id and the \c nodes_id are the same. 
deba@1409
  1298
    template <typename _IdReader>
deba@1409
  1299
    NodeReader(LemonReader& _reader, const _IdReader& _idReader, 
deba@1409
  1300
	       const std::string& _id = std::string()) 
deba@1409
  1301
      : Parent(_reader), id(_id), 
deba@1409
  1302
	idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {} 
deba@1408
  1303
deba@1409
  1304
    /// \brief Destructor.
deba@1409
  1305
    ///
deba@1409
  1306
    /// Destructor for NodeReader.
deba@1409
  1307
    virtual ~NodeReader() {}
deba@1409
  1308
deba@1409
  1309
  private:
deba@1409
  1310
    NodeReader(const NodeReader&);
deba@1409
  1311
    void operator=(const NodeReader&);
deba@1409
  1312
deba@1409
  1313
  public:
deba@1409
  1314
deba@1409
  1315
    /// \brief Add a node reader command for the NodeReader.
deba@1409
  1316
    ///
deba@1409
  1317
    /// Add a node reader command for the NodeReader.
deba@1409
  1318
    void readNode(const std::string& name, Item& item) {
deba@1409
  1319
      if (readers.find(name) != readers.end()) {
deba@1409
  1320
	ErrorMessage msg;
deba@1409
  1321
	msg << "Multiple read rule for node: " << name;
deba@1409
  1322
	throw IOParameterError(msg.message());
deba@1409
  1323
      }
deba@1409
  1324
      readers.insert(make_pair(name, &item));
deba@1409
  1325
    }
deba@1409
  1326
deba@1409
  1327
  protected:
deba@1409
  1328
deba@1409
  1329
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  1330
    /// the section with the given header line.
deba@1409
  1331
    ///
deba@1421
  1332
    /// It gives back true when the header line start with \c \@nodes,
deba@1409
  1333
    /// and the header line's id and the reader's id are the same.
deba@1409
  1334
    virtual bool header(const std::string& line) {
deba@1409
  1335
      std::istringstream ls(line);
deba@1409
  1336
      std::string command;
deba@1409
  1337
      std::string name;
deba@1409
  1338
      ls >> command >> name;
deba@1409
  1339
      return command == "@nodes" && name == id;
deba@1409
  1340
    }
deba@1409
  1341
deba@1409
  1342
    /// \brief Reader function of the section.
deba@1409
  1343
    ///
deba@1409
  1344
    /// It reads the content of the section.
deba@1409
  1345
    virtual void read(std::istream& is) {
deba@1409
  1346
      std::string line;
deba@1409
  1347
      while (getline(is, line)) {
deba@1409
  1348
	std::istringstream ls(line);
deba@1409
  1349
	std::string id;
deba@1409
  1350
	ls >> id;
deba@1409
  1351
	typename ItemReaders::iterator it = readers.find(id);
deba@1409
  1352
	if (it != readers.end()) {
deba@1409
  1353
	  *(it->second) = idReader->read(ls); 
deba@1409
  1354
	}	
deba@1409
  1355
      }
deba@1409
  1356
    }
deba@1409
  1357
    
deba@1409
  1358
  private:
deba@1409
  1359
deba@1409
  1360
    std::string id;
deba@1409
  1361
deba@1409
  1362
    typedef std::map<std::string, Item*> ItemReaders;
deba@1409
  1363
    ItemReaders readers;
deba@1409
  1364
    std::auto_ptr<IdReaderBase<Item> > idReader;
deba@1409
  1365
  };
deba@1409
  1366
deba@1409
  1367
  /// \ingroup io_group
deba@1409
  1368
  /// \brief SectionReader for reading labeled edges.
deba@1409
  1369
  ///
deba@1409
  1370
  /// The edges section's header line is \c \@edges \c edges_id, but the
deba@1409
  1371
  /// \c edges_id may be empty.
deba@1409
  1372
  ///
deba@1409
  1373
  /// Each line in the section contains the name of the edge 
deba@1409
  1374
  /// and then the edge id. 
deba@1409
  1375
  ///
deba@1409
  1376
  /// \relates LemonReader
deba@1409
  1377
  template <typename _Graph>
deba@1409
  1378
  class EdgeReader : public CommonSectionReaderBase {
deba@1409
  1379
    typedef CommonSectionReaderBase Parent;
deba@1409
  1380
    typedef _Graph Graph;
deba@1409
  1381
    typedef typename Graph::Edge Item;
deba@1409
  1382
  public:
deba@1409
  1383
    
deba@1409
  1384
    /// \brief Constructor.
deba@1409
  1385
    ///
deba@1409
  1386
    /// Constructor for EdgeReader. It creates the EdgeReader and
deba@1409
  1387
    /// attach it into the given LemonReader. It will use the given
deba@1409
  1388
    /// edge id reader to give back the edges. The reader will read the 
deba@1421
  1389
    /// section only if the \c _id and the \c edges_id are the same. 
deba@1409
  1390
    template <typename _IdReader>
deba@1409
  1391
    EdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
deba@1409
  1392
	       const std::string& _id = std::string()) 
deba@1409
  1393
      : Parent(_reader), id(_id), 
deba@1409
  1394
	idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {} 
deba@1409
  1395
deba@1409
  1396
    /// \brief Destructor.
deba@1409
  1397
    ///
deba@1409
  1398
    /// Destructor for EdgeReader.
deba@1409
  1399
    virtual ~EdgeReader() {}
deba@1409
  1400
  private:
deba@1409
  1401
    EdgeReader(const EdgeReader&);
deba@1409
  1402
    void operator=(const EdgeReader&);
deba@1409
  1403
deba@1409
  1404
  public:
deba@1409
  1405
deba@1409
  1406
    /// \brief Add an edge reader command for the EdgeReader.
deba@1409
  1407
    ///
deba@1409
  1408
    /// Add an edge reader command for the EdgeReader.
deba@1409
  1409
    void readEdge(const std::string& name, Item& item) {
deba@1409
  1410
      if (readers.find(name) != readers.end()) {
deba@1409
  1411
	ErrorMessage msg;
deba@1409
  1412
	msg << "Multiple read rule for edge: " << name;
deba@1409
  1413
	throw IOParameterError(msg.message());
deba@1409
  1414
      }
deba@1409
  1415
      readers.insert(make_pair(name, &item));
deba@1409
  1416
    }
deba@1409
  1417
deba@1409
  1418
  protected:
deba@1409
  1419
deba@1409
  1420
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  1421
    /// the section with the given header line.
deba@1409
  1422
    ///
deba@1421
  1423
    /// It gives back true when the header line start with \c \@edges,
deba@1421
  1424
    /// and the header line's id and the reader's id are the same.
deba@1421
  1425
    virtual bool header(const std::string& line) {
deba@1421
  1426
      std::istringstream ls(line);
deba@1421
  1427
      std::string command;
deba@1421
  1428
      std::string name;
deba@1421
  1429
      ls >> command >> name;
deba@1421
  1430
      return command == "@edges" && name == id;
deba@1421
  1431
    }
deba@1421
  1432
deba@1421
  1433
    /// \brief Reader function of the section.
deba@1421
  1434
    ///
deba@1421
  1435
    /// It reads the content of the section.
deba@1421
  1436
    virtual void read(std::istream& is) {
deba@1421
  1437
      std::string line;
deba@1421
  1438
      while (getline(is, line)) {
deba@1421
  1439
	std::istringstream ls(line);
deba@1421
  1440
	std::string id;
deba@1421
  1441
	ls >> id;
deba@1421
  1442
	typename ItemReaders::iterator it = readers.find(id);
deba@1421
  1443
	if (it != readers.end()) {
deba@1421
  1444
	  *(it->second) = idReader->read(ls); 
deba@1421
  1445
	}	
deba@1421
  1446
      }
deba@1421
  1447
    }
deba@1421
  1448
    
deba@1421
  1449
  private:
deba@1421
  1450
deba@1421
  1451
    std::string id;
deba@1421
  1452
deba@1421
  1453
    typedef std::map<std::string, Item*> ItemReaders;
deba@1421
  1454
    ItemReaders readers;
deba@1421
  1455
    std::auto_ptr<IdReaderBase<Item> > idReader;
deba@1421
  1456
  };
deba@1421
  1457
deba@1421
  1458
  /// \ingroup io_group
deba@1421
  1459
  /// \brief SectionReader for reading labeled undirected edges.
deba@1421
  1460
  ///
deba@1421
  1461
  /// The undirected edges section's header line is \c \@undiredges 
deba@1421
  1462
  /// \c undiredges_id, but the \c undiredges_id may be empty.
deba@1421
  1463
  ///
deba@1421
  1464
  /// Each line in the section contains the name of the undirected edge 
deba@1421
  1465
  /// and then the undirected edge id. 
deba@1421
  1466
  ///
deba@1421
  1467
  /// \relates LemonReader
deba@1421
  1468
  template <typename _Graph>
deba@1421
  1469
  class UndirEdgeReader : public CommonSectionReaderBase {
deba@1421
  1470
    typedef CommonSectionReaderBase Parent;
deba@1421
  1471
    typedef _Graph Graph;
deba@1421
  1472
    typedef typename Graph::UndirEdge Item;
deba@1421
  1473
  public:
deba@1421
  1474
    
deba@1421
  1475
    /// \brief Constructor.
deba@1421
  1476
    ///
deba@1421
  1477
    /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
deba@1421
  1478
    /// attach it into the given LemonReader. It will use the given
deba@1421
  1479
    /// undirected edge id reader to give back the edges. The reader will 
deba@1421
  1480
    /// read the section only if the \c _id and the \c undiredges_id are 
deba@1421
  1481
    /// the same. 
deba@1421
  1482
    template <typename _IdReader>
deba@1421
  1483
    UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
deba@1421
  1484
	       const std::string& _id = std::string()) 
deba@1421
  1485
      : Parent(_reader), id(_id), 
deba@1421
  1486
	idReader(new IdReader<typename Graph::UndirEdge, _IdReader>(_idReader))
deba@1421
  1487
    {} 
deba@1421
  1488
deba@1421
  1489
    /// \brief Destructor.
deba@1421
  1490
    ///
deba@1421
  1491
    /// Destructor for UndirEdgeReader.
deba@1421
  1492
    virtual ~UndirEdgeReader() {}
deba@1421
  1493
  private:
deba@1421
  1494
    UndirEdgeReader(const UndirEdgeReader&);
deba@1421
  1495
    void operator=(const UndirEdgeReader&);
deba@1421
  1496
deba@1421
  1497
  public:
deba@1421
  1498
deba@1421
  1499
    /// \brief Add an undirected edge reader command for the UndirEdgeReader.
deba@1421
  1500
    ///
deba@1421
  1501
    /// Add an undirected edge reader command for the UndirEdgeReader.
deba@1421
  1502
    void readUndirEdge(const std::string& name, Item& item) {
deba@1421
  1503
      if (readers.find(name) != readers.end()) {
deba@1421
  1504
	ErrorMessage msg;
deba@1421
  1505
	msg << "Multiple read rule for edge: " << name;
deba@1421
  1506
	throw IOParameterError(msg.message());
deba@1421
  1507
      }
deba@1421
  1508
      readers.insert(make_pair(name, &item));
deba@1421
  1509
    }
deba@1421
  1510
deba@1421
  1511
  protected:
deba@1421
  1512
deba@1421
  1513
    /// \brief Gives back true when the SectionReader can process 
deba@1421
  1514
    /// the section with the given header line.
deba@1421
  1515
    ///
deba@1421
  1516
    /// It gives back true when the header line start with \c \@edges,
deba@1409
  1517
    /// and the header line's id and the reader's id are the same.
deba@1409
  1518
    virtual bool header(const std::string& line) {
deba@1409
  1519
      std::istringstream ls(line);
deba@1409
  1520
      std::string command;
deba@1409
  1521
      std::string name;
deba@1409
  1522
      ls >> command >> name;
deba@1409
  1523
      return command == "@edges" && name == id;
deba@1409
  1524
    }
deba@1409
  1525
deba@1409
  1526
    /// \brief Reader function of the section.
deba@1409
  1527
    ///
deba@1409
  1528
    /// It reads the content of the section.
deba@1409
  1529
    virtual void read(std::istream& is) {
deba@1409
  1530
      std::string line;
deba@1409
  1531
      while (getline(is, line)) {
deba@1409
  1532
	std::istringstream ls(line);
deba@1409
  1533
	std::string id;
deba@1409
  1534
	ls >> id;
deba@1409
  1535
	typename ItemReaders::iterator it = readers.find(id);
deba@1409
  1536
	if (it != readers.end()) {
deba@1409
  1537
	  *(it->second) = idReader->read(ls); 
deba@1409
  1538
	}	
deba@1409
  1539
      }
deba@1409
  1540
    }
deba@1409
  1541
    
deba@1409
  1542
  private:
deba@1409
  1543
deba@1409
  1544
    std::string id;
deba@1409
  1545
deba@1409
  1546
    typedef std::map<std::string, Item*> ItemReaders;
deba@1409
  1547
    ItemReaders readers;
deba@1409
  1548
    std::auto_ptr<IdReaderBase<Item> > idReader;
deba@1409
  1549
  };
deba@1409
  1550
deba@1409
  1551
  /// \ingroup io_group
deba@1409
  1552
  /// \brief SectionReader for attributes.
deba@1409
  1553
  ///
deba@1409
  1554
  /// The lemon format can store multiple attribute set. Each set has
deba@1409
  1555
  /// the header line \c \@attributes \c attributeset_id, but the 
deba@1409
  1556
  /// attributeset_id may be empty.
deba@1409
  1557
  ///
deba@1409
  1558
  /// The attributeset section contains several lines. Each of them starts
deba@1409
  1559
  /// with an attribute and then a the value for the id.
deba@1409
  1560
  ///
deba@1409
  1561
  /// \relates LemonReader
deba@1408
  1562
  template <typename _Traits = DefaultReaderTraits>
deba@1408
  1563
  class AttributeReader : public CommonSectionReaderBase {
deba@1408
  1564
    typedef CommonSectionReaderBase Parent;
deba@1408
  1565
    typedef _Traits Traits; 
deba@1408
  1566
  public:
deba@1409
  1567
    /// \brief Constructor.
deba@1409
  1568
    ///
deba@1409
  1569
    /// Constructor for AttributeReader. It creates the AttributeReader and
deba@1409
  1570
    /// attach it into the given LemonReader. The reader process a section
deba@1409
  1571
    /// only if the \c section_id and the \c _id are the same.
deba@1408
  1572
    AttributeReader(LemonReader& _reader, 
deba@1409
  1573
		    const std::string& _id = std::string()) 
deba@1409
  1574
      : Parent(_reader), id(_id) {}
deba@1408
  1575
deba@1409
  1576
    /// \brief Destructor.
deba@1409
  1577
    ///
deba@1409
  1578
    /// Destructor for AttributeReader.
deba@1408
  1579
    virtual ~AttributeReader() {
deba@1408
  1580
      for (typename Readers::iterator it = readers.begin(); 
deba@1408
  1581
	   it != readers.end(); ++it) {
deba@1408
  1582
	delete it->second;
deba@1408
  1583
      }
deba@1408
  1584
    }
deba@1408
  1585
deba@1408
  1586
  private:
deba@1408
  1587
    AttributeReader(const AttributeReader&);
deba@1408
  1588
    void operator=(AttributeReader&);
deba@1408
  1589
deba@1408
  1590
  public:
deba@1409
  1591
    /// \brief Add an attribute reader command for the reader.
deba@1409
  1592
    ///
deba@1409
  1593
    /// Add an attribute reader command for the reader.
deba@1408
  1594
    template <typename Value>
deba@1408
  1595
    AttributeReader& readAttribute(const std::string& id, Value& value) {
deba@1408
  1596
      return readAttribute<typename Traits::template Reader<Value> >
deba@1408
  1597
	(id, value);
deba@1408
  1598
    }
deba@1408
  1599
deba@1409
  1600
    /// \brief Add an attribute reader command for the reader.
deba@1409
  1601
    ///
deba@1409
  1602
    /// Add an attribute reader command for the reader.
deba@1408
  1603
    template <typename Reader, typename Value>
deba@1408
  1604
    AttributeReader& readAttribute(const std::string& name, Value& value,
deba@1408
  1605
				   const Reader& reader = Reader()) {
deba@1408
  1606
      if (readers.find(name) != readers.end()) {
deba@1408
  1607
	ErrorMessage msg;
deba@1408
  1608
	msg << "Multiple read rule for attribute: " << name;
deba@1408
  1609
	throw IOParameterError(msg.message());
deba@1408
  1610
      }
deba@1408
  1611
      readers.insert(make_pair(name, new ValueReader<Value, Reader>
deba@1408
  1612
      			       (value, reader)));
deba@1408
  1613
      return *this;
deba@1408
  1614
    }
deba@1408
  1615
deba@1409
  1616
  protected:
deba@1409
  1617
deba@1409
  1618
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  1619
    /// the section with the given header line.
deba@1409
  1620
    ///
deba@1421
  1621
    /// It gives back true when the header line start with \c \@attributes,
deba@1409
  1622
    /// and the header line's id and the attributeset's id are the same.
deba@1408
  1623
    bool header(const std::string& line) {
deba@1408
  1624
      std::istringstream ls(line);
deba@1408
  1625
      std::string command;
deba@1408
  1626
      std::string name;
deba@1408
  1627
      ls >> command >> name;
deba@1408
  1628
      return command == "@attributes" && name == id;
deba@1408
  1629
    }
deba@1408
  1630
deba@1409
  1631
    /// \brief Reader function of the section.
deba@1409
  1632
    ///
deba@1409
  1633
    /// It reads the content of the section.
deba@1408
  1634
    void read(std::istream& is) {
deba@1408
  1635
      std::string line;
deba@1408
  1636
      while (getline(is, line)) {
deba@1408
  1637
	std::istringstream ls(line);
deba@1408
  1638
	std::string id;
deba@1408
  1639
	ls >> id;
deba@1408
  1640
	typename Readers::iterator it = readers.find(id);
deba@1408
  1641
	if (it != readers.end()) {
deba@1408
  1642
	  it->second->read(ls);
deba@1408
  1643
	}
deba@1408
  1644
      }
deba@1408
  1645
    }    
deba@1408
  1646
deba@1408
  1647
  private:
deba@1408
  1648
    std::string id;
deba@1408
  1649
deba@1408
  1650
    typedef std::map<std::string, ValueReaderBase*> Readers;
deba@1409
  1651
    Readers readers;  
deba@1408
  1652
  };
deba@1408
  1653
deba@1408
  1654
}
deba@1408
  1655
#endif