lemon/lemon_reader.h
author deba
Wed, 01 Mar 2006 10:25:30 +0000
changeset 1991 d7442141d9ef
parent 1946 17eb3eaad9f8
child 1993 2115143eceea
permissions -rw-r--r--
The graph adadptors can be alteration observed.
In most cases it uses the adapted graph alteration notifiers.
Only special case is now the UndirGraphAdaptor, where
we have to proxy the signals from the graph.

The SubBidirGraphAdaptor is removed, because it doest not
gives more feature than the EdgeSubGraphAdaptor<UndirGraphAdaptor<Graph>>.

The ResGraphAdaptor is based on this composition.
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@1408
    19
///\ingroup io_group
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@1421
    38
#include <lemon/utility.h>
deba@1409
    39
#include <lemon/bits/item_reader.h>
deba@1408
    40
deba@1705
    41
#include <lemon/xy.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>
deba@1705
   186
    struct Ref<XMap<Map> > { 
deba@1705
   187
      typedef XMap<Map> Type;
deba@1705
   188
    };
deba@1705
   189
    template <typename Map>
deba@1705
   190
    struct Arg<XMap<Map> > { 
deba@1705
   191
      typedef const XMap<Map>& Type;
deba@1705
   192
    };
deba@1705
   193
deba@1705
   194
    template <typename Map>
deba@1705
   195
    struct Ref<YMap<Map> > { 
deba@1705
   196
      typedef YMap<Map> Type;
deba@1705
   197
    };
deba@1705
   198
    template <typename Map>
deba@1705
   199
    struct Arg<YMap<Map> > { 
deba@1705
   200
      typedef const 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@1409
   459
  /// \ingroup io_group
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@1408
   526
      int blen() { return _eptr - _base; }
deba@1408
   527
deba@1408
   528
      void setb(char_type* buf, int 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@1408
   584
      virtual int 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@1408
   615
      virtual int 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@1408
   654
    };
deba@1408
   655
deba@1409
   656
    /// \brief Constructor for LemonReader.
deba@1409
   657
    ///
deba@1409
   658
    /// Constructor for LemonReader which reads from the given stream.
deba@1408
   659
    LemonReader(std::istream& _is) 
deba@1408
   660
      : is(&_is), own_is(false) {}
deba@1408
   661
deba@1409
   662
    /// \brief Constructor for LemonReader.
deba@1409
   663
    ///
deba@1409
   664
    /// Constructor for LemonReader which reads from the given file.
deba@1408
   665
    LemonReader(const std::string& filename) 
deba@1408
   666
      : is(0), own_is(true) {
deba@1408
   667
      is = new std::ifstream(filename.c_str());
deba@1746
   668
      if (is->fail()) {
deba@1746
   669
	throw FileOpenError(filename);
deba@1746
   670
      }
deba@1408
   671
    }
deba@1408
   672
deba@1409
   673
    /// \brief Desctructor for LemonReader.
deba@1409
   674
    ///
deba@1409
   675
    /// Desctructor for LemonReader.
deba@1408
   676
    ~LemonReader() {
deba@1408
   677
      if (own_is) {
deba@1408
   678
	delete is;
deba@1408
   679
      }
deba@1408
   680
    }
deba@1408
   681
deba@1408
   682
  private:
deba@1408
   683
    LemonReader(const LemonReader&);
deba@1408
   684
    void operator=(const LemonReader&);
deba@1408
   685
deba@1408
   686
    void attach(SectionReader& reader) {
deba@1408
   687
      readers.push_back(&reader);
deba@1408
   688
    }
deba@1408
   689
deba@1409
   690
  public:
deba@1409
   691
    /// \brief Executes the LemonReader.
deba@1409
   692
    /// 
deba@1409
   693
    /// It executes the LemonReader.
deba@1408
   694
    void run() {
deba@1408
   695
      int line_num = 0;
deba@1408
   696
      std::string line;
deba@1408
   697
      try {
deba@1408
   698
	while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
deba@1408
   699
	  SectionReaders::iterator it;
deba@1408
   700
	  for (it = readers.begin(); it != readers.end(); ++it) {
deba@1408
   701
	    if ((*it)->header(line)) {
deba@1408
   702
	      char buf[2048];
deba@1408
   703
	      FilterStreamBuf buffer(*is, line_num);
deba@1408
   704
	      buffer.pubsetbuf(buf, sizeof(buf));
deba@1408
   705
	      std::istream is(&buffer);
deba@1408
   706
	      (*it)->read(is);
deba@1408
   707
	      break;
deba@1408
   708
	    }
deba@1408
   709
	  }
deba@1408
   710
	}
deba@1408
   711
      } catch (DataFormatError& error) {
deba@1408
   712
	error.line(line_num);
deba@1408
   713
	throw error;
deba@1408
   714
      }	
deba@1408
   715
    }
deba@1408
   716
deba@1408
   717
deba@1408
   718
  private:
deba@1408
   719
deba@1408
   720
    std::istream* is;
deba@1408
   721
    bool own_is;
deba@1408
   722
deba@1408
   723
    typedef std::vector<SectionReader*> SectionReaders;
deba@1408
   724
    SectionReaders readers;
deba@1408
   725
deba@1408
   726
  };
deba@1408
   727
deba@1409
   728
  /// \ingroup io_group
deba@1409
   729
  /// \brief SectionReader for reading a graph's nodeset.
deba@1409
   730
  ///
deba@1409
   731
  /// The lemon format can store multiple graph nodesets with several maps.
deba@1901
   732
  /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but the
deba@1901
   733
  /// \c nodeset_name may be empty.
deba@1409
   734
  ///
deba@1409
   735
  /// The first line of the section contains the names of the maps separated
deba@1409
   736
  /// with white spaces. Each next lines describes a node in the nodeset, and
deba@1409
   737
  /// contains the mapped values for each map.
deba@1409
   738
  ///
deba@1901
   739
  /// If the nodeset contains an \c "label" named map then it will be regarded
deba@1409
   740
  /// as id map. This map should contain only unique values and when the 
deba@1901
   741
  /// \c readLabel() member will read a value from the given stream it will
deba@1409
   742
  /// give back that node which is mapped to this value.
deba@1409
   743
  ///
deba@1409
   744
  /// \relates LemonReader
