lemon/lemon_reader.h
author deba
Fri, 19 Sep 2008 15:14:41 +0000
changeset 2618 6aa6fcaeaea5
parent 2553 bfced05fa852
permissions -rw-r--r--
G++-4.3 compatibility changes
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@2553
     5
 * Copyright (C) 2003-2008
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1408
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1408
     8
 *
deba@1408
     9
 * Permission to use, modify and distribute this software is granted
deba@1408
    10
 * provided that this copyright notice appears in all copies. For
deba@1408
    11
 * precise terms see the accompanying LICENSE file.
deba@1408
    12
 *
deba@1408
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@1408
    14
 * express or implied, and with no claim as to its suitability for any
deba@1408
    15
 * purpose.
deba@1408
    16
 *
deba@1408
    17
 */
deba@1408
    18
deba@2084
    19
///\ingroup lemon_io
deba@1408
    20
///\file
deba@1408
    21
///\brief Lemon Format reader.
deba@1408
    22
deba@1421
    23
deba@1408
    24
#ifndef LEMON_LEMON_READER_H
deba@1408
    25
#define LEMON_LEMON_READER_H
deba@1408
    26
deba@1421
    27
deba@1408
    28
#include <iostream>
deba@1408
    29
#include <fstream>
deba@1408
    30
#include <string>
deba@1408
    31
#include <vector>
deba@1408
    32
#include <algorithm>
deba@1408
    33
#include <map>
deba@1408
    34
#include <memory>
deba@1408
    35
deba@1408
    36
#include <lemon/error.h>
deba@1421
    37
#include <lemon/graph_utils.h>
deba@1993
    38
#include <lemon/bits/utility.h>
deba@1409
    39
#include <lemon/bits/item_reader.h>
deba@1408
    40
alpar@2207
    41
#include <lemon/dim2.h>
deba@1705
    42
deba@1476
    43
#include <lemon/concept_check.h>
alpar@2260
    44
#include <lemon/concepts/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@2467
    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@2282
   120
      const Graph& graph;
deba@1705
   121
      typename Ref<Map>::Type map;
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@2282
   150
      const Graph& graph;
deba@1705
   151
      typename Ref<Map>::Type map;
deba@1705
   152
    };
deba@1705
   153
deba@1705
   154
deba@1705
   155
    template <typename Graph, typename Map>
deba@1705
   156
    BackwardComposeMap<Graph, Map>
deba@1705
   157
    backwardComposeMap(const Graph& graph, const Map& map) {
deba@1705
   158
      return BackwardComposeMap<Graph, Map>(graph, map);
deba@1705
   159
    }
deba@1705
   160
deba@1705
   161
    template <typename Graph, typename Map>
deba@1705
   162
    BackwardComposeMap<Graph, Map>
deba@1705
   163
    backwardComposeMap(const Graph& graph, Map& map) {
deba@1705
   164
      return BackwardComposeMap<Graph, Map>(graph, map);
deba@1705
   165
    }
deba@1705
   166
deba@1705
   167
    template <typename Graph, typename Map>
deba@1705
   168
    struct Ref<ForwardComposeMap<Graph, Map> > { 
deba@1705
   169
      typedef ForwardComposeMap<Graph, Map> Type;
deba@1705
   170
    };
deba@1705
   171
    template <typename Graph, typename Map>
deba@1705
   172
    struct Arg<ForwardComposeMap<Graph, Map> > { 
deba@1705
   173
      typedef const ForwardComposeMap<Graph, Map>& Type;
deba@1705
   174
    };
deba@1705
   175
deba@1705
   176
    template <typename Graph, typename Map>
deba@1705
   177
    struct Ref<BackwardComposeMap<Graph, Map> > { 
deba@1705
   178
      typedef BackwardComposeMap<Graph, Map> Type; 
deba@1705
   179
    };
deba@1705
   180
    template <typename Graph, typename Map>
deba@1705
   181
    struct Arg<BackwardComposeMap<Graph, Map> > { 
deba@1705
   182
      typedef const BackwardComposeMap<Graph, Map>& Type; 
deba@1705
   183
    };
deba@1705
   184
deba@1705
   185
    template <typename Map>
alpar@2207
   186
    struct Ref<dim2::XMap<Map> > { 
alpar@2207
   187
      typedef dim2::XMap<Map> Type;
deba@1705
   188
    };
deba@1705
   189
    template <typename Map>
alpar@2207
   190
    struct Arg<dim2::XMap<Map> > { 
alpar@2207
   191
      typedef const dim2::XMap<Map>& Type;
deba@1705
   192
    };
deba@1705
   193
deba@1705
   194
    template <typename Map>
alpar@2207
   195
    struct Ref<dim2::YMap<Map> > { 
alpar@2207
   196
      typedef dim2::YMap<Map> Type;
deba@1705
   197
    };
deba@1705
   198
    template <typename Map>
alpar@2207
   199
    struct Arg<dim2::YMap<Map> > { 
alpar@2207
   200
      typedef const dim2::YMap<Map>& Type;
deba@1705
   201
    };
deba@1705
   202
deba@1845
   203
deba@1845
   204
    template <typename _Item>
deba@1845
   205
    class MapReaderBase;
deba@1845
   206
    
deba@1845
   207
    template <typename _Item>
deba@1845
   208
    class MapInverterBase : public MapReaderBase<_Item> {
deba@1845
   209
    public:
deba@1845
   210
      typedef _Item Item;
deba@1845
   211
      virtual void read(std::istream&, const Item&) = 0;
deba@1845
   212
      virtual Item read(std::istream&) const = 0;
deba@1845
   213
deba@1845
   214
      virtual MapInverterBase<_Item>* getInverter() {
deba@1845
   215
	return this;
deba@1845
   216
      }
deba@1845
   217
    };
deba@1845
   218
deba@1845
   219
    template <typename _Item, typename _Map, typename _Reader>
deba@1845
   220
    class MapReaderInverter : public MapInverterBase<_Item> {
deba@1845
   221
    public:
deba@1845
   222
      typedef _Item Item;
deba@1845
   223
      typedef _Reader Reader;
deba@1845
   224
      typedef typename Reader::Value Value;
deba@1845
   225
      typedef _Map Map;
deba@1845
   226
      typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
deba@1845
   227
deba@1845
   228
      typename _reader_bits::Ref<Map>::Type map;
deba@1845
   229
      Reader reader;
deba@1845
   230
      Inverse inverse;
deba@1845
   231
deba@1845
   232
      MapReaderInverter(typename _reader_bits::Arg<Map>::Type _map,
deba@1845
   233
			const Reader& _reader) 
deba@1845
   234
	: map(_map), reader(_reader) {}
deba@1845
   235
deba@1845
   236
      virtual ~MapReaderInverter() {}
deba@1845
   237
deba@1845
   238
      virtual void read(std::istream& is, const Item& item) {
deba@1845
   239
	Value value;
deba@1845
   240
	reader.read(is, value);
deba@1845
   241
	map.set(item, value);
deba@1845
   242
	typename Inverse::iterator it = inverse.find(value);
deba@1845
   243
	if (it == inverse.end()) {
deba@1845
   244
	  inverse.insert(std::make_pair(value, item));
deba@1845
   245
	} else {
deba@1901
   246
	  throw DataFormatError("Multiple label occurence");
deba@1845
   247
	}
deba@1845
   248
      }
deba@1845
   249
deba@1845
   250
      virtual Item read(std::istream& is) const {
deba@1845
   251
	Value value;
deba@1845
   252
	reader.read(is, value);	
deba@1845
   253
	typename Inverse::const_iterator it = inverse.find(value);
deba@1845
   254
	if (it != inverse.end()) {
deba@1845
   255
	  return it->second;
deba@1845
   256
	} else {
deba@2461
   257
	  ErrorMessage msg;
deba@2467
   258
	  msg << "Invalid label error"; 
deba@2461
   259
	  throw DataFormatError(msg.message());
deba@1845
   260
	}
deba@1845
   261
      }      
deba@1845
   262
    };
deba@1845
   263
deba@1845
   264
    template <typename _Item, typename _Reader>
deba@1845
   265
    class SkipReaderInverter : public MapInverterBase<_Item> {
deba@1845
   266
    public:
deba@1845
   267
      typedef _Item Item;
deba@1845
   268
      typedef _Reader Reader;
deba@1845
   269
      typedef typename Reader::Value Value;
deba@1845
   270
      typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
deba@1845
   271
deba@1845
   272
      Reader reader;
deba@1845
   273
deba@1845
   274
      SkipReaderInverter(const Reader& _reader) 
deba@1845
   275
	: reader(_reader) {}
deba@1845
   276
deba@1845
   277
      virtual ~SkipReaderInverter() {}
deba@1845
   278
deba@1845
   279
      virtual void read(std::istream& is, const Item& item) {
deba@1845
   280
	Value value;
deba@1845
   281
	reader.read(is, value);
deba@1845
   282
	typename Inverse::iterator it = inverse.find(value);
deba@1845
   283
	if (it == inverse.end()) {
deba@1845
   284
	  inverse.insert(std::make_pair(value, item));
deba@1845
   285
	} else {
deba@1901
   286
	  throw DataFormatError("Multiple label occurence error");
deba@1845
   287
	}
deba@1845
   288
      }
deba@1845
   289
deba@1845
   290
      virtual Item read(std::istream& is) const {
deba@1845
   291
	Value value;
deba@2467
   292
	reader.read(is, value);
deba@1845
   293
	typename Inverse::const_iterator it = inverse.find(value);
deba@1845
   294
	if (it != inverse.end()) {
deba@1845
   295
	  return it->second;
deba@1845
   296
	} else {
deba@2461
   297
	  ErrorMessage msg;
deba@2461
   298
	  msg << "Invalid label error: " << value; 
deba@2461
   299
	  throw DataFormatError(msg.message());
deba@1845
   300
	}
deba@1845
   301
      }
deba@1845
   302
deba@1845
   303
    private:
deba@1845
   304
      Inverse inverse;
deba@1845
   305
    };
deba@1845
   306
deba@1845
   307
    template <typename _Item>    
deba@1845
   308
    class MapReaderBase {
deba@1845
   309
    public:
deba@1845
   310
      typedef _Item Item;
deba@1845
   311
deba@1845
   312
      MapReaderBase() { _touched = false; }
deba@1845
   313
      
deba@2502
   314
      void touch(bool value = true) { _touched = value; }
deba@1845
   315
      bool touched() const { return _touched; }
deba@1845
   316
deba@1845
   317
      virtual ~MapReaderBase() {}
deba@1845
   318
deba@1845
   319
      virtual void read(std::istream& is, const Item& item) = 0;
deba@1845
   320
      virtual MapInverterBase<_Item>* getInverter() = 0;
deba@1845
   321
deba@1845
   322
    private:      
deba@1845
   323
      bool _touched;
deba@1845
   324
deba@1845
   325
    };
deba@1845
   326
deba@1845
   327
    template <typename _Item, typename _Map, typename _Reader>
deba@1845
   328
    class MapReader : public MapReaderBase<_Item> {
deba@1845
   329
    public:
deba@1845
   330
      typedef _Map Map;
deba@1845
   331
      typedef _Reader Reader;
deba@1845
   332
      typedef typename Reader::Value Value;
deba@1845
   333
      typedef _Item Item;
deba@1845
   334
      
deba@1845
   335
      typename _reader_bits::Ref<Map>::Type map;
deba@1845
   336
      Reader reader;
deba@1845
   337
deba@1845
   338
      MapReader(typename _reader_bits::Arg<Map>::Type _map, 
deba@1845
   339
		const Reader& _reader) 
deba@1845
   340
	: map(_map), reader(_reader) {}
deba@1845
   341
deba@1845
   342
      virtual ~MapReader() {}
deba@1845
   343
deba@1845
   344
      virtual void read(std::istream& is, const Item& item) {
deba@1845
   345
	Value value;
deba@1845
   346
	reader.read(is, value);
deba@1845
   347
	map.set(item, value);
deba@1845
   348
      }
deba@1845
   349
deba@1845
   350
      virtual MapInverterBase<_Item>* getInverter() {
deba@1845
   351
	return new MapReaderInverter<Item, Map, Reader>(map, reader);
deba@1845
   352
      }
deba@1845
   353
    };
deba@1845
   354
deba@1845
   355
deba@1845
   356
    template <typename _Item, typename _Reader>
deba@1845
   357
    class SkipReader : public MapReaderBase<_Item> {
deba@1845
   358
    public:
deba@1845
   359
      typedef _Reader Reader;
deba@1845
   360
      typedef typename Reader::Value Value;
deba@1845
   361
      typedef _Item Item;
deba@1845
   362
deba@1845
   363
      Reader reader;
deba@1845
   364
      SkipReader(const Reader& _reader) : reader(_reader) {}
deba@1845
   365
deba@1845
   366
      virtual ~SkipReader() {}
deba@1845
   367
deba@1845
   368
      virtual void read(std::istream& is, const Item&) {
deba@1845
   369
	Value value;
deba@1845
   370
	reader.read(is, value);
deba@1845
   371
      }      
deba@1845
   372
deba@1845
   373
      virtual MapInverterBase<Item>* getInverter() {
deba@1845
   374
	return new SkipReaderInverter<Item, Reader>(reader);
deba@1845
   375
      }
deba@1845
   376
    };
deba@1845
   377
deba@1845
   378
    template <typename _Item>
deba@1901
   379
    class LabelReaderBase {
deba@1845
   380
    public:
deba@1845
   381
      typedef _Item Item;
deba@1901
   382
      virtual ~LabelReaderBase() {}
deba@1845
   383
      virtual Item read(std::istream& is) const = 0;
deba@1901
   384
      virtual bool isLabelReader() const = 0;
deba@2467
   385
      virtual LabelReaderBase<_Item>* clone() const = 0;
deba@1845
   386
    };
deba@1845
   387
deba@1901
   388
    template <typename _Item, typename _BoxedLabelReader>
deba@1901
   389
    class LabelReader : public LabelReaderBase<_Item> {
deba@1845
   390
    public:
deba@1845
   391
      typedef _Item Item;
deba@1901
   392
      typedef _BoxedLabelReader BoxedLabelReader;
deba@1845
   393
      
deba@2467
   394
      const BoxedLabelReader& labelReader;
deba@2467
   395
deba@2467
   396
      LabelReader(const BoxedLabelReader& _labelReader) 
deba@2467
   397
	: labelReader(_labelReader) {}
deba@1845
   398
deba@1845
   399
      virtual Item read(std::istream& is) const {
deba@1845
   400
	Item item;
deba@2467
   401
	labelReader.readLabel(is, item);
deba@1845
   402
	return item;
deba@1845
   403
      }
deba@1845
   404
deba@1901
   405
      virtual bool isLabelReader() const {
deba@2467
   406
	return labelReader.isLabelReader();
deba@2467
   407
      }
deba@2467
   408
      
deba@2467
   409
      LabelReader<Item, BoxedLabelReader>* clone() const {
deba@2467
   410
	return new LabelReader<Item, BoxedLabelReader>(labelReader);
deba@1845
   411
      }
deba@1845
   412
    };
deba@1845
   413
deba@1845
   414
    template <typename _Item>
deba@1845
   415
    class ItemStore {
deba@1845
   416
    public:
deba@1845
   417
deba@1845
   418
      typedef _Item Item;
deba@1845
   419
deba@1845
   420
      ItemStore(Item& _item) : item(&_item) { 
deba@1845
   421
	_touched = false; 
deba@1845
   422
      }
deba@1845
   423
      
deba@1845
   424
      void touch() { _touched = true; }
deba@1845
   425
      bool touched() const { return _touched; }
deba@1845
   426
deba@1845
   427
      void read(const Item& _item) {
deba@1845
   428
	*item = _item;
deba@1845
   429
      }
deba@1845
   430
      
deba@1845
   431
    private:
deba@1845
   432
      Item* item;
deba@1845
   433
      bool _touched;
deba@1845
   434
    };
deba@1845
   435
deba@1845
   436
    class ValueReaderBase {
deba@1845
   437
    public:
deba@1845
   438
      virtual void read(std::istream&) {};
deba@1846
   439
      ValueReaderBase() { _touched = false; }
deba@1846
   440
deba@1846
   441
      void touch() { _touched = true; }
deba@1846
   442
      bool touched() const { return _touched; }
deba@1846
   443
deba@1845
   444
      virtual ~ValueReaderBase() {}
deba@1846
   445
    private:
deba@1846
   446
      bool _touched;
deba@1845
   447
    };
deba@1845
   448
deba@1845
   449
    template <typename _Value, typename _Reader>
deba@1845
   450
    class ValueReader : public ValueReaderBase {
deba@1845
   451
    public:
deba@1845
   452
      typedef _Value Value;
deba@1845
   453
      typedef _Reader Reader;
deba@1845
   454
deba@1845
   455
      ValueReader(Value& _value, const Reader& _reader)
deba@1845
   456
 	: value(_value), reader(_reader) {}
deba@1845
   457
deba@1845
   458
      virtual void read(std::istream& is) {
deba@1845
   459
	reader.read(is, value);
deba@1845
   460
      }
deba@1845
   461
    private:
deba@1845
   462
      Value& value;
deba@1845
   463
      Reader reader;
deba@1845
   464
    };
deba@1845
   465
deba@1421
   466
  }
deba@1421
   467
deba@2084
   468
  /// \ingroup lemon_io
deba@1408
   469
  /// \brief Lemon Format reader class.
deba@1408
   470
  /// 
deba@1409
   471
  /// The Lemon Format contains several sections. We do not want to
deba@1409
   472
  /// determine what sections are in a lemon file we give only a framework
deba@1409
   473
  /// to read a section oriented format.
deba@1409
   474
  ///
athos@2334
   475
  /// In the Lemon Format each section starts with a line containing a
athos@2334
   476
  /// \c \@ character on the first not white space position. This line
athos@2334
   477
  /// is the header line of the section. Each of the next lines belong
athos@2334
   478
  /// to this section until a line starting with \c \@ character is
athos@2334
   479
  /// found. This line can start a new section or it can close the
athos@2334
   480
  /// file with the \c \@end line.  The file format ignores the empty
athos@2334
   481
  /// and comment lines. The line is comment line if it starts with a
athos@2334
   482
  /// \c # character.
deba@1409
   483
  ///
deba@1409
   484
  /// The framework provides an abstract LemonReader::SectionReader class
athos@2334
   485
  /// that defines the interface of a SectionReader. The SectionReader
athos@2334
   486
  /// has the \c header() member function that gets a header line string and
athos@2334
   487
  /// decides if it wants to process the next section. Several SectionReaders
athos@2334
   488
  /// can be attached to a LemonReader and the first attached that can
athos@2334
   489
  /// process the section will be used. Its \c read() member will be called
athos@2334
   490
  /// with a stream containing the section. From this stream the empty and
deba@1427
   491
  /// comment lines are filtered out.
deba@1409
   492
  ///
deba@1409
   493
  /// \relates GraphReader
deba@1409
   494
  /// \relates NodeSetReader
deba@1409
   495
  /// \relates EdgeSetReader
deba@1409
   496
  /// \relates NodesReader
deba@1409
   497
  /// \relates EdgesReader
deba@1409
   498
  /// \relates AttributeReader
