lemon/lemon_reader.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2153 b1fb96088350
child 2260 4274224f8a7d
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

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