deba@1408
   745
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@1845
   746
  class NodeSetReader : public LemonReader::SectionReader {
deba@1845
   747
    typedef LemonReader::SectionReader Parent;
deba@1408
   748
  public:
deba@1408
   749
deba@1408
   750
    typedef _Graph Graph;
deba@1408
   751
    typedef _Traits Traits;
deba@1429
   752
    typedef typename Graph::Node Node;
deba@1408
   753
    typedef typename Traits::Skipper DefaultSkipper;
deba@1408
   754
deba@1409
   755
    /// \brief Constructor.
deba@1409
   756
    ///
deba@1409
   757
    /// Constructor for NodeSetReader. It creates the NodeSetReader and
deba@1409
   758
    /// attach it into the given LemonReader. The nodeset reader will
deba@1409
   759
    /// add the readed nodes to the given Graph. The reader will read
deba@1901
   760
    /// the section when the \c section_name and the \c _name are the same. 
deba@1421
   761
    NodeSetReader(LemonReader& _reader, 
deba@1705
   762
		  Graph& _graph, 
deba@1901
   763
		  const std::string& _name = std::string(),
deba@1409
   764
		  const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1901
   765
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {} 
deba@1408
   766
deba@1409
   767
deba@1409
   768
    /// \brief Destructor.
deba@1409
   769
    ///
deba@1409
   770
    /// Destructor for NodeSetReader.
deba@1408
   771
    virtual ~NodeSetReader() {
deba@1408
   772
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1408
   773
	   it != readers.end(); ++it) {
deba@1408
   774
	delete it->second;
deba@1408
   775
      }
deba@1408
   776
    }
deba@1408
   777
deba@1408
   778
  private:
deba@1408
   779
    NodeSetReader(const NodeSetReader&);
deba@1408
   780
    void operator=(const NodeSetReader&);
deba@1408
   781
  
deba@1408
   782
  public:
deba@1408
   783
deba@1408
   784
    /// \brief Add a new node map reader command for the reader.
deba@1408
   785
    ///
deba@1408
   786
    /// Add a new node map reader command for the reader.
deba@1408
   787
    template <typename Map>
deba@1421
   788
    NodeSetReader& readNodeMap(std::string name, Map& map) {
deba@1421
   789
      return _readMap<
deba@1421
   790
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1705
   791
	typename _reader_bits::Arg<Map>::Type>(name, map);
deba@1421
   792
    }
deba@1421
   793
deba@1421
   794
    template <typename Map>
deba@1421
   795
    NodeSetReader& readNodeMap(std::string name, const Map& map) {
deba@1421
   796
      return _readMap<
deba@1421
   797
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1705
   798
	typename _reader_bits::Arg<Map>::Type>(name, map);
deba@1408
   799
    }
deba@1408
   800
deba@1408
   801
    /// \brief Add a new node map reader command for the reader.
deba@1408
   802
    ///
deba@1408
   803
    /// Add a new node map reader command for the reader.
deba@1408
   804
    template <typename Reader, typename Map>
deba@1421
   805
    NodeSetReader& readNodeMap(std::string name, Map& map, 
deba@1421
   806
			       const Reader& reader = Reader()) {
deba@1705
   807
      return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
deba@1429
   808
	(name, map, reader);
deba@1421
   809
    }
deba@1421
   810
deba@1421
   811
    template <typename Reader, typename Map>
deba@1421
   812
    NodeSetReader& readNodeMap(std::string name, const Map& map, 
deba@1421
   813
			       const Reader& reader = Reader()) {
deba@1705
   814
      return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
deba@1429
   815
	(name, map, reader);
deba@1421
   816
    }
deba@1421
   817
deba@1421
   818
  private:
deba@1421
   819
deba@1421
   820
    template <typename Reader, typename Map, typename MapParameter>
deba@1421
   821
    NodeSetReader& _readMap(std::string name, MapParameter map, 
deba@1421
   822
			    const Reader& reader = Reader()) {
deba@1492
   823
      checkConcept<concept::WriteMap<Node, typename Map::Value>, Map>();
deba@1492
   824
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
deba@1408
   825
      if (readers.find(name) != readers.end()) {
deba@1408
   826
	ErrorMessage msg;
deba@1408
   827
	msg << "Multiple read rule for node map: " << name;
deba@1408
   828
	throw IOParameterError(msg.message());
deba@1845
   829
      }      
deba@1408
   830
      readers.insert(
deba@1845
   831
        make_pair(name, new _reader_bits::
deba@1845
   832
		  MapReader<Node, Map, Reader>(map, reader)));
deba@1408
   833
      return *this;
deba@1408
   834
    }
deba@1408
   835
deba@1421
   836
  public:
deba@1421
   837
deba@1408
   838
    /// \brief Add a new node map skipper command for the reader.
deba@1408
   839
    ///
deba@1408
   840
    /// Add a new node map skipper command for the reader.
deba@1408
   841
    template <typename Reader>
deba@1421
   842
    NodeSetReader& skipNodeMap(std::string name, 
deba@1408
   843
			   const Reader& reader = Reader()) {
deba@1408
   844
      if (readers.find(name) != readers.end()) {
deba@1408
   845
	ErrorMessage msg;
deba@1408
   846
	msg << "Multiple read rule for node map: " << name;
deba@1408
   847
	throw IOParameterError(msg.message());
deba@1408
   848
      }
deba@1845
   849
      readers.insert(make_pair(name, new _reader_bits::
deba@1845
   850
			       SkipReader<Node, Reader>(reader)));
deba@1408
   851
      return *this;
deba@1408
   852
    }
deba@1408
   853
deba@1409
   854
  protected:
deba@1409
   855
deba@1409
   856
    /// \brief Gives back true when the SectionReader can process 
deba@1409
   857
    /// the section with the given header line.
deba@1409
   858
    ///
deba@1421
   859
    /// It gives back true when the header line starts with \c \@nodeset,
deba@1901
   860
    /// and the header line's name and the nodeset's name are the same.
deba@1408
   861
    virtual bool header(const std::string& line) {
deba@1408
   862
      std::istringstream ls(line);
deba@1408
   863
      std::string command;
deba@1901
   864
      std::string id;
deba@1408
   865
      ls >> command >> name;
deba@1408
   866
      return command == "@nodeset" && name == id;
deba@1408
   867
    }
deba@1408
   868
deba@1409
   869
    /// \brief Reader function of the section.
deba@1409
   870
    ///
deba@1409
   871
    /// It reads the content of the section.
deba@1408
   872
    virtual void read(std::istream& is) {
deba@1845
   873
      std::vector<_reader_bits::MapReaderBase<Node>* > index;
deba@1408
   874
      std::string line;
deba@1408
   875
deba@1408
   876
      getline(is, line);
deba@1901
   877
      std::istringstream ls(line);
deba@1901
   878
      std::string id;
deba@1408
   879
      while (ls >> id) {
deba@1408
   880
	typename MapReaders::iterator it = readers.find(id);
deba@1408
   881
	if (it != readers.end()) {
deba@1845
   882
	  it->second->touch();
deba@1408
   883
	  index.push_back(it->second);
deba@1408
   884
	} else {
deba@1408
   885
	  index.push_back(&skipper);
deba@1408
   886
	}
deba@1901
   887
	if (id == "label" || (id =="id" && inverter.get() == 0)) {
deba@1408
   888
	  inverter.reset(index.back()->getInverter());
deba@1408
   889
	  index.back() = inverter.get();
deba@1408
   890
	}
deba@1408
   891
      }
deba@1845
   892
      for (typename MapReaders::iterator it = readers.begin();
deba@1845
   893
	   it != readers.end(); ++it) {
deba@1845
   894
	if (!it->second->touched()) {
deba@1845
   895
	  ErrorMessage msg;
deba@1845
   896
	  msg << "Map not found in file: " << it->first;
deba@1845
   897
	  throw IOParameterError(msg.message());
deba@1845
   898
	}
deba@1845
   899
      }
deba@1408
   900
      while (getline(is, line)) {	
deba@1429
   901
	Node node = graph.addNode();
deba@1408
   902
	std::istringstream ls(line);
deba@1408
   903
	for (int i = 0; i < (int)index.size(); ++i) {
deba@1408
   904
	  index[i]->read(ls, node);
deba@1408
   905
	}
deba@1408
   906
      }
deba@1408
   907
    }
deba@1408
   908
deba@1409
   909
  public:
deba@1409
   910
deba@1901
   911
    /// \brief Returns true if the nodeset can give back the node by its label.
deba@1409
   912
    ///
deba@1901
   913
    /// Returns true if the nodeset can give back the node by its label.
deba@1901
   914
    /// It is possible only if an "label" named map was read.
deba@1901
   915
    bool isLabelReader() const {
deba@1408
   916
      return inverter.get() != 0;
deba@1408
   917
    }
deba@1408
   918
deba@1901
   919
    /// \brief Gives back the node by its label.
deba@1409
   920
    ///
deba@1409
   921
    /// It reads an id from the stream and gives back which node belongs to
deba@1901
   922
    /// it. It is possible only if there was read an "label" named map.
deba@1901
   923
    void readLabel(std::istream& is, Node& node) const {
deba@1492
   924
      node = inverter->read(is);
deba@1408
   925
    } 
deba@1408
   926
deba@1408
   927
  private:
deba@1408
   928
deba@1845
   929
    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
deba@1408
   930
    MapReaders readers;
deba@1408
   931
   
deba@1705
   932
    Graph& graph;   
deba@1901
   933
    std::string name;
deba@1845
   934
    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
deba@1408
   935
deba@1845
   936
    std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
deba@1408
   937
  };
deba@1408
   938
deba@1409
   939
  /// \ingroup io_group
deba@1409
   940
  /// \brief SectionReader for reading a graph's edgeset.
deba@1409
   941
  ///
deba@1409
   942
  /// The lemon format can store multiple graph edgesets with several maps.
deba@1901
   943
  /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
deba@1901
   944
  /// \c edgeset_name may be empty.
deba@1409
   945
  ///
deba@1409
   946
  /// The first line of the section contains the names of the maps separated
deba@1421
   947
  /// with white spaces. Each next lines describes an edge in the edgeset. The
deba@1421
   948
  /// line contains the source and the target nodes' id and the mapped 
deba@1421
   949
  /// values for each map.
deba@1409
   950
  ///
deba@1901
   951
  /// If the edgeset contains an \c "label" named map then it will be regarded
deba@1409
   952
  /// as id map. This map should contain only unique values and when the 
deba@1901
   953
  /// \c readLabel() member will read a value from the given stream it will
deba@1409
   954
  /// give back that edge which is mapped to this value.
deba@1409
   955
  ///
deba@1409
   956
  /// The edgeset reader needs a node id reader to identify which nodes
deba@1901
   957
  /// have to be connected. If a NodeSetReader reads an "label" named map,
deba@1409
   958
  /// it will be able to resolve the nodes by ids.
deba@1409
   959
  ///
deba@1409
   960
  /// \relates LemonReader
deba@1408
   961
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@1845
   962
  class EdgeSetReader : public LemonReader::SectionReader {
deba@1845
   963
    typedef LemonReader::SectionReader Parent;
deba@1408
   964
  public:
deba@1408
   965
deba@1408
   966
    typedef _Graph Graph;
deba@1408
   967
    typedef _Traits Traits;
deba@1429
   968
    typedef typename Graph::Node Node;
deba@1429
   969
    typedef typename Graph::Edge Edge;
deba@1408
   970
    typedef typename Traits::Skipper DefaultSkipper;
deba@1408
   971
deba@1409
   972
    /// \brief Constructor.
deba@1409
   973
    ///
deba@1409
   974
    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
deba@1409
   975
    /// attach it into the given LemonReader. The edgeset reader will
deba@1409
   976
    /// add the readed edges to the given Graph. It will use the given
deba@1409
   977
    /// node id reader to read the source and target nodes of the edges.
deba@1901
   978
    /// The reader will read the section only if the \c _name and the 
deba@1901
   979
    /// \c edgset_name are the same. 
deba@1901
   980
    template <typename NodeLabelReader>
deba@1421
   981
    EdgeSetReader(LemonReader& _reader, 
deba@1705
   982
		  Graph& _graph, 
deba@1901
   983
		  const NodeLabelReader& _nodeLabelReader, 
deba@1901
   984
		  const std::string& _name = std::string(),
deba@1409
   985
		  const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1901
   986
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
deba@1901
   987
      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
deba@1901
   988
      nodeLabelReader.reset(new _reader_bits::
deba@1901
   989
			 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
deba@1476
   990
    }
deba@1409
   991
    /// \brief Destructor.
deba@1409
   992
    ///
deba@1409
   993
    /// Destructor for EdgeSetReader.
deba@1408
   994
    virtual ~EdgeSetReader() {
deba@1408
   995
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1408
   996
	   it != readers.end(); ++it) {
deba@1408
   997
	delete it->second;
deba@1408
   998
      }
deba@1408
   999
    }
deba@1408
  1000
deba@1408
  1001
  private:
deba@1408
  1002
    EdgeSetReader(const EdgeSetReader&);
deba@1408
  1003
    void operator=(const EdgeSetReader&);
deba@1408
  1004
deba@1408
  1005
  public:
deba@1408
  1006
deba@1409
  1007
    /// \brief Add a new edge map reader command for the reader.
deba@1408
  1008
    ///
deba@1409
  1009
    /// Add a new edge map reader command for the reader.
deba@1408
  1010
    template <typename Map>
deba@1421
  1011
    EdgeSetReader& readEdgeMap(std::string name, Map& map) {
deba@1421
  1012
      return _readMap<
deba@1421
  1013
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1705
  1014
	typename _reader_bits::Arg<Map>::Type>(name, map);
deba@1421
  1015
    }
deba@1421
  1016
deba@1421
  1017
    template <typename Map>
deba@1421
  1018
    EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
deba@1421
  1019
      return _readMap<
deba@1421
  1020
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1705
  1021
	typename _reader_bits::Arg<Map>::Type>(name, map);
deba@1408
  1022
    }
deba@1408
  1023
deba@1409
  1024
    /// \brief Add a new edge map reader command for the reader.
deba@1408
  1025
    ///
deba@1409
  1026
    /// Add a new edge map reader command for the reader.
deba@1408
  1027
    template <typename Reader, typename Map>
deba@1421
  1028
    EdgeSetReader& readEdgeMap(std::string name, Map& map, 
deba@1421
  1029
			   const Reader& reader = Reader()) {
deba@1429
  1030
      return _readMap<Reader, Map,
deba@1705
  1031
	typename _reader_bits::Arg<Map>::Type>(name, map, reader);
deba@1421
  1032
    }
deba@1421
  1033
deba@1421
  1034
    template <typename Reader, typename Map>
deba@1421
  1035
    EdgeSetReader& readEdgeMap(std::string name, const Map& map, 
deba@1421
  1036
			       const Reader& reader = Reader()) {
deba@1429
  1037
      return _readMap<Reader, Map,
deba@1705
  1038
	typename _reader_bits::Arg<Map>::Type>(name, map, reader);
deba@1421
  1039
    }
deba@1421
  1040
deba@1421
  1041
  private:
deba@1421
  1042
deba@1421
  1043
    template <typename Reader, typename Map, typename MapParameter>