deba@1408
   499
  class LemonReader {
deba@1408
   500
  private:
deba@1408
   501
    
deba@1408
   502
    class FilterStreamBuf : public std::streambuf {
deba@1408
   503
    public:
deba@1408
   504
deba@1408
   505
      typedef std::streambuf Parent;
deba@1408
   506
      typedef Parent::char_type char_type;
deba@1408
   507
      FilterStreamBuf(std::istream& is, int& num) 
deba@1408
   508
	: _is(is), _base(0), _eptr(0), 
deba@1408
   509
	  _num(num), skip_state(after_endl) {}
deba@1408
   510
deba@1408
   511
    protected:
deba@1408
   512
deba@1408
   513
      enum skip_state_type {
deba@1408
   514
	no_skip,
deba@1408
   515
	after_endl,
deba@1427
   516
	comment_line
deba@1408
   517
      };
deba@1408
   518
deba@1408
   519
      char_type small_buf[1];
deba@1408
   520
deba@1408
   521
deba@1408
   522
      std::istream& _is;
deba@1408
   523
deba@1408
   524
      char_type* _base;
deba@1408
   525
      char_type* _eptr;
deba@1408
   526
deba@1408
   527
      int& _num;
deba@1408
   528
deba@1408
   529
      skip_state_type skip_state;
deba@1408
   530
deba@1408
   531
deba@1408
   532
      char_type* base() { return _base; }
deba@1408
   533
deba@1408
   534
      char_type* eptr() { return _eptr; }
deba@1408
   535
deba@2084
   536
      int_type blen() { return _eptr - _base; }
deba@1408
   537
deba@2084
   538
      void setb(char_type* buf, int_type len) {
deba@1408
   539
	_base = buf;
deba@1408
   540
	_eptr = buf + len;
deba@1408
   541
      }
deba@1408
   542
  
ladanyi@1722
   543
      virtual std::streambuf* setbuf(char *buf, std::streamsize len) {
deba@1408
   544
	if (base()) return 0;
deba@2386
   545
	if (buf != 0 && len >= int(sizeof(small_buf))) {
deba@1408
   546
	  setb(buf, len);
deba@1408
   547
	} else {
deba@1408
   548
	  setb(small_buf, sizeof(small_buf));
deba@1408
   549
	}
deba@1408
   550
	setg(0, 0, 0);
deba@1408
   551
	return this;
deba@1408
   552
      }
deba@1408
   553
deba@1408
   554
      bool put_char(char c) {
deba@1408
   555
	switch (skip_state) {
deba@1408
   556
	case no_skip:
deba@1408
   557
	  switch (c) {
deba@1408
   558
	  case '\n': 
deba@1408
   559
	    skip_state = after_endl;
deba@1408
   560
	    return true;
deba@1408
   561
	  default:
deba@1408
   562
	    return true;
deba@1408
   563
	  }
deba@1408
   564
	case after_endl:
deba@1408
   565
	  switch (c) {
deba@1408
   566
	  case '@':
deba@1408
   567
	    return false;
deba@1408
   568
	  case '\n': 
deba@1408
   569
	    return false;
deba@1408
   570
	  case '#':
deba@1427
   571
	    skip_state = comment_line;
deba@1408
   572
	    return false;
deba@1408
   573
	  default:
deba@1408
   574
	    if (!isspace(c)) {
deba@1408
   575
	      skip_state = no_skip;
deba@1408
   576
	      return true;
deba@1408
   577
	    } else {
deba@1408
   578
	      return false;
deba@1408
   579
	    }
deba@1408
   580
	  }
deba@1408
   581
	  break;
deba@1427
   582
	case comment_line:
deba@1408
   583
	  switch (c) {
deba@1408
   584
	  case '\n': 
deba@1408
   585
	    skip_state = after_endl;
deba@1408
   586
	    return false;
deba@1408
   587
	  default:
deba@1408
   588
	    return false;
deba@1408
   589
	  }
deba@1408
   590
	}
deba@1408
   591
	return false;
deba@1408
   592
      }
deba@1408
   593
deba@2084
   594
      virtual int_type underflow() {
deba@1408
   595
	char c;
deba@2502
   596
	if ((c = _is.peek()) != EOF) {
deba@1408
   597
	  if (c == '@') {
deba@1408
   598
	    return EOF;
deba@1408
   599
	  }
deba@1408
   600
	} else {
deba@1408
   601
	  return EOF;
deba@1408
   602
	}
deba@1408
   603
	char_type *ptr;
deba@1408
   604
	for (ptr = base(); ptr != eptr(); ++ptr) {
deba@2502
   605
	  if ((c = _is.get()) != EOF) {
deba@1408
   606
	    if (c == '\n') ++_num;
deba@1408
   607
	    if (put_char(c)) {
deba@1408
   608
	      *ptr = c;
deba@1408
   609
	    } else {
deba@1408
   610
	      if (skip_state == after_endl && c == '@') {
deba@2502
   611
		_is.putback(c);
deba@1408
   612
		break;
deba@1408
   613
	      }
deba@1408
   614
	      --ptr;
deba@1408
   615
	    }
deba@1408
   616
	  } else {
deba@1408
   617
	    break;
deba@1408
   618
	  }
deba@1408
   619
	}
deba@1408
   620
	setg(base(), base(), ptr);
deba@1408
   621
	return *base();
deba@1408
   622
      }
deba@1408
   623
deba@2084
   624
      virtual int_type sync() {
deba@1408
   625
	return EOF;
deba@1408
   626
      }
deba@2460
   627
deba@2460
   628
    public:
deba@2460
   629
deba@2460
   630
      int line_num() const {
deba@2460
   631
	int r = _num;
deba@2460
   632
	for (char_type* p = gptr(); p != egptr(); ++p) {
deba@2460
   633
	  if (*p == '\n') --r;
deba@2460
   634
	}
deba@2460
   635
	return r;
deba@2460
   636
      }
deba@2460
   637
deba@1408
   638
    };
deba@1408
   639
deba@2502
   640
    static void skipPreSection(std::istream& is, int& line_num) {
deba@2502
   641
      enum skip_state_type { skip, after_endl };
deba@2502
   642
deba@2502
   643
      skip_state_type skip_state = after_endl;
deba@2502
   644
      char c;
deba@2502
   645
      
deba@2502
   646
      while ((c = is.get()) != EOF) {
deba@2502
   647
	if (c == '\n') ++line_num;
deba@2502
   648
deba@2502
   649
	switch (skip_state) {
deba@2502
   650
	case skip:
deba@2502
   651
	  if (c == '\n') skip_state = after_endl;
deba@2502
   652
	  break;
deba@2502
   653
	case after_endl:
deba@2502
   654
	  switch (c) {
deba@2502
   655
	  case '@':
deba@2502
   656
	    is.putback(c);
deba@2502
   657
	    return;
deba@2502
   658
	  case '\n':
deba@2502
   659
	    continue;
deba@2502
   660
	  default:
deba@2502
   661
	    if (!isspace(c)) {
deba@2502
   662
	      skip_state = skip;
deba@2502
   663
	    }
deba@2502
   664
	    break;
deba@2502
   665
	  }
deba@2502
   666
	}	
deba@2502
   667
      }
deba@2502
   668
    }
deba@2502
   669
deba@1408
   670
  public:
deba@1408
   671
deba@1409
   672
    /// \brief Abstract base class for reading a section.
deba@1409
   673
    ///
deba@1409
   674
    /// This class has an \c header() member function what get a 
deba@1409
   675
    /// header line string and decides if it want to process the next 
deba@1409
   676
    /// section. Several SectionReaders can be attached to an LemonReader 
deba@1409
   677
    /// and the first attached what can process the section will be used. 
deba@1409
   678
    /// Its \c read() member will called with a stream contains the section. 
deba@1409
   679
    /// From this stream the empty lines and comments are filtered out.
deba@1408
   680
    class SectionReader {
deba@1409
   681
      friend class LemonReader;
deba@1409
   682
    protected:
deba@1409
   683
      /// \brief Constructor for SectionReader.
deba@1409
   684
      ///
deba@1409
   685
      /// Constructor for SectionReader. It attach this reader to
deba@1409
   686
      /// the given LemonReader.
deba@1409
   687
      SectionReader(LemonReader& reader) {
deba@1409
   688
	reader.attach(*this);
deba@1409
   689
      }
deba@1409
   690
alpar@1494
   691
      virtual ~SectionReader() {}
alpar@1494
   692
deba@1409
   693
      /// \brief Gives back true when the SectionReader can process 
deba@1409
   694
      /// the section with the given header line.
deba@1409
   695
      ///
deba@1409
   696
      /// It gives back true when the SectionReader can process
deba@1409
   697
      /// the section with the given header line.
deba@1408
   698
      virtual bool header(const std::string& line) = 0;
deba@1409
   699
deba@1409
   700
      /// \brief Reader function of the section.
deba@1409
   701
      ///
deba@1409
   702
      /// It reads the content of the section.
deba@1408
   703
      virtual void read(std::istream& is) = 0;
deba@2000
   704
deba@2000
   705
      /// \brief The given section missing in the file.
deba@2000
   706
      ///
deba@2000
   707
      /// The given section missing in the file.
deba@2000
   708
      virtual void missing() {};
deba@1408
   709
    };
deba@1408
   710
deba@1409
   711
    /// \brief Constructor for LemonReader.
deba@1409
   712
    ///
deba@1409
   713
    /// Constructor for LemonReader which reads from the given stream.
deba@1408
   714
    LemonReader(std::istream& _is) 
deba@1408
   715
      : is(&_is), own_is(false) {}
deba@1408
   716
deba@1409
   717
    /// \brief Constructor for LemonReader.
deba@1409
   718
    ///
deba@1409
   719
    /// Constructor for LemonReader which reads from the given file.
deba@1408
   720
    LemonReader(const std::string& filename) 
deba@1408
   721
      : is(0), own_is(true) {
deba@1408
   722
      is = new std::ifstream(filename.c_str());
deba@1746
   723
      if (is->fail()) {
deba@1746
   724
	throw FileOpenError(filename);
deba@1746
   725
      }
deba@1408
   726
    }
deba@1408
   727
deba@1409
   728
    /// \brief Desctructor for LemonReader.
deba@1409
   729
    ///
deba@1409
   730
    /// Desctructor for LemonReader.
deba@1408
   731
    ~LemonReader() {
deba@1408
   732
      if (own_is) {
deba@1408
   733
	delete is;
deba@1408
   734
      }
deba@1408
   735
    }
deba@1408
   736
deba@1408
   737
  private:
deba@1408
   738
    LemonReader(const LemonReader&);
deba@1408
   739
    void operator=(const LemonReader&);
deba@1408
   740
deba@1408
   741
    void attach(SectionReader& reader) {
deba@2000
   742
      readers.push_back(std::make_pair(&reader, false));
deba@1408
   743
    }
deba@1408
   744
deba@1409
   745
  public:
deba@1409
   746
    /// \brief Executes the LemonReader.
deba@1409
   747
    /// 
deba@1409
   748
    /// It executes the LemonReader.
deba@1408
   749
    void run() {
deba@1408
   750
      int line_num = 0;
deba@1408
   751
      std::string line;
deba@2460
   752
      
deba@2460
   753
      SectionReaders::iterator it;
deba@2502
   754
      skipPreSection(*is, line_num);
deba@2460
   755
      while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
deba@2460
   756
	for (it = readers.begin(); it != readers.end(); ++it) {
deba@2460
   757
	  if (it->first->header(line)) {
deba@2460
   758
	    it->second = true;
deba@2460
   759
	    char buf[2048];
deba@2460
   760
	    FilterStreamBuf buffer(*is, line_num);
deba@2460
   761
	    try {
deba@1408
   762
	      buffer.pubsetbuf(buf, sizeof(buf));
deba@2386
   763
	      std::istream ss(&buffer);
deba@2386
   764
	      it->first->read(ss);
deba@2502
   765
	      skipPreSection(*is, line_num);
deba@1408
   766
	      break;
deba@2460
   767
	    } catch (DataFormatError& error) {
deba@2460
   768
	      error.line(buffer.line_num());
deba@2460
   769
	      throw;
deba@2460
   770
	    }	
deba@1408
   771
	  }
deba@1408
   772
	}
deba@2460
   773
      }
deba@2460
   774
      for (it = readers.begin(); it != readers.end(); ++it) {
deba@2460
   775
	if (!it->second) {
deba@2460
   776
	  try {
deba@2460
   777
	    it->first->missing();
deba@2460
   778
	  } catch (DataFormatError& error) {
deba@2460
   779
	    error.line(line_num);
deba@2460
   780
	    throw;
deba@2460
   781
	  }	
deba@2460
   782
	}
deba@2460
   783
      }
deba@1408
   784
    }
deba@1408
   785
deba@1408
   786
deba@1408
   787
  private:
deba@1408
   788
deba@1408
   789
    std::istream* is;
deba@1408
   790
    bool own_is;
deba@1408
   791
deba@2000
   792
    typedef std::vector<std::pair<SectionReader*, bool> > SectionReaders;
deba@1408
   793
    SectionReaders readers;
deba@1408
   794
deba@1408
   795
  };
deba@1408
   796
deba@2016
   797
  /// \ingroup section_io
deba@1409
   798
  /// \brief SectionReader for reading a graph's nodeset.
deba@1409
   799
  ///
deba@2368
   800
  /// The lemon format can store multiple graph nodesets with several
deba@2368
   801
  /// maps.  The nodeset section's header line is \c \@nodeset \c
deba@2368
   802
  /// nodeset_name, but the \c nodeset_name may be empty.
deba@1409
   803
  ///
deba@1409
   804
  /// The first line of the section contains the names of the maps separated
deba@1409
   805
  /// with white spaces. Each next lines describes a node in the nodeset, and
deba@1409
   806
  /// contains the mapped values for each map.
deba@1409
   807
  ///
deba@1901
   808
  /// If the nodeset contains an \c "label" named map then it will be regarded
deba@1409
   809
  /// as id map. This map should contain only unique values and when the 
deba@1901
   810
  /// \c readLabel() member will read a value from the given stream it will
deba@1409
   811
  /// give back that node which is mapped to this value.
deba@1409
   812
  ///
deba@1409
   813
  /// \relates LemonReader
deba@1408
   814
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@1845
   815
  class NodeSetReader : public LemonReader::SectionReader {
deba@1845
   816
    typedef LemonReader::SectionReader Parent;
deba@1408
   817
  public:
deba@1408
   818
deba@1408
   819
    typedef _Graph Graph;
deba@1408
   820
    typedef _Traits Traits;
deba@1429
   821
    typedef typename Graph::Node Node;
deba@1408
   822
    typedef typename Traits::Skipper DefaultSkipper;
deba@1408
   823
deba@1409
   824
    /// \brief Constructor.
deba@1409
   825
    ///
deba@1409
   826
    /// Constructor for NodeSetReader. It creates the NodeSetReader and
deba@1409
   827
    /// attach it into the given LemonReader. The nodeset reader will
deba@2100
   828
    /// add the read nodes to the given Graph. The reader will read
deba@1901
   829
    /// the section when the \c section_name and the \c _name are the same. 
deba@1421
   830
    NodeSetReader(LemonReader& _reader, 
deba@1705
   831
		  Graph& _graph, 
deba@1901
   832
		  const std::string& _name = std::string(),
deba@1409
   833
		  const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1901
   834
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {} 
deba@1408
   835
deba@1409
   836
deba@1409
   837
    /// \brief Destructor.
deba@1409
   838
    ///
deba@1409
   839
    /// Destructor for NodeSetReader.
deba@1408
   840
    virtual ~NodeSetReader() {
deba@1408
   841
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1408
   842
	   it != readers.end(); ++it) {
deba@1408
   843
	delete it->second;
deba@1408
   844
      }
deba@1408
   845
    }
deba@1408
   846
deba@1408
   847
  private:
deba@1408
   848
    NodeSetReader(const NodeSetReader&);
deba@1408
   849
    void operator=(const NodeSetReader&);
deba@1408
   850
  
deba@1408
   851
  public:
deba@1408
   852
deba@1408
   853
    /// \brief Add a new node map reader command for the reader.
deba@1408
   854
    ///
deba@1408
   855
    /// Add a new node map reader command for the reader.
deba@1408
   856
    template <typename Map>
deba@2386
   857
    NodeSetReader& readNodeMap(std::string label, Map& map) {
deba@1421
   858
      return _readMap<
deba@1421
   859
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2386
   860
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1421
   861
    }
deba@1421
   862
deba@1421
   863
    template <typename Map>
deba@2386
   864
    NodeSetReader& readNodeMap(std::string label, const Map& map) {
deba@1421
   865
      return _readMap<
deba@1421
   866
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2386
   867
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1408
   868
    }
deba@1408
   869
deba@1408
   870
    /// \brief Add a new node map reader command for the reader.
deba@1408
   871
    ///
deba@1408
   872
    /// Add a new node map reader command for the reader.
deba@2386
   873
    template <typename ItemReader, typename Map>
deba@2386
   874
    NodeSetReader& readNodeMap(std::string label, Map& map, 
deba@2386
   875
			       const ItemReader& ir = ItemReader()) {
deba@2386
   876
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2386
   877
	(label, map, ir);
deba@1421
   878
    }
deba@1421
   879
deba@2386
   880
    template <typename ItemReader, typename Map>
deba@2386
   881
    NodeSetReader& readNodeMap(std::string label, const Map& map, 
deba@2386
   882
			       const ItemReader& ir = ItemReader()) {
deba@2386
   883
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2386
   884
	(label, map, ir);
deba@1421
   885
    }
deba@1421
   886
deba@1421
   887
  private:
deba@1421
   888
deba@2386
   889
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2386
   890
    NodeSetReader& _readMap(std::string label, MapParameter map, 
deba@2386
   891
			    const ItemReader& ir = ItemReader()) {
alpar@2260
   892
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@2386
   893
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2386
   894
      if (readers.find(label) != readers.end()) {
deba@1408
   895
	ErrorMessage msg;
deba@2386
   896
	msg << "Multiple read rule for node map: " << label;
alpar@2153
   897
	throw IoParameterError(msg.message());
deba@1845
   898
      }      
deba@1408
   899
      readers.insert(
deba@2386
   900
        make_pair(label, new _reader_bits::
deba@2386
   901
		  MapReader<Node, Map, ItemReader>(map, ir)));
deba@1408
   902
      return *this;
deba@1408
   903
    }
deba@1408
   904
deba@1421
   905
  public:
deba@1421
   906
deba@1408
   907
    /// \brief Add a new node map skipper command for the reader.
deba@1408
   908
    ///
deba@1408
   909
    /// Add a new node map skipper command for the reader.
deba@2386
   910
    template <typename ItemReader>
deba@2386
   911
    NodeSetReader& skipNodeMap(std::string label, 
deba@2386
   912
                               const ItemReader& ir = ItemReader()) {
deba@2386
   913
      if (readers.find(label) != readers.end()) {
deba@1408
   914
	ErrorMessage msg;
deba@2386
   915
	msg << "Multiple read rule for node map: " << label;
alpar@2153
   916
	throw IoParameterError(msg.message());
deba@1408
   917
      }
deba@2386
   918
      readers.insert(make_pair(label, new _reader_bits::
deba@2386
   919
			       SkipReader<Node, ItemReader>(ir)));
deba@1408
   920
      return *this;
deba@1408
   921
    }
deba@1408
   922
deba@1409
   923
  protected:
deba@1409
   924
deba@1409
   925
    /// \brief Gives back true when the SectionReader can process 
deba@1409
   926
    /// the section with the given header line.
deba@1409
   927
    ///
deba@1421
   928
    /// It gives back true when the header line starts with \c \@nodeset,
deba@1901
   929
    /// and the header line's name and the nodeset's name are the same.
deba@1408
   930
    virtual bool header(const std::string& line) {
deba@1408
   931
      std::istringstream ls(line);
deba@1408
   932
      std::string command;
deba@1901
   933
      std::string id;
klao@1997
   934
      ls >> command >> id;
deba@1408
   935
      return command == "@nodeset" && name == id;
deba@1408
   936
    }
deba@1408
   937
deba@1409
   938
    /// \brief Reader function of the section.
deba@1409
   939
    ///
deba@1409
   940
    /// It reads the content of the section.
deba@1408
   941
    virtual void read(std::istream& is) {
deba@1845
   942
      std::vector<_reader_bits::MapReaderBase<Node>* > index;
deba@1408
   943
      std::string line;
deba@1408
   944
deba@2386
   945
      {
deba@2386
   946
        getline(is, line);
deba@2386
   947
        std::istringstream ls(line);
deba@2386
   948
        std::string id;
deba@2386
   949
        while (ls >> id) {
deba@2386
   950
          typename MapReaders::iterator it = readers.find(id);
deba@2386
   951
          if (it != readers.end()) {
deba@2386
   952
            it->second->touch();
deba@2386
   953
            index.push_back(it->second);
deba@2386
   954
          } else {
deba@2386
   955
            index.push_back(&skipper);
deba@2386
   956
          }
deba@2386
   957
          if (id == "label") {
deba@2386
   958
            inverter.reset(index.back()->getInverter());
deba@2386
   959
            index.back() = inverter.get();
deba@2386
   960
          }
deba@2386
   961
        }
deba@1408
   962
      }
deba@1845
   963
      for (typename MapReaders::iterator it = readers.begin();
deba@1845
   964
	   it != readers.end(); ++it) {
deba@1845
   965
	if (!it->second->touched()) {
deba@1845
   966
	  ErrorMessage msg;
deba@1845
   967
	  msg << "Map not found in file: " << it->first;
alpar@2153
   968
	  throw IoParameterError(msg.message());
deba@1845
   969
	}
deba@1845
   970
      }
deba@1408
   971
      while (getline(is, line)) {	
deba@1429
   972
	Node node = graph.addNode();
deba@1408
   973
	std::istringstream ls(line);
deba@2386
   974
	for (int i = 0; i < int(index.size()); ++i) {
deba@1408
   975
	  index[i]->read(ls, node);
deba@1408
   976
	}
deba@1408
   977
      }
deba@1408
   978
    }
deba@1408
   979
deba@2000
   980
    virtual void missing() {
deba@2000
   981
      if (readers.empty()) return;
deba@2000
   982
      ErrorMessage msg;
deba@2001
   983
      msg << "NodeSet section not found in file: @nodeset " << name;
alpar@2153
   984
      throw IoParameterError(msg.message());
deba@2000
   985
    }
deba@2000
   986
deba@1409
   987
  public:
deba@1409
   988
deba@1901
   989
    /// \brief Returns true if the nodeset can give back the node by its label.
deba@1409
   990
    ///
deba@1901
   991
    /// Returns true if the nodeset can give back the node by its label.
deba@1901
   992
    /// It is possible only if an "label" named map was read.
deba@1901
   993
    bool isLabelReader() const {
deba@1408
   994
      return inverter.get() != 0;
deba@1408
   995
    }
deba@1408
   996
deba@1901
   997
    /// \brief Gives back the node by its label.
deba@1409
   998
    ///
deba@1409
   999
    /// It reads an id from the stream and gives back which node belongs to
deba@1901
  1000
    /// it. It is possible only if there was read an "label" named map.
deba@1901
  1001
    void readLabel(std::istream& is, Node& node) const {
deba@1492
  1002
      node = inverter->read(is);
deba@1408
  1003
    } 
deba@1408
  1004
deba@1408
  1005
  private:
deba@1408
  1006
deba@1845
  1007
    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
deba@1408
  1008
    MapReaders readers;
deba@1408
  1009
   
deba@1705
  1010
    Graph& graph;   
deba@1901
  1011
    std::string name;
deba@1845
  1012
    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
deba@1408
  1013
deba@1845
  1014
    std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
deba@1408
  1015
  };
deba@1408
  1016
deba@2016
  1017
  /// \ingroup section_io
deba@2502
  1018
  /// \brief SectionReader for reading a bipartite graph's nodeset.
deba@2502
  1019
  ///
deba@2502
  1020
  /// The lemon format can store multiple bipartite graph nodesets
deba@2502
  1021
  /// with several maps. The bipartite graph nodeset section's header
