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