deba@1421
  1044
    EdgeSetReader& _readMap(std::string name, MapParameter map, 
deba@1421
  1045
			    const Reader& reader = Reader()) {
deba@1492
  1046
      checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
deba@1492
  1047
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
deba@1408
  1048
      if (readers.find(name) != readers.end()) {
deba@1408
  1049
	ErrorMessage msg;
deba@1408
  1050
	msg << "Multiple read rule for edge map: " << name;
deba@1408
  1051
	throw IOParameterError(msg.message());
deba@1408
  1052
      }
deba@1408
  1053
      readers.insert(
deba@1845
  1054
	make_pair(name, new _reader_bits::
deba@1845
  1055
		  MapReader<Edge, Map, Reader>(map, reader)));
deba@1408
  1056
      return *this;
deba@1408
  1057
    }
deba@1408
  1058
deba@1421
  1059
  public:
deba@1421
  1060
deba@1409
  1061
    /// \brief Add a new edge map skipper command for the reader.
deba@1408
  1062
    ///
deba@1409
  1063
    /// Add a new edge map skipper command for the reader.
deba@1408
  1064
    template <typename Reader>
deba@1421
  1065
    EdgeSetReader& skipEdgeMap(std::string name, 
deba@1421
  1066
			       const Reader& reader = Reader()) {
deba@1408
  1067
      if (readers.find(name) != readers.end()) {
deba@1408
  1068
	ErrorMessage msg;
deba@1421
  1069
	msg << "Multiple read rule for edge map: " << name;
deba@1408
  1070
	throw IOParameterError(msg.message());
deba@1408
  1071
      }
deba@1845
  1072
      readers.insert(make_pair(name, new _reader_bits::
deba@1845
  1073
			       SkipReader<Edge, Reader>(reader)));
deba@1408
  1074
      return *this;
deba@1408
  1075
    }
deba@1408
  1076
deba@1409
  1077
  protected:
deba@1409
  1078
deba@1409
  1079
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  1080
    /// the section with the given header line.
deba@1409
  1081
    ///
deba@1421
  1082
    /// It gives back true when the header line starts with \c \@edgeset,
deba@1901
  1083
    /// and the header line's name and the edgeset's name are the same.
deba@1408
  1084
    virtual bool header(const std::string& line) {
deba@1408
  1085
      std::istringstream ls(line);
deba@1408
  1086
      std::string command;
deba@1901
  1087
      std::string id;
deba@1408
  1088
      ls >> command >> name;
deba@1408
  1089
      return command == "@edgeset" && name == id;
deba@1408
  1090
    }
deba@1408
  1091
deba@1409
  1092
    /// \brief Reader function of the section.
deba@1409
  1093
    ///
deba@1409
  1094
    /// It reads the content of the section.
deba@1408
  1095
    virtual void read(std::istream& is) {
deba@1901
  1096
      if (!nodeLabelReader->isLabelReader()) {
deba@1901
  1097
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
  1098
      }
deba@1845
  1099
      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
deba@1408
  1100
      std::string line;
deba@1408
  1101
deba@1408
  1102
      getline(is, line);
deba@1408
  1103
      std::istringstream ls(line);	
deba@1901
  1104
      std::string id;
deba@1408
  1105
      while (ls >> id) {
deba@1408
  1106
	typename MapReaders::iterator it = readers.find(id);
deba@1408
  1107
	if (it != readers.end()) {
deba@1408
  1108
	  index.push_back(it->second);
deba@1845
  1109
	  it->second->touch();
deba@1408
  1110
	} else {
deba@1408
  1111
	  index.push_back(&skipper);
deba@1408
  1112
	}
deba@1901
  1113
	if (id == "label" || (id =="id" && inverter.get() == 0)) {
deba@1408
  1114
	  inverter.reset(index.back()->getInverter());
deba@1408
  1115
	  index.back() = inverter.get();
deba@1408
  1116
	}
deba@1408
  1117
      }
deba@1845
  1118
      for (typename MapReaders::iterator it = readers.begin();
deba@1845
  1119
	   it != readers.end(); ++it) {
deba@1845
  1120
	if (!it->second->touched()) {
deba@1845
  1121
	  ErrorMessage msg;
deba@1845
  1122
	  msg << "Map not found in file: " << it->first;
deba@1845
  1123
	  throw IOParameterError(msg.message());
deba@1845
  1124
	}
deba@1845
  1125
      }
deba@1408
  1126
      while (getline(is, line)) {	
deba@1408
  1127
	std::istringstream ls(line);
deba@1901
  1128
	Node from = nodeLabelReader->read(ls);
deba@1901
  1129
	Node to = nodeLabelReader->read(ls);
deba@1429
  1130
	Edge edge = graph.addEdge(from, to);
deba@1408
  1131
	for (int i = 0; i < (int)index.size(); ++i) {
deba@1408
  1132
	  index[i]->read(ls, edge);
deba@1408
  1133
	}
deba@1408
  1134
      }
deba@1408
  1135
    }
deba@1408
  1136
deba@1409
  1137
  public:
deba@1409
  1138
deba@1901
  1139
    /// \brief Returns true if the edgeset can give back the edge by its label.
deba@1409
  1140
    ///
deba@1901
  1141
    /// Returns true if the edgeset can give back the edge by its label.
deba@1901
  1142
    /// It is possible only if an "label" named map was read.
deba@1901
  1143
    bool isLabelReader() const {
deba@1408
  1144
      return inverter.get() != 0;
deba@1408
  1145
    }
deba@1408
  1146
deba@1901
  1147
    /// \brief Gives back the edge by its label.
deba@1409
  1148
    ///
deba@1409
  1149
    /// It reads an id from the stream and gives back which edge belongs to
deba@1901
  1150
    /// it. It is possible only if there was read an "label" named map.
deba@1901
  1151
    void readLabel(std::istream& is, Edge& edge) const {
deba@1492
  1152
      edge = inverter->read(is);
deba@1408
  1153
    } 
deba@1408
  1154
deba@1408
  1155
  private:
deba@1408
  1156
deba@1845
  1157
    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
deba@1408
  1158
    MapReaders readers;
deba@1408
  1159
   
deba@1705
  1160
    Graph& graph;   
deba@1901
  1161
    std::string name;
deba@1845
  1162
    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
deba@1421
  1163
deba@1845
  1164
    std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
deba@1901
  1165
    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
deba@1421
  1166
  };
deba@1421
  1167
deba@1421
  1168
  /// \ingroup io_group
deba@1421
  1169
  /// \brief SectionReader for reading a undirected graph's edgeset.
deba@1421
  1170
  ///
deba@1421
  1171
  /// The lemon format can store multiple undirected edgesets with several 
klao@1909
  1172
  /// maps. The undirected edgeset section's header line is \c \@uedgeset 
klao@1909
  1173
  /// \c uedgeset_name, but the \c uedgeset_name may be empty.
deba@1421
  1174
  ///
deba@1421
  1175
  /// The first line of the section contains the names of the maps separated
deba@1421
  1176
  /// with white spaces. Each next lines describes an edge in the edgeset. The
deba@1421
  1177
  /// line contains the connected nodes' id and the mapped values for each map.
deba@1421
  1178
  ///
deba@1421
  1179
  /// The section can handle the directed as a syntactical sugar. Two
deba@1421
  1180
  /// undirected edge map describes one directed edge map. This two maps
deba@1421
  1181
  /// are the forward map and the backward map and the names of this map
deba@1421
  1182
  /// is near the same just with a prefix \c '+' or \c '-' character 
deba@1421
  1183
  /// difference.
deba@1421
  1184
  ///
deba@1901
  1185
  /// If the edgeset contains an \c "label" named map then it will be regarded
deba@1421
  1186
  /// as id map. This map should contain only unique values and when the 
deba@1901
  1187
  /// \c readLabel() member will read a value from the given stream it will
klao@1909
  1188
  /// give back that uicted edge which is mapped to this value.
deba@1421
  1189
  ///
deba@1421
  1190
  /// The undirected edgeset reader needs a node id reader to identify which 
deba@1901
  1191
  /// nodes have to be connected. If a NodeSetReader reads an "label" named map,
deba@1421
  1192
  /// it will be able to resolve the nodes by ids.
deba@1421
  1193
  ///
deba@1421
  1194
  /// \relates LemonReader