deba@2502
  1022
  /// line is \c \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name
deba@2502
  1023
  /// may be empty.
deba@2502
  1024
  ///
deba@2502
  1025
  /// The first line of the section contains \c "&anodeset" and the
deba@2502
  1026
  /// the names of the A-node maps and regular maps separated with
deba@2502
  1027
  /// white spaces. Each next lines describes an A-node in the anodeset,
deba@2502
  1028
  /// and contains the mapped values for each map. If one of the line
deba@2502
  1029
  /// starts with \c "&bnodeset" then this line contains the names of
deba@2502
  1030
  /// the B-node maps and the regular node maps. And the remaining lines
deba@2502
  1031
  /// contains the mapped values to the B-nodes.
deba@2502
  1032
  ///
deba@2502
  1033
  /// If there is "label" named map then it should be defined in both
deba@2502
  1034
  /// nodeset, and it will be regarded as id map. This map should
deba@2502
  1035
  /// contain only unique values and when the \c readLabel() member
deba@2502
  1036
  /// will read a value from the given stream it will give back that
deba@2502
  1037
  /// node which is mapped to this value.
deba@2502
  1038
  ///
deba@2502
  1039
  /// \relates LemonReader
deba@2502
  1040
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@2502
  1041
  class BpNodeSetReader : public LemonReader::SectionReader {
deba@2502
  1042
    typedef LemonReader::SectionReader Parent;
deba@2502
  1043
  public:
deba@2502
  1044
deba@2502
  1045
    typedef _Graph Graph;
deba@2502
  1046
    typedef _Traits Traits;
deba@2502
  1047
    typedef typename Graph::Node Node;
deba@2502
  1048
    typedef typename Traits::Skipper DefaultSkipper;
deba@2502
  1049
deba@2502
  1050
    /// \brief Constructor.
deba@2502
  1051
    ///
deba@2502
  1052
    /// Constructor for BpNodeSetReader. It creates the BpNodeSetReader and
deba@2502
  1053
    /// attach it into the given LemonReader. The nodeset reader will
deba@2502
  1054
    /// add the read nodes to the given Graph. The reader will read
deba@2502
  1055
    /// the section when the \c section_name and the \c _name are the same. 
deba@2502
  1056
    BpNodeSetReader(LemonReader& _reader, 
deba@2502
  1057
		  Graph& _graph, 
deba@2502
  1058
		  const std::string& _name = std::string(),
deba@2502
  1059
		  const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@2502
  1060
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {} 
deba@2502
  1061
deba@2502
  1062
deba@2502
  1063
    /// \brief Destructor.
deba@2502
  1064
    ///
deba@2502
  1065
    /// Destructor for BpNodeSetReader.
deba@2502
  1066
    virtual ~BpNodeSetReader() {
deba@2502
  1067
      for (typename MapReaders::iterator it = readers.begin(); 
deba@2502
  1068
	   it != readers.end(); ++it) {
deba@2502
  1069
	delete it->second;
deba@2502
  1070
      }
deba@2502
  1071
    }
deba@2502
  1072
deba@2502
  1073
  private:
deba@2502
  1074
    BpNodeSetReader(const BpNodeSetReader&);
deba@2502
  1075
    void operator=(const BpNodeSetReader&);
deba@2502
  1076
  
deba@2502
  1077
  public:
deba@2502
  1078
deba@2502
  1079
    /// \brief Add a new node map reader command for the reader.
deba@2502
  1080
    ///
deba@2502
  1081
    /// Add a new node map reader command for the reader.
deba@2502
  1082
    template <typename Map>
deba@2502
  1083
    BpNodeSetReader& readNodeMap(std::string label, Map& map) {
deba@2502
  1084
      return _readMap<
deba@2502
  1085
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2502
  1086
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2502
  1087
    }
deba@2502
  1088
deba@2502
  1089
    template <typename Map>
deba@2502
  1090
    BpNodeSetReader& readNodeMap(std::string label, const Map& map) {
deba@2502
  1091
      return _readMap<
deba@2502
  1092
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2502
  1093
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2502
  1094
    }
deba@2502
  1095
deba@2502
  1096
    /// \brief Add a new node map reader command for the reader.
deba@2502
  1097
    ///
deba@2502
  1098
    /// Add a new node map reader command for the reader.
deba@2502
  1099
    template <typename ItemReader, typename Map>
deba@2502
  1100
    BpNodeSetReader& readNodeMap(std::string label, Map& map, 
deba@2502
  1101
			       const ItemReader& ir = ItemReader()) {
deba@2502
  1102
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2502
  1103
	(label, map, ir);
deba@2502
  1104
    }
deba@2502
  1105
deba@2502
  1106
    template <typename ItemReader, typename Map>
deba@2502
  1107
    BpNodeSetReader& readNodeMap(std::string label, const Map& map, 
deba@2502
  1108
			       const ItemReader& ir = ItemReader()) {
deba@2502
  1109
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2502
  1110
	(label, map, ir);
deba@2502
  1111
    }
deba@2502
  1112
deba@2502
  1113
  private:
deba@2502
  1114
deba@2502
  1115
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2502
  1116
    BpNodeSetReader& _readMap(std::string label, MapParameter map, 
deba@2502
  1117
			    const ItemReader& ir = ItemReader()) {
deba@2502
  1118
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@2502
  1119
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2502
  1120
      if (areaders.find(label) != areaders.end() ||
deba@2502
  1121
	  breaders.find(label) != breaders.end() ||
deba@2502
  1122
	  readers.find(label) != readers.end()) {
deba@2502
  1123
	ErrorMessage msg;
deba@2502
  1124
	msg << "Multiple read rule for node map: " << label;
deba@2502
  1125
	throw IoParameterError(msg.message());
deba@2502
  1126
      }      
deba@2502
  1127
      readers.insert(make_pair(label, new _reader_bits::
deba@2502
  1128
		  MapReader<Node, Map, ItemReader>(map, ir)));
deba@2502
  1129
      return *this;
deba@2502
  1130
    }
deba@2502
  1131
deba@2502
  1132
  public:
deba@2502
  1133
deba@2502
  1134
    /// \brief Add a new A-node map reader command for the reader.
deba@2502
  1135
    ///
deba@2502
  1136
    /// Add a new A-node map reader command for the reader.
deba@2502
  1137
    template <typename Map>
deba@2502
  1138
    BpNodeSetReader& readANodeMap(std::string label, Map& map) {
deba@2502
  1139
      return _readAMap<
deba@2502
  1140
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2502
  1141
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2502
  1142
    }
deba@2502
  1143
deba@2502
  1144
    template <typename Map>
deba@2502
  1145
    BpNodeSetReader& readANodeMap(std::string label, const Map& map) {
deba@2502
  1146
      return _readAMap<
deba@2502
  1147
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2502
  1148
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2502
  1149
    }
deba@2502
  1150
deba@2502
  1151
    /// \brief Add a new A-node map reader command for the reader.
deba@2502
  1152
    ///
deba@2502
  1153
    /// Add a new A-node map reader command for the reader.
deba@2502
  1154
    template <typename ItemReader, typename Map>
deba@2502
  1155
    BpNodeSetReader& readANodeMap(std::string label, Map& map, 
deba@2502
  1156
			       const ItemReader& ir = ItemReader()) {
deba@2502
  1157
      return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2502
  1158
	(label, map, ir);
deba@2502
  1159
    }
deba@2502
  1160
deba@2502
  1161
    template <typename ItemReader, typename Map>
deba@2502
  1162
    BpNodeSetReader& readANodeMap(std::string label, const Map& map, 
deba@2502
  1163
			       const ItemReader& ir = ItemReader()) {
deba@2502
  1164
      return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2502
  1165
	(label, map, ir);
deba@2502
  1166
    }
deba@2502
  1167
deba@2502
  1168
  private:
deba@2502
  1169
deba@2502
  1170
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2502
  1171
    BpNodeSetReader& _readAMap(std::string label, MapParameter map, 
deba@2502
  1172
			    const ItemReader& ir = ItemReader()) {
deba@2502
  1173
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@2502
  1174
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2502
  1175
      if (label == "label") {
deba@2502
  1176
	throw IoParameterError("Label cannot be A-node map");
deba@2502
  1177
      }
deba@2502
  1178
      if (areaders.find(label) != areaders.end() ||
deba@2502
  1179
	  readers.find(label) != readers.end()) {
deba@2502
  1180
	ErrorMessage msg;
deba@2502
  1181
	msg << "Multiple read rule for A-node map: " << label;
deba@2502
  1182
	throw IoParameterError(msg.message());
deba@2502
  1183
      }
deba@2502
  1184
      areaders.insert(make_pair(label, new _reader_bits::
deba@2502
  1185
				MapReader<Node, Map, ItemReader>(map, ir)));
deba@2502
  1186
      return *this;
deba@2502
  1187
    }
deba@2502
  1188
deba@2502
  1189
  public:
deba@2502
  1190
deba@2502
  1191
    /// \brief Add a new B-node map reader command for the reader.
deba@2502
  1192
    ///
deba@2502
  1193
    /// Add a new B-node map reader command for the reader.
deba@2502
  1194
    template <typename Map>
deba@2502
  1195
    BpNodeSetReader& readBNodeMap(std::string label, Map& map) {
deba@2502
  1196
      return _readBMap<
deba@2502
  1197
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2502
  1198
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2502
  1199
    }
deba@2502
  1200
deba@2502
  1201
    template <typename Map>
deba@2502
  1202
    BpNodeSetReader& readBNodeMap(std::string label, const Map& map) {
deba@2502
  1203
      return _readBMap<
deba@2502
  1204
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2502
  1205
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2502
  1206
    }
deba@2502
  1207
deba@2502
  1208
    /// \brief Add a new B-node map reader command for the reader.
deba@2502
  1209
    ///
deba@2502
  1210
    /// Add a new B-node map reader command for the reader.
deba@2502
  1211
    template <typename ItemReader, typename Map>
deba@2502
  1212
    BpNodeSetReader& readBNodeMap(std::string label, Map& map, 
deba@2502
  1213
			       const ItemReader& ir = ItemReader()) {
deba@2502
  1214
      return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2502
  1215
	(label, map, ir);
deba@2502
  1216
    }
deba@2502
  1217
deba@2502
  1218
    template <typename ItemReader, typename Map>
deba@2502
  1219
    BpNodeSetReader& readBNodeMap(std::string label, const Map& map, 
deba@2502
  1220
			       const ItemReader& ir = ItemReader()) {
deba@2502
  1221
      return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2502
  1222
	(label, map, ir);
deba@2502
  1223
    }
deba@2502
  1224
deba@2502
  1225
  private:
deba@2502
  1226
deba@2502
  1227
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2502
  1228
    BpNodeSetReader& _readBMap(std::string label, MapParameter map, 
deba@2502
  1229
			    const ItemReader& ir = ItemReader()) {
deba@2502
  1230
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@2502
  1231
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2502
  1232
      if (label == "label") {
deba@2502
  1233
	throw IoParameterError("Label cannot be B-node map");
deba@2502
  1234
      }
deba@2502
  1235
      if (breaders.find(label) != breaders.end() ||
deba@2502
  1236
	  readers.find(label) != readers.end()) {
deba@2502
  1237
	ErrorMessage msg;
deba@2502
  1238
	msg << "Multiple read rule for B-node map: " << label;
deba@2502
  1239
	throw IoParameterError(msg.message());
deba@2502
  1240
      }
deba@2502
  1241
      breaders.insert(make_pair(label, new _reader_bits::
deba@2502
  1242
				MapReader<Node, Map, ItemReader>(map, ir)));
deba@2502
  1243
      return *this;
deba@2502
  1244
    }
deba@2502
  1245
deba@2502
  1246
  public:
deba@2502
  1247
deba@2502
  1248
    /// \brief Add a new node map skipper command for the reader.
deba@2502
  1249
    ///
deba@2502
  1250
    /// Add a new node map skipper command for the reader.
deba@2502
  1251
    template <typename ItemReader>
deba@2502
  1252
    BpNodeSetReader& skipNodeMap(std::string label, 
deba@2502
  1253
				 const ItemReader& ir = ItemReader()) {
deba@2502
  1254
      if (areaders.find(label) != areaders.end() ||
deba@2502
  1255
	  breaders.find(label) != breaders.end() ||
deba@2502
  1256
	  readers.find(label) != readers.end()) {
deba@2502
  1257
	ErrorMessage msg;
deba@2502
  1258
	msg << "Multiple read rule for node map: " << label;
deba@2502
  1259
	throw IoParameterError(msg.message());
deba@2502
  1260
      }
deba@2502
  1261
      readers.insert(make_pair(label, new _reader_bits::
deba@2502
  1262
			       SkipReader<Node, ItemReader>(ir)));
deba@2502
  1263
      return *this;
deba@2502
  1264
    }
deba@2502
  1265
deba@2502
  1266
    /// \brief Add a new A-node map skipper command for the reader.
deba@2502
  1267
    ///
deba@2502
  1268
    /// Add a new A-node map skipper command for the reader.
deba@2502
  1269
    template <typename ItemReader>
deba@2502
  1270
    BpNodeSetReader& skipANodeMap(std::string label, 
deba@2502
  1271
				  const ItemReader& ir = ItemReader()) {
deba@2502
  1272
      if (label == "label") {
deba@2502
  1273
	throw IoParameterError("Label cannot be A-node map");
deba@2502
  1274
      }
deba@2502
  1275
      if (areaders.find(label) != areaders.end() ||
deba@2502
  1276
	  readers.find(label) != readers.end()) {
deba@2502
  1277
	ErrorMessage msg;
deba@2502
  1278
	msg << "Multiple read rule for A-node map: " << label;
deba@2502
  1279
	throw IoParameterError(msg.message());
deba@2502
  1280
      }
deba@2502
  1281
      areaders.insert(make_pair(label, new _reader_bits::
deba@2502
  1282
				SkipReader<Node, ItemReader>(ir)));
deba@2502
  1283
      return *this;
deba@2502
  1284
    }
deba@2502
  1285
deba@2502
  1286
    /// \brief Add a new B-node map skipper command for the reader.
deba@2502
  1287
    ///
deba@2502
  1288
    /// Add a new B-node map skipper command for the reader.
deba@2502
  1289
    template <typename ItemReader>
deba@2502
  1290
    BpNodeSetReader& skipBNodeMap(std::string label, 
deba@2502
  1291
				  const ItemReader& ir = ItemReader()) {
deba@2502
  1292
      if (label == "label") {
deba@2502
  1293
	throw IoParameterError("Label cannot be B-node map");
deba@2502
  1294
      }
deba@2502
  1295
      if (breaders.find(label) != breaders.end() ||
deba@2502
  1296
	  readers.find(label) != readers.end()) {
deba@2502
  1297
	ErrorMessage msg;
deba@2502
  1298
	msg << "Multiple read rule for B-node map: " << label;
deba@2502
  1299
	throw IoParameterError(msg.message());
deba@2502
  1300
      }
deba@2502
  1301
      breaders.insert(make_pair(label, new _reader_bits::
deba@2502
  1302
				SkipReader<Node, ItemReader>(ir)));
deba@2502
  1303
      return *this;
deba@2502
  1304
    }
deba@2502
  1305
deba@2502
  1306
deba@2502
  1307
  protected:
deba@2502
  1308
deba@2502
  1309
    /// \brief Gives back true when the SectionReader can process 
deba@2502
  1310
    /// the section with the given header line.
deba@2502
  1311
    ///
deba@2502
  1312
    /// It gives back true when the header line starts with \c \@nodeset,
deba@2502
  1313
    /// and the header line's name and the nodeset's name are the same.
deba@2502
  1314
    virtual bool header(const std::string& line) {
deba@2502
  1315
      std::istringstream ls(line);
deba@2502
  1316
      std::string command;
deba@2502
  1317
      std::string id;
deba@2502
  1318
      ls >> command >> id;
deba@2502
  1319
      return command == "@bpnodeset" && name == id;
deba@2502
  1320
    }
deba@2502
  1321
deba@2502
  1322
    /// \brief Reader function of the section.
deba@2502
  1323
    ///
deba@2502
  1324
    /// It reads the content of the section.
deba@2502
  1325
    virtual void read(std::istream& is) {
deba@2502
  1326
      std::string line;
deba@2502
  1327
      {
deba@2502
  1328
	std::vector<_reader_bits::MapReaderBase<Node>* > index;
deba@2502
  1329
	{
deba@2502
  1330
	  getline(is, line);
deba@2502
  1331
	  std::istringstream ls(line);
deba@2502
  1332
	  std::string id;
deba@2502
  1333
	  ls >> id;
deba@2502
  1334
	  if (id != "&anodeset") {
deba@2502
  1335
	    throw IoParameterError("Cannot find &anodeset subsection");
deba@2502
  1336
	  }
deba@2502
  1337
	  while (ls >> id) {
deba@2502
  1338
	    typename MapReaders::iterator it = readers.find(id);
deba@2502
  1339
	    typename MapReaders::iterator ait = areaders.find(id);
deba@2502
  1340
	    if (it != readers.end()) {
deba@2502
  1341
	      it->second->touch();
deba@2502
  1342
	      index.push_back(it->second);
deba@2502
  1343
	    } else if (ait != areaders.end()) {
deba@2502
  1344
	      ait->second->touch();
deba@2502
  1345
	      index.push_back(ait->second);
deba@2504
  1346
	    } else {
deba@2504
  1347
	      index.push_back(&skipper);
deba@2502
  1348
	    }
deba@2502
  1349
	    if (id == "label") {
deba@2502
  1350
	      inverter.reset(index.back()->getInverter());
deba@2502
  1351
	      index.back() = inverter.get();
deba@2502
  1352
	    }
deba@2502
  1353
	  }
deba@2502
  1354
	}
deba@2502
  1355
	for (typename MapReaders::iterator it = areaders.begin();
deba@2502
  1356
	     it != areaders.end(); ++it) {
deba@2502
  1357
	  if (!it->second->touched()) {
deba@2502
  1358
	    ErrorMessage msg;
deba@2502
  1359
	    msg << "Map not found in file: " << it->first;
deba@2502
  1360
	    throw IoParameterError(msg.message());
deba@2502
  1361
	  }
deba@2502
  1362
	}
deba@2502
  1363
	for (typename MapReaders::iterator it = readers.begin();
deba@2502
  1364
	     it != readers.end(); ++it) {
deba@2502
  1365
	  if (!it->second->touched()) {
deba@2502
  1366
	    ErrorMessage msg;
deba@2502
  1367
	    msg << "Map not found in file: " << it->first;
deba@2502
  1368
	    throw IoParameterError(msg.message());
deba@2502
  1369
	  }
deba@2502
  1370
	  it->second->touch(false);
deba@2502
  1371
	}
deba@2502
  1372
deba@2502
  1373
	while (getline(is, line)) {
deba@2502
  1374
	  if (line[0] == '&') {
deba@2502
  1375
	    std::istringstream ls(line);
deba@2502
  1376
	    std::string id;
deba@2502
  1377
	    ls >> id;
deba@2502
  1378
	    if (id == "&bnodeset") break;
deba@2502
  1379
	  }
deba@2502
  1380
	  Node node = graph.addANode();
deba@2502
  1381
	  std::istringstream ls(line);
deba@2502
  1382
	  for (int i = 0; i < int(index.size()); ++i) {
deba@2502
  1383
	    index[i]->read(ls, node);
deba@2502
  1384
	  }
deba@2502
  1385
	}
deba@2502
  1386
      }
deba@2502
  1387
deba@2502
  1388
      {
deba@2502
  1389
	std::vector<_reader_bits::MapReaderBase<Node>* > index;
deba@2502
  1390
	{
deba@2502
  1391
	  std::istringstream ls(line);
deba@2502
  1392
	  std::string id;
deba@2502
  1393
	  ls >> id;
deba@2502
  1394
	  if (id != "&bnodeset") {
deba@2502
  1395
	    throw IoParameterError("Cannot find &bnodeset subsection");
deba@2502
  1396
	  }
deba@2502
  1397
	  while (ls >> id) {
deba@2502
  1398
	    typename MapReaders::iterator it = readers.find(id);
deba@2502
  1399
	    typename MapReaders::iterator bit = breaders.find(id);
deba@2502
  1400
	    if (it != readers.end()) {
deba@2502
  1401
	      it->second->touch();
deba@2502
  1402
	      index.push_back(it->second);
deba@2502
  1403
	    } else if (bit != breaders.end()) {
deba@2502
  1404
	      bit->second->touch();
deba@2502
  1405
	      index.push_back(bit->second);
deba@2504
  1406
	    } else {
deba@2504
  1407
	      index.push_back(&skipper);
deba@2502
  1408
	    }
deba@2502
  1409
	    if (id == "label" && inverter.get() != 0) {
deba@2502
  1410
	      index.back() = inverter.get();
deba@2502
  1411
	    }
deba@2502
  1412
	  }
deba@2502
  1413
	}
deba@2502
  1414
	for (typename MapReaders::iterator it = breaders.begin();
deba@2502
  1415
	     it != breaders.end(); ++it) {
deba@2502
  1416
	  if (!it->second->touched()) {
deba@2502
  1417
	    ErrorMessage msg;
deba@2502
  1418
	    msg << "Map not found in file: " << it->first;
deba@2502
  1419
	    throw IoParameterError(msg.message());
deba@2502
  1420
	  }
deba@2502
  1421
	}
deba@2502
  1422
	for (typename MapReaders::iterator it = readers.begin();
deba@2502
  1423
	     it != readers.end(); ++it) {
deba@2502
  1424
	  if (!it->second->touched()) {
deba@2502
  1425
	    ErrorMessage msg;
deba@2502
  1426
	    msg << "Map not found in file: " << it->first;
deba@2502
  1427
	    throw IoParameterError(msg.message());
deba@2502
  1428
	  }
deba@2502
  1429
	}
deba@2502
  1430
	while (getline(is, line)) {	
deba@2502
  1431
	  Node node = graph.addBNode();
deba@2502
  1432
	  std::istringstream ls(line);
deba@2502
  1433
	  for (int i = 0; i < int(index.size()); ++i) {
deba@2502
  1434
	    index[i]->read(ls, node);
deba@2502
  1435
	  }
deba@2502
  1436
	}
deba@2502
  1437
      }
deba@2502
  1438
    }
deba@2502
  1439
deba@2502
  1440
    virtual void missing() {
deba@2502
  1441
      if (readers.empty()) return;
deba@2502
  1442
      ErrorMessage msg;
deba@2502
  1443
      msg << "BpNodeSet section not found in file: @bpnodeset " << name;
deba@2502
  1444
      throw IoParameterError(msg.message());
deba@2502
  1445
    }
deba@2502
  1446
deba@2502
  1447
  public:
deba@2502
  1448
deba@2502
  1449
    /// \brief Returns true if the nodeset can give back the node by its label.
deba@2502
  1450
    ///
deba@2502
  1451
    /// Returns true if the nodeset can give back the node by its label.
deba@2502
  1452
    /// It is possible only if an "label" named map was read.
deba@2502
  1453
    bool isLabelReader() const {
deba@2502
  1454
      return inverter.get() != 0;
deba@2502
  1455
    }
deba@2502
  1456
deba@2502
  1457
    /// \brief Gives back the node by its label.
deba@2502
  1458
    ///
deba@2502
  1459
    /// It reads an id from the stream and gives back which node belongs to
deba@2502
  1460
    /// it. It is possible only if there was read an "label" named map.
deba@2502
  1461
    void readLabel(std::istream& is, Node& node) const {
deba@2502
  1462
      node = inverter->read(is);
deba@2502
  1463
    } 
deba@2502
  1464
deba@2502
  1465
  private:
deba@2502
  1466
deba@2502
  1467
    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> 
deba@2502
  1468
    MapReaders;
deba@2502
  1469
    
deba@2502
  1470
    MapReaders areaders, breaders, readers;
deba@2502
  1471
   
deba@2502
  1472
    Graph& graph;
deba@2502
  1473
    std::string name;
deba@2502
  1474
    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
deba@2502
  1475
deba@2502
  1476
    std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
deba@2502
  1477
  };
deba@2502
  1478
deba@2502
  1479
deba@2502
  1480
  /// \ingroup section_io
deba@1409
  1481
  /// \brief SectionReader for reading a graph's edgeset.
deba@1409
  1482
  ///
deba@1409
  1483
  /// The lemon format can store multiple graph edgesets with several maps.
deba@1901
  1484
  /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
deba@1901
  1485
  /// \c edgeset_name may be empty.
deba@1409
  1486
  ///
deba@1409
  1487
  /// The first line of the section contains the names of the maps separated
deba@1421
  1488
  /// with white spaces. Each next lines describes an edge in the edgeset. The
deba@1421
  1489
  /// line contains the source and the target nodes' id and the mapped 
deba@1421
  1490
  /// values for each map.
deba@1409
  1491
  ///
deba@1901
  1492
  /// If the edgeset contains an \c "label" named map then it will be regarded
deba@1409
  1493
  /// as id map. This map should contain only unique values and when the 
deba@1901
  1494
  /// \c readLabel() member will read a value from the given stream it will
deba@1409
  1495
  /// give back that edge which is mapped to this value.
deba@1409
  1496
  ///
deba@1409
  1497
  /// The edgeset reader needs a node id reader to identify which nodes
deba@1901
  1498
  /// have to be connected. If a NodeSetReader reads an "label" named map,
deba@1409
  1499
  /// it will be able to resolve the nodes by ids.
deba@1409
  1500
  ///
deba@1409
  1501
  /// \relates LemonReader
deba@1408
  1502
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@1845
  1503
  class EdgeSetReader : public LemonReader::SectionReader {
deba@1845
  1504
    typedef LemonReader::SectionReader Parent;
deba@1408
  1505
  public:
deba@1408
  1506
deba@1408
  1507
    typedef _Graph Graph;
deba@1408
  1508
    typedef _Traits Traits;
deba@1429
  1509
    typedef typename Graph::Node Node;
deba@1429
  1510
    typedef typename Graph::Edge Edge;
deba@1408
  1511
    typedef typename Traits::Skipper DefaultSkipper;
deba@1408
  1512
deba@1409
  1513
    /// \brief Constructor.
deba@1409
  1514
    ///
deba@1409
  1515
    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
deba@1409
  1516
    /// attach it into the given LemonReader. The edgeset reader will
deba@2100
  1517
    /// add the read edges to the given Graph. It will use the given
deba@1409
  1518
    /// node id reader to read the source and target nodes of the edges.
deba@1901
  1519
    /// The reader will read the section only if the \c _name and the 
deba@1901
  1520
    /// \c edgset_name are the same. 
deba@1901
  1521
    template <typename NodeLabelReader>
deba@1421
  1522
    EdgeSetReader(LemonReader& _reader, 
deba@1705
  1523
		  Graph& _graph, 
deba@1901
  1524
		  const NodeLabelReader& _nodeLabelReader, 
deba@1901
  1525
		  const std::string& _name = std::string(),
deba@1409
  1526
		  const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1901
  1527
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
deba@1901
  1528
      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
deba@1901
  1529
      nodeLabelReader.reset(new _reader_bits::
deba@1901
  1530
			 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
deba@1476
  1531
    }
deba@1409
  1532
    /// \brief Destructor.
deba@1409
  1533
    ///
deba@1409
  1534
    /// Destructor for EdgeSetReader.
deba@1408
  1535
    virtual ~EdgeSetReader() {
deba@1408
  1536
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1408
  1537
	   it != readers.end(); ++it) {
deba@1408
  1538
	delete it->second;
deba@1408
  1539
      }
deba@1408
  1540
    }
deba@1408
  1541
deba@1408
  1542
  private:
deba@1408
  1543
    EdgeSetReader(const EdgeSetReader&);
deba@1408
  1544
    void operator=(const EdgeSetReader&);
deba@1408
  1545
deba@1408
  1546
  public:
deba@1408
  1547
deba@1409
  1548
    /// \brief Add a new edge map reader command for the reader.
deba@1408
  1549
    ///
deba@1409
  1550
    /// Add a new edge map reader command for the reader.
deba@1408
  1551
    template <typename Map>
deba@2386
  1552
    EdgeSetReader& readEdgeMap(std::string label, Map& map) {
deba@1421
  1553
      return _readMap<
deba@1421
  1554
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2386
  1555
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1421
  1556
    }
deba@1421
  1557
deba@1421
  1558
    template <typename Map>
deba@2386
  1559
    EdgeSetReader& readEdgeMap(std::string label, const Map& map) {
deba@1421
  1560
      return _readMap<
deba@1421
  1561
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2386
  1562
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1408
  1563
    }
deba@1408
  1564
deba@1409
  1565
    /// \brief Add a new edge map reader command for the reader.
deba@1408
  1566
    ///
deba@1409
  1567
    /// Add a new edge map reader command for the reader.
deba@2386
  1568
    template <typename ItemReader, typename Map>
deba@2386
  1569
    EdgeSetReader& readEdgeMap(std::string label, Map& map, 
deba@2386
  1570
                               const ItemReader& ir = ItemReader()) {
deba@2386
  1571
      return _readMap<ItemReader, Map,
deba@2386
  1572
	typename _reader_bits::Arg<Map>::Type>(label, map, ir);
deba@1421
  1573
    }
deba@1421
  1574
deba@2386
  1575
    template <typename ItemReader, typename Map>
deba@2386
  1576
    EdgeSetReader& readEdgeMap(std::string label, const Map& map, 
deba@2386
  1577
			       const ItemReader& ir = ItemReader()) {
deba@2386
  1578
      return _readMap<ItemReader, Map,
deba@2386
  1579
	typename _reader_bits::Arg<Map>::Type>(label, map, ir);
deba@1421
  1580
    }
deba@1421
  1581
deba@1421
  1582
  private:
deba@1421
  1583
deba@2386
  1584
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2386
  1585
    EdgeSetReader& _readMap(std::string label, MapParameter map, 
deba@2386
  1586
			    const ItemReader& ir = ItemReader()) {
alpar@2260
  1587
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
deba@2386
  1588
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2386
  1589
      if (readers.find(label) != readers.end()) {
deba@1408
  1590
	ErrorMessage msg;
deba@2386
  1591
	msg << "Multiple read rule for edge map: " << label;
alpar@2153
  1592
	throw IoParameterError(msg.message());
deba@1408
  1593
      }
deba@1408
  1594
      readers.insert(
deba@2386
  1595
	make_pair(label, new _reader_bits::
deba@2386
  1596
		  MapReader<Edge, Map, ItemReader>(map, ir)));
deba@1408
  1597
      return *this;
deba@1408
  1598
    }
deba@1408
  1599
deba@1421
  1600
  public:
deba@1421
  1601
deba@1409
  1602
    /// \brief Add a new edge map skipper command for the reader.
deba@1408
  1603
    ///
deba@1409
  1604
    /// Add a new edge map skipper command for the reader.
deba@2386
  1605
    template <typename ItemReader>
deba@2386
  1606
    EdgeSetReader& skipEdgeMap(std::string label, 
deba@2386
  1607
			       const ItemReader& ir = ItemReader()) {
deba@2386
  1608
      if (readers.find(label) != readers.end()) {
deba@1408
  1609
	ErrorMessage msg;
deba@2386
  1610
	msg << "Multiple read rule for edge map: " << label;
alpar@2153
  1611
	throw IoParameterError(msg.message());
deba@1408
  1612
      }
deba@2386
  1613
      readers.insert(make_pair(label, new _reader_bits::
deba@2386
  1614
			       SkipReader<Edge, ItemReader>(ir)));
deba@1408
  1615
      return *this;
deba@1408
  1616
    }
deba@1408
  1617
deba@1409
  1618
  protected:
deba@1409
  1619
deba@1409
  1620
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  1621
    /// the section with the given header line.
deba@1409
  1622
    ///
deba@1421
  1623
    /// It gives back true when the header line starts with \c \@edgeset,
deba@1901
  1624
    /// and the header line's name and the edgeset's name are the same.
kpeter@2476
  1625
    /// The sections with \@uedgeset head line could be read with this
deba@2464
  1626
    /// section reader too.
deba@1408
  1627
    virtual bool header(const std::string& line) {
deba@1408
  1628
      std::istringstream ls(line);
deba@1408
  1629
      std::string command;
deba@1901
  1630
      std::string id;
klao@1997
  1631
      ls >> command >> id;
deba@2464
  1632
      return (command == "@edgeset" || command == "@uedgeset") && name == id;
deba@1408
  1633
    }
deba@1408
  1634
deba@1409
  1635
    /// \brief Reader function of the section.
deba@1409
  1636
    ///
deba@1409
  1637
    /// It reads the content of the section.
deba@1408
  1638
    virtual void read(std::istream& is) {
deba@1901
  1639
      if (!nodeLabelReader->isLabelReader()) {
deba@1901
  1640
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
  1641
      }
deba@1845
  1642
      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
deba@1408
  1643
      std::string line;
deba@1408
  1644
deba@2386
  1645
      {
deba@2386
  1646
        getline(is, line);
deba@2386
  1647
        std::istringstream ls(line);	
deba@2386
  1648
        std::string id;
deba@2386
  1649
        while (ls >> id) {
deba@2386
  1650
          typename MapReaders::iterator it = readers.find(id);
deba@2386
  1651
          if (it != readers.end()) {
deba@2386
  1652
            index.push_back(it->second);
deba@2386
  1653
            it->second->touch();
deba@2386
  1654
          } else {
deba@2386
  1655
            index.push_back(&skipper);
deba@2386
  1656
          }
deba@2386
  1657
          if (id == "label") {
deba@2386
  1658
            inverter.reset(index.back()->getInverter());
deba@2386
  1659
            index.back() = inverter.get();
deba@2386
  1660
          }
deba@2386
  1661
        }
deba@1408
  1662
      }
deba@1845
  1663
      for (typename MapReaders::iterator it = readers.begin();
deba@1845
  1664
	   it != readers.end(); ++it) {
deba@1845
  1665
	if (!it->second->touched()) {
deba@1845
  1666
	  ErrorMessage msg;
deba@1845
  1667
	  msg << "Map not found in file: " << it->first;
alpar@2153
  1668
	  throw IoParameterError(msg.message());
deba@1845
  1669
	}
deba@1845
  1670
      }
deba@1408
  1671
      while (getline(is, line)) {	
deba@1408
  1672
	std::istringstream ls(line);
deba@1901
  1673
	Node from = nodeLabelReader->read(ls);
deba@1901
  1674
	Node to = nodeLabelReader->read(ls);
deba@1429
  1675
	Edge edge = graph.addEdge(from, to);
deba@2386
  1676
	for (int i = 0; i < int(index.size()); ++i) {
deba@1408
  1677
	  index[i]->read(ls, edge);
deba@1408
  1678
	}
deba@1408
  1679
      }
deba@1408
  1680
    }
deba@1408
  1681
deba@2000
  1682
    virtual void missing() {
deba@2000
  1683
      if (readers.empty()) return;
deba@2000
  1684
      ErrorMessage msg;
deba@2001
  1685
      msg << "EdgeSet section not found in file: @edgeset " << name;
alpar@2153
  1686
      throw IoParameterError(msg.message());
deba@2000
  1687
    }
deba@2000
  1688
deba@1409
  1689
  public:
deba@1409
  1690
deba@1901
  1691
    /// \brief Returns true if the edgeset can give back the edge by its label.
deba@1409
  1692
    ///
deba@1901
  1693
    /// Returns true if the edgeset can give back the edge by its label.
deba@1901
  1694
    /// It is possible only if an "label" named map was read.
deba@1901
  1695
    bool isLabelReader() const {
deba@1408
  1696
      return inverter.get() != 0;
deba@1408
  1697
    }
deba@1408
  1698
deba@1901
  1699
    /// \brief Gives back the edge by its label.
deba@1409
  1700
    ///
deba@1409
  1701
    /// It reads an id from the stream and gives back which edge belongs to
deba@1901
  1702
    /// it. It is possible only if there was read an "label" named map.
deba@1901
  1703
    void readLabel(std::istream& is, Edge& edge) const {
deba@1492
  1704
      edge = inverter->read(is);
deba@1408
  1705
    } 
deba@1408
  1706
deba@1408
  1707
  private:
deba@1408
  1708
deba@2001
  1709
    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> 
deba@2001
  1710
    MapReaders;
deba@2001
  1711
    
deba@1408
  1712
    MapReaders readers;
deba@1408
  1713
   
deba@1705
  1714
    Graph& graph;   
deba@1901
  1715
    std::string name;
deba@1845
  1716
    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
deba@1421
  1717
deba@1845
  1718
    std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
deba@1901
  1719
    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
deba@1421
  1720
  };
deba@1421
  1721
deba@2016
  1722
  /// \ingroup section_io
deba@1421
  1723
  /// \brief SectionReader for reading a undirected graph's edgeset.
deba@1421
  1724
  ///
deba@1421
  1725
  /// The lemon format can store multiple undirected edgesets with several 
klao@1909
  1726
  /// maps. The undirected edgeset section's header line is \c \@uedgeset 
klao@1909
  1727
  /// \c uedgeset_name, but the \c uedgeset_name may be empty.
deba@1421
  1728
  ///
deba@1421
  1729
  /// The first line of the section contains the names of the maps separated
deba@1421
  1730
  /// with white spaces. Each next lines describes an edge in the edgeset. The
deba@1421
  1731
  /// line contains the connected nodes' id and the mapped values for each map.
deba@1421
  1732
  ///
deba@1421
  1733
  /// The section can handle the directed as a syntactical sugar. Two
deba@1421
  1734
  /// undirected edge map describes one directed edge map. This two maps
deba@1421
  1735
  /// are the forward map and the backward map and the names of this map
deba@1421
  1736
  /// is near the same just with a prefix \c '+' or \c '-' character 
deba@1421
  1737
  /// difference.
deba@1421
  1738
  ///
deba@1901
  1739
  /// If the edgeset contains an \c "label" named map then it will be regarded
deba@1421
  1740
  /// as id map. This map should contain only unique values and when the 
deba@1901
  1741
  /// \c readLabel() member will read a value from the given stream it will
klao@1909
  1742
  /// give back that uicted edge which is mapped to this value.
deba@1421
  1743
  ///
deba@1421
  1744
  /// The undirected edgeset reader needs a node id reader to identify which 
deba@2001
  1745
  /// nodes have to be connected. If a NodeSetReader reads an "label" named 
deba@2001
  1746
  /// map, it will be able to resolve the nodes by ids.
deba@1421
  1747
  ///
deba@1421
  1748
  /// \relates LemonReader
deba@1421
  1749
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
klao@1909
  1750
  class UEdgeSetReader : public LemonReader::SectionReader {
deba@1845
  1751
    typedef LemonReader::SectionReader Parent;
deba@1421
  1752
  public:
deba@1421
  1753
deba@1421
  1754
    typedef _Graph Graph;
deba@1421
  1755
    typedef _Traits Traits;
deba@1429
  1756
    typedef typename Graph::Node Node;
deba@1429
  1757
    typedef typename Graph::Edge Edge;
klao@1909
  1758
    typedef typename Graph::UEdge UEdge;
deba@1421
  1759
    typedef typename Traits::Skipper DefaultSkipper;
deba@1421
  1760
deba@1421
  1761
    /// \brief Constructor.
deba@1421
  1762
    ///
klao@1909
  1763
    /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader 
deba@1421
  1764
    /// and attach it into the given LemonReader. The undirected edgeset 
deba@2100
  1765
    /// reader will add the read undirected edges to the given Graph. It 
deba@1421
  1766
    /// will use the given node id reader to read the source and target 
deba@1421
  1767
    /// nodes of the edges. The reader will read the section only if the 
klao@1909
  1768
    /// \c _name and the \c uedgset_name are the same. 
deba@1901
  1769
    template <typename NodeLabelReader>
klao@1909
  1770
    UEdgeSetReader(LemonReader& _reader, 
deba@1705
  1771
		       Graph& _graph, 
deba@1901
  1772
		       const NodeLabelReader& _nodeLabelReader, 
deba@1901
  1773
		       const std::string& _name = std::string(),
deba@1421
  1774
		       const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1901
  1775
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
deba@1901
  1776
      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
deba@1901
  1777
      nodeLabelReader.reset(new _reader_bits::
deba@1901
  1778
			 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
deba@1476
  1779
    }
deba@1421
  1780
    /// \brief Destructor.
deba@1421
  1781
    ///
klao@1909
  1782
    /// Destructor for UEdgeSetReader.
klao@1909
  1783
    virtual ~UEdgeSetReader() {
deba@1421
  1784
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1421
  1785
	   it != readers.end(); ++it) {
deba@1421
  1786
	delete it->second;
deba@1421
  1787
      }
deba@1421
  1788
    }
deba@1421
  1789
deba@1421
  1790
  private:
klao@1909
  1791
    UEdgeSetReader(const UEdgeSetReader&);
klao@1909
  1792
    void operator=(const UEdgeSetReader&);
deba@1421
  1793
deba@1421
  1794
  public:
deba@1421
  1795
deba@1421
  1796
    /// \brief Add a new undirected edge map reader command for the reader.
deba@1421
  1797
    ///
deba@1421
  1798
    /// Add a new edge undirected map reader command for the reader.
deba@1421
  1799
    template <typename Map>
deba@2386
  1800
    UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
deba@1421
  1801
      return _readMap<
deba@1421
  1802
	typename Traits::template Reader<typename Map::Value>, Map, 
deba@2386
  1803
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1421
  1804
    }
deba@1421
  1805
deba@1421
  1806
    template <typename Map>
deba@2386
  1807
    UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
deba@1421
  1808
      return _readMap<
deba@1421
  1809
	typename Traits::template Reader<typename Map::Value>, Map, 
deba@2386
  1810
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1421
  1811
    }
