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