deba@1421
  1195
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
klao@1909
  1196
  class UEdgeSetReader : public LemonReader::SectionReader {
deba@1845
  1197
    typedef LemonReader::SectionReader Parent;
deba@1421
  1198
  public:
deba@1421
  1199
deba@1421
  1200
    typedef _Graph Graph;
deba@1421
  1201
    typedef _Traits Traits;
deba@1429
  1202
    typedef typename Graph::Node Node;
deba@1429
  1203
    typedef typename Graph::Edge Edge;
klao@1909
  1204
    typedef typename Graph::UEdge UEdge;
deba@1421
  1205
    typedef typename Traits::Skipper DefaultSkipper;
deba@1421
  1206
deba@1421
  1207
    /// \brief Constructor.
deba@1421
  1208
    ///
klao@1909
  1209
    /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader 
deba@1421
  1210
    /// and attach it into the given LemonReader. The undirected edgeset 
deba@1421
  1211
    /// reader will add the readed undirected edges to the given Graph. It 
deba@1421
  1212
    /// will use the given node id reader to read the source and target 
deba@1421
  1213
    /// nodes of the edges. The reader will read the section only if the 
klao@1909
  1214
    /// \c _name and the \c uedgset_name are the same. 
deba@1901
  1215
    template <typename NodeLabelReader>
klao@1909
  1216
    UEdgeSetReader(LemonReader& _reader, 
deba@1705
  1217
		       Graph& _graph, 
deba@1901
  1218
		       const NodeLabelReader& _nodeLabelReader, 
deba@1901
  1219
		       const std::string& _name = std::string(),
deba@1421
  1220
		       const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1901
  1221
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
deba@1901
  1222
      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
deba@1901
  1223
      nodeLabelReader.reset(new _reader_bits::
deba@1901
  1224
			 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
deba@1476
  1225
    }
deba@1421
  1226
    /// \brief Destructor.
deba@1421
  1227
    ///
klao@1909
  1228
    /// Destructor for UEdgeSetReader.
klao@1909
  1229
    virtual ~UEdgeSetReader() {
deba@1421
  1230
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1421
  1231
	   it != readers.end(); ++it) {
deba@1421
  1232
	delete it->second;
deba@1421
  1233
      }
deba@1421
  1234
    }
deba@1421
  1235
deba@1421
  1236
  private:
klao@1909
  1237
    UEdgeSetReader(const UEdgeSetReader&);
klao@1909
  1238
    void operator=(const UEdgeSetReader&);
deba@1421
  1239
deba@1421
  1240
  public:
deba@1421
  1241
deba@1421
  1242
    /// \brief Add a new undirected edge map reader command for the reader.
deba@1421
  1243
    ///
deba@1421
  1244
    /// Add a new edge undirected map reader command for the reader.
deba@1421
  1245
    template <typename Map>
klao@1909
  1246
    UEdgeSetReader& readUEdgeMap(std::string name, Map& map) {
deba@1421
  1247
      return _readMap<
deba@1421
  1248
	typename Traits::template Reader<typename Map::Value>, Map, 
deba@1705
  1249
	typename _reader_bits::Arg<Map>::Type>(name, map);
deba@1421
  1250
    }
deba@1421
  1251
deba@1421
  1252
    template <typename Map>
klao@1909
  1253
    UEdgeSetReader& readUEdgeMap(std::string name, const Map& map) {
deba@1421
  1254
      return _readMap<
deba@1421
  1255
	typename Traits::template Reader<typename Map::Value>, Map, 
deba@1705
  1256
	typename _reader_bits::Arg<Map>::Type>(name, map);
deba@1421
  1257
    }
deba@1421
  1258
deba@1421
  1259
    /// \brief Add a new undirected edge map reader command for the reader.
deba@1421
  1260
    ///
deba@1421
  1261
    /// Add a new edge undirected map reader command for the reader.
deba@1421
  1262
    template <typename Reader, typename Map>
klao@1909
  1263
    UEdgeSetReader& readUEdgeMap(std::string name, Map& map, 
deba@1421
  1264
					 const Reader& reader = Reader()) {
deba@1705
  1265
      return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
deba@1421
  1266
	(name, map, reader);
deba@1421
  1267
    }
deba@1421
  1268
deba@1421
  1269
    template <typename Reader, typename Map>
klao@1909
  1270
    UEdgeSetReader& readUEdgeMap(std::string name, const Map& map, 
deba@1421
  1271
					 const Reader& reader = Reader()) {
deba@1705
  1272
      return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type >
deba@1421
  1273
	(name, map, reader);
deba@1421
  1274
    }
deba@1421
  1275
deba@1421
  1276
  private:
deba@1421
  1277
deba@1421
  1278
    template <typename Reader, typename Map, typename MapParameter>
klao@1909
  1279
    UEdgeSetReader& _readMap(std::string name, MapParameter map,
deba@1421
  1280
				 const Reader& reader = Reader()) {
klao@1909
  1281
      checkConcept<concept::WriteMap<UEdge, typename Map::Value>, Map>();
deba@1492
  1282
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
deba@1421
  1283
      if (readers.find(name) != readers.end()) {
deba@1421
  1284
	ErrorMessage msg;
deba@1421
  1285
	msg << "Multiple read rule for edge map: " << name;
deba@1421
  1286
	throw IOParameterError(msg.message());
deba@1421
  1287
      }
deba@1421
  1288
      readers.insert(
deba@1845
  1289
	make_pair(name, new _reader_bits::
klao@1909
  1290
		  MapReader<UEdge, Map, Reader>(map, reader)));
deba@1421
  1291
      return *this;
deba@1421
  1292
    }
deba@1421
  1293
deba@1421
  1294
  public:
deba@1421
  1295
deba@1421
  1296
    /// \brief Add a new undirected edge map skipper command for the reader.
deba@1421
  1297
    ///
deba@1421
  1298
    /// Add a new undirected edge map skipper command for the reader.
deba@1421
  1299
    template <typename Reader>
klao@1909
  1300
    UEdgeSetReader& skipUEdgeMap(std::string name, 
deba@1421
  1301
					 const Reader& reader = Reader()) {
deba@1421
  1302
      if (readers.find(name) != readers.end()) {
deba@1421
  1303
	ErrorMessage msg;
deba@1421
  1304
	msg << "Multiple read rule for node map: " << name;
deba@1421
  1305
	throw IOParameterError(msg.message());
deba@1421
  1306
      }
deba@1845
  1307
      readers.insert(make_pair(name, new _reader_bits::
klao@1909
  1308
			       SkipReader<UEdge, Reader>(reader)));
deba@1421
  1309
      return *this;
deba@1421
  1310
    }
deba@1421
  1311
deba@1421
  1312
    /// \brief Add a new directed edge map reader command for the reader.
deba@1421
  1313
    ///
deba@1421
  1314
    /// Add a new directed edge map reader command for the reader.
deba@1421
  1315
    template <typename Map>
klao@1909
  1316
    UEdgeSetReader& readEdgeMap(std::string name, Map& map) {
deba@1421
  1317
      return _readDirMap<
deba@1421
  1318
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1705
  1319
	typename _reader_bits::Arg<Map>::Type>(name, map);
deba@1421
  1320
    }
deba@1421
  1321
deba@1421
  1322
    template <typename Map>
klao@1909
  1323
    UEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
deba@1421
  1324
      return _readDirMap<
deba@1421
  1325
	typename Traits::template Reader<typename Map::Value>, Map,
deba@1705
  1326
	typename _reader_bits::Arg<Map>::Type>(name, map);
deba@1421
  1327
    }
deba@1421
  1328
deba@1421
  1329
    /// \brief Add a new directed edge map reader command for the reader.
deba@1421
  1330
    ///
deba@1421
  1331
    /// Add a new directed edge map reader command for the reader.
deba@1421
  1332
    template <typename Reader, typename Map>
klao@1909
  1333
    UEdgeSetReader& readEdgeMap(std::string name, Map& map, 
deba@1421
  1334
				    const Reader& reader = Reader()) {
deba@1705
  1335
      return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
deba@1421
  1336
	(name, map, reader);
deba@1421
  1337
    }
deba@1421
  1338
deba@1421
  1339
    template <typename Reader, typename Map>
klao@1909
  1340
    UEdgeSetReader& readEdgeMap(std::string name, const Map& map, 
deba@1421
  1341
				    const Reader& reader = Reader()) {
deba@1705
  1342
      return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
deba@1421
  1343
	(name, map, reader);
deba@1421
  1344
    }
deba@1421
  1345
deba@1421
  1346
  private:
deba@1421
  1347
deba@1421
  1348
    template <typename Reader, typename Map, typename MapParameter>
klao@1909
  1349
    UEdgeSetReader& _readDirMap(std::string name, MapParameter map,
deba@1492
  1350
				    const Reader& reader = Reader()) { 
deba@1492
  1351
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
deba@1492
  1352
      checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
deba@1421
  1353
      readMap("+" + name, 
deba@1705
  1354
	      _reader_bits::forwardComposeMap(graph, map), reader);
deba@1421
  1355
      readMap("-" + name, 
deba@1705
  1356
	      _reader_bits::backwardComposeMap(graph, map), reader);
deba@1421
  1357
      return *this;      
deba@1421
  1358
    }
deba@1421
  1359
deba@1421
  1360
  public:
deba@1421
  1361
deba@1421
  1362
    /// \brief Add a new directed edge map skipper command for the reader.
deba@1421
  1363
    ///
deba@1421
  1364
    /// Add a new directed edge map skipper command for the reader.
deba@1421
  1365
    template <typename Reader>
klao@1909
  1366
    UEdgeSetReader& skipEdgeMap(std::string name, 
deba@1421
  1367
				    const Reader& reader = Reader()) {
deba@1421
  1368
      skipMap("+" + name, reader);
deba@1421
  1369
      skipMap("-" + name, reader);
deba@1421
  1370
      return *this;
deba@1421
  1371
    }
deba@1421
  1372
deba@1421
  1373
  protected:
deba@1421
  1374
deba@1421
  1375
    /// \brief Gives back true when the SectionReader can process 
deba@1421
  1376
    /// the section with the given header line.
deba@1421
  1377
    ///
klao@1909
  1378
    /// It gives back true when the header line starts with \c \@uedgeset,
deba@1901
  1379
    /// and the header line's name and the edgeset's name are the same.
deba@1421
  1380
    virtual bool header(const std::string& line) {
deba@1421
  1381
      std::istringstream ls(line);
deba@1421
  1382
      std::string command;
deba@1901
  1383
      std::string id;
deba@1421
  1384
      ls >> command >> name;
klao@1909
  1385
      return command == "@uedgeset" && name == id;
deba@1421
  1386
    }
deba@1421
  1387
deba@1421
  1388
    /// \brief Reader function of the section.
deba@1421
  1389
    ///
deba@1421
  1390
    /// It reads the content of the section.
deba@1421
  1391
    virtual void read(std::istream& is) {
deba@1901
  1392
      if (!nodeLabelReader->isLabelReader()) {
deba@1901
  1393
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
  1394
      }
klao@1909
  1395
      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
deba@1421
  1396
      std::string line;
deba@1421
  1397
deba@1421
  1398
      getline(is, line);
deba@1421
  1399
      std::istringstream ls(line);	
deba@1901
  1400
      std::string id;
deba@1421
  1401
      while (ls >> id) {
deba@1421
  1402
	typename MapReaders::iterator it = readers.find(id);
deba@1421
  1403
	if (it != readers.end()) {
deba@1421
  1404
	  index.push_back(it->second);
deba@1845
  1405
	  it->second->touch();
deba@1421
  1406
	} else {
deba@1421
  1407
	  index.push_back(&skipper);
deba@1421
  1408
	}
deba@1901
  1409
	if (id == "label" || (id =="id" && inverter.get() == 0)) {
deba@1421
  1410
	  inverter.reset(index.back()->getInverter());
deba@1421
  1411
	  index.back() = inverter.get();
deba@1421
  1412
	}
deba@1421
  1413
      }
deba@1845
  1414
      for (typename MapReaders::iterator it = readers.begin();
deba@1845
  1415
	   it != readers.end(); ++it) {
deba@1845
  1416
	if (!it->second->touched()) {
deba@1845
  1417
	  ErrorMessage msg;
deba@1845
  1418
	  msg << "Map not found in file: " << it->first;
deba@1845
  1419
	  throw IOParameterError(msg.message());
deba@1845
  1420
	}
deba@1845
  1421
      }
deba@1421
  1422
      while (getline(is, line)) {	
deba@1421
  1423
	std::istringstream ls(line);
deba@1901
  1424
	Node from = nodeLabelReader->read(ls);
deba@1901
  1425
	Node to = nodeLabelReader->read(ls);
klao@1909
  1426
	UEdge edge = graph.addEdge(from, to);
deba@1421
  1427
	for (int i = 0; i < (int)index.size(); ++i) {
deba@1421
  1428
	  index[i]->read(ls, edge);
deba@1421
  1429
	}
deba@1421
  1430
      }
deba@1421
  1431
    }
deba@1421
  1432
deba@1421
  1433
  public:
deba@1421
  1434
deba@1901
  1435
    /// \brief Returns true if the edgeset can give back the edge by its label.
deba@1421
  1436
    ///
deba@1421
  1437
    /// Returns true if the edgeset can give back the undirected edge by its 
deba@1901
  1438
    /// id. It is possible only if an "label" named map was read.