deba@1421
  1812
deba@1421
  1813
    /// \brief Add a new undirected edge map reader command for the reader.
deba@1421
  1814
    ///
deba@1421
  1815
    /// Add a new edge undirected map reader command for the reader.
deba@2386
  1816
    template <typename ItemReader, typename Map>
deba@2386
  1817
    UEdgeSetReader& readUEdgeMap(std::string label, Map& map, 
deba@2386
  1818
                                 const ItemReader& ir = ItemReader()) {
deba@2386
  1819
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2386
  1820
	(label, map, ir);
deba@1421
  1821
    }
deba@1421
  1822
deba@2386
  1823
    template <typename ItemReader, typename Map>
deba@2386
  1824
    UEdgeSetReader& readUEdgeMap(std::string label, const Map& map, 
deba@2386
  1825
                                 const ItemReader& ir = ItemReader()) {
deba@2386
  1826
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type >
deba@2386
  1827
	(label, map, ir);
deba@1421
  1828
    }
deba@1421
  1829
deba@1421
  1830
  private:
deba@1421
  1831
deba@2386
  1832
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2386
  1833
    UEdgeSetReader& _readMap(std::string label, MapParameter map,
deba@2386
  1834
                             const ItemReader& ir = ItemReader()) {
alpar@2260
  1835
      checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
deba@2386
  1836
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2386
  1837
      if (readers.find(label) != readers.end()) {
deba@1421
  1838
	ErrorMessage msg;
deba@2386
  1839
	msg << "Multiple read rule for edge map: " << label;
alpar@2153
  1840
	throw IoParameterError(msg.message());
deba@1421
  1841
      }
deba@1421
  1842
      readers.insert(
deba@2386
  1843
	make_pair(label, new _reader_bits::
deba@2386
  1844
		  MapReader<UEdge, Map, ItemReader>(map, ir)));
deba@1421
  1845
      return *this;
deba@1421
  1846
    }