deba@1901
  1439
    bool isLabelReader() const {
deba@1421
  1440
      return inverter.get() != 0;
deba@1421
  1441
    }
deba@1421
  1442
deba@1901
  1443
    /// \brief Gives back the undirected edge by its label.
deba@1421
  1444
    ///
deba@1421
  1445
    /// It reads an id from the stream and gives back which undirected edge 
deba@1901
  1446
    /// belongs to it. It is possible only if there was read an "label" named map.
klao@1909
  1447
    void readLabel(std::istream& is, UEdge& uEdge) const {
klao@1909
  1448
      uEdge = inverter->read(is);
deba@1421
  1449
    } 
deba@1421
  1450
deba@1901
  1451
    /// \brief Gives back the directed edge by its label.
deba@1429
  1452
    ///
deba@1429
  1453
    /// It reads an id from the stream and gives back which directed edge 
deba@1429
  1454
    /// belongs to it. The directed edge id is the \c '+' or \c '-' character
deba@1429
  1455
    /// and the undirected edge id. It is possible only if there was read 
deba@1901
  1456
    /// an "label" named map.
deba@1901
  1457
    void readLabel(std::istream& is, Edge& edge) const {
deba@1429
  1458
      char c;
deba@1429
  1459
      is >> c;
klao@1909
  1460
      UEdge uEdge = inverter->read(is);
deba@1429
  1461
      if (c == '+') {
klao@1909
  1462
	edge = graph.direct(uEdge, true);
deba@1429
  1463
      } else if (c == '-') {
klao@1909
  1464
        edge = graph.direct(uEdge, false);
deba@1429
  1465
      } else {
deba@1429
  1466
	throw DataFormatError("Wrong id format for edge "
deba@1429
  1467
			      "in undirected edgeset");
deba@1429
  1468
      }
deba@1429
  1469
    } 
deba@1429
  1470
deba@1421
  1471
  private:
deba@1421
  1472
deba@1845
  1473
    typedef std::map<std::string, 
klao@1909
  1474
		     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
deba@1421
  1475
    MapReaders readers;
deba@1421
  1476
   
deba@1705
  1477
    Graph& graph;   
deba@1901
  1478
    std::string name;
klao@1909
  1479
    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
deba@1408
  1480
klao@1909
  1481
    std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
deba@1901
  1482
    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
deba@1408
  1483
  };
deba@1408
  1484
deba@1409
  1485
  /// \ingroup io_group
deba@1409
  1486
  /// \brief SectionReader for reading labeled nodes.
deba@1409
  1487
  ///
deba@1901
  1488
  /// The nodes section's header line is \c \@nodes \c nodes_name, but the
deba@1901
  1489
  /// \c nodes_name may be empty.
deba@1409
  1490
  ///
deba@1409
  1491
  /// Each line in the section contains the name of the node 
deba@1409
  1492
  /// and then the node id. 
deba@1409
  1493
  ///
deba@1409
  1494
  /// \relates LemonReader
deba@1409
  1495
  template <typename _Graph>
deba@1845
  1496
  class NodeReader : public LemonReader::SectionReader {
deba@1845
  1497
    typedef LemonReader::SectionReader Parent;
deba@1409
  1498
    typedef _Graph Graph;
deba@1429
  1499
    typedef typename Graph::Node Node;
deba@1409
  1500
  public:
deba@1409
  1501
    
deba@1409
  1502
    /// \brief Constructor.
deba@1409
  1503
    ///
deba@1409
  1504
    /// Constructor for NodeReader. It creates the NodeReader and
deba@1409
  1505
    /// attach it into the given LemonReader. It will use the given
deba@1409
  1506
    /// node id reader to give back the nodes. The reader will read the 
deba@1901
  1507
    /// section only if the \c _name and the \c nodes_name are the same. 
deba@1901
  1508
    template <typename _LabelReader>
deba@1901
  1509
    NodeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
deba@1901
  1510
	       const std::string& _name = std::string()) 
deba@1901
  1511
      : Parent(_reader), name(_name) {
deba@1901
  1512
      checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
deba@1901
  1513
      nodeLabelReader.reset(new _reader_bits::
deba@1901
  1514
			 LabelReader<Node, _LabelReader>(_labelReader));
deba@1476
  1515
    }
deba@1408
  1516
deba@1409
  1517
    /// \brief Destructor.
deba@1409
  1518
    ///
deba@1409
  1519
    /// Destructor for NodeReader.
deba@1409
  1520
    virtual ~NodeReader() {}
deba@1409
  1521
deba@1409
  1522
  private:
deba@1409
  1523
    NodeReader(const NodeReader&);
deba@1409
  1524
    void operator=(const NodeReader&);
deba@1409
  1525
deba@1409
  1526
  public:
deba@1409
  1527
deba@1409
  1528
    /// \brief Add a node reader command for the NodeReader.
deba@1409
  1529
    ///
deba@1409
  1530
    /// Add a node reader command for the NodeReader.
deba@1429
  1531
    void readNode(const std::string& name, Node& item) {
deba@1409
  1532
      if (readers.find(name) != readers.end()) {
deba@1409
  1533
	ErrorMessage msg;
deba@1409
  1534
	msg << "Multiple read rule for node: " << name;
deba@1409
  1535
	throw IOParameterError(msg.message());
deba@1409
  1536
      }
deba@1845
  1537
      readers.insert(make_pair(name, _reader_bits::ItemStore<Node>(item)));
deba@1409
  1538
    }
deba@1409
  1539
deba@1409
  1540
  protected:
deba@1409
  1541
deba@1409
  1542
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  1543
    /// the section with the given header line.
deba@1409
  1544
    ///
deba@1421
  1545
    /// It gives back true when the header line start with \c \@nodes,
deba@1901
  1546
    /// and the header line's name and the reader's name are the same.
deba@1409
  1547
    virtual bool header(const std::string& line) {
deba@1409
  1548
      std::istringstream ls(line);
deba@1409
  1549
      std::string command;
deba@1901
  1550
      std::string id;
deba@1409
  1551
      ls >> command >> name;
deba@1409
  1552
      return command == "@nodes" && name == id;
deba@1409
  1553
    }
deba@1409
  1554
deba@1409
  1555
    /// \brief Reader function of the section.
deba@1409
  1556
    ///
deba@1409
  1557
    /// It reads the content of the section.
deba@1409
  1558
    virtual void read(std::istream& is) {
deba@1901
  1559
      if (!nodeLabelReader->isLabelReader()) {
deba@1901
  1560
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
  1561
      }
deba@1409
  1562
      std::string line;
deba@1409
  1563
      while (getline(is, line)) {
deba@1409
  1564
	std::istringstream ls(line);
deba@1409
  1565
	std::string id;
deba@1409
  1566
	ls >> id;
deba@1429
  1567
	typename NodeReaders::iterator it = readers.find(id);
deba@1409
  1568
	if (it != readers.end()) {
deba@1901
  1569
	  it->second.read(nodeLabelReader->read(ls));
deba@1845
  1570
	  it->second.touch();
deba@1409
  1571
	}	
deba@1409
  1572
      }
deba@1845
  1573
      for (typename NodeReaders::iterator it = readers.begin();
deba@1845
  1574
	   it != readers.end(); ++it) {
deba@1845
  1575
	if (!it->second.touched()) {
deba@1845
  1576
	  ErrorMessage msg;
deba@1845
  1577
	  msg << "Node not found in file: " << it->first;
deba@1845
  1578
	  throw IOParameterError(msg.message());
deba@1845
  1579
	}
deba@1845
  1580
      }
deba@1409
  1581
    }
deba@1409
  1582
    
deba@1409
  1583
  private:
deba@1409
  1584
deba@1901
  1585
    std::string name;
deba@1409
  1586
deba@1845
  1587
    typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
deba@1429
  1588
    NodeReaders readers;
deba@1901
  1589
    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
deba@1409
  1590
  };
deba@1409
  1591
deba@1409
  1592
  /// \ingroup io_group
deba@1409
  1593
  /// \brief SectionReader for reading labeled edges.
deba@1409
  1594
  ///
deba@1901
  1595
  /// The edges section's header line is \c \@edges \c edges_name, but the
deba@1901
  1596
  /// \c edges_name may be empty.
deba@1409
  1597
  ///
deba@1409
  1598
  /// Each line in the section contains the name of the edge 
deba@1409
  1599
  /// and then the edge id. 
deba@1409
  1600
  ///
deba@1409
  1601
  /// \relates LemonReader
deba@1409
  1602
  template <typename _Graph>
deba@1845
  1603
  class EdgeReader : public LemonReader::SectionReader {
deba@1845
  1604
    typedef LemonReader::SectionReader Parent;
deba@1409
  1605
    typedef _Graph Graph;
deba@1429
  1606
    typedef typename Graph::Edge Edge;
deba@1409
  1607
  public:
deba@1409
  1608
    
deba@1409
  1609
    /// \brief Constructor.
deba@1409
  1610
    ///
deba@1409
  1611
    /// Constructor for EdgeReader. It creates the EdgeReader and
deba@1409
  1612
    /// attach it into the given LemonReader. It will use the given
deba@1409
  1613
    /// edge id reader to give back the edges. The reader will read the 
deba@1901
  1614
    /// section only if the \c _name and the \c edges_name are the same. 
deba@1901
  1615
    template <typename _LabelReader>
deba@1901
  1616
    EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
deba@1901
  1617
	       const std::string& _name = std::string()) 
deba@1901
  1618
      : Parent(_reader), name(_name) {
deba@1901
  1619
      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
deba@1901
  1620
      edgeLabelReader.reset(new _reader_bits::
deba@1901
  1621
			 LabelReader<Edge, _LabelReader>(_labelReader));
deba@1476
  1622
    }
deba@1409
  1623
deba@1409
  1624
    /// \brief Destructor.
deba@1409
  1625
    ///
deba@1409
  1626
    /// Destructor for EdgeReader.
deba@1409
  1627
    virtual ~EdgeReader() {}
deba@1409
  1628
  private:
deba@1409
  1629
    EdgeReader(const EdgeReader&);
deba@1409
  1630
    void operator=(const EdgeReader&);
deba@1409
  1631
deba@1409
  1632
  public:
deba@1409
  1633
deba@1409
  1634
    /// \brief Add an edge reader command for the EdgeReader.
deba@1409
  1635
    ///
deba@1409
  1636
    /// Add an edge reader command for the EdgeReader.
deba@1429
  1637
    void readEdge(const std::string& name, Edge& item) {
deba@1409
  1638
      if (readers.find(name) != readers.end()) {
deba@1409
  1639
	ErrorMessage msg;
deba@1409
  1640
	msg << "Multiple read rule for edge: " << name;
deba@1409
  1641
	throw IOParameterError(msg.message());
deba@1409
  1642
      }
deba@1845
  1643
      readers.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
deba@1409
  1644
    }
deba@1409
  1645
deba@1409
  1646
  protected:
deba@1409
  1647
deba@1409
  1648
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  1649
    /// the section with the given header line.
deba@1409
  1650
    ///
deba@1421
  1651
    /// It gives back true when the header line start with \c \@edges,
deba@1901
  1652
    /// and the header line's name and the reader's name are the same.
deba@1421
  1653
    virtual bool header(const std::string& line) {
deba@1421
  1654
      std::istringstream ls(line);
deba@1421
  1655
      std::string command;
deba@1901
  1656
      std::string id;
deba@1421
  1657
      ls >> command >> name;
deba@1421
  1658
      return command == "@edges" && name == id;
deba@1421
  1659
    }
deba@1421
  1660
deba@1421
  1661
    /// \brief Reader function of the section.
deba@1421
  1662
    ///
deba@1421
  1663
    /// It reads the content of the section.
deba@1421
  1664
    virtual void read(std::istream& is) {
deba@1901
  1665
      if (!edgeLabelReader->isLabelReader()) {
deba@1901
  1666
	throw DataFormatError("Cannot find edgeset or label map");
deba@1476
  1667
      }
deba@1421
  1668
      std::string line;
deba@1421
  1669
      while (getline(is, line)) {
deba@1421
  1670
	std::istringstream ls(line);
deba@1421
  1671
	std::string id;
deba@1421
  1672
	ls >> id;
deba@1429
  1673
	typename EdgeReaders::iterator it = readers.find(id);
deba@1421
  1674
	if (it != readers.end()) {
deba@1901
  1675
	  it->second.read(edgeLabelReader->read(ls));
deba@1845
  1676
	  it->second.touch();
deba@1421
  1677
	}	
deba@1421
  1678
      }
deba@1845
  1679
      for (typename EdgeReaders::iterator it = readers.begin();
deba@1845
  1680
	   it != readers.end(); ++it) {
deba@1845
  1681
	if (!it->second.touched()) {
deba@1845
  1682
	  ErrorMessage msg;
deba@1845
  1683
	  msg << "Edge not found in file: " << it->first;
deba@1845
  1684
	  throw IOParameterError(msg.message());
deba@1845
  1685
	}
deba@1845
  1686
      }
deba@1421
  1687
    }
deba@1421
  1688
    
deba@1421
  1689
  private:
deba@1421
  1690
deba@1901
  1691
    std::string name;
deba@1421
  1692
deba@1845
  1693
    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
deba@1429
  1694
    EdgeReaders readers;
deba@1901
  1695
    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
deba@1421
  1696
  };
deba@1421
  1697
deba@1421
  1698
  /// \ingroup io_group
deba@1421
  1699
  /// \brief SectionReader for reading labeled undirected edges.
deba@1421
  1700
  ///
klao@1909
  1701
  /// The undirected edges section's header line is \c \@uedges 
klao@1909
  1702
  /// \c uedges_name, but the \c uedges_name may be empty.
deba@1421
  1703
  ///
deba@1421
  1704
  /// Each line in the section contains the name of the undirected edge 
deba@1421
  1705
  /// and then the undirected edge id. 
deba@1421
  1706
  ///
deba@1421
  1707
  /// \relates LemonReader
deba@1421
  1708
  template <typename _Graph>
klao@1909
  1709
  class UEdgeReader : public LemonReader::SectionReader {
deba@1845
  1710
    typedef LemonReader::SectionReader Parent;
deba@1421
  1711
    typedef _Graph Graph;
deba@1429
  1712
    typedef typename Graph::Edge Edge;
klao@1909
  1713
    typedef typename Graph::UEdge UEdge;
deba@1421
  1714
  public:
deba@1421
  1715
    
deba@1421
  1716
    /// \brief Constructor.
deba@1421
  1717
    ///
klao@1909
  1718
    /// Constructor for UEdgeReader. It creates the UEdgeReader and
deba@1421
  1719
    /// attach it into the given LemonReader. It will use the given
deba@1421
  1720
    /// undirected edge id reader to give back the edges. The reader will 
klao@1909
  1721
    /// read the section only if the \c _name and the \c uedges_name are 
deba@1421
  1722
    /// the same. 
deba@1901
  1723
    template <typename _LabelReader>
klao@1909
  1724
    UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
deba@1901
  1725
	       const std::string& _name = std::string()) 
deba@1901
  1726
      : Parent(_reader), name(_name) {
klao@1909
  1727
      checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
deba@1901
  1728
      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
klao@1909
  1729
      uEdgeLabelReader.reset(new _reader_bits::
klao@1909
  1730
			      LabelReader<UEdge, _LabelReader>(_labelReader));
deba@1901
  1731
      edgeLabelReader.reset(new _reader_bits::
deba@1901
  1732
			 LabelReader<Edge, _LabelReader>(_labelReader));
deba@1476
  1733
    }
deba@1421
  1734
deba@1421
  1735
    /// \brief Destructor.
deba@1421
  1736
    ///
klao@1909
  1737
    /// Destructor for UEdgeReader.
klao@1909
  1738
    virtual ~UEdgeReader() {}
deba@1421
  1739
  private:
klao@1909
  1740
    UEdgeReader(const UEdgeReader&);
klao@1909
  1741
    void operator=(const UEdgeReader&);
deba@1421
  1742
deba@1421
  1743
  public:
deba@1421
  1744
klao@1909
  1745
    /// \brief Add an undirected edge reader command for the UEdgeReader.
deba@1421
  1746
    ///
klao@1909
  1747
    /// Add an undirected edge reader command for the UEdgeReader.
klao@1909
  1748
    void readUEdge(const std::string& name, UEdge& item) {
klao@1909
  1749
      if (uEdgeReaders.find(name) != uEdgeReaders.end()) {
deba@1429
  1750
	ErrorMessage msg;
deba@1429
  1751
	msg << "Multiple read rule for undirected edge: " << name;
deba@1429
  1752
	throw IOParameterError(msg.message());
deba@1429
  1753
      }
klao@1909
  1754
      uEdgeReaders.insert(make_pair(name, _reader_bits::
klao@1909
  1755
					ItemStore<UEdge>(item)));
deba@1429
  1756
    }
deba@1429
  1757
klao@1909
  1758
    /// \brief Add an edge reader command for the UEdgeReader.
deba@1429
  1759
    ///
klao@1909
  1760
    /// Add an edge reader command for the UEdgeReader.
deba@1429
  1761
    void readEdge(const std::string& name, Edge& item) {
deba@1429
  1762
      if (edgeReaders.find(name) != edgeReaders.end()) {
deba@1421
  1763
	ErrorMessage msg;
deba@1421
  1764
	msg << "Multiple read rule for edge: " << name;
deba@1421
  1765
	throw IOParameterError(msg.message());
deba@1421
  1766
      }
deba@1845
  1767
      edgeReaders.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
deba@1421
  1768
    }
deba@1421
  1769
deba@1421
  1770
  protected:
deba@1421
  1771
deba@1421
  1772
    /// \brief Gives back true when the SectionReader can process 
deba@1421
  1773
    /// the section with the given header line.
deba@1421
  1774
    ///
deba@1421
  1775
    /// It gives back true when the header line start with \c \@edges,
deba@1901
  1776
    /// and the header line's name and the reader's name are the same.
deba@1409
  1777
    virtual bool header(const std::string& line) {
deba@1409
  1778
      std::istringstream ls(line);
deba@1409
  1779
      std::string command;
deba@1901
  1780
      std::string id;
deba@1409
  1781
      ls >> command >> name;
klao@1909
  1782
      return command == "@uedges" && name == id;
deba@1409
  1783
    }
deba@1409
  1784
deba@1409
  1785
    /// \brief Reader function of the section.
deba@1409
  1786
    ///
deba@1409
  1787
    /// It reads the content of the section.
deba@1409
  1788
    virtual void read(std::istream& is) {
deba@1901
  1789
      if (!edgeLabelReader->isLabelReader()) {
deba@1901
  1790
	throw DataFormatError("Cannot find undirected edgeset or label map");
deba@1476
  1791
      }
klao@1909
  1792
      if (!uEdgeLabelReader->isLabelReader()) {
deba@1901
  1793
	throw DataFormatError("Cannot find undirected edgeset or label map");
deba@1476
  1794
      }
deba@1409
  1795
      std::string line;
deba@1409
  1796
      while (getline(is, line)) {
deba@1409
  1797
	std::istringstream ls(line);
deba@1409
  1798
	std::string id;
deba@1409
  1799
	ls >> id;
deba@1429
  1800
	{
klao@1909
  1801
	  typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
klao@1909
  1802
	  if (it != uEdgeReaders.end()) {
klao@1909
  1803
	    it->second.read(uEdgeLabelReader->read(ls));
deba@1845
  1804
	    it->second.touch();
deba@1845
  1805
	    continue;
deba@1429
  1806
	  }	
deba@1429
  1807
	} {
deba@1429
  1808
	  typename EdgeReaders::iterator it = edgeReaders.find(id);
deba@1429
  1809
	  if (it != edgeReaders.end()) {
deba@1901
  1810
	    it->second.read(edgeLabelReader->read(ls));
deba@1845
  1811
	    it->second.touch();
deba@1845
  1812
	    continue;
deba@1429
  1813
	  }	
deba@1429
  1814
	}
deba@1409
  1815
      }
deba@1845
  1816
      for (typename EdgeReaders::iterator it = edgeReaders.begin();
deba@1845
  1817
	   it != edgeReaders.end(); ++it) {
deba@1845
  1818
	if (!it->second.touched()) {
deba@1845
  1819
	  ErrorMessage msg;
deba@1845
  1820
	  msg << "Edge not found in file: " << it->first;
deba@1845
  1821
	  throw IOParameterError(msg.message());
deba@1845
  1822
	}
deba@1845
  1823
      }
klao@1909
  1824
      for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
klao@1909
  1825
	   it != uEdgeReaders.end(); ++it) {
deba@1845
  1826
	if (!it->second.touched()) {
deba@1845
  1827
	  ErrorMessage msg;
klao@1909
  1828
	  msg << "UEdge not found in file: " << it->first;
deba@1845
  1829
	  throw IOParameterError(msg.message());
deba@1845
  1830
	}
deba@1845
  1831
      }
deba@1409
  1832
    }
deba@1409
  1833
    
deba@1409
  1834
  private:
deba@1409
  1835
deba@1901
  1836
    std::string name;
deba@1409
  1837
deba@1845
  1838
    typedef std::map<std::string, 
klao@1909
  1839
		     _reader_bits::ItemStore<UEdge> > UEdgeReaders;
klao@1909
  1840
    UEdgeReaders uEdgeReaders;
klao@1909
  1841
    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
deba@1429
  1842