deba@1421
  1847
deba@1421
  1848
  public:
deba@1421
  1849
deba@1421
  1850
    /// \brief Add a new undirected edge map skipper command for the reader.
deba@1421
  1851
    ///
deba@1421
  1852
    /// Add a new undirected edge map skipper command for the reader.
deba@2386
  1853
    template <typename ItemReader>
deba@2386
  1854
    UEdgeSetReader& skipUEdgeMap(std::string label, 
deba@2386
  1855
                                 const ItemReader& ir = ItemReader()) {
deba@2386
  1856
      if (readers.find(label) != readers.end()) {
deba@1421
  1857
	ErrorMessage msg;
deba@2386
  1858
	msg << "Multiple read rule for node map: " << label;
alpar@2153
  1859
	throw IoParameterError(msg.message());
deba@1421
  1860
      }
deba@2386
  1861
      readers.insert(make_pair(label, new _reader_bits::
deba@2386
  1862
			       SkipReader<UEdge, ItemReader>(ir)));
deba@1421
  1863
      return *this;
deba@1421
  1864
    }
deba@1421
  1865
deba@1421
  1866
    /// \brief Add a new directed edge map reader command for the reader.
deba@1421
  1867
    ///
deba@1421
  1868
    /// Add a new directed edge map reader command for the reader.
deba@1421
  1869
    template <typename Map>
deba@2386
  1870
    UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
deba@1421
  1871
      return _readDirMap<
deba@1421
  1872
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2386
  1873
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1421
  1874
    }
deba@1421
  1875
deba@1421
  1876
    template <typename Map>
deba@2386
  1877
    UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
deba@1421
  1878
      return _readDirMap<
deba@1421
  1879
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2386
  1880
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1421
  1881
    }
deba@1421
  1882
deba@1421
  1883
    /// \brief Add a new directed edge map reader command for the reader.
deba@1421
  1884
    ///
deba@1421
  1885
    /// Add a new directed edge map reader command for the reader.
deba@2386
  1886
    template <typename ItemReader, typename Map>
deba@2386
  1887
    UEdgeSetReader& readEdgeMap(std::string label, Map& map, 
deba@2386
  1888
				    const ItemReader& ir = ItemReader()) {
deba@2386
  1889
      return _readDirMap<ItemReader, Map, 
deba@2386
  1890
        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
deba@1421
  1891
    }
deba@1421
  1892
deba@2386
  1893
    template <typename ItemReader, typename Map>
deba@2386
  1894
    UEdgeSetReader& readEdgeMap(std::string label, const Map& map, 
deba@2386
  1895
				    const ItemReader& ir = ItemReader()) {
deba@2386
  1896
      return _readDirMap<ItemReader, Map, 
deba@2386
  1897
        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
deba@1421
  1898
    }
deba@1421
  1899
deba@1421
  1900
  private:
deba@1421
  1901
deba@2386
  1902
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2386
  1903
    UEdgeSetReader& _readDirMap(std::string label, MapParameter map,
deba@2386
  1904
				    const ItemReader& ir = ItemReader()) { 
deba@2386
  1905
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
alpar@2260
  1906
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
deba@2386
  1907
      readUEdgeMap("+" + label, 
deba@2386
  1908
                   _reader_bits::forwardComposeMap(graph, map), ir);
deba@2386
  1909
      readUEdgeMap("-" + label, 
deba@2386
  1910
                   _reader_bits::backwardComposeMap(graph, map), ir);
deba@1421
  1911
      return *this;      
deba@1421
  1912
    }
deba@1421
  1913
deba@1421
  1914
  public:
deba@1421
  1915
deba@1421
  1916
    /// \brief Add a new directed edge map skipper command for the reader.
deba@1421
  1917
    ///
deba@1421
  1918
    /// Add a new directed edge map skipper command for the reader.
deba@2386
  1919
    template <typename ItemReader>
deba@2386
  1920
    UEdgeSetReader& skipEdgeMap(std::string label, 
deba@2386
  1921
                                const ItemReader& ir = ItemReader()) {
deba@2386
  1922
      skipUEdgeMap("+" + label, ir);
deba@2386
  1923
      skipUEdgeMap("-" + label, ir);
deba@1421
  1924
      return *this;
deba@1421
  1925
    }
deba@1421
  1926
deba@1421
  1927
  protected:
deba@1421
  1928
deba@1421
  1929
    /// \brief Gives back true when the SectionReader can process 
deba@1421
  1930
    /// the section with the given header line.
deba@1421
  1931
    ///
klao@1909
  1932
    /// It gives back true when the header line starts with \c \@uedgeset,
deba@1901
  1933
    /// and the header line's name and the edgeset's name are the same.
kpeter@2476
  1934
    /// The sections with \@edgeset head line could be read with this
deba@2464
  1935
    /// section reader too.
deba@1421
  1936
    virtual bool header(const std::string& line) {
deba@1421
  1937
      std::istringstream ls(line);
deba@1421
  1938
      std::string command;
deba@1901
  1939
      std::string id;
klao@1997
  1940
      ls >> command >> id;
deba@2464
  1941
      return (command == "@edgeset" || command == "@uedgeset") && name == id;
deba@1421
  1942
    }
deba@1421
  1943
deba@1421
  1944
    /// \brief Reader function of the section.
deba@1421
  1945
    ///
deba@1421
  1946
    /// It reads the content of the section.
deba@1421
  1947
    virtual void read(std::istream& is) {
deba@1901
  1948
      if (!nodeLabelReader->isLabelReader()) {
deba@1901
  1949
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
  1950
      }
klao@1909
  1951
      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
deba@1421
  1952
      std::string line;
deba@1421
  1953
deba@2386
  1954
      {
deba@2386
  1955
        getline(is, line);
deba@2386
  1956
        std::istringstream ls(line);	
deba@2386
  1957
        std::string id;
deba@2386
  1958
        while (ls >> id) {
deba@2386
  1959
          typename MapReaders::iterator it = readers.find(id);
deba@2386
  1960
          if (it != readers.end()) {
deba@2386
  1961
            index.push_back(it->second);
deba@2386
  1962
            it->second->touch();
deba@2386
  1963
          } else {
deba@2386
  1964
            index.push_back(&skipper);
deba@2386
  1965
          }
deba@2386
  1966
          if (id == "label") {
deba@2386
  1967
            inverter.reset(index.back()->getInverter());
deba@2386
  1968
            index.back() = inverter.get();
deba@2386
  1969
          }
deba@2386
  1970
        }
deba@2386
  1971
        for (typename MapReaders::iterator it = readers.begin();
deba@2386
  1972
             it != readers.end(); ++it) {
deba@2386
  1973
          if (!it->second->touched()) {
deba@2386
  1974
            ErrorMessage msg;
deba@2386
  1975
            msg << "Map not found in file: " << it->first;
deba@2386
  1976
            throw IoParameterError(msg.message());
deba@2386
  1977
          }
deba@2386
  1978
        }
deba@1845
  1979
      }
deba@1421
  1980
      while (getline(is, line)) {	
deba@1421
  1981
	std::istringstream ls(line);
deba@1901
  1982
	Node from = nodeLabelReader->read(ls);
deba@1901
  1983
	Node to = nodeLabelReader->read(ls);
klao@1909
  1984
	UEdge edge = graph.addEdge(from, to);
deba@2386
  1985
	for (int i = 0; i < int(index.size()); ++i) {
deba@1421
  1986
	  index[i]->read(ls, edge);
deba@1421
  1987
	}
deba@1421
  1988
      }
deba@1421
  1989
    }
deba@1421
  1990
deba@2000
  1991
    virtual void missing() {
deba@2000
  1992
      if (readers.empty()) return;
deba@2000
  1993
      ErrorMessage msg;
deba@2001
  1994
      msg << "UEdgeSet section not found in file: @uedgeset " << name;
alpar@2153
  1995
      throw IoParameterError(msg.message());
deba@2000
  1996
    }
deba@2000
  1997
deba@1421
  1998
  public:
deba@1421
  1999
deba@1901
  2000
    /// \brief Returns true if the edgeset can give back the edge by its label.
deba@1421
  2001
    ///
deba@1421
  2002
    /// Returns true if the edgeset can give back the undirected edge by its 
deba@1901
  2003
    /// id. It is possible only if an "label" named map was read.
deba@1901
  2004
    bool isLabelReader() const {
deba@1421
  2005
      return inverter.get() != 0;
deba@1421
  2006
    }
deba@1421
  2007
deba@1901
  2008
    /// \brief Gives back the undirected edge by its label.
deba@1421
  2009
    ///
deba@1421
  2010
    /// It reads an id from the stream and gives back which undirected edge 
deba@1901
  2011
    /// belongs to it. It is possible only if there was read an "label" named map.
deba@2467
  2012
    void readLabel(std::istream& is, UEdge& uedge) const {
deba@2467
  2013
      uedge = inverter->read(is);
deba@1421
  2014
    } 
deba@1421
  2015
deba@1901
  2016
    /// \brief Gives back the directed edge by its label.
deba@1429
  2017
    ///
deba@1429
  2018
    /// It reads an id from the stream and gives back which directed edge 
deba@1429
  2019
    /// belongs to it. The directed edge id is the \c '+' or \c '-' character
deba@1429
  2020
    /// and the undirected edge id. It is possible only if there was read 
deba@1901
  2021
    /// an "label" named map.
deba@1901
  2022
    void readLabel(std::istream& is, Edge& edge) const {
deba@1429
  2023
      char c;
deba@1429
  2024
      is >> c;
deba@2467
  2025
      UEdge uedge = inverter->read(is);
deba@1429
  2026
      if (c == '+') {
deba@2467
  2027
	edge = graph.direct(uedge, true);
deba@1429
  2028
      } else if (c == '-') {
deba@2467
  2029
        edge = graph.direct(uedge, false);
deba@1429
  2030
      } else {
deba@1429
  2031
	throw DataFormatError("Wrong id format for edge "
deba@1429
  2032
			      "in undirected edgeset");
deba@1429
  2033
      }
deba@1429
  2034
    } 
deba@1429
  2035
deba@1421
  2036
  private:
deba@1421
  2037
deba@1845
  2038
    typedef std::map<std::string, 
klao@1909
  2039
		     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
deba@1421
  2040
    MapReaders readers;
deba@1421
  2041
   
deba@1705
  2042
    Graph& graph;   
deba@1901
  2043
    std::string name;
klao@1909
  2044
    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
deba@1408
  2045
klao@1909
  2046
    std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
deba@1901
  2047
    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
deba@1408
  2048
  };
deba@1408
  2049
deba@2016
  2050
  /// \ingroup section_io
deba@1409
  2051
  /// \brief SectionReader for reading labeled nodes.
deba@1409
  2052
  ///
deba@1901
  2053
  /// The nodes section's header line is \c \@nodes \c nodes_name, but the
deba@1901
  2054
  /// \c nodes_name may be empty.
deba@1409
  2055
  ///
deba@1409
  2056
  /// Each line in the section contains the name of the node 
deba@1409
  2057
  /// and then the node id. 
deba@1409
  2058
  ///
deba@1409
  2059
  /// \relates LemonReader
deba@1409
  2060
  template <typename _Graph>
deba@1845
  2061
  class NodeReader : public LemonReader::SectionReader {
deba@1845
  2062
    typedef LemonReader::SectionReader Parent;
deba@1409
  2063
    typedef _Graph Graph;
deba@1429
  2064
    typedef typename Graph::Node Node;
deba@1409
  2065
  public:
deba@1409
  2066
    
deba@1409
  2067
    /// \brief Constructor.
deba@1409
  2068
    ///
deba@1409
  2069
    /// Constructor for NodeReader. It creates the NodeReader and
deba@1409
  2070
    /// attach it into the given LemonReader. It will use the given
deba@1409
  2071
    /// node id reader to give back the nodes. The reader will read the 
deba@1901
  2072
    /// section only if the \c _name and the \c nodes_name are the same. 
deba@1901
  2073
    template <typename _LabelReader>
deba@1901
  2074
    NodeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
deba@1901
  2075
	       const std::string& _name = std::string()) 
deba@1901
  2076
      : Parent(_reader), name(_name) {
deba@1901
  2077
      checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
deba@1901
  2078
      nodeLabelReader.reset(new _reader_bits::
deba@1901
  2079
			 LabelReader<Node, _LabelReader>(_labelReader));
deba@1476
  2080
    }
deba@1408
  2081
deba@1409
  2082
    /// \brief Destructor.
deba@1409
  2083
    ///
deba@1409
  2084
    /// Destructor for NodeReader.
deba@1409
  2085
    virtual ~NodeReader() {}
deba@1409
  2086
deba@1409
  2087
  private:
deba@1409
  2088
    NodeReader(const NodeReader&);
deba@1409
  2089
    void operator=(const NodeReader&);
deba@1409
  2090
deba@1409
  2091
  public:
deba@1409
  2092
deba@1409
  2093
    /// \brief Add a node reader command for the NodeReader.
deba@1409
  2094
    ///
deba@1409
  2095
    /// Add a node reader command for the NodeReader.
deba@2386
  2096
    void readNode(std::string label, Node& item) {
deba@2386
  2097
      if (readers.find(label) != readers.end()) {
deba@1409
  2098
	ErrorMessage msg;
deba@2386
  2099
	msg << "Multiple read rule for node: " << label;
alpar@2153
  2100
	throw IoParameterError(msg.message());
deba@1409
  2101
      }
deba@2386
  2102
      readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
deba@1409
  2103
    }
deba@1409
  2104
deba@1409
  2105
  protected:
deba@1409
  2106
deba@1409
  2107
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  2108
    /// the section with the given header line.
deba@1409
  2109
    ///
deba@1421
  2110
    /// It gives back true when the header line start with \c \@nodes,
deba@1901
  2111
    /// and the header line's name and the reader's name are the same.
deba@1409
  2112
    virtual bool header(const std::string& line) {
deba@1409
  2113
      std::istringstream ls(line);
deba@1409
  2114
      std::string command;
deba@1901
  2115
      std::string id;
klao@1997
  2116
      ls >> command >> id;
deba@1409
  2117
      return command == "@nodes" && name == id;
deba@1409
  2118
    }
deba@1409
  2119
deba@1409
  2120
    /// \brief Reader function of the section.
deba@1409
  2121
    ///
deba@1409
  2122
    /// It reads the content of the section.
deba@1409
  2123
    virtual void read(std::istream& is) {
deba@1901
  2124
      if (!nodeLabelReader->isLabelReader()) {
deba@1901
  2125
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
  2126
      }
deba@1409
  2127
      std::string line;
deba@1409
  2128
      while (getline(is, line)) {
deba@1409
  2129
	std::istringstream ls(line);
deba@1409
  2130
	std::string id;
deba@1409
  2131
	ls >> id;
deba@1429
  2132
	typename NodeReaders::iterator it = readers.find(id);
deba@1409
  2133
	if (it != readers.end()) {
deba@1901
  2134
	  it->second.read(nodeLabelReader->read(ls));
deba@1845
  2135
	  it->second.touch();
deba@1409
  2136
	}	
deba@1409
  2137
      }
deba@1845
  2138
      for (typename NodeReaders::iterator it = readers.begin();
deba@1845
  2139
	   it != readers.end(); ++it) {
deba@1845
  2140
	if (!it->second.touched()) {
deba@1845
  2141
	  ErrorMessage msg;
deba@1845
  2142
	  msg << "Node not found in file: " << it->first;
alpar@2153
  2143
	  throw IoParameterError(msg.message());
deba@1845
  2144
	}
deba@1845
  2145
      }
deba@1409
  2146
    }
deba@2000
  2147
deba@2000
  2148
    virtual void missing() {
deba@2000
  2149
      if (readers.empty()) return;
deba@2000
  2150
      ErrorMessage msg;
deba@2001
  2151
      msg << "Nodes section not found in file: @nodes " << name;
alpar@2153
  2152
      throw IoParameterError(msg.message());
deba@2000
  2153
    }
deba@1409
  2154
    
deba@1409
  2155
  private:
deba@1409
  2156
deba@1901
  2157
    std::string name;
deba@1409
  2158
deba@1845
  2159
    typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
deba@1429
  2160
    NodeReaders readers;
deba@1901
  2161
    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
deba@1409
  2162
  };
deba@1409
  2163
deba@2016
  2164
  /// \ingroup section_io
deba@1409
  2165
  /// \brief SectionReader for reading labeled edges.
deba@1409
  2166
  ///
deba@1901
  2167
  /// The edges section's header line is \c \@edges \c edges_name, but the
deba@1901
  2168
  /// \c edges_name may be empty.
deba@1409
  2169
  ///
deba@1409
  2170
  /// Each line in the section contains the name of the edge 
deba@1409
  2171
  /// and then the edge id. 
deba@1409
  2172
  ///
deba@1409
  2173
  /// \relates LemonReader
deba@1409
  2174
  template <typename _Graph>
deba@1845
  2175
  class EdgeReader : public LemonReader::SectionReader {
deba@1845
  2176
    typedef LemonReader::SectionReader Parent;
deba@1409
  2177
    typedef _Graph Graph;
deba@1429
  2178
    typedef typename Graph::Edge Edge;
deba@1409
  2179
  public:
deba@1409
  2180
    
deba@1409
  2181
    /// \brief Constructor.
deba@1409
  2182
    ///
deba@1409
  2183
    /// Constructor for EdgeReader. It creates the EdgeReader and
deba@1409
  2184
    /// attach it into the given LemonReader. It will use the given
deba@1409
  2185
    /// edge id reader to give back the edges. The reader will read the 
deba@1901
  2186
    /// section only if the \c _name and the \c edges_name are the same. 
deba@1901
  2187
    template <typename _LabelReader>
deba@1901
  2188
    EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
deba@1901
  2189
	       const std::string& _name = std::string()) 
deba@1901
  2190
      : Parent(_reader), name(_name) {
deba@1901
  2191
      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
deba@1901
  2192
      edgeLabelReader.reset(new _reader_bits::
deba@1901
  2193
			 LabelReader<Edge, _LabelReader>(_labelReader));
deba@1476
  2194
    }
deba@1409
  2195
deba@1409
  2196
    /// \brief Destructor.
deba@1409
  2197
    ///
deba@1409
  2198
    /// Destructor for EdgeReader.
deba@1409
  2199
    virtual ~EdgeReader() {}
deba@1409
  2200
  private:
deba@1409
  2201
    EdgeReader(const EdgeReader&);
deba@1409
  2202
    void operator=(const EdgeReader&);
deba@1409
  2203
deba@1409
  2204
  public:
deba@1409
  2205
deba@1409
  2206
    /// \brief Add an edge reader command for the EdgeReader.
deba@1409
  2207
    ///
deba@1409
  2208
    /// Add an edge reader command for the EdgeReader.
deba@2386
  2209
    void readEdge(std::string label, Edge& item) {
deba@2386
  2210
      if (readers.find(label) != readers.end()) {
deba@1409
  2211
	ErrorMessage msg;
deba@2386
  2212
	msg << "Multiple read rule for edge: " << label;
alpar@2153
  2213
	throw IoParameterError(msg.message());
deba@1409
  2214
      }
deba@2386
  2215
      readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
deba@1409
  2216
    }
deba@1409
  2217
deba@1409
  2218
  protected:
deba@1409
  2219
deba@1409
  2220
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  2221
    /// the section with the given header line.
deba@1409
  2222
    ///
deba@1421
  2223
    /// It gives back true when the header line start with \c \@edges,
deba@1901
  2224
    /// and the header line's name and the reader's name are the same.
deba@1421
  2225
    virtual bool header(const std::string& line) {
deba@1421
  2226
      std::istringstream ls(line);
deba@1421
  2227
      std::string command;
deba@1901
  2228
      std::string id;
klao@1997
  2229
      ls >> command >> id;
deba@1421
  2230
      return command == "@edges" && name == id;
deba@1421
  2231
    }
deba@1421
  2232
deba@1421
  2233
    /// \brief Reader function of the section.
deba@1421
  2234
    ///
deba@1421
  2235
    /// It reads the content of the section.
deba@1421
  2236
    virtual void read(std::istream& is) {
deba@1901
  2237
      if (!edgeLabelReader->isLabelReader()) {
deba@1901
  2238
	throw DataFormatError("Cannot find edgeset or label map");
deba@1476
  2239
      }
deba@1421
  2240
      std::string line;
deba@1421
  2241
      while (getline(is, line)) {
deba@1421
  2242
	std::istringstream ls(line);
deba@1421
  2243
	std::string id;
deba@1421
  2244
	ls >> id;
deba@1429
  2245
	typename EdgeReaders::iterator it = readers.find(id);
deba@1421
  2246
	if (it != readers.end()) {
deba@1901
  2247
	  it->second.read(edgeLabelReader->read(ls));
deba@1845
  2248
	  it->second.touch();
deba@1421
  2249
	}	
deba@1421
  2250
      }
deba@1845
  2251
      for (typename EdgeReaders::iterator it = readers.begin();
deba@1845
  2252
	   it != readers.end(); ++it) {
deba@1845
  2253
	if (!it->second.touched()) {
deba@1845
  2254
	  ErrorMessage msg;
deba@1845
  2255
	  msg << "Edge not found in file: " << it->first;
alpar@2153
  2256
	  throw IoParameterError(msg.message());
deba@1845
  2257
	}
deba@1845
  2258
      }
deba@1421
  2259
    }
deba@2000
  2260
deba@2000
  2261
    virtual void missing() {
deba@2000
  2262
      if (readers.empty()) return;
deba@2000
  2263
      ErrorMessage msg;
deba@2001
  2264
      msg << "Edges section not found in file: @edges " << name;
alpar@2153
  2265
      throw IoParameterError(msg.message());
deba@2000
  2266
    }
deba@1421
  2267
    
deba@1421
  2268
  private:
deba@1421
  2269
deba@1901
  2270
    std::string name;
deba@1421
  2271
deba@1845
  2272
    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
deba@1429
  2273
    EdgeReaders readers;
deba@1901
  2274
    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
deba@1421
  2275
  };
deba@1421
  2276
deba@2016
  2277
  /// \ingroup section_io
deba@1421
  2278
  /// \brief SectionReader for reading labeled undirected edges.
deba@1421
  2279
  ///
klao@1909
  2280
  /// The undirected edges section's header line is \c \@uedges 
klao@1909
  2281
  /// \c uedges_name, but the \c uedges_name may be empty.
deba@1421
  2282
  ///
deba@1421
  2283
  /// Each line in the section contains the name of the undirected edge 
deba@1421
  2284
  /// and then the undirected edge id. 
deba@1421
  2285
  ///
deba@1421
  2286
  /// \relates LemonReader
deba@1421
  2287
  template <typename _Graph>
klao@1909
  2288
  class UEdgeReader : public LemonReader::SectionReader {
deba@1845
  2289
    typedef LemonReader::SectionReader Parent;
deba@1421
  2290
    typedef _Graph Graph;
deba@1429
  2291
    typedef typename Graph::Edge Edge;
klao@1909
  2292
    typedef typename Graph::UEdge UEdge;
deba@1421
  2293
  public:
deba@1421
  2294
    
deba@1421
  2295
    /// \brief Constructor.
deba@1421
  2296
    ///
klao@1909
  2297
    /// Constructor for UEdgeReader. It creates the UEdgeReader and
deba@1421
  2298
    /// attach it into the given LemonReader. It will use the given
deba@1421
  2299
    /// undirected edge id reader to give back the edges. The reader will 
klao@1909
  2300
    /// read the section only if the \c _name and the \c uedges_name are 
deba@1421
  2301
    /// the same. 
deba@1901
  2302
    template <typename _LabelReader>
klao@1909
  2303
    UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
deba@1901
  2304
	       const std::string& _name = std::string()) 
deba@1901
  2305
      : Parent(_reader), name(_name) {
klao@1909
  2306
      checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
deba@1901
  2307
      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
deba@2467
  2308
      uedgeLabelReader.reset(new _reader_bits::
deba@2467
  2309
			     LabelReader<UEdge, _LabelReader>(_labelReader));
deba@1901
  2310
      edgeLabelReader.reset(new _reader_bits::
deba@2467
  2311
			    LabelReader<Edge, _LabelReader>(_labelReader));
deba@1476
  2312
    }
deba@1421
  2313
deba@1421
  2314
    /// \brief Destructor.
deba@1421
  2315
    ///
klao@1909
  2316
    /// Destructor for UEdgeReader.
klao@1909
  2317
    virtual ~UEdgeReader() {}
deba@1421
  2318
  private:
klao@1909
  2319
    UEdgeReader(const UEdgeReader&);
klao@1909
  2320
    void operator=(const UEdgeReader&);
deba@1421
  2321
deba@1421
  2322
  public:
deba@1421
  2323
klao@1909
  2324
    /// \brief Add an undirected edge reader command for the UEdgeReader.
deba@1421
  2325
    ///
klao@1909
  2326
    /// Add an undirected edge reader command for the UEdgeReader.
deba@2386
  2327
    void readUEdge(std::string label, UEdge& item) {
deba@2467
  2328
      if (uedgeReaders.find(label) != uedgeReaders.end()) {
deba@1429
  2329
	ErrorMessage msg;
deba@2386
  2330
	msg << "Multiple read rule for undirected edge: " << label;
alpar@2153
  2331
	throw IoParameterError(msg.message());
deba@1429
  2332
      }
deba@2467
  2333
      uedgeReaders.insert(make_pair(label, _reader_bits::
klao@1909
  2334
					ItemStore<UEdge>(item)));
deba@1429
  2335
    }
deba@1429
  2336
klao@1909
  2337
    /// \brief Add an edge reader command for the UEdgeReader.
deba@1429
  2338
    ///
klao@1909
  2339
    /// Add an edge reader command for the UEdgeReader.
deba@2386
  2340
    void readEdge(std::string label, Edge& item) {
deba@2386
  2341
      if (edgeReaders.find(label) != edgeReaders.end()) {
deba@1421
  2342
	ErrorMessage msg;
deba@2386
  2343
	msg << "Multiple read rule for edge: " << label;
alpar@2153
  2344
	throw IoParameterError(msg.message());
deba@1421
  2345
      }
deba@2386
  2346
      edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
deba@1421
  2347
    }
deba@1421
  2348
deba@1421
  2349
  protected:
deba@1421
  2350
deba@1421
  2351
    /// \brief Gives back true when the SectionReader can process 
deba@1421
  2352
    /// the section with the given header line.
deba@1421
  2353
    ///
deba@1421
  2354
    /// It gives back true when the header line start with \c \@edges,
deba@1901
  2355
    /// and the header line's name and the reader's name are the same.
deba@1409
  2356
    virtual bool header(const std::string& line) {
deba@1409
  2357
      std::istringstream ls(line);
deba@1409
  2358
      std::string command;
deba@1901
  2359
      std::string id;
klao@1997
  2360
      ls >> command >> id;
klao@1909
  2361
      return command == "@uedges" && name == id;
deba@1409
  2362
    }
deba@1409
  2363
deba@1409
  2364
    /// \brief Reader function of the section.
deba@1409
  2365
    ///
deba@1409
  2366
    /// It reads the content of the section.
deba@1409
  2367
    virtual void read(std::istream& is) {
deba@1901
  2368
      if (!edgeLabelReader->isLabelReader()) {
deba@1901
  2369
	throw DataFormatError("Cannot find undirected edgeset or label map");
deba@1476
  2370
      }
deba@2467
  2371
      if (!uedgeLabelReader->isLabelReader()) {
deba@1901
  2372
	throw DataFormatError("Cannot find undirected edgeset or label map");
deba@1476
  2373
      }
deba@1409
  2374
      std::string line;
deba@1409
  2375
      while (getline(is, line)) {
deba@1409
  2376
	std::istringstream ls(line);
deba@1409
  2377
	std::string id;
deba@1409
  2378
	ls >> id;
deba@1429
  2379
	{
deba@2467
  2380
	  typename UEdgeReaders::iterator it = uedgeReaders.find(id);
deba@2467
  2381
	  if (it != uedgeReaders.end()) {
deba@2467
  2382
	    it->second.read(uedgeLabelReader->read(ls));
deba@1845
  2383
	    it->second.touch();
deba@1845
  2384
	    continue;
deba@1429
  2385
	  }	
deba@1429
  2386
	} {
deba@1429
  2387
	  typename EdgeReaders::iterator it = edgeReaders.find(id);
deba@1429
  2388
	  if (it != edgeReaders.end()) {
deba@1901
  2389
	    it->second.read(edgeLabelReader->read(ls));
deba@1845
  2390
	    it->second.touch();
deba@1845
  2391
	    continue;
deba@1429
  2392
	  }	
deba@1429
  2393
	}
deba@1409
  2394
      }
deba@1845
  2395
      for (typename EdgeReaders::iterator it = edgeReaders.begin();
deba@1845
  2396
	   it != edgeReaders.end(); ++it) {
deba@1845
  2397
	if (!it->second.touched()) {
deba@1845
  2398
	  ErrorMessage msg;
deba@1845
  2399
	  msg << "Edge not found in file: " << it->first;
alpar@2153
  2400
	  throw IoParameterError(msg.message());
deba@1845
  2401
	}
deba@1845
  2402
      }
deba@2467
  2403
      for (typename UEdgeReaders::iterator it = uedgeReaders.begin();
deba@2467
  2404
	   it != uedgeReaders.end(); ++it) {
deba@1845
  2405
	if (!it->second.touched()) {
deba@1845
  2406
	  ErrorMessage msg;
klao@1909
  2407
	  msg << "UEdge not found in file: " << it->first;
alpar@2153
  2408
	  throw IoParameterError(msg.message());
deba@1845
  2409
	}
deba@1845
  2410
      }
deba@1409
  2411
    }
deba@2000
  2412
deba@2000
  2413
    virtual void missing() {
deba@2467
  2414
      if (edgeReaders.empty() && uedgeReaders.empty()) return;
deba@2000
  2415
      ErrorMessage msg;
deba@2001
  2416
      msg << "UEdges section not found in file: @uedges " << name;
alpar@2153
  2417
      throw IoParameterError(msg.message());
deba@2000
  2418
    }
deba@1409
  2419
    
deba@1409
  2420
  private:
deba@1409
  2421
deba@1901
  2422
    std::string name;
deba@1409
  2423
deba@1845
  2424
    typedef std::map<std::string, 
klao@1909
  2425
		     _reader_bits::ItemStore<UEdge> > UEdgeReaders;
deba@2467
  2426
    UEdgeReaders uedgeReaders;
deba@2467
  2427
    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uedgeLabelReader;
deba@1429
  2428
deba@1845
  2429
    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
deba@1429
  2430
    EdgeReaders edgeReaders;
deba@1901
  2431
    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
deba@1409
  2432
  };
deba@1409
  2433
deba@2016
  2434
  /// \ingroup section_io
deba@1409
  2435
  /// \brief SectionReader for attributes.
deba@1409
  2436
  ///
deba@1409
  2437
  /// The lemon format can store multiple attribute set. Each set has
deba@1901
  2438
  /// the header line \c \@attributes \c attributeset_name, but the 
deba@1901
  2439
  /// attributeset_name may be empty.
deba@1409
  2440
  ///
deba@1409
  2441
  /// The attributeset section contains several lines. Each of them starts
deba@1409
  2442
  /// with an attribute and then a the value for the id.
deba@1409
  2443
  ///
deba@1409
  2444
  /// \relates LemonReader
deba@1408
  2445
  template <typename _Traits = DefaultReaderTraits>
deba@1845
  2446
  class AttributeReader : public LemonReader::SectionReader {
deba@1845
  2447
    typedef LemonReader::SectionReader Parent;
deba@1408
  2448
    typedef _Traits Traits; 
deba@1408
  2449
  public:
deba@1409
  2450
    /// \brief Constructor.
deba@1409
  2451
    ///
deba@1409
  2452
    /// Constructor for AttributeReader. It creates the AttributeReader and
deba@1409
  2453
    /// attach it into the given LemonReader. The reader process a section
deba@1901
  2454
    /// only if the \c section_name and the \c _name are the same.
deba@1408
  2455
    AttributeReader(LemonReader& _reader, 
deba@1901
  2456
		    const std::string& _name = std::string()) 
deba@1901
  2457
      : Parent(_reader), name(_name) {}
deba@1408
  2458
deba@1409
  2459
    /// \brief Destructor.
deba@1409
  2460
    ///
deba@1409
  2461
    /// Destructor for AttributeReader.
deba@1408
  2462
    virtual ~AttributeReader() {
deba@1408
  2463
      for (typename Readers::iterator it = readers.begin(); 
deba@1408
  2464
	   it != readers.end(); ++it) {
deba@1408
  2465
	delete it->second;
deba@1408
  2466
      }
deba@1408
  2467
    }
deba@1408
  2468
deba@1408
  2469
  private:
deba@1408
  2470
    AttributeReader(const AttributeReader&);
deba@1408
  2471
    void operator=(AttributeReader&);
deba@1408
  2472
deba@1408
  2473
  public:
deba@1409
  2474
    /// \brief Add an attribute reader command for the reader.
deba@1409
  2475
    ///
deba@1409
  2476
    /// Add an attribute reader command for the reader.
deba@1408
  2477
    template <typename Value>
deba@2416
  2478
    AttributeReader& readAttribute(const std::string& label, Value& value) {
deba@1408
  2479
      return readAttribute<typename Traits::template Reader<Value> >
deba@2416
  2480
	(label, value);
deba@1408
  2481
    }
deba@1408
  2482
deba@1409
  2483
    /// \brief Add an attribute reader command for the reader.
deba@1409
  2484
    ///
deba@1409
  2485
    /// Add an attribute reader command for the reader.
deba@2386
  2486
    template <typename ItemReader, typename Value>
deba@2416
  2487
    AttributeReader& readAttribute(const std::string& label, Value& value,
deba@2386
  2488
				   const ItemReader& ir = ItemReader()) {
deba@2386
  2489
      checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
deba@2386
  2490
      if (readers.find(label) != readers.end()) {
deba@1408
  2491
	ErrorMessage msg;
deba@2386
  2492
	msg << "Multiple read rule for attribute: " << label;
alpar@2153
  2493
	throw IoParameterError(msg.message());
deba@1408
  2494
      }
deba@2386
  2495
      readers.insert(make_pair(label, new _reader_bits::
deba@2386
  2496
			       ValueReader<Value, ItemReader>(value, ir)));
deba@1408
  2497
      return *this;
deba@1408
  2498
    }
deba@1408
  2499
deba@1409
  2500
  protected:
deba@1409
  2501
deba@1409
  2502
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  2503
    /// the section with the given header line.
deba@1409
  2504
    ///
deba@1421
  2505
    /// It gives back true when the header line start with \c \@attributes,
deba@1409
  2506
    /// and the header line's id and the attributeset's id are the same.
deba@1408
  2507
    bool header(const std::string& line) {
deba@1408
  2508
      std::istringstream ls(line);
deba@1408
  2509
      std::string command;
deba@1901
  2510
      std::string id;
klao@1997
  2511
      ls >> command >> id;
deba@1408
  2512
      return command == "@attributes" && name == id;
deba@1408
  2513
    }
deba@1408
  2514
deba@1409
  2515
    /// \brief Reader function of the section.
deba@1409
  2516
    ///
deba@1409
  2517
    /// It reads the content of the section.
deba@1408
  2518
    void read(std::istream& is) {
deba@1408
  2519
      std::string line;
deba@1408
  2520
      while (getline(is, line)) {
deba@1408
  2521
	std::istringstream ls(line);
deba@1408
  2522
	std::string id;
deba@1408
  2523
	ls >> id;
deba@1408
  2524
	typename Readers::iterator it = readers.find(id);
deba@1408
  2525
	if (it != readers.end()) {
deba@1408
  2526
	  it->second->read(ls);
deba@1901
  2527
 	  it->second->touch();
deba@1408
  2528
	}
deba@1408
  2529
      }
deba@1846
  2530
      for (typename Readers::iterator it = readers.begin();
deba@1846
  2531
	   it != readers.end(); ++it) {
deba@1846
  2532
	if (!it->second->touched()) {
deba@1846
  2533
	  ErrorMessage msg;
deba@1846
  2534
	  msg << "Attribute not found in file: " << it->first;
alpar@2153
  2535
	  throw IoParameterError(msg.message());
deba@1846
  2536
	}	
deba@1846
  2537
      }
deba@1408
  2538
    }    
deba@2416
  2539
    
deba@2000
  2540
    virtual void missing() {
deba@2000
  2541
      if (readers.empty()) return;
deba@2000
  2542
      ErrorMessage msg;
deba@2001
  2543
      msg << "Attribute section not found in file: @attributes " << name;
alpar@2153
  2544
      throw IoParameterError(msg.message());
deba@2000
  2545
    }
deba@2000
  2546
deba@1408
  2547
  private:
deba@1901
  2548
    std::string name;
deba@1408
  2549
deba@1845
  2550
    typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
deba@1409
  2551
    Readers readers;  
deba@1408
  2552
  };
deba@1408
  2553
deba@2016
  2554
  /// \ingroup section_io
deba@2467
  2555
  /// \brief SectionReader for reading extra node maps.
deba@2467
  2556
  ///
deba@2467
  2557
  /// The lemon format can store maps in the nodeset sections. This
deba@2467
  2558
  /// class let you make distinict section to store maps.  The main
deba@2467
  2559
  /// purpose of this class is a logical separation of some maps. The
deba@2467
  2560
  /// other useful application could be to store paths in node maps.
deba@2467
  2561
  ///
deba@2467
  2562
  /// The first line of the section contains the names of the maps
deba@2467
  2563
  /// separated with white spaces. Each next line describes an item
deba@2467
  2564
  /// in the itemset, and contains in the first column the label of
deba@2467
  2565
  /// the item and then the mapped values for each map.
deba@2467
  2566
  ///
deba@2467
  2567
  /// \relates LemonReader
deba@2467
  2568
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@2467
  2569
  class NodeMapReader : public LemonReader::SectionReader {
deba@2467
  2570
    typedef LemonReader::SectionReader Parent;
deba@2467
  2571
  public:
deba@2467
  2572
deba@2467
  2573
    typedef _Graph Graph;
deba@2467
  2574
    typedef typename Graph::Node Node;
deba@2467
  2575
    typedef _Traits Traits;
deba@2467
  2576
    typedef typename Traits::Skipper DefaultSkipper;
deba@2467
  2577
deba@2467
  2578
    /// \brief Constructor.
deba@2467
  2579
    ///
deba@2467
  2580
    /// Constructor for NodeMapReader. It creates the NodeMapReader and
deba@2467
  2581
    /// attach it into the given LemonReader. The reader will read
deba@2467
  2582
    /// the section when the \c section_name and the \c _name are the same.
deba@2467
  2583
    template <typename _LabelReader>
deba@2467
  2584
    NodeMapReader(LemonReader& _reader, 
deba@2467
  2585
		  const Graph& _graph, 
deba@2467
  2586
		  const _LabelReader& _labelReader,
deba@2467
  2587
		  const std::string& _name = std::string(),
deba@2467
  2588
		  const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@2467
  2589
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
deba@2467
  2590
      labelReader.reset(new _reader_bits::
deba@2467
  2591
			LabelReader<Node, _LabelReader>(_labelReader));
deba@2467
  2592
    } 
deba@2467
  2593
deba@2467
  2594
deba@2467
  2595
    /// \brief Destructor.
deba@2467
  2596
    ///
deba@2467
  2597
    /// Destructor for NodeMapReader.
deba@2467
  2598
    virtual ~NodeMapReader() {
deba@2467
  2599
      for (typename MapReaders::iterator it = readers.begin(); 
deba@2467
  2600
	   it != readers.end(); ++it) {
deba@2467
  2601
	delete it->second;
deba@2467
  2602
      }
deba@2467
  2603
    }
deba@2467
  2604
deba@2467
  2605
  private:
deba@2467
  2606
    NodeMapReader(const NodeMapReader&);
deba@2467
  2607
    void operator=(const NodeMapReader&);
deba@2467
  2608
  
deba@2467
  2609
  public:
deba@2467
  2610
deba@2467
  2611
    /// \brief Add a new node map reader command for the reader.
deba@2467
  2612
    ///
deba@2467
  2613
    /// Add a new node map reader command for the reader.
deba@2467
  2614
    template <typename Map>
deba@2467
  2615
    NodeMapReader& readNodeMap(std::string label, Map& map) {
deba@2467
  2616
      return _readMap<
deba@2467
  2617
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  2618
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  2619
    }
deba@2467
  2620
deba@2467
  2621
    template <typename Map>
deba@2467
  2622
    NodeMapReader& readNodeMap(std::string label, const Map& map) {
deba@2467
  2623
      return _readMap<
deba@2467
  2624
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  2625
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  2626
    }
deba@2467
  2627
deba@2467
  2628
    /// \brief Add a new node map reader command for the reader.
deba@2467
  2629
    ///
deba@2467
  2630
    /// Add a new node map reader command for the reader.
deba@2467
  2631
    template <typename ItemReader, typename Map>
deba@2467
  2632
    NodeMapReader& readNodeMap(std::string label, Map& map, 
deba@2467
  2633
			       const ItemReader& ir = ItemReader()) {
deba@2467
  2634
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2467
  2635
	(label, map, ir);
deba@2467
  2636
    }
deba@2467
  2637
deba@2467
  2638
    template <typename ItemReader, typename Map>
deba@2467
  2639
    NodeMapReader& readNodeMap(std::string label, const Map& map, 
deba@2467
  2640
			       const ItemReader& ir = ItemReader()) {
deba@2467
  2641
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2467
  2642
	(label, map, ir);
deba@2467
  2643
    }
deba@2467
  2644
deba@2467
  2645
  private:
deba@2467
  2646
deba@2467
  2647
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2467
  2648
    NodeMapReader& _readMap(std::string label, MapParameter map, 
deba@2467
  2649
			   const ItemReader& ir = ItemReader()) {
deba@2467
  2650
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@2467
  2651
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2467
  2652
      if (readers.find(label) != readers.end()) {
deba@2467
  2653
	ErrorMessage msg;
deba@2467
  2654
	msg << "Multiple read rule for map: " << label;
deba@2467
  2655
	throw IoParameterError(msg.message());
deba@2467
  2656
      }      
deba@2467
  2657
      readers.insert(
deba@2467
  2658
	make_pair(label, new _reader_bits::
deba@2467
  2659
		  MapReader<Node, Map, ItemReader>(map, ir)));
deba@2467
  2660
      return *this;
deba@2467
  2661
    }
deba@2467
  2662
deba@2467
  2663
  public:
deba@2467
  2664
deba@2467
  2665
    /// \brief Add a new node map skipper command for the reader.
deba@2467
  2666
    ///
deba@2467
  2667
    /// Add a new node map skipper command for the reader.
deba@2467
  2668
    template <typename ItemReader>
deba@2467
  2669
    NodeMapReader& skipNodeMap(std::string label, 
deba@2467
  2670
			       const ItemReader& ir = ItemReader()) {
deba@2467
  2671
      if (readers.find(label) != readers.end()) {
deba@2467
  2672
	ErrorMessage msg;
deba@2467
  2673
	msg << "Multiple read rule for map: " << label;
deba@2467
  2674
	throw IoParameterError(msg.message());
deba@2467
  2675
      }
deba@2467
  2676
      readers.insert(make_pair(label, new _reader_bits::
deba@2467
  2677
			       SkipReader<Node, ItemReader>(ir)));
deba@2467
  2678
      return *this;
deba@2467
  2679
    }
deba@2467
  2680
deba@2467
  2681
  protected:
deba@2467
  2682
deba@2467
  2683
    /// \brief Gives back true when the SectionReader can process 
deba@2467
  2684
    /// the section with the given header line.
deba@2467
  2685
    ///
deba@2467
  2686
    /// It gives back true when the header line starts with \c \@mapset,
deba@2467
  2687
    /// and the header line's name and the mapset's name are the same.
deba@2467
  2688
    virtual bool header(const std::string& line) {
deba@2467
  2689
      std::istringstream ls(line);
deba@2467
  2690
      std::string command;
deba@2467
  2691
      std::string id;
deba@2467
  2692
      ls >> command >> id;
deba@2467
  2693
      return command == "@nodemaps" && name == id;
deba@2467
  2694
    }
deba@2467
  2695
deba@2467
  2696
    /// \brief Reader function of the section.
deba@2467
  2697
    ///
deba@2467
  2698
    /// It reads the content of the section.
deba@2467
  2699
    virtual void read(std::istream& is) {
deba@2467
  2700
      std::vector<_reader_bits::MapReaderBase<Node>* > index;
deba@2467
  2701
      std::string line;
deba@2467
  2702
deba@2467
  2703
      {
deba@2467
  2704
        getline(is, line);
deba@2467
  2705
        std::istringstream ls(line);
deba@2467
  2706
        std::string id;
deba@2467
  2707
        while (ls >> id) {
deba@2467
  2708
          typename MapReaders::iterator it = readers.find(id);
deba@2467
  2709
          if (it != readers.end()) {
deba@2467
  2710
            it->second->touch();
deba@2467
  2711
            index.push_back(it->second);
deba@2467
  2712
          } else {
deba@2467
  2713
            index.push_back(&skipper);
deba@2467
  2714
          }
deba@2467
  2715
        }
deba@2467
  2716
      }
deba@2467
  2717
      for (typename MapReaders::iterator it = readers.begin();
deba@2467
  2718
	   it != readers.end(); ++it) {
deba@2467
  2719
	if (!it->second->touched()) {
deba@2467
  2720
	  ErrorMessage msg;
deba@2467
  2721
	  msg << "Map not found in file: " << it->first;
deba@2467
  2722
	  throw IoParameterError(msg.message());
deba@2467
  2723
	}
deba@2467
  2724
      }
deba@2467
  2725
      while (getline(is, line)) {	
deba@2467
  2726
	std::istringstream ls(line);
deba@2467
  2727
	Node node = labelReader->read(ls);
deba@2467
  2728
	for (int i = 0; i < int(index.size()); ++i) {
deba@2467
  2729
	  index[i]->read(ls, node);
deba@2467
  2730
	}
deba@2467
  2731
      }
deba@2467
  2732
    }
deba@2467
  2733
deba@2467
  2734
    virtual void missing() {
deba@2467
  2735
      if (readers.empty()) return;
deba@2467
  2736
      ErrorMessage msg;
deba@2467
  2737
      msg << "NodeMap section not found in file: @nodemaps " << name;
deba@2467
  2738
      throw IoParameterError(msg.message());
deba@2467
  2739
    }
deba@2467
  2740
deba@2467
  2741
  private:
deba@2467
  2742
deba@2467
  2743
    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
deba@2467
  2744
    MapReaders readers;
deba@2467
  2745
   
deba@2467
  2746
    const Graph& graph;   
deba@2467
  2747
    std::string name;
deba@2467
  2748
    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
deba@2467
  2749
    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > labelReader;
deba@2467
  2750
deba@2467
  2751
  };