deba@1845
  1843
    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
deba@1429
  1844
    EdgeReaders edgeReaders;
deba@1901
  1845
    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
deba@1409
  1846
  };
deba@1409
  1847
deba@1409
  1848
  /// \ingroup io_group
deba@1409
  1849
  /// \brief SectionReader for attributes.
deba@1409
  1850
  ///
deba@1409
  1851
  /// The lemon format can store multiple attribute set. Each set has
deba@1901
  1852
  /// the header line \c \@attributes \c attributeset_name, but the 
deba@1901
  1853
  /// attributeset_name may be empty.
deba@1409
  1854
  ///
deba@1409
  1855
  /// The attributeset section contains several lines. Each of them starts
deba@1409
  1856
  /// with an attribute and then a the value for the id.
deba@1409
  1857
  ///
deba@1409
  1858
  /// \relates LemonReader
deba@1408
  1859
  template <typename _Traits = DefaultReaderTraits>
deba@1845
  1860
  class AttributeReader : public LemonReader::SectionReader {
deba@1845
  1861
    typedef LemonReader::SectionReader Parent;
deba@1408
  1862
    typedef _Traits Traits; 
deba@1408
  1863
  public:
deba@1409
  1864
    /// \brief Constructor.
deba@1409
  1865
    ///
deba@1409
  1866
    /// Constructor for AttributeReader. It creates the AttributeReader and
deba@1409
  1867
    /// attach it into the given LemonReader. The reader process a section
deba@1901
  1868
    /// only if the \c section_name and the \c _name are the same.
deba@1408
  1869
    AttributeReader(LemonReader& _reader, 
deba@1901
  1870
		    const std::string& _name = std::string()) 
deba@1901
  1871
      : Parent(_reader), name(_name) {}
deba@1408
  1872
deba@1409
  1873
    /// \brief Destructor.
deba@1409
  1874
    ///
deba@1409
  1875
    /// Destructor for AttributeReader.
deba@1408
  1876
    virtual ~AttributeReader() {
deba@1408
  1877
      for (typename Readers::iterator it = readers.begin(); 
deba@1408
  1878
	   it != readers.end(); ++it) {
deba@1408
  1879
	delete it->second;
deba@1408
  1880
      }
deba@1408
  1881
    }
deba@1408
  1882
deba@1408
  1883
  private:
deba@1408
  1884
    AttributeReader(const AttributeReader&);
deba@1408
  1885
    void operator=(AttributeReader&);
deba@1408
  1886
deba@1408
  1887
  public:
deba@1409
  1888
    /// \brief Add an attribute reader command for the reader.
deba@1409
  1889
    ///
deba@1409
  1890
    /// Add an attribute reader command for the reader.
deba@1408
  1891
    template <typename Value>
deba@1408
  1892
    AttributeReader& readAttribute(const std::string& id, Value& value) {
deba@1408
  1893
      return readAttribute<typename Traits::template Reader<Value> >
deba@1408
  1894
	(id, value);
deba@1408
  1895
    }
deba@1408
  1896
deba@1409
  1897
    /// \brief Add an attribute reader command for the reader.
deba@1409
  1898
    ///
deba@1409
  1899
    /// Add an attribute reader command for the reader.
deba@1408
  1900
    template <typename Reader, typename Value>
deba@1408
  1901
    AttributeReader& readAttribute(const std::string& name, Value& value,
deba@1408
  1902
				   const Reader& reader = Reader()) {
deba@1492
  1903
      checkConcept<_reader_bits::ItemReader<Value>, Reader>();
deba@1408
  1904
      if (readers.find(name) != readers.end()) {
deba@1408
  1905
	ErrorMessage msg;
deba@1408
  1906
	msg << "Multiple read rule for attribute: " << name;
deba@1408
  1907
	throw IOParameterError(msg.message());
deba@1408
  1908
      }
deba@1845
  1909
      readers.insert(make_pair(name, new _reader_bits::
deba@1845
  1910
			       ValueReader<Value, Reader>(value, reader)));
deba@1408
  1911
      return *this;
deba@1408
  1912
    }
deba@1408
  1913
deba@1409
  1914
  protected:
deba@1409
  1915
deba@1409
  1916
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  1917
    /// the section with the given header line.
deba@1409
  1918
    ///
deba@1421
  1919
    /// It gives back true when the header line start with \c \@attributes,
deba@1409
  1920
    /// and the header line's id and the attributeset's id are the same.
deba@1408
  1921
    bool header(const std::string& line) {
deba@1408
  1922
      std::istringstream ls(line);
deba@1408
  1923
      std::string command;
deba@1901
  1924
      std::string id;
deba@1408
  1925
      ls >> command >> name;
deba@1408
  1926
      return command == "@attributes" && name == id;
deba@1408
  1927
    }
deba@1408
  1928
deba@1409
  1929
    /// \brief Reader function of the section.
deba@1409
  1930
    ///
deba@1409
  1931
    /// It reads the content of the section.
deba@1408
  1932
    void read(std::istream& is) {
deba@1408
  1933
      std::string line;
deba@1408
  1934
      while (getline(is, line)) {
deba@1408
  1935
	std::istringstream ls(line);
deba@1408
  1936
	std::string id;
deba@1408
  1937
	ls >> id;
deba@1408
  1938
	typename Readers::iterator it = readers.find(id);
deba@1408
  1939
	if (it != readers.end()) {
deba@1408
  1940
	  it->second->read(ls);
deba@1901
  1941
 	  it->second->touch();
deba@1408
  1942
	}
deba@1408
  1943
      }
deba@1846
  1944
      for (typename Readers::iterator it = readers.begin();
deba@1846
  1945
	   it != readers.end(); ++it) {
deba@1846
  1946
	if (!it->second->touched()) {
deba@1846
  1947
	  ErrorMessage msg;
deba@1846
  1948
	  msg << "Attribute not found in file: " << it->first;
deba@1846
  1949
	  throw IOParameterError(msg.message());
deba@1846
  1950
	}	
deba@1846
  1951
      }
deba@1408
  1952
    }    
deba@1408
  1953
deba@1408
  1954
  private:
deba@1901
  1955
    std::string name;
deba@1408
  1956
deba@1845
  1957
    typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
deba@1409
  1958
    Readers readers;  
deba@1408
  1959
  };
deba@1408
  1960
deba@1423
  1961
  /// \ingroup io_group
deba@1423
  1962
  /// \brief SectionReader for retrieve what is in the file.
deba@1423
  1963
  ///
deba@1423
  1964
  /// SectionReader for retrieve what is in the file. If you want
deba@1423
  1965
  /// to know which sections, maps and items are in the file
deba@1423
  1966
  /// use the next code:
alpar@1946
  1967
  ///\code
deba@1423
  1968
  /// LemonReader reader("input.lgf");
deba@1423
  1969
  /// ContentReader content(reader);
deba@1423
  1970
  /// reader.run();
alpar@1946
  1971
  ///\endcode