deba@2467
  2752
deba@2467
  2753
  /// \ingroup section_io
deba@2467
  2754
  /// \brief SectionReader for reading extra edge maps.
deba@2467
  2755
  ///
deba@2467
  2756
  /// The lemon format can store maps in the edgeset sections. This
deba@2467
  2757
  /// class let you make distinict section to store maps.  The main
deba@2467
  2758
  /// purpose of this class is a logical separation of some maps. The
deba@2467
  2759
  /// other useful application could be to store paths in edge maps.
deba@2467
  2760
  ///
deba@2467
  2761
  /// The first line of the section contains the names of the maps
deba@2467
  2762
  /// separated with white spaces. Each next line describes an item
deba@2467
  2763
  /// in the itemset, and contains in the first column the label of
deba@2467
  2764
  /// the item and then the mapped values for each map.
deba@2467
  2765
  ///
deba@2467
  2766
  /// \relates LemonReader
deba@2467
  2767
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@2467
  2768
  class EdgeMapReader : public LemonReader::SectionReader {
deba@2467
  2769
    typedef LemonReader::SectionReader Parent;
deba@2467
  2770
  public:
deba@2467
  2771
deba@2467
  2772
    typedef _Graph Graph;
deba@2467
  2773
    typedef typename Graph::Edge Edge;
deba@2467
  2774
    typedef _Traits Traits;
deba@2467
  2775
    typedef typename Traits::Skipper DefaultSkipper;
deba@2467
  2776
deba@2467
  2777
    /// \brief Constructor.
deba@2467
  2778
    ///
deba@2467
  2779
    /// Constructor for EdgeMapReader. It creates the EdgeMapReader and
deba@2467
  2780
    /// attach it into the given LemonReader. The reader will read
deba@2467
  2781
    /// the section when the \c section_name and the \c _name are the same.
deba@2467
  2782
    template <typename _LabelReader>
deba@2467
  2783
    EdgeMapReader(LemonReader& _reader, 
deba@2467
  2784
		   const Graph& _graph, 
deba@2467
  2785
		   const _LabelReader& _labelReader,
deba@2467
  2786
		   const std::string& _name = std::string(),
deba@2467
  2787
		   const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@2467
  2788
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
deba@2467
  2789
      labelReader.reset(new _reader_bits::
deba@2467
  2790
			LabelReader<Edge, _LabelReader>(_labelReader));
deba@2467
  2791
    } 
deba@2467
  2792
deba@2467
  2793
deba@2467
  2794
    /// \brief Destructor.
deba@2467
  2795
    ///
deba@2467
  2796
    /// Destructor for EdgeMapReader.
deba@2467
  2797
    virtual ~EdgeMapReader() {
deba@2467
  2798
      for (typename MapReaders::iterator it = readers.begin(); 
deba@2467
  2799
	   it != readers.end(); ++it) {
deba@2467
  2800
	delete it->second;
deba@2467
  2801
      }
deba@2467
  2802
    }
deba@2467
  2803
deba@2467
  2804
  private:
deba@2467
  2805
    EdgeMapReader(const EdgeMapReader&);
deba@2467
  2806
    void operator=(const EdgeMapReader&);
deba@2467
  2807
  
deba@2467
  2808
  public:
deba@2467
  2809
deba@2467
  2810
    /// \brief Add a new edge map reader command for the reader.
deba@2467
  2811
    ///
deba@2467
  2812
    /// Add a new edge map reader command for the reader.
deba@2467
  2813
    template <typename Map>
deba@2467
  2814
    EdgeMapReader& readEdgeMap(std::string label, Map& map) {
deba@2467
  2815
      return _readMap<
deba@2467
  2816
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  2817
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  2818
    }
deba@2467
  2819
deba@2467
  2820
    template <typename Map>
deba@2467
  2821
    EdgeMapReader& readEdgeMap(std::string label, const Map& map) {
deba@2467
  2822
      return _readMap<
deba@2467
  2823
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  2824
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  2825
    }
deba@2467
  2826
deba@2467
  2827
    /// \brief Add a new edge map reader command for the reader.
deba@2467
  2828
    ///
deba@2467
  2829
    /// Add a new edge map reader command for the reader.
deba@2467
  2830
    template <typename ItemReader, typename Map>
deba@2467
  2831
    EdgeMapReader& readEdgeMap(std::string label, Map& map, 
deba@2467
  2832
			  const ItemReader& ir = ItemReader()) {
deba@2467
  2833
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2467
  2834
	(label, map, ir);
deba@2467
  2835
    }
deba@2467
  2836
deba@2467
  2837
    template <typename ItemReader, typename Map>
deba@2467
  2838
    EdgeMapReader& readEdgeMap(std::string label, const Map& map, 
deba@2467
  2839
			  const ItemReader& ir = ItemReader()) {
deba@2467
  2840
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2467
  2841
	(label, map, ir);
deba@2467
  2842
    }
deba@2467
  2843
deba@2467
  2844
  private:
deba@2467
  2845
deba@2467
  2846
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2467
  2847
    EdgeMapReader& _readMap(std::string label, MapParameter map, 
deba@2467
  2848
				const ItemReader& ir = ItemReader()) {
deba@2467
  2849
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
deba@2467
  2850
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2467
  2851
      if (readers.find(label) != readers.end()) {
deba@2467
  2852
	ErrorMessage msg;
deba@2467
  2853
	msg << "Multiple read rule for map: " << label;
deba@2467
  2854
	throw IoParameterError(msg.message());
deba@2467
  2855
      }      
deba@2467
  2856
      readers.insert(
deba@2467
  2857
	make_pair(label, new _reader_bits::
deba@2467
  2858
		  MapReader<Edge, Map, ItemReader>(map, ir)));
deba@2467
  2859
      return *this;
deba@2467
  2860
    }
deba@2467
  2861
deba@2467
  2862
  public:
deba@2467
  2863
deba@2467
  2864
    /// \brief Add a new edge map skipper command for the reader.
deba@2467
  2865
    ///
deba@2467
  2866
    /// Add a new edge map skipper command for the reader.
deba@2467
  2867
    template <typename ItemReader>
deba@2467
  2868
    EdgeMapReader& skipEdgeMap(std::string label, 
deba@2467
  2869
			  const ItemReader& ir = ItemReader()) {
deba@2467
  2870
      if (readers.find(label) != readers.end()) {
deba@2467
  2871
	ErrorMessage msg;
deba@2467
  2872
	msg << "Multiple read rule for map: " << label;
deba@2467
  2873
	throw IoParameterError(msg.message());
deba@2467
  2874
      }
deba@2467
  2875
      readers.insert(make_pair(label, new _reader_bits::
deba@2467
  2876
			       SkipReader<Edge, ItemReader>(ir)));
deba@2467
  2877
      return *this;
deba@2467
  2878
    }
deba@2467
  2879
deba@2467
  2880
  protected:
deba@2467
  2881
deba@2467
  2882
    /// \brief Gives back true when the SectionReader can process 
deba@2467
  2883
    /// the section with the given header line.
deba@2467
  2884
    ///
deba@2467
  2885
    /// It gives back true when the header line starts with \c \@mapset,
deba@2467
  2886
    /// and the header line's name and the mapset's name are the same.
deba@2467
  2887
    virtual bool header(const std::string& line) {
deba@2467
  2888
      std::istringstream ls(line);
deba@2467
  2889
      std::string command;
deba@2467
  2890
      std::string id;
deba@2467
  2891
      ls >> command >> id;
deba@2467
  2892
      return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
deba@2467
  2893
    }
deba@2467
  2894
deba@2467
  2895
    /// \brief Reader function of the section.
deba@2467
  2896
    ///
deba@2467
  2897
    /// It reads the content of the section.
deba@2467
  2898
    virtual void read(std::istream& is) {
deba@2467
  2899
      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
deba@2467
  2900
      std::string line;
deba@2467
  2901
deba@2467
  2902
      {
deba@2467
  2903
        getline(is, line);
deba@2467
  2904
        std::istringstream ls(line);
deba@2467
  2905
        std::string id;
deba@2467
  2906
        while (ls >> id) {
deba@2467
  2907
          typename MapReaders::iterator it = readers.find(id);
deba@2467
  2908
          if (it != readers.end()) {
deba@2467
  2909
            it->second->touch();
deba@2467
  2910
            index.push_back(it->second);
deba@2467
  2911
          } else {
deba@2467
  2912
            index.push_back(&skipper);
deba@2467
  2913
          }
deba@2467
  2914
        }
deba@2467
  2915
      }
deba@2467
  2916
      for (typename MapReaders::iterator it = readers.begin();
deba@2467
  2917
	   it != readers.end(); ++it) {
deba@2467
  2918
	if (!it->second->touched()) {
deba@2467
  2919
	  ErrorMessage msg;
deba@2467
  2920
	  msg << "Map not found in file: " << it->first;
deba@2467
  2921
	  throw IoParameterError(msg.message());
deba@2467
  2922
	}
deba@2467
  2923
      }
deba@2467
  2924
      while (getline(is, line)) {	
deba@2467
  2925
	std::istringstream ls(line);
deba@2467
  2926
	Edge edge = labelReader->read(ls);
deba@2467
  2927
	for (int i = 0; i < int(index.size()); ++i) {
deba@2467
  2928
	  index[i]->read(ls, edge);
deba@2467
  2929
	}
deba@2467
  2930
      }
deba@2467
  2931
    }
deba@2467
  2932
deba@2467
  2933
    virtual void missing() {
deba@2467
  2934
      if (readers.empty()) return;
deba@2467
  2935
      ErrorMessage msg;
deba@2467
  2936
      msg << "EdgeMap section not found in file: @edgemaps " << name;
deba@2467
  2937
      throw IoParameterError(msg.message());
deba@2467
  2938
    }
deba@2467
  2939
deba@2467
  2940
  private:
deba@2467
  2941
deba@2467
  2942
    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
deba@2467
  2943
    MapReaders readers;
deba@2467
  2944
   
deba@2467
  2945
    const Graph& graph;   
deba@2467
  2946
    std::string name;
deba@2467
  2947
    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
deba@2467
  2948
    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > labelReader;
deba@2467
  2949
deba@2467
  2950
  };
deba@2467
  2951
deba@2467
  2952
  /// \ingroup section_io
deba@2467
  2953
  /// \brief SectionReader for reading extra undirected edge maps.
deba@2467
  2954
  ///
deba@2467
  2955
  /// The lemon format can store maps in the uedgeset sections. This
deba@2467
  2956
  /// class let you make distinict section to store maps.  The main
deba@2467
  2957
  /// purpose of this class is a logical separation of some maps. The
deba@2467
  2958
  /// other useful application could be to store paths in undirected
deba@2467
  2959
  /// edge maps.
deba@2467
  2960
  ///
deba@2467
  2961
  /// The first line of the section contains the names of the maps
deba@2467
  2962
  /// separated with white spaces. Each next line describes an item
deba@2467
  2963
  /// in the itemset, and contains in the first column the label of
deba@2467
  2964
  /// the item and then the mapped values for each map.
deba@2467
  2965
  ///
deba@2467
  2966
  /// \relates LemonReader
deba@2467
  2967
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@2467
  2968
  class UEdgeMapReader : public LemonReader::SectionReader {
deba@2467
  2969
    typedef LemonReader::SectionReader Parent;
deba@2467
  2970
  public:
deba@2467
  2971
deba@2467
  2972
    typedef _Graph Graph;
deba@2467
  2973
    typedef typename Graph::Edge Edge;
deba@2467
  2974
    typedef typename Graph::UEdge UEdge;
deba@2467
  2975
    typedef _Traits Traits;
deba@2467
  2976
    typedef typename Traits::Skipper DefaultSkipper;
deba@2467
  2977
deba@2467
  2978
    /// \brief Constructor.
deba@2467
  2979
    ///
deba@2467
  2980
    /// Constructor for UEdgeMapReader. It creates the UEdgeMapReader and
deba@2467
  2981
    /// attach it into the given LemonReader. The reader will read
deba@2467
  2982
    /// the section when the \c section_name and the \c _name are the same.
deba@2467
  2983
    template <typename _LabelReader>
deba@2467
  2984
    UEdgeMapReader(LemonReader& _reader, const Graph& _graph, 
deba@2467
  2985
		   const _LabelReader& _labelReader,
deba@2467
  2986
		   const std::string& _name = std::string(),
deba@2467
  2987
		   const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@2467
  2988
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
deba@2467
  2989
      labelReader.reset(new _reader_bits::
deba@2467
  2990
			LabelReader<UEdge, _LabelReader>(_labelReader));
deba@2467
  2991
    } 
deba@2467
  2992
deba@2467
  2993
deba@2467
  2994
    /// \brief Destructor.
deba@2467
  2995
    ///
deba@2467
  2996
    /// Destructor for UEdgeMapReader.
deba@2467
  2997
    virtual ~UEdgeMapReader() {
deba@2467
  2998
      for (typename MapReaders::iterator it = readers.begin(); 
deba@2467
  2999
	   it != readers.end(); ++it) {
deba@2467
  3000
	delete it->second;
deba@2467
  3001
      }
deba@2467
  3002
    }
deba@2467
  3003
deba@2467
  3004
  private:
deba@2467
  3005
    UEdgeMapReader(const UEdgeMapReader&);
deba@2467
  3006
    void operator=(const UEdgeMapReader&);
deba@2467
  3007
  
deba@2467
  3008
  public:
deba@2467
  3009
deba@2467
  3010
    /// \brief Add a new undirected edge map reader command for the
deba@2467
  3011
    /// reader.
deba@2467
  3012
    ///
deba@2467
  3013
    /// Add a new undirected edge map reader command for the reader.
deba@2467
  3014
    template <typename Map>
deba@2467
  3015
    UEdgeMapReader& readUEdgeMap(std::string label, Map& map) {
deba@2467
  3016
      return _readMap<
deba@2467
  3017
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  3018
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  3019
    }
deba@2467
  3020
deba@2467
  3021
    template <typename Map>
deba@2467
  3022
    UEdgeMapReader& readUEdgeMap(std::string label, const Map& map) {
deba@2467
  3023
      return _readMap<
deba@2467
  3024
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  3025
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  3026
    }
deba@2467
  3027
deba@2467
  3028
    /// \brief Add a new undirected edge map reader command for the
deba@2467
  3029
    /// reader.
deba@2467
  3030
    ///
deba@2467
  3031
    /// Add a new undirected edge map reader command for the reader.
deba@2467
  3032
    template <typename ItemReader, typename Map>
deba@2467
  3033
    UEdgeMapReader& readUEdgeMap(std::string label, Map& map, 
deba@2467
  3034
			  const ItemReader& ir = ItemReader()) {
deba@2467
  3035
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2467
  3036
	(label, map, ir);
deba@2467
  3037
    }
deba@2467
  3038
deba@2467
  3039
    template <typename ItemReader, typename Map>
deba@2467
  3040
    UEdgeMapReader& readUEdgeMap(std::string label, const Map& map, 
deba@2467
  3041
			  const ItemReader& ir = ItemReader()) {
deba@2467
  3042
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2467
  3043
	(label, map, ir);
deba@2467
  3044
    }
deba@2467
  3045
deba@2467
  3046
  private:
deba@2467
  3047
deba@2467
  3048
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2467
  3049
    UEdgeMapReader& _readMap(std::string label, MapParameter map, 
deba@2467
  3050
				const ItemReader& ir = ItemReader()) {
deba@2467
  3051
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
deba@2467
  3052
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2467
  3053
      if (readers.find(label) != readers.end()) {
deba@2467
  3054
	ErrorMessage msg;
deba@2467
  3055
	msg << "Multiple read rule for map: " << label;
deba@2467
  3056
	throw IoParameterError(msg.message());
deba@2467
  3057
      }      
deba@2467
  3058
      readers.insert(
deba@2467
  3059
	make_pair(label, new _reader_bits::
deba@2467
  3060
		  MapReader<UEdge, Map, ItemReader>(map, ir)));
deba@2467
  3061
      return *this;
deba@2467
  3062
    }
deba@2467
  3063
deba@2467
  3064
  public:
deba@2467
  3065
deba@2467
  3066
    /// \brief Add a new undirected edge map skipper command for the
deba@2467
  3067
    /// reader.
deba@2467
  3068
    ///
deba@2467
  3069
    /// Add a new undirected edge map skipper command for the reader.
deba@2467
  3070
    template <typename ItemReader>
deba@2467
  3071
    UEdgeMapReader& skipUEdgeMap(std::string label, 
deba@2467
  3072
			  const ItemReader& ir = ItemReader()) {
deba@2467
  3073
      if (readers.find(label) != readers.end()) {
deba@2467
  3074
	ErrorMessage msg;
deba@2467
  3075
	msg << "Multiple read rule for map: " << label;
deba@2467
  3076
	throw IoParameterError(msg.message());
deba@2467
  3077
      }
deba@2467
  3078
      readers.insert(make_pair(label, new _reader_bits::
deba@2467
  3079
			       SkipReader<Edge, ItemReader>(ir)));
deba@2467
  3080
      return *this;
deba@2467
  3081
    }
deba@2467
  3082
deba@2467
  3083
    /// \brief Add a new directed edge map reader command for the reader.
deba@2467
  3084
    ///
deba@2467
  3085
    /// Add a new directed edge map reader command for the reader.
deba@2467
  3086
    template <typename Map>
deba@2467
  3087
    UEdgeMapReader& readEdgeMap(std::string label, Map& map) {
deba@2467
  3088
      return _readDirMap<
deba@2467
  3089
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  3090
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  3091
    }
deba@2467
  3092
deba@2467
  3093
    template <typename Map>
deba@2467
  3094
    UEdgeMapReader& readEdgeMap(std::string label, const Map& map) {
deba@2467
  3095
      return _readDirMap<
deba@2467
  3096
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  3097
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  3098
    }
deba@2467
  3099
deba@2467
  3100
    /// \brief Add a new directed edge map reader command for the reader.
deba@2467
  3101
    ///
deba@2467
  3102
    /// Add a new directed edge map reader command for the reader.
deba@2467
  3103
    template <typename ItemReader, typename Map>
deba@2467
  3104
    UEdgeMapReader& readEdgeMap(std::string label, Map& map, 
deba@2467
  3105
				    const ItemReader& ir = ItemReader()) {
deba@2467
  3106
      return _readDirMap<ItemReader, Map, 
deba@2467
  3107
        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
deba@2467
  3108
    }
deba@2467
  3109
deba@2467
  3110
    template <typename ItemReader, typename Map>
deba@2467
  3111
    UEdgeMapReader& readEdgeMap(std::string label, const Map& map, 
deba@2467
  3112
				    const ItemReader& ir = ItemReader()) {
deba@2467
  3113
      return _readDirMap<ItemReader, Map, 
deba@2467
  3114
        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
deba@2467
  3115
    }
deba@2467
  3116
deba@2467
  3117
  private:
deba@2467
  3118
deba@2467
  3119
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2467
  3120
    UEdgeMapReader& _readDirMap(std::string label, MapParameter map,
deba@2467
  3121
				    const ItemReader& ir = ItemReader()) { 
deba@2467
  3122
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2467
  3123
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
deba@2467
  3124
      readUEdgeMap("+" + label, 
deba@2467
  3125
                   _reader_bits::forwardComposeMap(graph, map), ir);
deba@2467
  3126
      readUEdgeMap("-" + label, 
deba@2467
  3127
                   _reader_bits::backwardComposeMap(graph, map), ir);
deba@2467
  3128
      return *this;      
deba@2467
  3129
    }
deba@2467
  3130
deba@2467
  3131
  public:
deba@2467
  3132
deba@2467
  3133
    /// \brief Add a new directed edge map skipper command for the reader.
deba@2467
  3134
    ///
deba@2467
  3135
    /// Add a new directed edge map skipper command for the reader.
deba@2467
  3136
    template <typename ItemReader>
deba@2467
  3137
    UEdgeMapReader& skipEdgeMap(std::string label, 
deba@2467
  3138
                                const ItemReader& ir = ItemReader()) {
deba@2467
  3139
      skipUEdgeMap("+" + label, ir);
deba@2467
  3140
      skipUEdgeMap("-" + label, ir);
deba@2467
  3141
      return *this;
deba@2467
  3142
    }
deba@2467
  3143
deba@2467
  3144
  protected:
deba@2467
  3145
deba@2467
  3146
    /// \brief Gives back true when the SectionReader can process 
deba@2467
  3147
    /// the section with the given header line.
deba@2467
  3148
    ///
deba@2467
  3149
    /// It gives back true when the header line starts with \c \@mapset,
deba@2467
  3150
    /// and the header line's name and the mapset's name are the same.
deba@2467
  3151
    virtual bool header(const std::string& line) {
deba@2467
  3152
      std::istringstream ls(line);
deba@2467
  3153
      std::string command;
deba@2467
  3154
      std::string id;
deba@2467
  3155
      ls >> command >> id;
deba@2467
  3156
      return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
deba@2467
  3157
    }
deba@2467
  3158
deba@2467
  3159
    /// \brief Reader function of the section.
deba@2467
  3160
    ///
deba@2467
  3161
    /// It reads the content of the section.
deba@2467
  3162
    virtual void read(std::istream& is) {
deba@2467
  3163
      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
deba@2467
  3164
      std::string line;
deba@2467
  3165
deba@2467
  3166
      {
deba@2467
  3167
        getline(is, line);
deba@2467
  3168
        std::istringstream ls(line);
deba@2467
  3169
        std::string id;
deba@2467
  3170
        while (ls >> id) {
deba@2467
  3171
          typename MapReaders::iterator it = readers.find(id);
deba@2467
  3172
          if (it != readers.end()) {
deba@2467
  3173
            it->second->touch();
deba@2467
  3174
            index.push_back(it->second);
deba@2467
  3175
          } else {
deba@2467
  3176
            index.push_back(&skipper);
deba@2467
  3177
          }
deba@2467
  3178
        }
deba@2467
  3179
      }
deba@2467
  3180
      for (typename MapReaders::iterator it = readers.begin();
deba@2467
  3181
	   it != readers.end(); ++it) {
deba@2467
  3182
	if (!it->second->touched()) {
deba@2467
  3183
	  ErrorMessage msg;
deba@2467
  3184
	  msg << "Map not found in file: " << it->first;
deba@2467
  3185
	  throw IoParameterError(msg.message());
deba@2467
  3186
	}
deba@2467
  3187
      }
deba@2467
  3188
      while (getline(is, line)) {	
deba@2467
  3189
	std::istringstream ls(line);
deba@2467
  3190
	UEdge uedge = labelReader->read(ls);
deba@2467
  3191
	for (int i = 0; i < int(index.size()); ++i) {
deba@2467
  3192
	  index[i]->read(ls, uedge);
deba@2467
  3193
	}
deba@2467
  3194
      }
deba@2467
  3195
    }
deba@2467
  3196
deba@2467
  3197
    virtual void missing() {
deba@2467
  3198
      if (readers.empty()) return;
deba@2467
  3199
      ErrorMessage msg;
deba@2467
  3200
      msg << "UEdgeMap section not found in file: @uedgemaps " << name;
deba@2467
  3201
      throw IoParameterError(msg.message());
deba@2467
  3202
    }
deba@2467
  3203
deba@2467
  3204
  private:
deba@2467
  3205
deba@2467
  3206
    const Graph& graph;   
deba@2467
  3207
    std::string name;
deba@2467
  3208
deba@2467
  3209
    typedef std::map<std::string, 
deba@2467
  3210
		     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
deba@2467
  3211
   
deba@2467
  3212
    MapReaders readers;
deba@2467
  3213
    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
deba@2467
  3214
deba@2467
  3215
    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > labelReader;
deba@2467
  3216
deba@2467
  3217
  };
deba@2467
  3218
deba@2467
  3219
  /// \ingroup section_io
deba@1423
  3220
  /// \brief SectionReader for retrieve what is in the file.
deba@1423
  3221
  ///
deba@1423
  3222
  /// SectionReader for retrieve what is in the file. If you want
deba@1423
  3223
  /// to know which sections, maps and items are in the file
deba@1423
  3224
  /// use the next code:
alpar@1946
  3225
  ///\code
deba@1423
  3226
  /// LemonReader reader("input.lgf");
deba@1423
  3227
  /// ContentReader content(reader);
deba@1423
  3228
  /// reader.run();
alpar@1946
  3229
  ///\endcode
deba@1423
  3230
  class ContentReader : public LemonReader::SectionReader {
deba@1423
  3231
    typedef LemonReader::SectionReader Parent;
deba@1423
  3232
  public:
deba@1423
  3233
    /// \brief Constructor.
deba@1423
  3234
    ///
deba@1423
  3235
    /// Constructor for
deba@1423
  3236
    ContentReader(LemonReader& _reader) : Parent(_reader) {}
deba@1423
  3237
deba@1423
  3238
    /// \brief Desctructor.
deba@1423
  3239
    ///
deba@1423
  3240
    /// Desctructor.
deba@1423
  3241
    virtual ~ContentReader() {}
deba@1423
  3242
deba@1423
  3243
    /// \brief Gives back how many nodesets are in the file.
deba@1423
  3244
    ///
deba@1423
  3245
    /// Gives back how many nodesets are in the file.
deba@1423
  3246
    int nodeSetNum() const {
deba@1423
  3247
      return nodesets.size();
deba@1423
  3248
    }
deba@1423
  3249
deba@1423
  3250
    /// \brief Gives back the name of nodeset on the indiced position.
deba@1423
  3251
    ///
deba@1423
  3252
    /// Gives back the name of nodeset on the indiced position.
deba@1423
  3253
    std::string nodeSetName(int index) const {
deba@1423
  3254
      return nodesets[index].name;
deba@1423
  3255
    }
deba@1423
  3256
deba@1423
  3257
    /// \brief Gives back the map names of nodeset on the indiced position.
deba@1423
  3258
    ///
deba@1423
  3259
    /// Gives back the map names of nodeset on the indiced position.
deba@1423
  3260
    const std::vector<std::string>& nodeSetMaps(int index) const {
deba@1423
  3261
      return nodesets[index].items;
deba@1423
  3262
    }
deba@1423
  3263
deba@1423
  3264
    /// \brief Gives back how many edgesets are in the file.
deba@1423
  3265
    ///
deba@1423
  3266
    /// Gives back how many edgesets are in the file.
deba@1423
  3267
    int edgeSetNum() const {
deba@1423
  3268
      return edgesets.size();
deba@1423
  3269
    }
deba@1423
  3270
deba@1423
  3271
    /// \brief Gives back the name of edgeset on the indiced position.
deba@1423
  3272
    ///
deba@1423
  3273
    /// Gives back the name of edgeset on the indiced position.
deba@1423
  3274
    std::string edgeSetName(int index) const {
deba@1423
  3275
      return edgesets[index].name;
deba@1423
  3276
    }
deba@1423
  3277
deba@1423
  3278
    /// \brief Gives back the map names of edgeset on the indiced position.
deba@1423
  3279
    ///
deba@1423
  3280
    /// Gives back the map names of edgeset on the indiced position.
deba@1423
  3281
    const std::vector<std::string>& edgeSetMaps(int index) const {
deba@1423
  3282
      return edgesets[index].items;
deba@1423
  3283
    }
deba@1423
  3284
deba@1423
  3285
    /// \brief Gives back how many undirected edgesets are in the file.
deba@1423
  3286
    ///
deba@1423
  3287
    /// Gives back how many undirected edgesets are in the file.
klao@1909
  3288
    int uEdgeSetNum() const {
klao@1909
  3289
      return uedgesets.size();
deba@1423
  3290
    }
deba@1423
  3291
deba@1423
  3292
    /// \brief Gives back the name of undirected edgeset on the indiced 
deba@1423
  3293
    /// position.
deba@1423
  3294
    ///
deba@1423
  3295
    /// Gives back the name of undirected edgeset on the indiced position.
klao@1909
  3296
    std::string uEdgeSetName(int index) const {
klao@1909
  3297
      return uedgesets[index].name;
deba@1423
  3298
    }
deba@1423
  3299
deba@1423
  3300
    /// \brief Gives back the map names of undirected edgeset on the indiced 
deba@1423
  3301
    /// position.
deba@1423
  3302
    ///
deba@1423
  3303
    /// Gives back the map names of undirected edgeset on the indiced position.
klao@1909
  3304
    const std::vector<std::string>& uEdgeSetMaps(int index) const {
klao@1909
  3305
      return uedgesets[index].items;
deba@1423
  3306
    }
deba@1423
  3307
deba@1423
  3308
    /// \brief Gives back how many labeled nodes section are in the file.
deba@1423
  3309
    ///
deba@1423
  3310
    /// Gives back how many labeled nodes section are in the file.
deba@1423
  3311
    int nodesNum() const {
deba@1423
  3312
      return nodes.size();
deba@1423
  3313
    }
deba@1423
  3314
deba@1423
  3315
    /// \brief Gives back the name of labeled nodes section on the indiced 
deba@1423
  3316
    /// position.
deba@1423
  3317
    ///
deba@1423
  3318
    /// Gives back the name of labeled nodes section on the indiced position.
deba@1423
  3319
    std::string nodesName(int index) const {
deba@1423
  3320
      return nodes[index].name;
deba@1423
  3321
    }
deba@1423
  3322
deba@1423
  3323
    /// \brief Gives back the names of the labeled nodes in the indiced 
deba@1423
  3324
    /// section.
deba@1423
  3325
    ///
deba@1423
  3326
    /// Gives back the names of the labeled nodes in the indiced section.
deba@1423
  3327
    const std::vector<std::string>& nodesItems(int index) const {
deba@1423
  3328
      return nodes[index].items;
deba@1423
  3329
    }
deba@1423
  3330
deba@1423
  3331
    /// \brief Gives back how many labeled edges section are in the file.
deba@1423
  3332
    ///
deba@1423
  3333
    /// Gives back how many labeled edges section are in the file.
deba@1423
  3334
    int edgesNum() const {
deba@1423
  3335
      return edges.size();
deba@1423
  3336
    }
deba@1423
  3337
deba@1423
  3338
    /// \brief Gives back the name of labeled edges section on the indiced 
deba@1423
  3339
    /// position.
deba@1423
  3340
    ///
deba@1423
  3341
    /// Gives back the name of labeled edges section on the indiced position.
deba@1423
  3342
    std::string edgesName(int index) const {
deba@1423
  3343
      return edges[index].name;
deba@1423
  3344
    }
deba@1423
  3345
deba@1423
  3346
    /// \brief Gives back the names of the labeled edges in the indiced 
deba@1423
  3347
    /// section.
deba@1423
  3348
    ///
deba@1423
  3349
    /// Gives back the names of the labeled edges in the indiced section.
deba@1423
  3350
    const std::vector<std::string>& edgesItems(int index) const {
deba@1423
  3351
      return edges[index].items;
deba@1423
  3352
    }
deba@1423
  3353
 
deba@1423
  3354
    /// \brief Gives back how many labeled undirected edges section are 
deba@1423
  3355
    /// in the file.
deba@1423
  3356
    ///
deba@1423
  3357
    /// Gives back how many labeled undirected edges section are in the file.
klao@1909
  3358
    int uEdgesNum() const {
klao@1909
  3359
      return uedges.size();
deba@1423
  3360
    }
deba@1423
  3361
deba@1423
  3362
    /// \brief Gives back the name of labeled undirected edges section 
deba@1423
  3363
    /// on the indiced position.
deba@1423
  3364
    ///
deba@1423
  3365
    /// Gives back the name of labeled undirected edges section on the 
deba@1423
  3366
    /// indiced position.
klao@1909
  3367
    std::string uEdgesName(int index) const {
klao@1909
  3368
      return uedges[index].name;
deba@1423
  3369
    }
deba@1423
  3370
deba@1423
  3371
    /// \brief Gives back the names of the labeled undirected edges in 
deba@1423
  3372
    /// the indiced section.
deba@1423
  3373
    ///
deba@1423
  3374
    /// Gives back the names of the labeled undirected edges in the 
deba@1423
  3375
    /// indiced section.
klao@1909
  3376
    const std::vector<std::string>& uEdgesItems(int index) const {
klao@1909
  3377
      return uedges[index].items;
deba@1423
  3378
    }
deba@1423
  3379
deba@1423
  3380
 
deba@1423
  3381
    /// \brief Gives back how many attributes section are in the file.
deba@1423
  3382
    ///
deba@1423
  3383
    /// Gives back how many attributes section are in the file.
deba@1423
  3384
    int attributesNum() const {
deba@1423
  3385
      return attributes.size();
deba@1423
  3386
    }
deba@1423
  3387
deba@1423
  3388
    /// \brief Gives back the name of attributes section on the indiced 
deba@1423
  3389
    /// position.
deba@1423
  3390
    ///
deba@1423
  3391
    /// Gives back the name of attributes section on the indiced position.
deba@1423
  3392
    std::string attributesName(int index) const {
deba@1423
  3393
      return attributes[index].name;
deba@1423
  3394
    }
deba@1423
  3395
deba@1423
  3396
    /// \brief Gives back the names of the attributes in the indiced section.
deba@1423
  3397
    ///
deba@1423
  3398
    /// Gives back the names of the attributes in the indiced section.
deba@1423
  3399
    const std::vector<std::string>& attributesItems(int index) const {
deba@1423
  3400
      return attributes[index].items;
deba@1423
  3401
    }
deba@1423
  3402
deba@1423
  3403
    const std::vector<std::string>& otherSections() const {
deba@1423
  3404
      return sections;
deba@1423
  3405
    }
deba@1423
  3406
deba@1423
  3407
  protected:
deba@1423
  3408
    
deba@1423
  3409
    /// \brief Gives back true when the SectionReader can process 
deba@1423
  3410
    /// the section with the given header line.
deba@1423
  3411
    ///
deba@1423
  3412
    /// It gives back true when the section is common section.
deba@1423
  3413
    bool header(const std::string& line) {
deba@1423
  3414
      std::istringstream ls(line);
deba@1423
  3415
      std::string command, name;
deba@1423
  3416
      ls >> command >> name;
deba@1423
  3417
      if (command == "@nodeset") {
deba@1423
  3418
	current = command;
deba@1423
  3419
	nodesets.push_back(SectionInfo(name));
deba@1423
  3420
      } else if (command == "@edgeset") {
deba@1423
  3421
	current = command;
deba@1423
  3422
	edgesets.push_back(SectionInfo(name));
klao@1909
  3423
      } else if (command == "@uedgeset") {
deba@1423
  3424
	current = command;
klao@1909
  3425
	uedgesets.push_back(SectionInfo(name));
deba@1423
  3426
      } else if (command == "@nodes") {
deba@1423
  3427
	current = command;
deba@1423
  3428
	nodes.push_back(SectionInfo(name));
deba@1423
  3429
      } else if (command == "@edges") {
deba@1423
  3430
	current = command;
deba@1423
  3431
	edges.push_back(SectionInfo(name));
klao@1909
  3432
      } else if (command == "@uedges") {
deba@1423
  3433
	current = command;
klao@1909
  3434
	uedges.push_back(SectionInfo(name));
deba@1423
  3435
      } else if (command == "@attributes") {
deba@1423
  3436
	current = command;
deba@1423
  3437
	attributes.push_back(SectionInfo(name));
deba@1423
  3438
      } else {
deba@1423
  3439
	sections.push_back(line);
deba@1423
  3440
	return false;
deba@1423
  3441
      }
deba@1423
  3442
      return true;
deba@1423
  3443
    }
deba@1423
  3444
deba@1423
  3445
    /// \brief Retrieve the items from various sections.
deba@1423
  3446
    ///
deba@1423
  3447
    /// Retrieve the items from various sections.
deba@1423
  3448
    void read(std::istream& is) {
deba@1423
  3449
      if (current == "@nodeset") {
deba@1423
  3450
	readMapNames(is, nodesets.back().items);
deba@1423
  3451
      } else if (current == "@edgeset") {
deba@1423
  3452
	readMapNames(is, edgesets.back().items);
klao@1909
  3453
      } else if (current == "@uedgeset") {
klao@1909
  3454
	readMapNames(is, uedgesets.back().items);
deba@1423
  3455
      } else if (current == "@nodes") {
deba@1423
  3456
	readItemNames(is, nodes.back().items);
deba@1423
  3457
      } else if (current == "@edges") {
deba@1423
  3458
	readItemNames(is, edges.back().items);
klao@1909
  3459
      } else if (current == "@uedges") {
klao@1909
  3460
	readItemNames(is, uedges.back().items);
deba@1423
  3461
      } else if (current == "@attributes") {
deba@1423
  3462
	readItemNames(is, attributes.back().items);
deba@1423
  3463
      }
deba@1423
  3464
    }    
deba@1423
  3465
deba@1423
  3466
  private:
deba@1423
  3467
deba@1423
  3468
    void readMapNames(std::istream& is, std::vector<std::string>& maps) {
deba@1901
  3469
      std::string line, name;
deba@1423
  3470
      std::getline(is, line);
deba@1423
  3471
      std::istringstream ls(line);
deba@1901
  3472
      while (ls >> name) {
deba@1901
  3473
	maps.push_back(name);
deba@1423
  3474
      }
deba@2618
  3475
      while (getline(is, line)) { }
deba@1423
  3476
    }
deba@1423
  3477
deba@1423
  3478
    void readItemNames(std::istream& is, std::vector<std::string>& maps) {
deba@1901
  3479
      std::string line, name;
deba@1423
  3480
      while (std::getline(is, line)) {
deba@1423
  3481
	std::istringstream ls(line);
deba@1901
  3482
	ls >> name;
deba@1901
  3483
	maps.push_back(name);
deba@1423
  3484
      }
deba@1423
  3485
    }
deba@1423
  3486
deba@1423
  3487
    struct SectionInfo {
deba@1423
  3488
      std::string name;
deba@1423
  3489
      std::vector<std::string> items;
deba@1423
  3490
deba@1423
  3491
      SectionInfo(const std::string& _name) : name(_name) {}
deba@1423
  3492
    };
deba@1423
  3493
deba@1423
  3494
    std::vector<SectionInfo> nodesets;
deba@1423
  3495
    std::vector<SectionInfo> edgesets;
klao@1909
  3496
    std::vector<SectionInfo> uedgesets;
deba@1423
  3497
deba@1423
  3498
    std::vector<SectionInfo> nodes;
deba@1423
  3499
    std::vector<SectionInfo> edges;
klao@1909
  3500
    std::vector<SectionInfo> uedges;
deba@1423
  3501
deba@1423
  3502
    std::vector<SectionInfo> attributes;
deba@1423
  3503
deba@1423
  3504
    std::vector<std::string> sections;
deba@1423
  3505
deba@1423
  3506
    std::string current;
deba@1423
  3507
deba@1423
  3508
  };
deba@1423
  3509
deba@1408
  3510
}
deba@1408
  3511
#endif