deba@1423
  1972
  class ContentReader : public LemonReader::SectionReader {
deba@1423
  1973
    typedef LemonReader::SectionReader Parent;
deba@1423
  1974
  public:
deba@1423
  1975
    /// \brief Constructor.
deba@1423
  1976
    ///
deba@1423
  1977
    /// Constructor for
deba@1423
  1978
    ContentReader(LemonReader& _reader) : Parent(_reader) {}
deba@1423
  1979
deba@1423
  1980
    /// \brief Desctructor.
deba@1423
  1981
    ///
deba@1423
  1982
    /// Desctructor.
deba@1423
  1983
    virtual ~ContentReader() {}
deba@1423
  1984
deba@1423
  1985
    /// \brief Gives back how many nodesets are in the file.
deba@1423
  1986
    ///
deba@1423
  1987
    /// Gives back how many nodesets are in the file.
deba@1423
  1988
    int nodeSetNum() const {
deba@1423
  1989
      return nodesets.size();
deba@1423
  1990
    }
deba@1423
  1991
deba@1423
  1992
    /// \brief Gives back the name of nodeset on the indiced position.
deba@1423
  1993
    ///
deba@1423
  1994
    /// Gives back the name of nodeset on the indiced position.
deba@1423
  1995
    std::string nodeSetName(int index) const {
deba@1423
  1996
      return nodesets[index].name;
deba@1423
  1997
    }
deba@1423
  1998
deba@1423
  1999
    /// \brief Gives back the map names of nodeset on the indiced position.
deba@1423
  2000
    ///
deba@1423
  2001
    /// Gives back the map names of nodeset on the indiced position.
deba@1423
  2002
    const std::vector<std::string>& nodeSetMaps(int index) const {
deba@1423
  2003
      return nodesets[index].items;
deba@1423
  2004
    }
deba@1423
  2005
deba@1423
  2006
    /// \brief Gives back how many edgesets are in the file.
deba@1423
  2007
    ///
deba@1423
  2008
    /// Gives back how many edgesets are in the file.
deba@1423
  2009
    int edgeSetNum() const {
deba@1423
  2010
      return edgesets.size();
deba@1423
  2011
    }
deba@1423
  2012
deba@1423
  2013
    /// \brief Gives back the name of edgeset on the indiced position.
deba@1423
  2014
    ///
deba@1423
  2015
    /// Gives back the name of edgeset on the indiced position.
deba@1423
  2016
    std::string edgeSetName(int index) const {
deba@1423
  2017
      return edgesets[index].name;
deba@1423
  2018
    }
deba@1423
  2019
deba@1423
  2020
    /// \brief Gives back the map names of edgeset on the indiced position.
deba@1423
  2021
    ///
deba@1423
  2022
    /// Gives back the map names of edgeset on the indiced position.
deba@1423
  2023
    const std::vector<std::string>& edgeSetMaps(int index) const {
deba@1423
  2024
      return edgesets[index].items;
deba@1423
  2025
    }
deba@1423
  2026
deba@1423
  2027
    /// \brief Gives back how many undirected edgesets are in the file.
deba@1423
  2028
    ///
deba@1423
  2029
    /// Gives back how many undirected edgesets are in the file.
klao@1909
  2030
    int uEdgeSetNum() const {
klao@1909
  2031
      return uedgesets.size();
deba@1423
  2032
    }
deba@1423
  2033
deba@1423
  2034
    /// \brief Gives back the name of undirected edgeset on the indiced 
deba@1423
  2035
    /// position.
deba@1423
  2036
    ///
deba@1423
  2037
    /// Gives back the name of undirected edgeset on the indiced position.
klao@1909
  2038
    std::string uEdgeSetName(int index) const {
klao@1909
  2039
      return uedgesets[index].name;
deba@1423
  2040
    }
deba@1423
  2041
deba@1423
  2042
    /// \brief Gives back the map names of undirected edgeset on the indiced 
deba@1423
  2043
    /// position.
deba@1423
  2044
    ///
deba@1423
  2045
    /// Gives back the map names of undirected edgeset on the indiced position.
klao@1909
  2046
    const std::vector<std::string>& uEdgeSetMaps(int index) const {
klao@1909
  2047
      return uedgesets[index].items;
deba@1423
  2048
    }
deba@1423
  2049
deba@1423
  2050
    /// \brief Gives back how many labeled nodes section are in the file.
deba@1423
  2051
    ///
deba@1423
  2052
    /// Gives back how many labeled nodes section are in the file.
deba@1423
  2053
    int nodesNum() const {
deba@1423
  2054
      return nodes.size();
deba@1423
  2055
    }
deba@1423
  2056
deba@1423
  2057
    /// \brief Gives back the name of labeled nodes section on the indiced 
deba@1423
  2058
    /// position.
deba@1423
  2059
    ///
deba@1423
  2060
    /// Gives back the name of labeled nodes section on the indiced position.
deba@1423
  2061
    std::string nodesName(int index) const {
deba@1423
  2062
      return nodes[index].name;
deba@1423
  2063
    }
deba@1423
  2064
deba@1423
  2065
    /// \brief Gives back the names of the labeled nodes in the indiced 
deba@1423
  2066
    /// section.
deba@1423
  2067
    ///
deba@1423
  2068
    /// Gives back the names of the labeled nodes in the indiced section.
deba@1423
  2069
    const std::vector<std::string>& nodesItems(int index) const {
deba@1423
  2070
      return nodes[index].items;
deba@1423
  2071
    }
deba@1423
  2072
deba@1423
  2073
    /// \brief Gives back how many labeled edges section are in the file.
deba@1423
  2074
    ///
deba@1423
  2075
    /// Gives back how many labeled edges section are in the file.
deba@1423
  2076
    int edgesNum() const {
deba@1423
  2077
      return edges.size();
deba@1423
  2078
    }
deba@1423
  2079
deba@1423
  2080
    /// \brief Gives back the name of labeled edges section on the indiced 
deba@1423
  2081
    /// position.
deba@1423
  2082
    ///
deba@1423
  2083
    /// Gives back the name of labeled edges section on the indiced position.
deba@1423
  2084
    std::string edgesName(int index) const {
deba@1423
  2085
      return edges[index].name;
deba@1423
  2086
    }
deba@1423
  2087
deba@1423
  2088
    /// \brief Gives back the names of the labeled edges in the indiced 
deba@1423
  2089
    /// section.
deba@1423
  2090
    ///
deba@1423
  2091
    /// Gives back the names of the labeled edges in the indiced section.
deba@1423
  2092
    const std::vector<std::string>& edgesItems(int index) const {
deba@1423
  2093
      return edges[index].items;
deba@1423
  2094
    }
deba@1423
  2095
 
deba@1423
  2096
    /// \brief Gives back how many labeled undirected edges section are 
deba@1423
  2097
    /// in the file.
deba@1423
  2098
    ///
deba@1423
  2099
    /// Gives back how many labeled undirected edges section are in the file.
klao@1909
  2100
    int uEdgesNum() const {
klao@1909
  2101
      return uedges.size();
deba@1423
  2102
    }
deba@1423
  2103
deba@1423
  2104
    /// \brief Gives back the name of labeled undirected edges section 
deba@1423
  2105
    /// on the indiced position.
deba@1423
  2106
    ///
deba@1423
  2107
    /// Gives back the name of labeled undirected edges section on the 
deba@1423
  2108
    /// indiced position.
klao@1909
  2109
    std::string uEdgesName(int index) const {
klao@1909
  2110
      return uedges[index].name;
deba@1423
  2111
    }
deba@1423
  2112
deba@1423
  2113
    /// \brief Gives back the names of the labeled undirected edges in 
deba@1423
  2114
    /// the indiced section.
deba@1423
  2115
    ///
deba@1423
  2116
    /// Gives back the names of the labeled undirected edges in the 
deba@1423
  2117
    /// indiced section.
klao@1909
  2118
    const std::vector<std::string>& uEdgesItems(int index) const {
klao@1909
  2119
      return uedges[index].items;
deba@1423
  2120
    }
deba@1423
  2121
deba@1423
  2122
 
deba@1423
  2123
    /// \brief Gives back how many attributes section are in the file.
deba@1423
  2124
    ///
deba@1423
  2125
    /// Gives back how many attributes section are in the file.
deba@1423
  2126
    int attributesNum() const {
deba@1423
  2127
      return attributes.size();
deba@1423
  2128
    }
deba@1423
  2129
deba@1423
  2130
    /// \brief Gives back the name of attributes section on the indiced 
deba@1423
  2131
    /// position.
deba@1423
  2132
    ///
deba@1423
  2133
    /// Gives back the name of attributes section on the indiced position.
deba@1423
  2134
    std::string attributesName(int index) const {
deba@1423
  2135
      return attributes[index].name;
deba@1423
  2136
    }
deba@1423
  2137
deba@1423
  2138
    /// \brief Gives back the names of the attributes in the indiced section.
deba@1423
  2139
    ///
deba@1423
  2140
    /// Gives back the names of the attributes in the indiced section.
deba@1423
  2141
    const std::vector<std::string>& attributesItems(int index) const {
deba@1423
  2142
      return attributes[index].items;
deba@1423
  2143
    }
deba@1423
  2144
deba@1423
  2145
    const std::vector<std::string>& otherSections() const {
deba@1423
  2146
      return sections;
deba@1423
  2147
    }
deba@1423
  2148
deba@1423
  2149
  protected:
deba@1423
  2150
    
deba@1423
  2151
    /// \brief Gives back true when the SectionReader can process 
deba@1423
  2152
    /// the section with the given header line.
deba@1423
  2153
    ///
deba@1423
  2154
    /// It gives back true when the section is common section.
deba@1423
  2155
    bool header(const std::string& line) {
deba@1423
  2156
      std::istringstream ls(line);
deba@1423
  2157
      std::string command, name;
deba@1423
  2158
      ls >> command >> name;
deba@1423
  2159
      if (command == "@nodeset") {
deba@1423
  2160
	current = command;
deba@1423
  2161
	nodesets.push_back(SectionInfo(name));
deba@1423
  2162
      } else if (command == "@edgeset") {
deba@1423
  2163
	current = command;
deba@1423
  2164
	edgesets.push_back(SectionInfo(name));
klao@1909
  2165
      } else if (command == "@uedgeset") {
deba@1423
  2166
	current = command;
klao@1909
  2167
	uedgesets.push_back(SectionInfo(name));
deba@1423
  2168
      } else if (command == "@nodes") {
deba@1423
  2169
	current = command;
deba@1423
  2170
	nodes.push_back(SectionInfo(name));
deba@1423
  2171
      } else if (command == "@edges") {
deba@1423
  2172
	current = command;
deba@1423
  2173
	edges.push_back(SectionInfo(name));
klao@1909
  2174
      } else if (command == "@uedges") {
deba@1423
  2175
	current = command;
klao@1909
  2176
	uedges.push_back(SectionInfo(name));
deba@1423
  2177
      } else if (command == "@attributes") {
deba@1423
  2178
	current = command;
deba@1423
  2179
	attributes.push_back(SectionInfo(name));
deba@1423
  2180
      } else {
deba@1423
  2181
	sections.push_back(line);
deba@1423
  2182
	return false;
deba@1423
  2183
      }
deba@1423
  2184
      return true;
deba@1423
  2185
    }
deba@1423
  2186
deba@1423
  2187
    /// \brief Retrieve the items from various sections.
deba@1423
  2188
    ///
deba@1423
  2189
    /// Retrieve the items from various sections.
deba@1423
  2190
    void read(std::istream& is) {
deba@1423
  2191
      if (current == "@nodeset") {
deba@1423
  2192
	readMapNames(is, nodesets.back().items);
deba@1423
  2193
      } else if (current == "@edgeset") {
deba@1423
  2194
	readMapNames(is, edgesets.back().items);
klao@1909
  2195
      } else if (current == "@uedgeset") {
klao@1909
  2196
	readMapNames(is, uedgesets.back().items);
deba@1423
  2197
      } else if (current == "@nodes") {
deba@1423
  2198
	readItemNames(is, nodes.back().items);
deba@1423
  2199
      } else if (current == "@edges") {
deba@1423
  2200
	readItemNames(is, edges.back().items);
klao@1909
  2201
      } else if (current == "@uedges") {
klao@1909
  2202
	readItemNames(is, uedges.back().items);
deba@1423
  2203
      } else if (current == "@attributes") {
deba@1423
  2204
	readItemNames(is, attributes.back().items);
deba@1423
  2205
      }
deba@1423
  2206
    }    
deba@1423
  2207
deba@1423
  2208
  private:
deba@1423
  2209
deba@1423
  2210
    void readMapNames(std::istream& is, std::vector<std::string>& maps) {
deba@1901
  2211
      std::string line, name;
deba@1423
  2212
      std::getline(is, line);
deba@1423
  2213
      std::istringstream ls(line);
deba@1901
  2214
      while (ls >> name) {
deba@1901
  2215
	maps.push_back(name);
deba@1423
  2216
      }
deba@1423
  2217
      while (getline(is, line));
deba@1423
  2218
    }
deba@1423
  2219
deba@1423
  2220
    void readItemNames(std::istream& is, std::vector<std::string>& maps) {
deba@1901
  2221
      std::string line, name;
deba@1423
  2222
      while (std::getline(is, line)) {
deba@1423
  2223
	std::istringstream ls(line);
deba@1901
  2224
	ls >> name;
deba@1901
  2225
	maps.push_back(name);
deba@1423
  2226
      }
deba@1423
  2227
    }
deba@1423
  2228
deba@1423
  2229
    struct SectionInfo {
deba@1423
  2230
      std::string name;
deba@1423
  2231
      std::vector<std::string> items;
deba@1423
  2232
deba@1423
  2233
      SectionInfo(const std::string& _name) : name(_name) {}
deba@1423
  2234
    };
deba@1423
  2235
deba@1423
  2236
    std::vector<SectionInfo> nodesets;
deba@1423
  2237
    std::vector<SectionInfo> edgesets;
klao@1909
  2238
    std::vector<SectionInfo> uedgesets;
deba@1423
  2239
deba@1423
  2240
    std::vector<SectionInfo> nodes;
deba@1423
  2241
    std::vector<SectionInfo> edges;
klao@1909
  2242
    std::vector<SectionInfo> uedges;
deba@1423
  2243
deba@1423
  2244
    std::vector<SectionInfo> attributes;
deba@1423
  2245
deba@1423
  2246
    std::vector<std::string> sections;
deba@1423
  2247
deba@1423
  2248
    std::string current;
deba@1423
  2249
deba@1423
  2250
  };
deba@1423
  2251
deba@1408
  2252
}
deba@1408
  2253
#endif