lemon/lemon_reader.h
author deba
Sun, 30 Sep 2007 19:19:33 +0000
changeset 2481 ddb851e1481a
parent 2467 2025a571895e
child 2502 9c23c3762bc5
permissions -rw-r--r--
Avoiding warnings
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@2391
     5
 * Copyright (C) 2003-2007
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@1845
   314
      void touch() { _touched = true; }
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@1408
   596
	if (_is.read(&c, 1)) {
deba@1408
   597
	  _is.putback(c);
deba@1408
   598
	  if (c == '@') {
deba@1408
   599
	    return EOF;
deba@1408
   600
	  }
deba@1408
   601
	} else {
deba@1408
   602
	  return EOF;
deba@1408
   603
	}
deba@1408
   604
	char_type *ptr;
deba@1408
   605
	for (ptr = base(); ptr != eptr(); ++ptr) {
deba@1408
   606
	  if (_is.read(&c, 1)) {
deba@1408
   607
	    if (c == '\n') ++_num;
deba@1408
   608
	    if (put_char(c)) {
deba@1408
   609
	      *ptr = c;
deba@1408
   610
	    } else {
deba@1408
   611
	      if (skip_state == after_endl && c == '@') {
deba@1408
   612
		_is.putback('@');
deba@1408
   613
		break;
deba@1408
   614
	      }
deba@1408
   615
	      --ptr;
deba@1408
   616
	    }
deba@1408
   617
	  } else {
deba@1408
   618
	    break;
deba@1408
   619
	  }
deba@1408
   620
	}
deba@1408
   621
	setg(base(), base(), ptr);
deba@1408
   622
	return *base();
deba@1408
   623
      }
deba@1408
   624
deba@2084
   625
      virtual int_type sync() {
deba@1408
   626
	return EOF;
deba@1408
   627
      }
deba@2460
   628
deba@2460
   629
    public:
deba@2460
   630
deba@2460
   631
      int line_num() const {
deba@2460
   632
	int r = _num;
deba@2460
   633
	for (char_type* p = gptr(); p != egptr(); ++p) {
deba@2460
   634
	  if (*p == '\n') --r;
deba@2460
   635
	}
deba@2460
   636
	return r;
deba@2460
   637
      }
deba@2460
   638
deba@1408
   639
    };
deba@1408
   640
deba@1408
   641
  public:
deba@1408
   642
deba@1409
   643
    /// \brief Abstract base class for reading a section.
deba@1409
   644
    ///
deba@1409
   645
    /// This class has an \c header() member function what get a 
deba@1409
   646
    /// header line string and decides if it want to process the next 
deba@1409
   647
    /// section. Several SectionReaders can be attached to an LemonReader 
deba@1409
   648
    /// and the first attached what can process the section will be used. 
deba@1409
   649
    /// Its \c read() member will called with a stream contains the section. 
deba@1409
   650
    /// From this stream the empty lines and comments are filtered out.
deba@1408
   651
    class SectionReader {
deba@1409
   652
      friend class LemonReader;
deba@1409
   653
    protected:
deba@1409
   654
      /// \brief Constructor for SectionReader.
deba@1409
   655
      ///
deba@1409
   656
      /// Constructor for SectionReader. It attach this reader to
deba@1409
   657
      /// the given LemonReader.
deba@1409
   658
      SectionReader(LemonReader& reader) {
deba@1409
   659
	reader.attach(*this);
deba@1409
   660
      }
deba@1409
   661
alpar@1494
   662
      virtual ~SectionReader() {}
alpar@1494
   663
deba@1409
   664
      /// \brief Gives back true when the SectionReader can process 
deba@1409
   665
      /// the section with the given header line.
deba@1409
   666
      ///
deba@1409
   667
      /// It gives back true when the SectionReader can process
deba@1409
   668
      /// the section with the given header line.
deba@1408
   669
      virtual bool header(const std::string& line) = 0;
deba@1409
   670
deba@1409
   671
      /// \brief Reader function of the section.
deba@1409
   672
      ///
deba@1409
   673
      /// It reads the content of the section.
deba@1408
   674
      virtual void read(std::istream& is) = 0;
deba@2000
   675
deba@2000
   676
      /// \brief The given section missing in the file.
deba@2000
   677
      ///
deba@2000
   678
      /// The given section missing in the file.
deba@2000
   679
      virtual void missing() {};
deba@1408
   680
    };
deba@1408
   681
deba@1409
   682
    /// \brief Constructor for LemonReader.
deba@1409
   683
    ///
deba@1409
   684
    /// Constructor for LemonReader which reads from the given stream.
deba@1408
   685
    LemonReader(std::istream& _is) 
deba@1408
   686
      : is(&_is), own_is(false) {}
deba@1408
   687
deba@1409
   688
    /// \brief Constructor for LemonReader.
deba@1409
   689
    ///
deba@1409
   690
    /// Constructor for LemonReader which reads from the given file.
deba@1408
   691
    LemonReader(const std::string& filename) 
deba@1408
   692
      : is(0), own_is(true) {
deba@1408
   693
      is = new std::ifstream(filename.c_str());
deba@1746
   694
      if (is->fail()) {
deba@1746
   695
	throw FileOpenError(filename);
deba@1746
   696
      }
deba@1408
   697
    }
deba@1408
   698
deba@1409
   699
    /// \brief Desctructor for LemonReader.
deba@1409
   700
    ///
deba@1409
   701
    /// Desctructor for LemonReader.
deba@1408
   702
    ~LemonReader() {
deba@1408
   703
      if (own_is) {
deba@1408
   704
	delete is;
deba@1408
   705
      }
deba@1408
   706
    }
deba@1408
   707
deba@1408
   708
  private:
deba@1408
   709
    LemonReader(const LemonReader&);
deba@1408
   710
    void operator=(const LemonReader&);
deba@1408
   711
deba@1408
   712
    void attach(SectionReader& reader) {
deba@2000
   713
      readers.push_back(std::make_pair(&reader, false));
deba@1408
   714
    }
deba@1408
   715
deba@1409
   716
  public:
deba@1409
   717
    /// \brief Executes the LemonReader.
deba@1409
   718
    /// 
deba@1409
   719
    /// It executes the LemonReader.
deba@1408
   720
    void run() {
deba@1408
   721
      int line_num = 0;
deba@1408
   722
      std::string line;
deba@2460
   723
      
deba@2460
   724
      SectionReaders::iterator it;
deba@2460
   725
      while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
deba@2460
   726
	for (it = readers.begin(); it != readers.end(); ++it) {
deba@2460
   727
	  if (it->first->header(line)) {
deba@2460
   728
	    it->second = true;
deba@2460
   729
	    char buf[2048];
deba@2460
   730
	    FilterStreamBuf buffer(*is, line_num);
deba@2460
   731
	    try {
deba@1408
   732
	      buffer.pubsetbuf(buf, sizeof(buf));
deba@2386
   733
	      std::istream ss(&buffer);
deba@2386
   734
	      it->first->read(ss);
deba@1408
   735
	      break;
deba@2460
   736
	    } catch (DataFormatError& error) {
deba@2460
   737
	      error.line(buffer.line_num());
deba@2460
   738
	      throw;
deba@2460
   739
	    }	
deba@1408
   740
	  }
deba@1408
   741
	}
deba@2460
   742
      }
deba@2460
   743
      for (it = readers.begin(); it != readers.end(); ++it) {
deba@2460
   744
	if (!it->second) {
deba@2460
   745
	  try {
deba@2460
   746
	    it->first->missing();
deba@2460
   747
	  } catch (DataFormatError& error) {
deba@2460
   748
	    error.line(line_num);
deba@2460
   749
	    throw;
deba@2460
   750
	  }	
deba@2460
   751
	}
deba@2460
   752
      }
deba@1408
   753
    }
deba@1408
   754
deba@1408
   755
deba@1408
   756
  private:
deba@1408
   757
deba@1408
   758
    std::istream* is;
deba@1408
   759
    bool own_is;
deba@1408
   760
deba@2000
   761
    typedef std::vector<std::pair<SectionReader*, bool> > SectionReaders;
deba@1408
   762
    SectionReaders readers;
deba@1408
   763
deba@1408
   764
  };
deba@1408
   765
deba@2016
   766
  /// \ingroup section_io
deba@1409
   767
  /// \brief SectionReader for reading a graph's nodeset.
deba@1409
   768
  ///
deba@2368
   769
  /// The lemon format can store multiple graph nodesets with several
deba@2368
   770
  /// maps.  The nodeset section's header line is \c \@nodeset \c
deba@2368
   771
  /// nodeset_name, but the \c nodeset_name may be empty.
deba@1409
   772
  ///
deba@1409
   773
  /// The first line of the section contains the names of the maps separated
deba@1409
   774
  /// with white spaces. Each next lines describes a node in the nodeset, and
deba@1409
   775
  /// contains the mapped values for each map.
deba@1409
   776
  ///
deba@1901
   777
  /// If the nodeset contains an \c "label" named map then it will be regarded
deba@1409
   778
  /// as id map. This map should contain only unique values and when the 
deba@1901
   779
  /// \c readLabel() member will read a value from the given stream it will
deba@1409
   780
  /// give back that node which is mapped to this value.
deba@1409
   781
  ///
deba@1409
   782
  /// \relates LemonReader
deba@1408
   783
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@1845
   784
  class NodeSetReader : public LemonReader::SectionReader {
deba@1845
   785
    typedef LemonReader::SectionReader Parent;
deba@1408
   786
  public:
deba@1408
   787
deba@1408
   788
    typedef _Graph Graph;
deba@1408
   789
    typedef _Traits Traits;
deba@1429
   790
    typedef typename Graph::Node Node;
deba@1408
   791
    typedef typename Traits::Skipper DefaultSkipper;
deba@1408
   792
deba@1409
   793
    /// \brief Constructor.
deba@1409
   794
    ///
deba@1409
   795
    /// Constructor for NodeSetReader. It creates the NodeSetReader and
deba@1409
   796
    /// attach it into the given LemonReader. The nodeset reader will
deba@2100
   797
    /// add the read nodes to the given Graph. The reader will read
deba@1901
   798
    /// the section when the \c section_name and the \c _name are the same. 
deba@1421
   799
    NodeSetReader(LemonReader& _reader, 
deba@1705
   800
		  Graph& _graph, 
deba@1901
   801
		  const std::string& _name = std::string(),
deba@1409
   802
		  const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1901
   803
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {} 
deba@1408
   804
deba@1409
   805
deba@1409
   806
    /// \brief Destructor.
deba@1409
   807
    ///
deba@1409
   808
    /// Destructor for NodeSetReader.
deba@1408
   809
    virtual ~NodeSetReader() {
deba@1408
   810
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1408
   811
	   it != readers.end(); ++it) {
deba@1408
   812
	delete it->second;
deba@1408
   813
      }
deba@1408
   814
    }
deba@1408
   815
deba@1408
   816
  private:
deba@1408
   817
    NodeSetReader(const NodeSetReader&);
deba@1408
   818
    void operator=(const NodeSetReader&);
deba@1408
   819
  
deba@1408
   820
  public:
deba@1408
   821
deba@1408
   822
    /// \brief Add a new node map reader command for the reader.
deba@1408
   823
    ///
deba@1408
   824
    /// Add a new node map reader command for the reader.
deba@1408
   825
    template <typename Map>
deba@2386
   826
    NodeSetReader& readNodeMap(std::string label, Map& map) {
deba@1421
   827
      return _readMap<
deba@1421
   828
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2386
   829
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1421
   830
    }
deba@1421
   831
deba@1421
   832
    template <typename Map>
deba@2386
   833
    NodeSetReader& readNodeMap(std::string label, const Map& map) {
deba@1421
   834
      return _readMap<
deba@1421
   835
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2386
   836
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1408
   837
    }
deba@1408
   838
deba@1408
   839
    /// \brief Add a new node map reader command for the reader.
deba@1408
   840
    ///
deba@1408
   841
    /// Add a new node map reader command for the reader.
deba@2386
   842
    template <typename ItemReader, typename Map>
deba@2386
   843
    NodeSetReader& readNodeMap(std::string label, Map& map, 
deba@2386
   844
			       const ItemReader& ir = ItemReader()) {
deba@2386
   845
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2386
   846
	(label, map, ir);
deba@1421
   847
    }
deba@1421
   848
deba@2386
   849
    template <typename ItemReader, typename Map>
deba@2386
   850
    NodeSetReader& readNodeMap(std::string label, const Map& map, 
deba@2386
   851
			       const ItemReader& ir = ItemReader()) {
deba@2386
   852
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2386
   853
	(label, map, ir);
deba@1421
   854
    }
deba@1421
   855
deba@1421
   856
  private:
deba@1421
   857
deba@2386
   858
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2386
   859
    NodeSetReader& _readMap(std::string label, MapParameter map, 
deba@2386
   860
			    const ItemReader& ir = ItemReader()) {
alpar@2260
   861
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@2386
   862
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2386
   863
      if (readers.find(label) != readers.end()) {
deba@1408
   864
	ErrorMessage msg;
deba@2386
   865
	msg << "Multiple read rule for node map: " << label;
alpar@2153
   866
	throw IoParameterError(msg.message());
deba@1845
   867
      }      
deba@1408
   868
      readers.insert(
deba@2386
   869
        make_pair(label, new _reader_bits::
deba@2386
   870
		  MapReader<Node, Map, ItemReader>(map, ir)));
deba@1408
   871
      return *this;
deba@1408
   872
    }
deba@1408
   873
deba@1421
   874
  public:
deba@1421
   875
deba@1408
   876
    /// \brief Add a new node map skipper command for the reader.
deba@1408
   877
    ///
deba@1408
   878
    /// Add a new node map skipper command for the reader.
deba@2386
   879
    template <typename ItemReader>
deba@2386
   880
    NodeSetReader& skipNodeMap(std::string label, 
deba@2386
   881
                               const ItemReader& ir = ItemReader()) {
deba@2386
   882
      if (readers.find(label) != readers.end()) {
deba@1408
   883
	ErrorMessage msg;
deba@2386
   884
	msg << "Multiple read rule for node map: " << label;
alpar@2153
   885
	throw IoParameterError(msg.message());
deba@1408
   886
      }
deba@2386
   887
      readers.insert(make_pair(label, new _reader_bits::
deba@2386
   888
			       SkipReader<Node, ItemReader>(ir)));
deba@1408
   889
      return *this;
deba@1408
   890
    }
deba@1408
   891
deba@1409
   892
  protected:
deba@1409
   893
deba@1409
   894
    /// \brief Gives back true when the SectionReader can process 
deba@1409
   895
    /// the section with the given header line.
deba@1409
   896
    ///
deba@1421
   897
    /// It gives back true when the header line starts with \c \@nodeset,
deba@1901
   898
    /// and the header line's name and the nodeset's name are the same.
deba@1408
   899
    virtual bool header(const std::string& line) {
deba@1408
   900
      std::istringstream ls(line);
deba@1408
   901
      std::string command;
deba@1901
   902
      std::string id;
klao@1997
   903
      ls >> command >> id;
deba@1408
   904
      return command == "@nodeset" && name == id;
deba@1408
   905
    }
deba@1408
   906
deba@1409
   907
    /// \brief Reader function of the section.
deba@1409
   908
    ///
deba@1409
   909
    /// It reads the content of the section.
deba@1408
   910
    virtual void read(std::istream& is) {
deba@1845
   911
      std::vector<_reader_bits::MapReaderBase<Node>* > index;
deba@1408
   912
      std::string line;
deba@1408
   913
deba@2386
   914
      {
deba@2386
   915
        getline(is, line);
deba@2386
   916
        std::istringstream ls(line);
deba@2386
   917
        std::string id;
deba@2386
   918
        while (ls >> id) {
deba@2386
   919
          typename MapReaders::iterator it = readers.find(id);
deba@2386
   920
          if (it != readers.end()) {
deba@2386
   921
            it->second->touch();
deba@2386
   922
            index.push_back(it->second);
deba@2386
   923
          } else {
deba@2386
   924
            index.push_back(&skipper);
deba@2386
   925
          }
deba@2386
   926
          if (id == "label") {
deba@2386
   927
            inverter.reset(index.back()->getInverter());
deba@2386
   928
            index.back() = inverter.get();
deba@2386
   929
          }
deba@2386
   930
        }
deba@1408
   931
      }
deba@1845
   932
      for (typename MapReaders::iterator it = readers.begin();
deba@1845
   933
	   it != readers.end(); ++it) {
deba@1845
   934
	if (!it->second->touched()) {
deba@1845
   935
	  ErrorMessage msg;
deba@1845
   936
	  msg << "Map not found in file: " << it->first;
alpar@2153
   937
	  throw IoParameterError(msg.message());
deba@1845
   938
	}
deba@1845
   939
      }
deba@1408
   940
      while (getline(is, line)) {	
deba@1429
   941
	Node node = graph.addNode();
deba@1408
   942
	std::istringstream ls(line);
deba@2386
   943
	for (int i = 0; i < int(index.size()); ++i) {
deba@1408
   944
	  index[i]->read(ls, node);
deba@1408
   945
	}
deba@1408
   946
      }
deba@1408
   947
    }
deba@1408
   948
deba@2000
   949
    virtual void missing() {
deba@2000
   950
      if (readers.empty()) return;
deba@2000
   951
      ErrorMessage msg;
deba@2001
   952
      msg << "NodeSet section not found in file: @nodeset " << name;
alpar@2153
   953
      throw IoParameterError(msg.message());
deba@2000
   954
    }
deba@2000
   955
deba@1409
   956
  public:
deba@1409
   957
deba@1901
   958
    /// \brief Returns true if the nodeset can give back the node by its label.
deba@1409
   959
    ///
deba@1901
   960
    /// Returns true if the nodeset can give back the node by its label.
deba@1901
   961
    /// It is possible only if an "label" named map was read.
deba@1901
   962
    bool isLabelReader() const {
deba@1408
   963
      return inverter.get() != 0;
deba@1408
   964
    }
deba@1408
   965
deba@1901
   966
    /// \brief Gives back the node by its label.
deba@1409
   967
    ///
deba@1409
   968
    /// It reads an id from the stream and gives back which node belongs to
deba@1901
   969
    /// it. It is possible only if there was read an "label" named map.
deba@1901
   970
    void readLabel(std::istream& is, Node& node) const {
deba@1492
   971
      node = inverter->read(is);
deba@1408
   972
    } 
deba@1408
   973
deba@1408
   974
  private:
deba@1408
   975
deba@1845
   976
    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
deba@1408
   977
    MapReaders readers;
deba@1408
   978
   
deba@1705
   979
    Graph& graph;   
deba@1901
   980
    std::string name;
deba@1845
   981
    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
deba@1408
   982
deba@1845
   983
    std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
deba@1408
   984
  };
deba@1408
   985
deba@2016
   986
  /// \ingroup section_io
deba@1409
   987
  /// \brief SectionReader for reading a graph's edgeset.
deba@1409
   988
  ///
deba@1409
   989
  /// The lemon format can store multiple graph edgesets with several maps.
deba@1901
   990
  /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
deba@1901
   991
  /// \c edgeset_name may be empty.
deba@1409
   992
  ///
deba@1409
   993
  /// The first line of the section contains the names of the maps separated
deba@1421
   994
  /// with white spaces. Each next lines describes an edge in the edgeset. The
deba@1421
   995
  /// line contains the source and the target nodes' id and the mapped 
deba@1421
   996
  /// values for each map.
deba@1409
   997
  ///
deba@1901
   998
  /// If the edgeset contains an \c "label" named map then it will be regarded
deba@1409
   999
  /// as id map. This map should contain only unique values and when the 
deba@1901
  1000
  /// \c readLabel() member will read a value from the given stream it will
deba@1409
  1001
  /// give back that edge which is mapped to this value.
deba@1409
  1002
  ///
deba@1409
  1003
  /// The edgeset reader needs a node id reader to identify which nodes
deba@1901
  1004
  /// have to be connected. If a NodeSetReader reads an "label" named map,
deba@1409
  1005
  /// it will be able to resolve the nodes by ids.
deba@1409
  1006
  ///
deba@1409
  1007
  /// \relates LemonReader
deba@1408
  1008
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@1845
  1009
  class EdgeSetReader : public LemonReader::SectionReader {
deba@1845
  1010
    typedef LemonReader::SectionReader Parent;
deba@1408
  1011
  public:
deba@1408
  1012
deba@1408
  1013
    typedef _Graph Graph;
deba@1408
  1014
    typedef _Traits Traits;
deba@1429
  1015
    typedef typename Graph::Node Node;
deba@1429
  1016
    typedef typename Graph::Edge Edge;
deba@1408
  1017
    typedef typename Traits::Skipper DefaultSkipper;
deba@1408
  1018
deba@1409
  1019
    /// \brief Constructor.
deba@1409
  1020
    ///
deba@1409
  1021
    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
deba@1409
  1022
    /// attach it into the given LemonReader. The edgeset reader will
deba@2100
  1023
    /// add the read edges to the given Graph. It will use the given
deba@1409
  1024
    /// node id reader to read the source and target nodes of the edges.
deba@1901
  1025
    /// The reader will read the section only if the \c _name and the 
deba@1901
  1026
    /// \c edgset_name are the same. 
deba@1901
  1027
    template <typename NodeLabelReader>
deba@1421
  1028
    EdgeSetReader(LemonReader& _reader, 
deba@1705
  1029
		  Graph& _graph, 
deba@1901
  1030
		  const NodeLabelReader& _nodeLabelReader, 
deba@1901
  1031
		  const std::string& _name = std::string(),
deba@1409
  1032
		  const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1901
  1033
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
deba@1901
  1034
      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
deba@1901
  1035
      nodeLabelReader.reset(new _reader_bits::
deba@1901
  1036
			 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
deba@1476
  1037
    }
deba@1409
  1038
    /// \brief Destructor.
deba@1409
  1039
    ///
deba@1409
  1040
    /// Destructor for EdgeSetReader.
deba@1408
  1041
    virtual ~EdgeSetReader() {
deba@1408
  1042
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1408
  1043
	   it != readers.end(); ++it) {
deba@1408
  1044
	delete it->second;
deba@1408
  1045
      }
deba@1408
  1046
    }
deba@1408
  1047
deba@1408
  1048
  private:
deba@1408
  1049
    EdgeSetReader(const EdgeSetReader&);
deba@1408
  1050
    void operator=(const EdgeSetReader&);
deba@1408
  1051
deba@1408
  1052
  public:
deba@1408
  1053
deba@1409
  1054
    /// \brief Add a new edge map reader command for the reader.
deba@1408
  1055
    ///
deba@1409
  1056
    /// Add a new edge map reader command for the reader.
deba@1408
  1057
    template <typename Map>
deba@2386
  1058
    EdgeSetReader& readEdgeMap(std::string label, Map& map) {
deba@1421
  1059
      return _readMap<
deba@1421
  1060
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2386
  1061
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1421
  1062
    }
deba@1421
  1063
deba@1421
  1064
    template <typename Map>
deba@2386
  1065
    EdgeSetReader& readEdgeMap(std::string label, const Map& map) {
deba@1421
  1066
      return _readMap<
deba@1421
  1067
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2386
  1068
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1408
  1069
    }
deba@1408
  1070
deba@1409
  1071
    /// \brief Add a new edge map reader command for the reader.
deba@1408
  1072
    ///
deba@1409
  1073
    /// Add a new edge map reader command for the reader.
deba@2386
  1074
    template <typename ItemReader, typename Map>
deba@2386
  1075
    EdgeSetReader& readEdgeMap(std::string label, Map& map, 
deba@2386
  1076
                               const ItemReader& ir = ItemReader()) {
deba@2386
  1077
      return _readMap<ItemReader, Map,
deba@2386
  1078
	typename _reader_bits::Arg<Map>::Type>(label, map, ir);
deba@1421
  1079
    }
deba@1421
  1080
deba@2386
  1081
    template <typename ItemReader, typename Map>
deba@2386
  1082
    EdgeSetReader& readEdgeMap(std::string label, const Map& map, 
deba@2386
  1083
			       const ItemReader& ir = ItemReader()) {
deba@2386
  1084
      return _readMap<ItemReader, Map,
deba@2386
  1085
	typename _reader_bits::Arg<Map>::Type>(label, map, ir);
deba@1421
  1086
    }
deba@1421
  1087
deba@1421
  1088
  private:
deba@1421
  1089
deba@2386
  1090
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2386
  1091
    EdgeSetReader& _readMap(std::string label, MapParameter map, 
deba@2386
  1092
			    const ItemReader& ir = ItemReader()) {
alpar@2260
  1093
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
deba@2386
  1094
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2386
  1095
      if (readers.find(label) != readers.end()) {
deba@1408
  1096
	ErrorMessage msg;
deba@2386
  1097
	msg << "Multiple read rule for edge map: " << label;
alpar@2153
  1098
	throw IoParameterError(msg.message());
deba@1408
  1099
      }
deba@1408
  1100
      readers.insert(
deba@2386
  1101
	make_pair(label, new _reader_bits::
deba@2386
  1102
		  MapReader<Edge, Map, ItemReader>(map, ir)));
deba@1408
  1103
      return *this;
deba@1408
  1104
    }
deba@1408
  1105
deba@1421
  1106
  public:
deba@1421
  1107
deba@1409
  1108
    /// \brief Add a new edge map skipper command for the reader.
deba@1408
  1109
    ///
deba@1409
  1110
    /// Add a new edge map skipper command for the reader.
deba@2386
  1111
    template <typename ItemReader>
deba@2386
  1112
    EdgeSetReader& skipEdgeMap(std::string label, 
deba@2386
  1113
			       const ItemReader& ir = ItemReader()) {
deba@2386
  1114
      if (readers.find(label) != readers.end()) {
deba@1408
  1115
	ErrorMessage msg;
deba@2386
  1116
	msg << "Multiple read rule for edge map: " << label;
alpar@2153
  1117
	throw IoParameterError(msg.message());
deba@1408
  1118
      }
deba@2386
  1119
      readers.insert(make_pair(label, new _reader_bits::
deba@2386
  1120
			       SkipReader<Edge, ItemReader>(ir)));
deba@1408
  1121
      return *this;
deba@1408
  1122
    }
deba@1408
  1123
deba@1409
  1124
  protected:
deba@1409
  1125
deba@1409
  1126
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  1127
    /// the section with the given header line.
deba@1409
  1128
    ///
deba@1421
  1129
    /// It gives back true when the header line starts with \c \@edgeset,
deba@1901
  1130
    /// and the header line's name and the edgeset's name are the same.
kpeter@2476
  1131
    /// The sections with \@uedgeset head line could be read with this
deba@2464
  1132
    /// section reader too.
deba@1408
  1133
    virtual bool header(const std::string& line) {
deba@1408
  1134
      std::istringstream ls(line);
deba@1408
  1135
      std::string command;
deba@1901
  1136
      std::string id;
klao@1997
  1137
      ls >> command >> id;
deba@2464
  1138
      return (command == "@edgeset" || command == "@uedgeset") && name == id;
deba@1408
  1139
    }
deba@1408
  1140
deba@1409
  1141
    /// \brief Reader function of the section.
deba@1409
  1142
    ///
deba@1409
  1143
    /// It reads the content of the section.
deba@1408
  1144
    virtual void read(std::istream& is) {
deba@1901
  1145
      if (!nodeLabelReader->isLabelReader()) {
deba@1901
  1146
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
  1147
      }
deba@1845
  1148
      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
deba@1408
  1149
      std::string line;
deba@1408
  1150
deba@2386
  1151
      {
deba@2386
  1152
        getline(is, line);
deba@2386
  1153
        std::istringstream ls(line);	
deba@2386
  1154
        std::string id;
deba@2386
  1155
        while (ls >> id) {
deba@2386
  1156
          typename MapReaders::iterator it = readers.find(id);
deba@2386
  1157
          if (it != readers.end()) {
deba@2386
  1158
            index.push_back(it->second);
deba@2386
  1159
            it->second->touch();
deba@2386
  1160
          } else {
deba@2386
  1161
            index.push_back(&skipper);
deba@2386
  1162
          }
deba@2386
  1163
          if (id == "label") {
deba@2386
  1164
            inverter.reset(index.back()->getInverter());
deba@2386
  1165
            index.back() = inverter.get();
deba@2386
  1166
          }
deba@2386
  1167
        }
deba@1408
  1168
      }
deba@1845
  1169
      for (typename MapReaders::iterator it = readers.begin();
deba@1845
  1170
	   it != readers.end(); ++it) {
deba@1845
  1171
	if (!it->second->touched()) {
deba@1845
  1172
	  ErrorMessage msg;
deba@1845
  1173
	  msg << "Map not found in file: " << it->first;
alpar@2153
  1174
	  throw IoParameterError(msg.message());
deba@1845
  1175
	}
deba@1845
  1176
      }
deba@1408
  1177
      while (getline(is, line)) {	
deba@1408
  1178
	std::istringstream ls(line);
deba@1901
  1179
	Node from = nodeLabelReader->read(ls);
deba@1901
  1180
	Node to = nodeLabelReader->read(ls);
deba@1429
  1181
	Edge edge = graph.addEdge(from, to);
deba@2386
  1182
	for (int i = 0; i < int(index.size()); ++i) {
deba@1408
  1183
	  index[i]->read(ls, edge);
deba@1408
  1184
	}
deba@1408
  1185
      }
deba@1408
  1186
    }
deba@1408
  1187
deba@2000
  1188
    virtual void missing() {
deba@2000
  1189
      if (readers.empty()) return;
deba@2000
  1190
      ErrorMessage msg;
deba@2001
  1191
      msg << "EdgeSet section not found in file: @edgeset " << name;
alpar@2153
  1192
      throw IoParameterError(msg.message());
deba@2000
  1193
    }
deba@2000
  1194
deba@1409
  1195
  public:
deba@1409
  1196
deba@1901
  1197
    /// \brief Returns true if the edgeset can give back the edge by its label.
deba@1409
  1198
    ///
deba@1901
  1199
    /// Returns true if the edgeset can give back the edge by its label.
deba@1901
  1200
    /// It is possible only if an "label" named map was read.
deba@1901
  1201
    bool isLabelReader() const {
deba@1408
  1202
      return inverter.get() != 0;
deba@1408
  1203
    }
deba@1408
  1204
deba@1901
  1205
    /// \brief Gives back the edge by its label.
deba@1409
  1206
    ///
deba@1409
  1207
    /// It reads an id from the stream and gives back which edge belongs to
deba@1901
  1208
    /// it. It is possible only if there was read an "label" named map.
deba@1901
  1209
    void readLabel(std::istream& is, Edge& edge) const {
deba@1492
  1210
      edge = inverter->read(is);
deba@1408
  1211
    } 
deba@1408
  1212
deba@1408
  1213
  private:
deba@1408
  1214
deba@2001
  1215
    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> 
deba@2001
  1216
    MapReaders;
deba@2001
  1217
    
deba@1408
  1218
    MapReaders readers;
deba@1408
  1219
   
deba@1705
  1220
    Graph& graph;   
deba@1901
  1221
    std::string name;
deba@1845
  1222
    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
deba@1421
  1223
deba@1845
  1224
    std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
deba@1901
  1225
    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
deba@1421
  1226
  };
deba@1421
  1227
deba@2016
  1228
  /// \ingroup section_io
deba@1421
  1229
  /// \brief SectionReader for reading a undirected graph's edgeset.
deba@1421
  1230
  ///
deba@1421
  1231
  /// The lemon format can store multiple undirected edgesets with several 
klao@1909
  1232
  /// maps. The undirected edgeset section's header line is \c \@uedgeset 
klao@1909
  1233
  /// \c uedgeset_name, but the \c uedgeset_name may be empty.
deba@1421
  1234
  ///
deba@1421
  1235
  /// The first line of the section contains the names of the maps separated
deba@1421
  1236
  /// with white spaces. Each next lines describes an edge in the edgeset. The
deba@1421
  1237
  /// line contains the connected nodes' id and the mapped values for each map.
deba@1421
  1238
  ///
deba@1421
  1239
  /// The section can handle the directed as a syntactical sugar. Two
deba@1421
  1240
  /// undirected edge map describes one directed edge map. This two maps
deba@1421
  1241
  /// are the forward map and the backward map and the names of this map
deba@1421
  1242
  /// is near the same just with a prefix \c '+' or \c '-' character 
deba@1421
  1243
  /// difference.
deba@1421
  1244
  ///
deba@1901
  1245
  /// If the edgeset contains an \c "label" named map then it will be regarded
deba@1421
  1246
  /// as id map. This map should contain only unique values and when the 
deba@1901
  1247
  /// \c readLabel() member will read a value from the given stream it will
klao@1909
  1248
  /// give back that uicted edge which is mapped to this value.
deba@1421
  1249
  ///
deba@1421
  1250
  /// The undirected edgeset reader needs a node id reader to identify which 
deba@2001
  1251
  /// nodes have to be connected. If a NodeSetReader reads an "label" named 
deba@2001
  1252
  /// map, it will be able to resolve the nodes by ids.
deba@1421
  1253
  ///
deba@1421
  1254
  /// \relates LemonReader
deba@1421
  1255
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
klao@1909
  1256
  class UEdgeSetReader : public LemonReader::SectionReader {
deba@1845
  1257
    typedef LemonReader::SectionReader Parent;
deba@1421
  1258
  public:
deba@1421
  1259
deba@1421
  1260
    typedef _Graph Graph;
deba@1421
  1261
    typedef _Traits Traits;
deba@1429
  1262
    typedef typename Graph::Node Node;
deba@1429
  1263
    typedef typename Graph::Edge Edge;
klao@1909
  1264
    typedef typename Graph::UEdge UEdge;
deba@1421
  1265
    typedef typename Traits::Skipper DefaultSkipper;
deba@1421
  1266
deba@1421
  1267
    /// \brief Constructor.
deba@1421
  1268
    ///
klao@1909
  1269
    /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader 
deba@1421
  1270
    /// and attach it into the given LemonReader. The undirected edgeset 
deba@2100
  1271
    /// reader will add the read undirected edges to the given Graph. It 
deba@1421
  1272
    /// will use the given node id reader to read the source and target 
deba@1421
  1273
    /// nodes of the edges. The reader will read the section only if the 
klao@1909
  1274
    /// \c _name and the \c uedgset_name are the same. 
deba@1901
  1275
    template <typename NodeLabelReader>
klao@1909
  1276
    UEdgeSetReader(LemonReader& _reader, 
deba@1705
  1277
		       Graph& _graph, 
deba@1901
  1278
		       const NodeLabelReader& _nodeLabelReader, 
deba@1901
  1279
		       const std::string& _name = std::string(),
deba@1421
  1280
		       const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@1901
  1281
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
deba@1901
  1282
      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
deba@1901
  1283
      nodeLabelReader.reset(new _reader_bits::
deba@1901
  1284
			 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
deba@1476
  1285
    }
deba@1421
  1286
    /// \brief Destructor.
deba@1421
  1287
    ///
klao@1909
  1288
    /// Destructor for UEdgeSetReader.
klao@1909
  1289
    virtual ~UEdgeSetReader() {
deba@1421
  1290
      for (typename MapReaders::iterator it = readers.begin(); 
deba@1421
  1291
	   it != readers.end(); ++it) {
deba@1421
  1292
	delete it->second;
deba@1421
  1293
      }
deba@1421
  1294
    }
deba@1421
  1295
deba@1421
  1296
  private:
klao@1909
  1297
    UEdgeSetReader(const UEdgeSetReader&);
klao@1909
  1298
    void operator=(const UEdgeSetReader&);
deba@1421
  1299
deba@1421
  1300
  public:
deba@1421
  1301
deba@1421
  1302
    /// \brief Add a new undirected edge map reader command for the reader.
deba@1421
  1303
    ///
deba@1421
  1304
    /// Add a new edge undirected map reader command for the reader.
deba@1421
  1305
    template <typename Map>
deba@2386
  1306
    UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
deba@1421
  1307
      return _readMap<
deba@1421
  1308
	typename Traits::template Reader<typename Map::Value>, Map, 
deba@2386
  1309
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1421
  1310
    }
deba@1421
  1311
deba@1421
  1312
    template <typename Map>
deba@2386
  1313
    UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
deba@1421
  1314
      return _readMap<
deba@1421
  1315
	typename Traits::template Reader<typename Map::Value>, Map, 
deba@2386
  1316
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1421
  1317
    }
deba@1421
  1318
deba@1421
  1319
    /// \brief Add a new undirected edge map reader command for the reader.
deba@1421
  1320
    ///
deba@1421
  1321
    /// Add a new edge undirected map reader command for the reader.
deba@2386
  1322
    template <typename ItemReader, typename Map>
deba@2386
  1323
    UEdgeSetReader& readUEdgeMap(std::string label, Map& map, 
deba@2386
  1324
                                 const ItemReader& ir = ItemReader()) {
deba@2386
  1325
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2386
  1326
	(label, map, ir);
deba@1421
  1327
    }
deba@1421
  1328
deba@2386
  1329
    template <typename ItemReader, typename Map>
deba@2386
  1330
    UEdgeSetReader& readUEdgeMap(std::string label, const Map& map, 
deba@2386
  1331
                                 const ItemReader& ir = ItemReader()) {
deba@2386
  1332
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type >
deba@2386
  1333
	(label, map, ir);
deba@1421
  1334
    }
deba@1421
  1335
deba@1421
  1336
  private:
deba@1421
  1337
deba@2386
  1338
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2386
  1339
    UEdgeSetReader& _readMap(std::string label, MapParameter map,
deba@2386
  1340
                             const ItemReader& ir = ItemReader()) {
alpar@2260
  1341
      checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
deba@2386
  1342
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2386
  1343
      if (readers.find(label) != readers.end()) {
deba@1421
  1344
	ErrorMessage msg;
deba@2386
  1345
	msg << "Multiple read rule for edge map: " << label;
alpar@2153
  1346
	throw IoParameterError(msg.message());
deba@1421
  1347
      }
deba@1421
  1348
      readers.insert(
deba@2386
  1349
	make_pair(label, new _reader_bits::
deba@2386
  1350
		  MapReader<UEdge, Map, ItemReader>(map, ir)));
deba@1421
  1351
      return *this;
deba@1421
  1352
    }
deba@1421
  1353
deba@1421
  1354
  public:
deba@1421
  1355
deba@1421
  1356
    /// \brief Add a new undirected edge map skipper command for the reader.
deba@1421
  1357
    ///
deba@1421
  1358
    /// Add a new undirected edge map skipper command for the reader.
deba@2386
  1359
    template <typename ItemReader>
deba@2386
  1360
    UEdgeSetReader& skipUEdgeMap(std::string label, 
deba@2386
  1361
                                 const ItemReader& ir = ItemReader()) {
deba@2386
  1362
      if (readers.find(label) != readers.end()) {
deba@1421
  1363
	ErrorMessage msg;
deba@2386
  1364
	msg << "Multiple read rule for node map: " << label;
alpar@2153
  1365
	throw IoParameterError(msg.message());
deba@1421
  1366
      }
deba@2386
  1367
      readers.insert(make_pair(label, new _reader_bits::
deba@2386
  1368
			       SkipReader<UEdge, ItemReader>(ir)));
deba@1421
  1369
      return *this;
deba@1421
  1370
    }
deba@1421
  1371
deba@1421
  1372
    /// \brief Add a new directed edge map reader command for the reader.
deba@1421
  1373
    ///
deba@1421
  1374
    /// Add a new directed edge map reader command for the reader.
deba@1421
  1375
    template <typename Map>
deba@2386
  1376
    UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
deba@1421
  1377
      return _readDirMap<
deba@1421
  1378
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2386
  1379
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1421
  1380
    }
deba@1421
  1381
deba@1421
  1382
    template <typename Map>
deba@2386
  1383
    UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
deba@1421
  1384
      return _readDirMap<
deba@1421
  1385
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2386
  1386
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@1421
  1387
    }
deba@1421
  1388
deba@1421
  1389
    /// \brief Add a new directed edge map reader command for the reader.
deba@1421
  1390
    ///
deba@1421
  1391
    /// Add a new directed edge map reader command for the reader.
deba@2386
  1392
    template <typename ItemReader, typename Map>
deba@2386
  1393
    UEdgeSetReader& readEdgeMap(std::string label, Map& map, 
deba@2386
  1394
				    const ItemReader& ir = ItemReader()) {
deba@2386
  1395
      return _readDirMap<ItemReader, Map, 
deba@2386
  1396
        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
deba@1421
  1397
    }
deba@1421
  1398
deba@2386
  1399
    template <typename ItemReader, typename Map>
deba@2386
  1400
    UEdgeSetReader& readEdgeMap(std::string label, const Map& map, 
deba@2386
  1401
				    const ItemReader& ir = ItemReader()) {
deba@2386
  1402
      return _readDirMap<ItemReader, Map, 
deba@2386
  1403
        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
deba@1421
  1404
    }
deba@1421
  1405
deba@1421
  1406
  private:
deba@1421
  1407
deba@2386
  1408
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2386
  1409
    UEdgeSetReader& _readDirMap(std::string label, MapParameter map,
deba@2386
  1410
				    const ItemReader& ir = ItemReader()) { 
deba@2386
  1411
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
alpar@2260
  1412
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
deba@2386
  1413
      readUEdgeMap("+" + label, 
deba@2386
  1414
                   _reader_bits::forwardComposeMap(graph, map), ir);
deba@2386
  1415
      readUEdgeMap("-" + label, 
deba@2386
  1416
                   _reader_bits::backwardComposeMap(graph, map), ir);
deba@1421
  1417
      return *this;      
deba@1421
  1418
    }
deba@1421
  1419
deba@1421
  1420
  public:
deba@1421
  1421
deba@1421
  1422
    /// \brief Add a new directed edge map skipper command for the reader.
deba@1421
  1423
    ///
deba@1421
  1424
    /// Add a new directed edge map skipper command for the reader.
deba@2386
  1425
    template <typename ItemReader>
deba@2386
  1426
    UEdgeSetReader& skipEdgeMap(std::string label, 
deba@2386
  1427
                                const ItemReader& ir = ItemReader()) {
deba@2386
  1428
      skipUEdgeMap("+" + label, ir);
deba@2386
  1429
      skipUEdgeMap("-" + label, ir);
deba@1421
  1430
      return *this;
deba@1421
  1431
    }
deba@1421
  1432
deba@1421
  1433
  protected:
deba@1421
  1434
deba@1421
  1435
    /// \brief Gives back true when the SectionReader can process 
deba@1421
  1436
    /// the section with the given header line.
deba@1421
  1437
    ///
klao@1909
  1438
    /// It gives back true when the header line starts with \c \@uedgeset,
deba@1901
  1439
    /// and the header line's name and the edgeset's name are the same.
kpeter@2476
  1440
    /// The sections with \@edgeset head line could be read with this
deba@2464
  1441
    /// section reader too.
deba@1421
  1442
    virtual bool header(const std::string& line) {
deba@1421
  1443
      std::istringstream ls(line);
deba@1421
  1444
      std::string command;
deba@1901
  1445
      std::string id;
klao@1997
  1446
      ls >> command >> id;
deba@2464
  1447
      return (command == "@edgeset" || command == "@uedgeset") && name == id;
deba@1421
  1448
    }
deba@1421
  1449
deba@1421
  1450
    /// \brief Reader function of the section.
deba@1421
  1451
    ///
deba@1421
  1452
    /// It reads the content of the section.
deba@1421
  1453
    virtual void read(std::istream& is) {
deba@1901
  1454
      if (!nodeLabelReader->isLabelReader()) {
deba@1901
  1455
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
  1456
      }
klao@1909
  1457
      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
deba@1421
  1458
      std::string line;
deba@1421
  1459
deba@2386
  1460
      {
deba@2386
  1461
        getline(is, line);
deba@2386
  1462
        std::istringstream ls(line);	
deba@2386
  1463
        std::string id;
deba@2386
  1464
        while (ls >> id) {
deba@2386
  1465
          typename MapReaders::iterator it = readers.find(id);
deba@2386
  1466
          if (it != readers.end()) {
deba@2386
  1467
            index.push_back(it->second);
deba@2386
  1468
            it->second->touch();
deba@2386
  1469
          } else {
deba@2386
  1470
            index.push_back(&skipper);
deba@2386
  1471
          }
deba@2386
  1472
          if (id == "label") {
deba@2386
  1473
            inverter.reset(index.back()->getInverter());
deba@2386
  1474
            index.back() = inverter.get();
deba@2386
  1475
          }
deba@2386
  1476
        }
deba@2386
  1477
        for (typename MapReaders::iterator it = readers.begin();
deba@2386
  1478
             it != readers.end(); ++it) {
deba@2386
  1479
          if (!it->second->touched()) {
deba@2386
  1480
            ErrorMessage msg;
deba@2386
  1481
            msg << "Map not found in file: " << it->first;
deba@2386
  1482
            throw IoParameterError(msg.message());
deba@2386
  1483
          }
deba@2386
  1484
        }
deba@1845
  1485
      }
deba@1421
  1486
      while (getline(is, line)) {	
deba@1421
  1487
	std::istringstream ls(line);
deba@1901
  1488
	Node from = nodeLabelReader->read(ls);
deba@1901
  1489
	Node to = nodeLabelReader->read(ls);
klao@1909
  1490
	UEdge edge = graph.addEdge(from, to);
deba@2386
  1491
	for (int i = 0; i < int(index.size()); ++i) {
deba@1421
  1492
	  index[i]->read(ls, edge);
deba@1421
  1493
	}
deba@1421
  1494
      }
deba@1421
  1495
    }
deba@1421
  1496
deba@2000
  1497
    virtual void missing() {
deba@2000
  1498
      if (readers.empty()) return;
deba@2000
  1499
      ErrorMessage msg;
deba@2001
  1500
      msg << "UEdgeSet section not found in file: @uedgeset " << name;
alpar@2153
  1501
      throw IoParameterError(msg.message());
deba@2000
  1502
    }
deba@2000
  1503
deba@1421
  1504
  public:
deba@1421
  1505
deba@1901
  1506
    /// \brief Returns true if the edgeset can give back the edge by its label.
deba@1421
  1507
    ///
deba@1421
  1508
    /// Returns true if the edgeset can give back the undirected edge by its 
deba@1901
  1509
    /// id. It is possible only if an "label" named map was read.
deba@1901
  1510
    bool isLabelReader() const {
deba@1421
  1511
      return inverter.get() != 0;
deba@1421
  1512
    }
deba@1421
  1513
deba@1901
  1514
    /// \brief Gives back the undirected edge by its label.
deba@1421
  1515
    ///
deba@1421
  1516
    /// It reads an id from the stream and gives back which undirected edge 
deba@1901
  1517
    /// belongs to it. It is possible only if there was read an "label" named map.
deba@2467
  1518
    void readLabel(std::istream& is, UEdge& uedge) const {
deba@2467
  1519
      uedge = inverter->read(is);
deba@1421
  1520
    } 
deba@1421
  1521
deba@1901
  1522
    /// \brief Gives back the directed edge by its label.
deba@1429
  1523
    ///
deba@1429
  1524
    /// It reads an id from the stream and gives back which directed edge 
deba@1429
  1525
    /// belongs to it. The directed edge id is the \c '+' or \c '-' character
deba@1429
  1526
    /// and the undirected edge id. It is possible only if there was read 
deba@1901
  1527
    /// an "label" named map.
deba@1901
  1528
    void readLabel(std::istream& is, Edge& edge) const {
deba@1429
  1529
      char c;
deba@1429
  1530
      is >> c;
deba@2467
  1531
      UEdge uedge = inverter->read(is);
deba@1429
  1532
      if (c == '+') {
deba@2467
  1533
	edge = graph.direct(uedge, true);
deba@1429
  1534
      } else if (c == '-') {
deba@2467
  1535
        edge = graph.direct(uedge, false);
deba@1429
  1536
      } else {
deba@1429
  1537
	throw DataFormatError("Wrong id format for edge "
deba@1429
  1538
			      "in undirected edgeset");
deba@1429
  1539
      }
deba@1429
  1540
    } 
deba@1429
  1541
deba@1421
  1542
  private:
deba@1421
  1543
deba@1845
  1544
    typedef std::map<std::string, 
klao@1909
  1545
		     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
deba@1421
  1546
    MapReaders readers;
deba@1421
  1547
   
deba@1705
  1548
    Graph& graph;   
deba@1901
  1549
    std::string name;
klao@1909
  1550
    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
deba@1408
  1551
klao@1909
  1552
    std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
deba@1901
  1553
    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
deba@1408
  1554
  };
deba@1408
  1555
deba@2016
  1556
  /// \ingroup section_io
deba@1409
  1557
  /// \brief SectionReader for reading labeled nodes.
deba@1409
  1558
  ///
deba@1901
  1559
  /// The nodes section's header line is \c \@nodes \c nodes_name, but the
deba@1901
  1560
  /// \c nodes_name may be empty.
deba@1409
  1561
  ///
deba@1409
  1562
  /// Each line in the section contains the name of the node 
deba@1409
  1563
  /// and then the node id. 
deba@1409
  1564
  ///
deba@1409
  1565
  /// \relates LemonReader
deba@1409
  1566
  template <typename _Graph>
deba@1845
  1567
  class NodeReader : public LemonReader::SectionReader {
deba@1845
  1568
    typedef LemonReader::SectionReader Parent;
deba@1409
  1569
    typedef _Graph Graph;
deba@1429
  1570
    typedef typename Graph::Node Node;
deba@1409
  1571
  public:
deba@1409
  1572
    
deba@1409
  1573
    /// \brief Constructor.
deba@1409
  1574
    ///
deba@1409
  1575
    /// Constructor for NodeReader. It creates the NodeReader and
deba@1409
  1576
    /// attach it into the given LemonReader. It will use the given
deba@1409
  1577
    /// node id reader to give back the nodes. The reader will read the 
deba@1901
  1578
    /// section only if the \c _name and the \c nodes_name are the same. 
deba@1901
  1579
    template <typename _LabelReader>
deba@1901
  1580
    NodeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
deba@1901
  1581
	       const std::string& _name = std::string()) 
deba@1901
  1582
      : Parent(_reader), name(_name) {
deba@1901
  1583
      checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
deba@1901
  1584
      nodeLabelReader.reset(new _reader_bits::
deba@1901
  1585
			 LabelReader<Node, _LabelReader>(_labelReader));
deba@1476
  1586
    }
deba@1408
  1587
deba@1409
  1588
    /// \brief Destructor.
deba@1409
  1589
    ///
deba@1409
  1590
    /// Destructor for NodeReader.
deba@1409
  1591
    virtual ~NodeReader() {}
deba@1409
  1592
deba@1409
  1593
  private:
deba@1409
  1594
    NodeReader(const NodeReader&);
deba@1409
  1595
    void operator=(const NodeReader&);
deba@1409
  1596
deba@1409
  1597
  public:
deba@1409
  1598
deba@1409
  1599
    /// \brief Add a node reader command for the NodeReader.
deba@1409
  1600
    ///
deba@1409
  1601
    /// Add a node reader command for the NodeReader.
deba@2386
  1602
    void readNode(std::string label, Node& item) {
deba@2386
  1603
      if (readers.find(label) != readers.end()) {
deba@1409
  1604
	ErrorMessage msg;
deba@2386
  1605
	msg << "Multiple read rule for node: " << label;
alpar@2153
  1606
	throw IoParameterError(msg.message());
deba@1409
  1607
      }
deba@2386
  1608
      readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
deba@1409
  1609
    }
deba@1409
  1610
deba@1409
  1611
  protected:
deba@1409
  1612
deba@1409
  1613
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  1614
    /// the section with the given header line.
deba@1409
  1615
    ///
deba@1421
  1616
    /// It gives back true when the header line start with \c \@nodes,
deba@1901
  1617
    /// and the header line's name and the reader's name are the same.
deba@1409
  1618
    virtual bool header(const std::string& line) {
deba@1409
  1619
      std::istringstream ls(line);
deba@1409
  1620
      std::string command;
deba@1901
  1621
      std::string id;
klao@1997
  1622
      ls >> command >> id;
deba@1409
  1623
      return command == "@nodes" && name == id;
deba@1409
  1624
    }
deba@1409
  1625
deba@1409
  1626
    /// \brief Reader function of the section.
deba@1409
  1627
    ///
deba@1409
  1628
    /// It reads the content of the section.
deba@1409
  1629
    virtual void read(std::istream& is) {
deba@1901
  1630
      if (!nodeLabelReader->isLabelReader()) {
deba@1901
  1631
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
  1632
      }
deba@1409
  1633
      std::string line;
deba@1409
  1634
      while (getline(is, line)) {
deba@1409
  1635
	std::istringstream ls(line);
deba@1409
  1636
	std::string id;
deba@1409
  1637
	ls >> id;
deba@1429
  1638
	typename NodeReaders::iterator it = readers.find(id);
deba@1409
  1639
	if (it != readers.end()) {
deba@1901
  1640
	  it->second.read(nodeLabelReader->read(ls));
deba@1845
  1641
	  it->second.touch();
deba@1409
  1642
	}	
deba@1409
  1643
      }
deba@1845
  1644
      for (typename NodeReaders::iterator it = readers.begin();
deba@1845
  1645
	   it != readers.end(); ++it) {
deba@1845
  1646
	if (!it->second.touched()) {
deba@1845
  1647
	  ErrorMessage msg;
deba@1845
  1648
	  msg << "Node not found in file: " << it->first;
alpar@2153
  1649
	  throw IoParameterError(msg.message());
deba@1845
  1650
	}
deba@1845
  1651
      }
deba@1409
  1652
    }
deba@2000
  1653
deba@2000
  1654
    virtual void missing() {
deba@2000
  1655
      if (readers.empty()) return;
deba@2000
  1656
      ErrorMessage msg;
deba@2001
  1657
      msg << "Nodes section not found in file: @nodes " << name;
alpar@2153
  1658
      throw IoParameterError(msg.message());
deba@2000
  1659
    }
deba@1409
  1660
    
deba@1409
  1661
  private:
deba@1409
  1662
deba@1901
  1663
    std::string name;
deba@1409
  1664
deba@1845
  1665
    typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
deba@1429
  1666
    NodeReaders readers;
deba@1901
  1667
    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
deba@1409
  1668
  };
deba@1409
  1669
deba@2016
  1670
  /// \ingroup section_io
deba@1409
  1671
  /// \brief SectionReader for reading labeled edges.
deba@1409
  1672
  ///
deba@1901
  1673
  /// The edges section's header line is \c \@edges \c edges_name, but the
deba@1901
  1674
  /// \c edges_name may be empty.
deba@1409
  1675
  ///
deba@1409
  1676
  /// Each line in the section contains the name of the edge 
deba@1409
  1677
  /// and then the edge id. 
deba@1409
  1678
  ///
deba@1409
  1679
  /// \relates LemonReader
deba@1409
  1680
  template <typename _Graph>
deba@1845
  1681
  class EdgeReader : public LemonReader::SectionReader {
deba@1845
  1682
    typedef LemonReader::SectionReader Parent;
deba@1409
  1683
    typedef _Graph Graph;
deba@1429
  1684
    typedef typename Graph::Edge Edge;
deba@1409
  1685
  public:
deba@1409
  1686
    
deba@1409
  1687
    /// \brief Constructor.
deba@1409
  1688
    ///
deba@1409
  1689
    /// Constructor for EdgeReader. It creates the EdgeReader and
deba@1409
  1690
    /// attach it into the given LemonReader. It will use the given
deba@1409
  1691
    /// edge id reader to give back the edges. The reader will read the 
deba@1901
  1692
    /// section only if the \c _name and the \c edges_name are the same. 
deba@1901
  1693
    template <typename _LabelReader>
deba@1901
  1694
    EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
deba@1901
  1695
	       const std::string& _name = std::string()) 
deba@1901
  1696
      : Parent(_reader), name(_name) {
deba@1901
  1697
      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
deba@1901
  1698
      edgeLabelReader.reset(new _reader_bits::
deba@1901
  1699
			 LabelReader<Edge, _LabelReader>(_labelReader));
deba@1476
  1700
    }
deba@1409
  1701
deba@1409
  1702
    /// \brief Destructor.
deba@1409
  1703
    ///
deba@1409
  1704
    /// Destructor for EdgeReader.
deba@1409
  1705
    virtual ~EdgeReader() {}
deba@1409
  1706
  private:
deba@1409
  1707
    EdgeReader(const EdgeReader&);
deba@1409
  1708
    void operator=(const EdgeReader&);
deba@1409
  1709
deba@1409
  1710
  public:
deba@1409
  1711
deba@1409
  1712
    /// \brief Add an edge reader command for the EdgeReader.
deba@1409
  1713
    ///
deba@1409
  1714
    /// Add an edge reader command for the EdgeReader.
deba@2386
  1715
    void readEdge(std::string label, Edge& item) {
deba@2386
  1716
      if (readers.find(label) != readers.end()) {
deba@1409
  1717
	ErrorMessage msg;
deba@2386
  1718
	msg << "Multiple read rule for edge: " << label;
alpar@2153
  1719
	throw IoParameterError(msg.message());
deba@1409
  1720
      }
deba@2386
  1721
      readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
deba@1409
  1722
    }
deba@1409
  1723
deba@1409
  1724
  protected:
deba@1409
  1725
deba@1409
  1726
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  1727
    /// the section with the given header line.
deba@1409
  1728
    ///
deba@1421
  1729
    /// It gives back true when the header line start with \c \@edges,
deba@1901
  1730
    /// and the header line's name and the reader's name are the same.
deba@1421
  1731
    virtual bool header(const std::string& line) {
deba@1421
  1732
      std::istringstream ls(line);
deba@1421
  1733
      std::string command;
deba@1901
  1734
      std::string id;
klao@1997
  1735
      ls >> command >> id;
deba@1421
  1736
      return command == "@edges" && name == id;
deba@1421
  1737
    }
deba@1421
  1738
deba@1421
  1739
    /// \brief Reader function of the section.
deba@1421
  1740
    ///
deba@1421
  1741
    /// It reads the content of the section.
deba@1421
  1742
    virtual void read(std::istream& is) {
deba@1901
  1743
      if (!edgeLabelReader->isLabelReader()) {
deba@1901
  1744
	throw DataFormatError("Cannot find edgeset or label map");
deba@1476
  1745
      }
deba@1421
  1746
      std::string line;
deba@1421
  1747
      while (getline(is, line)) {
deba@1421
  1748
	std::istringstream ls(line);
deba@1421
  1749
	std::string id;
deba@1421
  1750
	ls >> id;
deba@1429
  1751
	typename EdgeReaders::iterator it = readers.find(id);
deba@1421
  1752
	if (it != readers.end()) {
deba@1901
  1753
	  it->second.read(edgeLabelReader->read(ls));
deba@1845
  1754
	  it->second.touch();
deba@1421
  1755
	}	
deba@1421
  1756
      }
deba@1845
  1757
      for (typename EdgeReaders::iterator it = readers.begin();
deba@1845
  1758
	   it != readers.end(); ++it) {
deba@1845
  1759
	if (!it->second.touched()) {
deba@1845
  1760
	  ErrorMessage msg;
deba@1845
  1761
	  msg << "Edge not found in file: " << it->first;
alpar@2153
  1762
	  throw IoParameterError(msg.message());
deba@1845
  1763
	}
deba@1845
  1764
      }
deba@1421
  1765
    }
deba@2000
  1766
deba@2000
  1767
    virtual void missing() {
deba@2000
  1768
      if (readers.empty()) return;
deba@2000
  1769
      ErrorMessage msg;
deba@2001
  1770
      msg << "Edges section not found in file: @edges " << name;
alpar@2153
  1771
      throw IoParameterError(msg.message());
deba@2000
  1772
    }
deba@1421
  1773
    
deba@1421
  1774
  private:
deba@1421
  1775
deba@1901
  1776
    std::string name;
deba@1421
  1777
deba@1845
  1778
    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
deba@1429
  1779
    EdgeReaders readers;
deba@1901
  1780
    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
deba@1421
  1781
  };
deba@1421
  1782
deba@2016
  1783
  /// \ingroup section_io
deba@1421
  1784
  /// \brief SectionReader for reading labeled undirected edges.
deba@1421
  1785
  ///
klao@1909
  1786
  /// The undirected edges section's header line is \c \@uedges 
klao@1909
  1787
  /// \c uedges_name, but the \c uedges_name may be empty.
deba@1421
  1788
  ///
deba@1421
  1789
  /// Each line in the section contains the name of the undirected edge 
deba@1421
  1790
  /// and then the undirected edge id. 
deba@1421
  1791
  ///
deba@1421
  1792
  /// \relates LemonReader
deba@1421
  1793
  template <typename _Graph>
klao@1909
  1794
  class UEdgeReader : public LemonReader::SectionReader {
deba@1845
  1795
    typedef LemonReader::SectionReader Parent;
deba@1421
  1796
    typedef _Graph Graph;
deba@1429
  1797
    typedef typename Graph::Edge Edge;
klao@1909
  1798
    typedef typename Graph::UEdge UEdge;
deba@1421
  1799
  public:
deba@1421
  1800
    
deba@1421
  1801
    /// \brief Constructor.
deba@1421
  1802
    ///
klao@1909
  1803
    /// Constructor for UEdgeReader. It creates the UEdgeReader and
deba@1421
  1804
    /// attach it into the given LemonReader. It will use the given
deba@1421
  1805
    /// undirected edge id reader to give back the edges. The reader will 
klao@1909
  1806
    /// read the section only if the \c _name and the \c uedges_name are 
deba@1421
  1807
    /// the same. 
deba@1901
  1808
    template <typename _LabelReader>
klao@1909
  1809
    UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
deba@1901
  1810
	       const std::string& _name = std::string()) 
deba@1901
  1811
      : Parent(_reader), name(_name) {
klao@1909
  1812
      checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
deba@1901
  1813
      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
deba@2467
  1814
      uedgeLabelReader.reset(new _reader_bits::
deba@2467
  1815
			     LabelReader<UEdge, _LabelReader>(_labelReader));
deba@1901
  1816
      edgeLabelReader.reset(new _reader_bits::
deba@2467
  1817
			    LabelReader<Edge, _LabelReader>(_labelReader));
deba@1476
  1818
    }
deba@1421
  1819
deba@1421
  1820
    /// \brief Destructor.
deba@1421
  1821
    ///
klao@1909
  1822
    /// Destructor for UEdgeReader.
klao@1909
  1823
    virtual ~UEdgeReader() {}
deba@1421
  1824
  private:
klao@1909
  1825
    UEdgeReader(const UEdgeReader&);
klao@1909
  1826
    void operator=(const UEdgeReader&);
deba@1421
  1827
deba@1421
  1828
  public:
deba@1421
  1829
klao@1909
  1830
    /// \brief Add an undirected edge reader command for the UEdgeReader.
deba@1421
  1831
    ///
klao@1909
  1832
    /// Add an undirected edge reader command for the UEdgeReader.
deba@2386
  1833
    void readUEdge(std::string label, UEdge& item) {
deba@2467
  1834
      if (uedgeReaders.find(label) != uedgeReaders.end()) {
deba@1429
  1835
	ErrorMessage msg;
deba@2386
  1836
	msg << "Multiple read rule for undirected edge: " << label;
alpar@2153
  1837
	throw IoParameterError(msg.message());
deba@1429
  1838
      }
deba@2467
  1839
      uedgeReaders.insert(make_pair(label, _reader_bits::
klao@1909
  1840
					ItemStore<UEdge>(item)));
deba@1429
  1841
    }
deba@1429
  1842
klao@1909
  1843
    /// \brief Add an edge reader command for the UEdgeReader.
deba@1429
  1844
    ///
klao@1909
  1845
    /// Add an edge reader command for the UEdgeReader.
deba@2386
  1846
    void readEdge(std::string label, Edge& item) {
deba@2386
  1847
      if (edgeReaders.find(label) != edgeReaders.end()) {
deba@1421
  1848
	ErrorMessage msg;
deba@2386
  1849
	msg << "Multiple read rule for edge: " << label;
alpar@2153
  1850
	throw IoParameterError(msg.message());
deba@1421
  1851
      }
deba@2386
  1852
      edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
deba@1421
  1853
    }
deba@1421
  1854
deba@1421
  1855
  protected:
deba@1421
  1856
deba@1421
  1857
    /// \brief Gives back true when the SectionReader can process 
deba@1421
  1858
    /// the section with the given header line.
deba@1421
  1859
    ///
deba@1421
  1860
    /// It gives back true when the header line start with \c \@edges,
deba@1901
  1861
    /// and the header line's name and the reader's name are the same.
deba@1409
  1862
    virtual bool header(const std::string& line) {
deba@1409
  1863
      std::istringstream ls(line);
deba@1409
  1864
      std::string command;
deba@1901
  1865
      std::string id;
klao@1997
  1866
      ls >> command >> id;
klao@1909
  1867
      return command == "@uedges" && name == id;
deba@1409
  1868
    }
deba@1409
  1869
deba@1409
  1870
    /// \brief Reader function of the section.
deba@1409
  1871
    ///
deba@1409
  1872
    /// It reads the content of the section.
deba@1409
  1873
    virtual void read(std::istream& is) {
deba@1901
  1874
      if (!edgeLabelReader->isLabelReader()) {
deba@1901
  1875
	throw DataFormatError("Cannot find undirected edgeset or label map");
deba@1476
  1876
      }
deba@2467
  1877
      if (!uedgeLabelReader->isLabelReader()) {
deba@1901
  1878
	throw DataFormatError("Cannot find undirected edgeset or label map");
deba@1476
  1879
      }
deba@1409
  1880
      std::string line;
deba@1409
  1881
      while (getline(is, line)) {
deba@1409
  1882
	std::istringstream ls(line);
deba@1409
  1883
	std::string id;
deba@1409
  1884
	ls >> id;
deba@1429
  1885
	{
deba@2467
  1886
	  typename UEdgeReaders::iterator it = uedgeReaders.find(id);
deba@2467
  1887
	  if (it != uedgeReaders.end()) {
deba@2467
  1888
	    it->second.read(uedgeLabelReader->read(ls));
deba@1845
  1889
	    it->second.touch();
deba@1845
  1890
	    continue;
deba@1429
  1891
	  }	
deba@1429
  1892
	} {
deba@1429
  1893
	  typename EdgeReaders::iterator it = edgeReaders.find(id);
deba@1429
  1894
	  if (it != edgeReaders.end()) {
deba@1901
  1895
	    it->second.read(edgeLabelReader->read(ls));
deba@1845
  1896
	    it->second.touch();
deba@1845
  1897
	    continue;
deba@1429
  1898
	  }	
deba@1429
  1899
	}
deba@1409
  1900
      }
deba@1845
  1901
      for (typename EdgeReaders::iterator it = edgeReaders.begin();
deba@1845
  1902
	   it != edgeReaders.end(); ++it) {
deba@1845
  1903
	if (!it->second.touched()) {
deba@1845
  1904
	  ErrorMessage msg;
deba@1845
  1905
	  msg << "Edge not found in file: " << it->first;
alpar@2153
  1906
	  throw IoParameterError(msg.message());
deba@1845
  1907
	}
deba@1845
  1908
      }
deba@2467
  1909
      for (typename UEdgeReaders::iterator it = uedgeReaders.begin();
deba@2467
  1910
	   it != uedgeReaders.end(); ++it) {
deba@1845
  1911
	if (!it->second.touched()) {
deba@1845
  1912
	  ErrorMessage msg;
klao@1909
  1913
	  msg << "UEdge not found in file: " << it->first;
alpar@2153
  1914
	  throw IoParameterError(msg.message());
deba@1845
  1915
	}
deba@1845
  1916
      }
deba@1409
  1917
    }
deba@2000
  1918
deba@2000
  1919
    virtual void missing() {
deba@2467
  1920
      if (edgeReaders.empty() && uedgeReaders.empty()) return;
deba@2000
  1921
      ErrorMessage msg;
deba@2001
  1922
      msg << "UEdges section not found in file: @uedges " << name;
alpar@2153
  1923
      throw IoParameterError(msg.message());
deba@2000
  1924
    }
deba@1409
  1925
    
deba@1409
  1926
  private:
deba@1409
  1927
deba@1901
  1928
    std::string name;
deba@1409
  1929
deba@1845
  1930
    typedef std::map<std::string, 
klao@1909
  1931
		     _reader_bits::ItemStore<UEdge> > UEdgeReaders;
deba@2467
  1932
    UEdgeReaders uedgeReaders;
deba@2467
  1933
    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uedgeLabelReader;
deba@1429
  1934
deba@1845
  1935
    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
deba@1429
  1936
    EdgeReaders edgeReaders;
deba@1901
  1937
    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
deba@1409
  1938
  };
deba@1409
  1939
deba@2016
  1940
  /// \ingroup section_io
deba@1409
  1941
  /// \brief SectionReader for attributes.
deba@1409
  1942
  ///
deba@1409
  1943
  /// The lemon format can store multiple attribute set. Each set has
deba@1901
  1944
  /// the header line \c \@attributes \c attributeset_name, but the 
deba@1901
  1945
  /// attributeset_name may be empty.
deba@1409
  1946
  ///
deba@1409
  1947
  /// The attributeset section contains several lines. Each of them starts
deba@1409
  1948
  /// with an attribute and then a the value for the id.
deba@1409
  1949
  ///
deba@1409
  1950
  /// \relates LemonReader
deba@1408
  1951
  template <typename _Traits = DefaultReaderTraits>
deba@1845
  1952
  class AttributeReader : public LemonReader::SectionReader {
deba@1845
  1953
    typedef LemonReader::SectionReader Parent;
deba@1408
  1954
    typedef _Traits Traits; 
deba@1408
  1955
  public:
deba@1409
  1956
    /// \brief Constructor.
deba@1409
  1957
    ///
deba@1409
  1958
    /// Constructor for AttributeReader. It creates the AttributeReader and
deba@1409
  1959
    /// attach it into the given LemonReader. The reader process a section
deba@1901
  1960
    /// only if the \c section_name and the \c _name are the same.
deba@1408
  1961
    AttributeReader(LemonReader& _reader, 
deba@1901
  1962
		    const std::string& _name = std::string()) 
deba@1901
  1963
      : Parent(_reader), name(_name) {}
deba@1408
  1964
deba@1409
  1965
    /// \brief Destructor.
deba@1409
  1966
    ///
deba@1409
  1967
    /// Destructor for AttributeReader.
deba@1408
  1968
    virtual ~AttributeReader() {
deba@1408
  1969
      for (typename Readers::iterator it = readers.begin(); 
deba@1408
  1970
	   it != readers.end(); ++it) {
deba@1408
  1971
	delete it->second;
deba@1408
  1972
      }
deba@1408
  1973
    }
deba@1408
  1974
deba@1408
  1975
  private:
deba@1408
  1976
    AttributeReader(const AttributeReader&);
deba@1408
  1977
    void operator=(AttributeReader&);
deba@1408
  1978
deba@1408
  1979
  public:
deba@1409
  1980
    /// \brief Add an attribute reader command for the reader.
deba@1409
  1981
    ///
deba@1409
  1982
    /// Add an attribute reader command for the reader.
deba@1408
  1983
    template <typename Value>
deba@2416
  1984
    AttributeReader& readAttribute(const std::string& label, Value& value) {
deba@1408
  1985
      return readAttribute<typename Traits::template Reader<Value> >
deba@2416
  1986
	(label, value);
deba@1408
  1987
    }
deba@1408
  1988
deba@1409
  1989
    /// \brief Add an attribute reader command for the reader.
deba@1409
  1990
    ///
deba@1409
  1991
    /// Add an attribute reader command for the reader.
deba@2386
  1992
    template <typename ItemReader, typename Value>
deba@2416
  1993
    AttributeReader& readAttribute(const std::string& label, Value& value,
deba@2386
  1994
				   const ItemReader& ir = ItemReader()) {
deba@2386
  1995
      checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
deba@2386
  1996
      if (readers.find(label) != readers.end()) {
deba@1408
  1997
	ErrorMessage msg;
deba@2386
  1998
	msg << "Multiple read rule for attribute: " << label;
alpar@2153
  1999
	throw IoParameterError(msg.message());
deba@1408
  2000
      }
deba@2386
  2001
      readers.insert(make_pair(label, new _reader_bits::
deba@2386
  2002
			       ValueReader<Value, ItemReader>(value, ir)));
deba@1408
  2003
      return *this;
deba@1408
  2004
    }
deba@1408
  2005
deba@1409
  2006
  protected:
deba@1409
  2007
deba@1409
  2008
    /// \brief Gives back true when the SectionReader can process 
deba@1409
  2009
    /// the section with the given header line.
deba@1409
  2010
    ///
deba@1421
  2011
    /// It gives back true when the header line start with \c \@attributes,
deba@1409
  2012
    /// and the header line's id and the attributeset's id are the same.
deba@1408
  2013
    bool header(const std::string& line) {
deba@1408
  2014
      std::istringstream ls(line);
deba@1408
  2015
      std::string command;
deba@1901
  2016
      std::string id;
klao@1997
  2017
      ls >> command >> id;
deba@1408
  2018
      return command == "@attributes" && name == id;
deba@1408
  2019
    }
deba@1408
  2020
deba@1409
  2021
    /// \brief Reader function of the section.
deba@1409
  2022
    ///
deba@1409
  2023
    /// It reads the content of the section.
deba@1408
  2024
    void read(std::istream& is) {
deba@1408
  2025
      std::string line;
deba@1408
  2026
      while (getline(is, line)) {
deba@1408
  2027
	std::istringstream ls(line);
deba@1408
  2028
	std::string id;
deba@1408
  2029
	ls >> id;
deba@1408
  2030
	typename Readers::iterator it = readers.find(id);
deba@1408
  2031
	if (it != readers.end()) {
deba@1408
  2032
	  it->second->read(ls);
deba@1901
  2033
 	  it->second->touch();
deba@1408
  2034
	}
deba@1408
  2035
      }
deba@1846
  2036
      for (typename Readers::iterator it = readers.begin();
deba@1846
  2037
	   it != readers.end(); ++it) {
deba@1846
  2038
	if (!it->second->touched()) {
deba@1846
  2039
	  ErrorMessage msg;
deba@1846
  2040
	  msg << "Attribute not found in file: " << it->first;
alpar@2153
  2041
	  throw IoParameterError(msg.message());
deba@1846
  2042
	}	
deba@1846
  2043
      }
deba@1408
  2044
    }    
deba@2416
  2045
    
deba@2000
  2046
    virtual void missing() {
deba@2000
  2047
      if (readers.empty()) return;
deba@2000
  2048
      ErrorMessage msg;
deba@2001
  2049
      msg << "Attribute section not found in file: @attributes " << name;
alpar@2153
  2050
      throw IoParameterError(msg.message());
deba@2000
  2051
    }
deba@2000
  2052
deba@1408
  2053
  private:
deba@1901
  2054
    std::string name;
deba@1408
  2055
deba@1845
  2056
    typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
deba@1409
  2057
    Readers readers;  
deba@1408
  2058
  };
deba@1408
  2059
deba@2016
  2060
  /// \ingroup section_io
deba@2467
  2061
  /// \brief SectionReader for reading extra node maps.
deba@2467
  2062
  ///
deba@2467
  2063
  /// The lemon format can store maps in the nodeset sections. This
deba@2467
  2064
  /// class let you make distinict section to store maps.  The main
deba@2467
  2065
  /// purpose of this class is a logical separation of some maps. The
deba@2467
  2066
  /// other useful application could be to store paths in node maps.
deba@2467
  2067
  ///
deba@2467
  2068
  /// The first line of the section contains the names of the maps
deba@2467
  2069
  /// separated with white spaces. Each next line describes an item
deba@2467
  2070
  /// in the itemset, and contains in the first column the label of
deba@2467
  2071
  /// the item and then the mapped values for each map.
deba@2467
  2072
  ///
deba@2467
  2073
  /// \relates LemonReader
deba@2467
  2074
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@2467
  2075
  class NodeMapReader : public LemonReader::SectionReader {
deba@2467
  2076
    typedef LemonReader::SectionReader Parent;
deba@2467
  2077
  public:
deba@2467
  2078
deba@2467
  2079
    typedef _Graph Graph;
deba@2467
  2080
    typedef typename Graph::Node Node;
deba@2467
  2081
    typedef _Traits Traits;
deba@2467
  2082
    typedef typename Traits::Skipper DefaultSkipper;
deba@2467
  2083
deba@2467
  2084
    /// \brief Constructor.
deba@2467
  2085
    ///
deba@2467
  2086
    /// Constructor for NodeMapReader. It creates the NodeMapReader and
deba@2467
  2087
    /// attach it into the given LemonReader. The reader will read
deba@2467
  2088
    /// the section when the \c section_name and the \c _name are the same.
deba@2467
  2089
    template <typename _LabelReader>
deba@2467
  2090
    NodeMapReader(LemonReader& _reader, 
deba@2467
  2091
		  const Graph& _graph, 
deba@2467
  2092
		  const _LabelReader& _labelReader,
deba@2467
  2093
		  const std::string& _name = std::string(),
deba@2467
  2094
		  const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@2467
  2095
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
deba@2467
  2096
      labelReader.reset(new _reader_bits::
deba@2467
  2097
			LabelReader<Node, _LabelReader>(_labelReader));
deba@2467
  2098
    } 
deba@2467
  2099
deba@2467
  2100
deba@2467
  2101
    /// \brief Destructor.
deba@2467
  2102
    ///
deba@2467
  2103
    /// Destructor for NodeMapReader.
deba@2467
  2104
    virtual ~NodeMapReader() {
deba@2467
  2105
      for (typename MapReaders::iterator it = readers.begin(); 
deba@2467
  2106
	   it != readers.end(); ++it) {
deba@2467
  2107
	delete it->second;
deba@2467
  2108
      }
deba@2467
  2109
    }
deba@2467
  2110
deba@2467
  2111
  private:
deba@2467
  2112
    NodeMapReader(const NodeMapReader&);
deba@2467
  2113
    void operator=(const NodeMapReader&);
deba@2467
  2114
  
deba@2467
  2115
  public:
deba@2467
  2116
deba@2467
  2117
    /// \brief Add a new node map reader command for the reader.
deba@2467
  2118
    ///
deba@2467
  2119
    /// Add a new node map reader command for the reader.
deba@2467
  2120
    template <typename Map>
deba@2467
  2121
    NodeMapReader& readNodeMap(std::string label, Map& map) {
deba@2467
  2122
      return _readMap<
deba@2467
  2123
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  2124
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  2125
    }
deba@2467
  2126
deba@2467
  2127
    template <typename Map>
deba@2467
  2128
    NodeMapReader& readNodeMap(std::string label, const Map& map) {
deba@2467
  2129
      return _readMap<
deba@2467
  2130
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  2131
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  2132
    }
deba@2467
  2133
deba@2467
  2134
    /// \brief Add a new node map reader command for the reader.
deba@2467
  2135
    ///
deba@2467
  2136
    /// Add a new node map reader command for the reader.
deba@2467
  2137
    template <typename ItemReader, typename Map>
deba@2467
  2138
    NodeMapReader& readNodeMap(std::string label, Map& map, 
deba@2467
  2139
			       const ItemReader& ir = ItemReader()) {
deba@2467
  2140
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2467
  2141
	(label, map, ir);
deba@2467
  2142
    }
deba@2467
  2143
deba@2467
  2144
    template <typename ItemReader, typename Map>
deba@2467
  2145
    NodeMapReader& readNodeMap(std::string label, const Map& map, 
deba@2467
  2146
			       const ItemReader& ir = ItemReader()) {
deba@2467
  2147
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2467
  2148
	(label, map, ir);
deba@2467
  2149
    }
deba@2467
  2150
deba@2467
  2151
  private:
deba@2467
  2152
deba@2467
  2153
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2467
  2154
    NodeMapReader& _readMap(std::string label, MapParameter map, 
deba@2467
  2155
			   const ItemReader& ir = ItemReader()) {
deba@2467
  2156
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@2467
  2157
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2467
  2158
      if (readers.find(label) != readers.end()) {
deba@2467
  2159
	ErrorMessage msg;
deba@2467
  2160
	msg << "Multiple read rule for map: " << label;
deba@2467
  2161
	throw IoParameterError(msg.message());
deba@2467
  2162
      }      
deba@2467
  2163
      readers.insert(
deba@2467
  2164
	make_pair(label, new _reader_bits::
deba@2467
  2165
		  MapReader<Node, Map, ItemReader>(map, ir)));
deba@2467
  2166
      return *this;
deba@2467
  2167
    }
deba@2467
  2168
deba@2467
  2169
  public:
deba@2467
  2170
deba@2467
  2171
    /// \brief Add a new node map skipper command for the reader.
deba@2467
  2172
    ///
deba@2467
  2173
    /// Add a new node map skipper command for the reader.
deba@2467
  2174
    template <typename ItemReader>
deba@2467
  2175
    NodeMapReader& skipNodeMap(std::string label, 
deba@2467
  2176
			       const ItemReader& ir = ItemReader()) {
deba@2467
  2177
      if (readers.find(label) != readers.end()) {
deba@2467
  2178
	ErrorMessage msg;
deba@2467
  2179
	msg << "Multiple read rule for map: " << label;
deba@2467
  2180
	throw IoParameterError(msg.message());
deba@2467
  2181
      }
deba@2467
  2182
      readers.insert(make_pair(label, new _reader_bits::
deba@2467
  2183
			       SkipReader<Node, ItemReader>(ir)));
deba@2467
  2184
      return *this;
deba@2467
  2185
    }
deba@2467
  2186
deba@2467
  2187
  protected:
deba@2467
  2188
deba@2467
  2189
    /// \brief Gives back true when the SectionReader can process 
deba@2467
  2190
    /// the section with the given header line.
deba@2467
  2191
    ///
deba@2467
  2192
    /// It gives back true when the header line starts with \c \@mapset,
deba@2467
  2193
    /// and the header line's name and the mapset's name are the same.
deba@2467
  2194
    virtual bool header(const std::string& line) {
deba@2467
  2195
      std::istringstream ls(line);
deba@2467
  2196
      std::string command;
deba@2467
  2197
      std::string id;
deba@2467
  2198
      ls >> command >> id;
deba@2467
  2199
      return command == "@nodemaps" && name == id;
deba@2467
  2200
    }
deba@2467
  2201
deba@2467
  2202
    /// \brief Reader function of the section.
deba@2467
  2203
    ///
deba@2467
  2204
    /// It reads the content of the section.
deba@2467
  2205
    virtual void read(std::istream& is) {
deba@2467
  2206
      std::vector<_reader_bits::MapReaderBase<Node>* > index;
deba@2467
  2207
      std::string line;
deba@2467
  2208
deba@2467
  2209
      {
deba@2467
  2210
        getline(is, line);
deba@2467
  2211
        std::istringstream ls(line);
deba@2467
  2212
        std::string id;
deba@2467
  2213
        while (ls >> id) {
deba@2467
  2214
          typename MapReaders::iterator it = readers.find(id);
deba@2467
  2215
          if (it != readers.end()) {
deba@2467
  2216
            it->second->touch();
deba@2467
  2217
            index.push_back(it->second);
deba@2467
  2218
          } else {
deba@2467
  2219
            index.push_back(&skipper);
deba@2467
  2220
          }
deba@2467
  2221
        }
deba@2467
  2222
      }
deba@2467
  2223
      for (typename MapReaders::iterator it = readers.begin();
deba@2467
  2224
	   it != readers.end(); ++it) {
deba@2467
  2225
	if (!it->second->touched()) {
deba@2467
  2226
	  ErrorMessage msg;
deba@2467
  2227
	  msg << "Map not found in file: " << it->first;
deba@2467
  2228
	  throw IoParameterError(msg.message());
deba@2467
  2229
	}
deba@2467
  2230
      }
deba@2467
  2231
      while (getline(is, line)) {	
deba@2467
  2232
	std::istringstream ls(line);
deba@2467
  2233
	Node node = labelReader->read(ls);
deba@2467
  2234
	for (int i = 0; i < int(index.size()); ++i) {
deba@2467
  2235
	  index[i]->read(ls, node);
deba@2467
  2236
	}
deba@2467
  2237
      }
deba@2467
  2238
    }
deba@2467
  2239
deba@2467
  2240
    virtual void missing() {
deba@2467
  2241
      if (readers.empty()) return;
deba@2467
  2242
      ErrorMessage msg;
deba@2467
  2243
      msg << "NodeMap section not found in file: @nodemaps " << name;
deba@2467
  2244
      throw IoParameterError(msg.message());
deba@2467
  2245
    }
deba@2467
  2246
deba@2467
  2247
  private:
deba@2467
  2248
deba@2467
  2249
    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
deba@2467
  2250
    MapReaders readers;
deba@2467
  2251
   
deba@2467
  2252
    const Graph& graph;   
deba@2467
  2253
    std::string name;
deba@2467
  2254
    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
deba@2467
  2255
    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > labelReader;
deba@2467
  2256
deba@2467
  2257
  };
deba@2467
  2258
deba@2467
  2259
  /// \ingroup section_io
deba@2467
  2260
  /// \brief SectionReader for reading extra edge maps.
deba@2467
  2261
  ///
deba@2467
  2262
  /// The lemon format can store maps in the edgeset sections. This
deba@2467
  2263
  /// class let you make distinict section to store maps.  The main
deba@2467
  2264
  /// purpose of this class is a logical separation of some maps. The
deba@2467
  2265
  /// other useful application could be to store paths in edge maps.
deba@2467
  2266
  ///
deba@2467
  2267
  /// The first line of the section contains the names of the maps
deba@2467
  2268
  /// separated with white spaces. Each next line describes an item
deba@2467
  2269
  /// in the itemset, and contains in the first column the label of
deba@2467
  2270
  /// the item and then the mapped values for each map.
deba@2467
  2271
  ///
deba@2467
  2272
  /// \relates LemonReader
deba@2467
  2273
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@2467
  2274
  class EdgeMapReader : public LemonReader::SectionReader {
deba@2467
  2275
    typedef LemonReader::SectionReader Parent;
deba@2467
  2276
  public:
deba@2467
  2277
deba@2467
  2278
    typedef _Graph Graph;
deba@2467
  2279
    typedef typename Graph::Edge Edge;
deba@2467
  2280
    typedef _Traits Traits;
deba@2467
  2281
    typedef typename Traits::Skipper DefaultSkipper;
deba@2467
  2282
deba@2467
  2283
    /// \brief Constructor.
deba@2467
  2284
    ///
deba@2467
  2285
    /// Constructor for EdgeMapReader. It creates the EdgeMapReader and
deba@2467
  2286
    /// attach it into the given LemonReader. The reader will read
deba@2467
  2287
    /// the section when the \c section_name and the \c _name are the same.
deba@2467
  2288
    template <typename _LabelReader>
deba@2467
  2289
    EdgeMapReader(LemonReader& _reader, 
deba@2467
  2290
		   const Graph& _graph, 
deba@2467
  2291
		   const _LabelReader& _labelReader,
deba@2467
  2292
		   const std::string& _name = std::string(),
deba@2467
  2293
		   const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@2467
  2294
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
deba@2467
  2295
      labelReader.reset(new _reader_bits::
deba@2467
  2296
			LabelReader<Edge, _LabelReader>(_labelReader));
deba@2467
  2297
    } 
deba@2467
  2298
deba@2467
  2299
deba@2467
  2300
    /// \brief Destructor.
deba@2467
  2301
    ///
deba@2467
  2302
    /// Destructor for EdgeMapReader.
deba@2467
  2303
    virtual ~EdgeMapReader() {
deba@2467
  2304
      for (typename MapReaders::iterator it = readers.begin(); 
deba@2467
  2305
	   it != readers.end(); ++it) {
deba@2467
  2306
	delete it->second;
deba@2467
  2307
      }
deba@2467
  2308
    }
deba@2467
  2309
deba@2467
  2310
  private:
deba@2467
  2311
    EdgeMapReader(const EdgeMapReader&);
deba@2467
  2312
    void operator=(const EdgeMapReader&);
deba@2467
  2313
  
deba@2467
  2314
  public:
deba@2467
  2315
deba@2467
  2316
    /// \brief Add a new edge map reader command for the reader.
deba@2467
  2317
    ///
deba@2467
  2318
    /// Add a new edge map reader command for the reader.
deba@2467
  2319
    template <typename Map>
deba@2467
  2320
    EdgeMapReader& readEdgeMap(std::string label, Map& map) {
deba@2467
  2321
      return _readMap<
deba@2467
  2322
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  2323
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  2324
    }
deba@2467
  2325
deba@2467
  2326
    template <typename Map>
deba@2467
  2327
    EdgeMapReader& readEdgeMap(std::string label, const Map& map) {
deba@2467
  2328
      return _readMap<
deba@2467
  2329
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  2330
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  2331
    }
deba@2467
  2332
deba@2467
  2333
    /// \brief Add a new edge map reader command for the reader.
deba@2467
  2334
    ///
deba@2467
  2335
    /// Add a new edge map reader command for the reader.
deba@2467
  2336
    template <typename ItemReader, typename Map>
deba@2467
  2337
    EdgeMapReader& readEdgeMap(std::string label, Map& map, 
deba@2467
  2338
			  const ItemReader& ir = ItemReader()) {
deba@2467
  2339
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2467
  2340
	(label, map, ir);
deba@2467
  2341
    }
deba@2467
  2342
deba@2467
  2343
    template <typename ItemReader, typename Map>
deba@2467
  2344
    EdgeMapReader& readEdgeMap(std::string label, const Map& map, 
deba@2467
  2345
			  const ItemReader& ir = ItemReader()) {
deba@2467
  2346
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2467
  2347
	(label, map, ir);
deba@2467
  2348
    }
deba@2467
  2349
deba@2467
  2350
  private:
deba@2467
  2351
deba@2467
  2352
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2467
  2353
    EdgeMapReader& _readMap(std::string label, MapParameter map, 
deba@2467
  2354
				const ItemReader& ir = ItemReader()) {
deba@2467
  2355
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
deba@2467
  2356
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2467
  2357
      if (readers.find(label) != readers.end()) {
deba@2467
  2358
	ErrorMessage msg;
deba@2467
  2359
	msg << "Multiple read rule for map: " << label;
deba@2467
  2360
	throw IoParameterError(msg.message());
deba@2467
  2361
      }      
deba@2467
  2362
      readers.insert(
deba@2467
  2363
	make_pair(label, new _reader_bits::
deba@2467
  2364
		  MapReader<Edge, Map, ItemReader>(map, ir)));
deba@2467
  2365
      return *this;
deba@2467
  2366
    }
deba@2467
  2367
deba@2467
  2368
  public:
deba@2467
  2369
deba@2467
  2370
    /// \brief Add a new edge map skipper command for the reader.
deba@2467
  2371
    ///
deba@2467
  2372
    /// Add a new edge map skipper command for the reader.
deba@2467
  2373
    template <typename ItemReader>
deba@2467
  2374
    EdgeMapReader& skipEdgeMap(std::string label, 
deba@2467
  2375
			  const ItemReader& ir = ItemReader()) {
deba@2467
  2376
      if (readers.find(label) != readers.end()) {
deba@2467
  2377
	ErrorMessage msg;
deba@2467
  2378
	msg << "Multiple read rule for map: " << label;
deba@2467
  2379
	throw IoParameterError(msg.message());
deba@2467
  2380
      }
deba@2467
  2381
      readers.insert(make_pair(label, new _reader_bits::
deba@2467
  2382
			       SkipReader<Edge, ItemReader>(ir)));
deba@2467
  2383
      return *this;
deba@2467
  2384
    }
deba@2467
  2385
deba@2467
  2386
  protected:
deba@2467
  2387
deba@2467
  2388
    /// \brief Gives back true when the SectionReader can process 
deba@2467
  2389
    /// the section with the given header line.
deba@2467
  2390
    ///
deba@2467
  2391
    /// It gives back true when the header line starts with \c \@mapset,
deba@2467
  2392
    /// and the header line's name and the mapset's name are the same.
deba@2467
  2393
    virtual bool header(const std::string& line) {
deba@2467
  2394
      std::istringstream ls(line);
deba@2467
  2395
      std::string command;
deba@2467
  2396
      std::string id;
deba@2467
  2397
      ls >> command >> id;
deba@2467
  2398
      return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
deba@2467
  2399
    }
deba@2467
  2400
deba@2467
  2401
    /// \brief Reader function of the section.
deba@2467
  2402
    ///
deba@2467
  2403
    /// It reads the content of the section.
deba@2467
  2404
    virtual void read(std::istream& is) {
deba@2467
  2405
      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
deba@2467
  2406
      std::string line;
deba@2467
  2407
deba@2467
  2408
      {
deba@2467
  2409
        getline(is, line);
deba@2467
  2410
        std::istringstream ls(line);
deba@2467
  2411
        std::string id;
deba@2467
  2412
        while (ls >> id) {
deba@2467
  2413
          typename MapReaders::iterator it = readers.find(id);
deba@2467
  2414
          if (it != readers.end()) {
deba@2467
  2415
            it->second->touch();
deba@2467
  2416
            index.push_back(it->second);
deba@2467
  2417
          } else {
deba@2467
  2418
            index.push_back(&skipper);
deba@2467
  2419
          }
deba@2467
  2420
        }
deba@2467
  2421
      }
deba@2467
  2422
      for (typename MapReaders::iterator it = readers.begin();
deba@2467
  2423
	   it != readers.end(); ++it) {
deba@2467
  2424
	if (!it->second->touched()) {
deba@2467
  2425
	  ErrorMessage msg;
deba@2467
  2426
	  msg << "Map not found in file: " << it->first;
deba@2467
  2427
	  throw IoParameterError(msg.message());
deba@2467
  2428
	}
deba@2467
  2429
      }
deba@2467
  2430
      while (getline(is, line)) {	
deba@2467
  2431
	std::istringstream ls(line);
deba@2467
  2432
	Edge edge = labelReader->read(ls);
deba@2467
  2433
	for (int i = 0; i < int(index.size()); ++i) {
deba@2467
  2434
	  index[i]->read(ls, edge);
deba@2467
  2435
	}
deba@2467
  2436
      }
deba@2467
  2437
    }
deba@2467
  2438
deba@2467
  2439
    virtual void missing() {
deba@2467
  2440
      if (readers.empty()) return;
deba@2467
  2441
      ErrorMessage msg;
deba@2467
  2442
      msg << "EdgeMap section not found in file: @edgemaps " << name;
deba@2467
  2443
      throw IoParameterError(msg.message());
deba@2467
  2444
    }
deba@2467
  2445
deba@2467
  2446
  private:
deba@2467
  2447
deba@2467
  2448
    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
deba@2467
  2449
    MapReaders readers;
deba@2467
  2450
   
deba@2467
  2451
    const Graph& graph;   
deba@2467
  2452
    std::string name;
deba@2467
  2453
    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
deba@2467
  2454
    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > labelReader;
deba@2467
  2455
deba@2467
  2456
  };
deba@2467
  2457
deba@2467
  2458
  /// \ingroup section_io
deba@2467
  2459
  /// \brief SectionReader for reading extra undirected edge maps.
deba@2467
  2460
  ///
deba@2467
  2461
  /// The lemon format can store maps in the uedgeset sections. This
deba@2467
  2462
  /// class let you make distinict section to store maps.  The main
deba@2467
  2463
  /// purpose of this class is a logical separation of some maps. The
deba@2467
  2464
  /// other useful application could be to store paths in undirected
deba@2467
  2465
  /// edge maps.
deba@2467
  2466
  ///
deba@2467
  2467
  /// The first line of the section contains the names of the maps
deba@2467
  2468
  /// separated with white spaces. Each next line describes an item
deba@2467
  2469
  /// in the itemset, and contains in the first column the label of
deba@2467
  2470
  /// the item and then the mapped values for each map.
deba@2467
  2471
  ///
deba@2467
  2472
  /// \relates LemonReader
deba@2467
  2473
  template <typename _Graph, typename _Traits = DefaultReaderTraits>
deba@2467
  2474
  class UEdgeMapReader : public LemonReader::SectionReader {
deba@2467
  2475
    typedef LemonReader::SectionReader Parent;
deba@2467
  2476
  public:
deba@2467
  2477
deba@2467
  2478
    typedef _Graph Graph;
deba@2467
  2479
    typedef typename Graph::Edge Edge;
deba@2467
  2480
    typedef typename Graph::UEdge UEdge;
deba@2467
  2481
    typedef _Traits Traits;
deba@2467
  2482
    typedef typename Traits::Skipper DefaultSkipper;
deba@2467
  2483
deba@2467
  2484
    /// \brief Constructor.
deba@2467
  2485
    ///
deba@2467
  2486
    /// Constructor for UEdgeMapReader. It creates the UEdgeMapReader and
deba@2467
  2487
    /// attach it into the given LemonReader. The reader will read
deba@2467
  2488
    /// the section when the \c section_name and the \c _name are the same.
deba@2467
  2489
    template <typename _LabelReader>
deba@2467
  2490
    UEdgeMapReader(LemonReader& _reader, const Graph& _graph, 
deba@2467
  2491
		   const _LabelReader& _labelReader,
deba@2467
  2492
		   const std::string& _name = std::string(),
deba@2467
  2493
		   const DefaultSkipper& _skipper = DefaultSkipper()) 
deba@2467
  2494
      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
deba@2467
  2495
      labelReader.reset(new _reader_bits::
deba@2467
  2496
			LabelReader<UEdge, _LabelReader>(_labelReader));
deba@2467
  2497
    } 
deba@2467
  2498
deba@2467
  2499
deba@2467
  2500
    /// \brief Destructor.
deba@2467
  2501
    ///
deba@2467
  2502
    /// Destructor for UEdgeMapReader.
deba@2467
  2503
    virtual ~UEdgeMapReader() {
deba@2467
  2504
      for (typename MapReaders::iterator it = readers.begin(); 
deba@2467
  2505
	   it != readers.end(); ++it) {
deba@2467
  2506
	delete it->second;
deba@2467
  2507
      }
deba@2467
  2508
    }
deba@2467
  2509
deba@2467
  2510
  private:
deba@2467
  2511
    UEdgeMapReader(const UEdgeMapReader&);
deba@2467
  2512
    void operator=(const UEdgeMapReader&);
deba@2467
  2513
  
deba@2467
  2514
  public:
deba@2467
  2515
deba@2467
  2516
    /// \brief Add a new undirected edge map reader command for the
deba@2467
  2517
    /// reader.
deba@2467
  2518
    ///
deba@2467
  2519
    /// Add a new undirected edge map reader command for the reader.
deba@2467
  2520
    template <typename Map>
deba@2467
  2521
    UEdgeMapReader& readUEdgeMap(std::string label, Map& map) {
deba@2467
  2522
      return _readMap<
deba@2467
  2523
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  2524
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  2525
    }
deba@2467
  2526
deba@2467
  2527
    template <typename Map>
deba@2467
  2528
    UEdgeMapReader& readUEdgeMap(std::string label, const Map& map) {
deba@2467
  2529
      return _readMap<
deba@2467
  2530
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  2531
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  2532
    }
deba@2467
  2533
deba@2467
  2534
    /// \brief Add a new undirected edge map reader command for the
deba@2467
  2535
    /// reader.
deba@2467
  2536
    ///
deba@2467
  2537
    /// Add a new undirected edge map reader command for the reader.
deba@2467
  2538
    template <typename ItemReader, typename Map>
deba@2467
  2539
    UEdgeMapReader& readUEdgeMap(std::string label, Map& map, 
deba@2467
  2540
			  const ItemReader& ir = ItemReader()) {
deba@2467
  2541
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2467
  2542
	(label, map, ir);
deba@2467
  2543
    }
deba@2467
  2544
deba@2467
  2545
    template <typename ItemReader, typename Map>
deba@2467
  2546
    UEdgeMapReader& readUEdgeMap(std::string label, const Map& map, 
deba@2467
  2547
			  const ItemReader& ir = ItemReader()) {
deba@2467
  2548
      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
deba@2467
  2549
	(label, map, ir);
deba@2467
  2550
    }
deba@2467
  2551
deba@2467
  2552
  private:
deba@2467
  2553
deba@2467
  2554
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2467
  2555
    UEdgeMapReader& _readMap(std::string label, MapParameter map, 
deba@2467
  2556
				const ItemReader& ir = ItemReader()) {
deba@2467
  2557
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
deba@2467
  2558
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2467
  2559
      if (readers.find(label) != readers.end()) {
deba@2467
  2560
	ErrorMessage msg;
deba@2467
  2561
	msg << "Multiple read rule for map: " << label;
deba@2467
  2562
	throw IoParameterError(msg.message());
deba@2467
  2563
      }      
deba@2467
  2564
      readers.insert(
deba@2467
  2565
	make_pair(label, new _reader_bits::
deba@2467
  2566
		  MapReader<UEdge, Map, ItemReader>(map, ir)));
deba@2467
  2567
      return *this;
deba@2467
  2568
    }
deba@2467
  2569
deba@2467
  2570
  public:
deba@2467
  2571
deba@2467
  2572
    /// \brief Add a new undirected edge map skipper command for the
deba@2467
  2573
    /// reader.
deba@2467
  2574
    ///
deba@2467
  2575
    /// Add a new undirected edge map skipper command for the reader.
deba@2467
  2576
    template <typename ItemReader>
deba@2467
  2577
    UEdgeMapReader& skipUEdgeMap(std::string label, 
deba@2467
  2578
			  const ItemReader& ir = ItemReader()) {
deba@2467
  2579
      if (readers.find(label) != readers.end()) {
deba@2467
  2580
	ErrorMessage msg;
deba@2467
  2581
	msg << "Multiple read rule for map: " << label;
deba@2467
  2582
	throw IoParameterError(msg.message());
deba@2467
  2583
      }
deba@2467
  2584
      readers.insert(make_pair(label, new _reader_bits::
deba@2467
  2585
			       SkipReader<Edge, ItemReader>(ir)));
deba@2467
  2586
      return *this;
deba@2467
  2587
    }
deba@2467
  2588
deba@2467
  2589
    /// \brief Add a new directed edge map reader command for the reader.
deba@2467
  2590
    ///
deba@2467
  2591
    /// Add a new directed edge map reader command for the reader.
deba@2467
  2592
    template <typename Map>
deba@2467
  2593
    UEdgeMapReader& readEdgeMap(std::string label, Map& map) {
deba@2467
  2594
      return _readDirMap<
deba@2467
  2595
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  2596
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  2597
    }
deba@2467
  2598
deba@2467
  2599
    template <typename Map>
deba@2467
  2600
    UEdgeMapReader& readEdgeMap(std::string label, const Map& map) {
deba@2467
  2601
      return _readDirMap<
deba@2467
  2602
	typename Traits::template Reader<typename Map::Value>, Map,
deba@2467
  2603
	typename _reader_bits::Arg<Map>::Type>(label, map);
deba@2467
  2604
    }
deba@2467
  2605
deba@2467
  2606
    /// \brief Add a new directed edge map reader command for the reader.
deba@2467
  2607
    ///
deba@2467
  2608
    /// Add a new directed edge map reader command for the reader.
deba@2467
  2609
    template <typename ItemReader, typename Map>
deba@2467
  2610
    UEdgeMapReader& readEdgeMap(std::string label, Map& map, 
deba@2467
  2611
				    const ItemReader& ir = ItemReader()) {
deba@2467
  2612
      return _readDirMap<ItemReader, Map, 
deba@2467
  2613
        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
deba@2467
  2614
    }
deba@2467
  2615
deba@2467
  2616
    template <typename ItemReader, typename Map>
deba@2467
  2617
    UEdgeMapReader& readEdgeMap(std::string label, const Map& map, 
deba@2467
  2618
				    const ItemReader& ir = ItemReader()) {
deba@2467
  2619
      return _readDirMap<ItemReader, Map, 
deba@2467
  2620
        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
deba@2467
  2621
    }
deba@2467
  2622
deba@2467
  2623
  private:
deba@2467
  2624
deba@2467
  2625
    template <typename ItemReader, typename Map, typename MapParameter>
deba@2467
  2626
    UEdgeMapReader& _readDirMap(std::string label, MapParameter map,
deba@2467
  2627
				    const ItemReader& ir = ItemReader()) { 
deba@2467
  2628
      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
deba@2467
  2629
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
deba@2467
  2630
      readUEdgeMap("+" + label, 
deba@2467
  2631
                   _reader_bits::forwardComposeMap(graph, map), ir);
deba@2467
  2632
      readUEdgeMap("-" + label, 
deba@2467
  2633
                   _reader_bits::backwardComposeMap(graph, map), ir);
deba@2467
  2634
      return *this;      
deba@2467
  2635
    }
deba@2467
  2636
deba@2467
  2637
  public:
deba@2467
  2638
deba@2467
  2639
    /// \brief Add a new directed edge map skipper command for the reader.
deba@2467
  2640
    ///
deba@2467
  2641
    /// Add a new directed edge map skipper command for the reader.
deba@2467
  2642
    template <typename ItemReader>
deba@2467
  2643
    UEdgeMapReader& skipEdgeMap(std::string label, 
deba@2467
  2644
                                const ItemReader& ir = ItemReader()) {
deba@2467
  2645
      skipUEdgeMap("+" + label, ir);
deba@2467
  2646
      skipUEdgeMap("-" + label, ir);
deba@2467
  2647
      return *this;
deba@2467
  2648
    }
deba@2467
  2649
deba@2467
  2650
  protected:
deba@2467
  2651
deba@2467
  2652
    /// \brief Gives back true when the SectionReader can process 
deba@2467
  2653
    /// the section with the given header line.
deba@2467
  2654
    ///
deba@2467
  2655
    /// It gives back true when the header line starts with \c \@mapset,
deba@2467
  2656
    /// and the header line's name and the mapset's name are the same.
deba@2467
  2657
    virtual bool header(const std::string& line) {
deba@2467
  2658
      std::istringstream ls(line);
deba@2467
  2659
      std::string command;
deba@2467
  2660
      std::string id;
deba@2467
  2661
      ls >> command >> id;
deba@2467
  2662
      return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
deba@2467
  2663
    }
deba@2467
  2664
deba@2467
  2665
    /// \brief Reader function of the section.
deba@2467
  2666
    ///
deba@2467
  2667
    /// It reads the content of the section.
deba@2467
  2668
    virtual void read(std::istream& is) {
deba@2467
  2669
      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
deba@2467
  2670
      std::string line;
deba@2467
  2671
deba@2467
  2672
      {
deba@2467
  2673
        getline(is, line);
deba@2467
  2674
        std::istringstream ls(line);
deba@2467
  2675
        std::string id;
deba@2467
  2676
        while (ls >> id) {
deba@2467
  2677
          typename MapReaders::iterator it = readers.find(id);
deba@2467
  2678
          if (it != readers.end()) {
deba@2467
  2679
            it->second->touch();
deba@2467
  2680
            index.push_back(it->second);
deba@2467
  2681
          } else {
deba@2467
  2682
            index.push_back(&skipper);
deba@2467
  2683
          }
deba@2467
  2684
        }
deba@2467
  2685
      }
deba@2467
  2686
      for (typename MapReaders::iterator it = readers.begin();
deba@2467
  2687
	   it != readers.end(); ++it) {
deba@2467
  2688
	if (!it->second->touched()) {
deba@2467
  2689
	  ErrorMessage msg;
deba@2467
  2690
	  msg << "Map not found in file: " << it->first;
deba@2467
  2691
	  throw IoParameterError(msg.message());
deba@2467
  2692
	}
deba@2467
  2693
      }
deba@2467
  2694
      while (getline(is, line)) {	
deba@2467
  2695
	std::istringstream ls(line);
deba@2467
  2696
	UEdge uedge = labelReader->read(ls);
deba@2467
  2697
	for (int i = 0; i < int(index.size()); ++i) {
deba@2467
  2698
	  index[i]->read(ls, uedge);
deba@2467
  2699
	}
deba@2467
  2700
      }
deba@2467
  2701
    }
deba@2467
  2702
deba@2467
  2703
    virtual void missing() {
deba@2467
  2704
      if (readers.empty()) return;
deba@2467
  2705
      ErrorMessage msg;
deba@2467
  2706
      msg << "UEdgeMap section not found in file: @uedgemaps " << name;
deba@2467
  2707
      throw IoParameterError(msg.message());
deba@2467
  2708
    }
deba@2467
  2709
deba@2467
  2710
  private:
deba@2467
  2711
deba@2467
  2712
    const Graph& graph;   
deba@2467
  2713
    std::string name;
deba@2467
  2714
deba@2467
  2715
    typedef std::map<std::string, 
deba@2467
  2716
		     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
deba@2467
  2717
   
deba@2467
  2718
    MapReaders readers;
deba@2467
  2719
    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
deba@2467
  2720
deba@2467
  2721
    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > labelReader;
deba@2467
  2722
deba@2467
  2723
  };
deba@2467
  2724
deba@2467
  2725
  /// \ingroup section_io
deba@1423
  2726
  /// \brief SectionReader for retrieve what is in the file.
deba@1423
  2727
  ///
deba@1423
  2728
  /// SectionReader for retrieve what is in the file. If you want
deba@1423
  2729
  /// to know which sections, maps and items are in the file
deba@1423
  2730
  /// use the next code:
alpar@1946
  2731
  ///\code
deba@1423
  2732
  /// LemonReader reader("input.lgf");
deba@1423
  2733
  /// ContentReader content(reader);
deba@1423
  2734
  /// reader.run();
alpar@1946
  2735
  ///\endcode
deba@1423
  2736
  class ContentReader : public LemonReader::SectionReader {
deba@1423
  2737
    typedef LemonReader::SectionReader Parent;
deba@1423
  2738
  public:
deba@1423
  2739
    /// \brief Constructor.
deba@1423
  2740
    ///
deba@1423
  2741
    /// Constructor for
deba@1423
  2742
    ContentReader(LemonReader& _reader) : Parent(_reader) {}
deba@1423
  2743
deba@1423
  2744
    /// \brief Desctructor.
deba@1423
  2745
    ///
deba@1423
  2746
    /// Desctructor.
deba@1423
  2747
    virtual ~ContentReader() {}
deba@1423
  2748
deba@1423
  2749
    /// \brief Gives back how many nodesets are in the file.
deba@1423
  2750
    ///
deba@1423
  2751
    /// Gives back how many nodesets are in the file.
deba@1423
  2752
    int nodeSetNum() const {
deba@1423
  2753
      return nodesets.size();
deba@1423
  2754
    }
deba@1423
  2755
deba@1423
  2756
    /// \brief Gives back the name of nodeset on the indiced position.
deba@1423
  2757
    ///
deba@1423
  2758
    /// Gives back the name of nodeset on the indiced position.
deba@1423
  2759
    std::string nodeSetName(int index) const {
deba@1423
  2760
      return nodesets[index].name;
deba@1423
  2761
    }
deba@1423
  2762
deba@1423
  2763
    /// \brief Gives back the map names of nodeset on the indiced position.
deba@1423
  2764
    ///
deba@1423
  2765
    /// Gives back the map names of nodeset on the indiced position.
deba@1423
  2766
    const std::vector<std::string>& nodeSetMaps(int index) const {
deba@1423
  2767
      return nodesets[index].items;
deba@1423
  2768
    }
deba@1423
  2769
deba@1423
  2770
    /// \brief Gives back how many edgesets are in the file.
deba@1423
  2771
    ///
deba@1423
  2772
    /// Gives back how many edgesets are in the file.
deba@1423
  2773
    int edgeSetNum() const {
deba@1423
  2774
      return edgesets.size();
deba@1423
  2775
    }
deba@1423
  2776
deba@1423
  2777
    /// \brief Gives back the name of edgeset on the indiced position.
deba@1423
  2778
    ///
deba@1423
  2779
    /// Gives back the name of edgeset on the indiced position.
deba@1423
  2780
    std::string edgeSetName(int index) const {
deba@1423
  2781
      return edgesets[index].name;
deba@1423
  2782
    }
deba@1423
  2783
deba@1423
  2784
    /// \brief Gives back the map names of edgeset on the indiced position.
deba@1423
  2785
    ///
deba@1423
  2786
    /// Gives back the map names of edgeset on the indiced position.
deba@1423
  2787
    const std::vector<std::string>& edgeSetMaps(int index) const {
deba@1423
  2788
      return edgesets[index].items;
deba@1423
  2789
    }
deba@1423
  2790
deba@1423
  2791
    /// \brief Gives back how many undirected edgesets are in the file.
deba@1423
  2792
    ///
deba@1423
  2793
    /// Gives back how many undirected edgesets are in the file.
klao@1909
  2794
    int uEdgeSetNum() const {
klao@1909
  2795
      return uedgesets.size();
deba@1423
  2796
    }
deba@1423
  2797
deba@1423
  2798
    /// \brief Gives back the name of undirected edgeset on the indiced 
deba@1423
  2799
    /// position.
deba@1423
  2800
    ///
deba@1423
  2801
    /// Gives back the name of undirected edgeset on the indiced position.
klao@1909
  2802
    std::string uEdgeSetName(int index) const {
klao@1909
  2803
      return uedgesets[index].name;
deba@1423
  2804
    }
deba@1423
  2805
deba@1423
  2806
    /// \brief Gives back the map names of undirected edgeset on the indiced 
deba@1423
  2807
    /// position.
deba@1423
  2808
    ///
deba@1423
  2809
    /// Gives back the map names of undirected edgeset on the indiced position.
klao@1909
  2810
    const std::vector<std::string>& uEdgeSetMaps(int index) const {
klao@1909
  2811
      return uedgesets[index].items;
deba@1423
  2812
    }
deba@1423
  2813
deba@1423
  2814
    /// \brief Gives back how many labeled nodes section are in the file.
deba@1423
  2815
    ///
deba@1423
  2816
    /// Gives back how many labeled nodes section are in the file.
deba@1423
  2817
    int nodesNum() const {
deba@1423
  2818
      return nodes.size();
deba@1423
  2819
    }
deba@1423
  2820
deba@1423
  2821
    /// \brief Gives back the name of labeled nodes section on the indiced 
deba@1423
  2822
    /// position.
deba@1423
  2823
    ///
deba@1423
  2824
    /// Gives back the name of labeled nodes section on the indiced position.
deba@1423
  2825
    std::string nodesName(int index) const {
deba@1423
  2826
      return nodes[index].name;
deba@1423
  2827
    }
deba@1423
  2828
deba@1423
  2829
    /// \brief Gives back the names of the labeled nodes in the indiced 
deba@1423
  2830
    /// section.
deba@1423
  2831
    ///
deba@1423
  2832
    /// Gives back the names of the labeled nodes in the indiced section.
deba@1423
  2833
    const std::vector<std::string>& nodesItems(int index) const {
deba@1423
  2834
      return nodes[index].items;
deba@1423
  2835
    }
deba@1423
  2836
deba@1423
  2837
    /// \brief Gives back how many labeled edges section are in the file.
deba@1423
  2838
    ///
deba@1423
  2839
    /// Gives back how many labeled edges section are in the file.
deba@1423
  2840
    int edgesNum() const {
deba@1423
  2841
      return edges.size();
deba@1423
  2842
    }
deba@1423
  2843
deba@1423
  2844
    /// \brief Gives back the name of labeled edges section on the indiced 
deba@1423
  2845
    /// position.
deba@1423
  2846
    ///
deba@1423
  2847
    /// Gives back the name of labeled edges section on the indiced position.
deba@1423
  2848
    std::string edgesName(int index) const {
deba@1423
  2849
      return edges[index].name;
deba@1423
  2850
    }
deba@1423
  2851
deba@1423
  2852
    /// \brief Gives back the names of the labeled edges in the indiced 
deba@1423
  2853
    /// section.
deba@1423
  2854
    ///
deba@1423
  2855
    /// Gives back the names of the labeled edges in the indiced section.
deba@1423
  2856
    const std::vector<std::string>& edgesItems(int index) const {
deba@1423
  2857
      return edges[index].items;
deba@1423
  2858
    }
deba@1423
  2859
 
deba@1423
  2860
    /// \brief Gives back how many labeled undirected edges section are 
deba@1423
  2861
    /// in the file.
deba@1423
  2862
    ///
deba@1423
  2863
    /// Gives back how many labeled undirected edges section are in the file.
klao@1909
  2864
    int uEdgesNum() const {
klao@1909
  2865
      return uedges.size();
deba@1423
  2866
    }
deba@1423
  2867
deba@1423
  2868
    /// \brief Gives back the name of labeled undirected edges section 
deba@1423
  2869
    /// on the indiced position.
deba@1423
  2870
    ///
deba@1423
  2871
    /// Gives back the name of labeled undirected edges section on the 
deba@1423
  2872
    /// indiced position.
klao@1909
  2873
    std::string uEdgesName(int index) const {
klao@1909
  2874
      return uedges[index].name;
deba@1423
  2875
    }
deba@1423
  2876
deba@1423
  2877
    /// \brief Gives back the names of the labeled undirected edges in 
deba@1423
  2878
    /// the indiced section.
deba@1423
  2879
    ///
deba@1423
  2880
    /// Gives back the names of the labeled undirected edges in the 
deba@1423
  2881
    /// indiced section.
klao@1909
  2882
    const std::vector<std::string>& uEdgesItems(int index) const {
klao@1909
  2883
      return uedges[index].items;
deba@1423
  2884
    }
deba@1423
  2885
deba@1423
  2886
 
deba@1423
  2887
    /// \brief Gives back how many attributes section are in the file.
deba@1423
  2888
    ///
deba@1423
  2889
    /// Gives back how many attributes section are in the file.
deba@1423
  2890
    int attributesNum() const {
deba@1423
  2891
      return attributes.size();
deba@1423
  2892
    }
deba@1423
  2893
deba@1423
  2894
    /// \brief Gives back the name of attributes section on the indiced 
deba@1423
  2895
    /// position.
deba@1423
  2896
    ///
deba@1423
  2897
    /// Gives back the name of attributes section on the indiced position.
deba@1423
  2898
    std::string attributesName(int index) const {
deba@1423
  2899
      return attributes[index].name;
deba@1423
  2900
    }
deba@1423
  2901
deba@1423
  2902
    /// \brief Gives back the names of the attributes in the indiced section.
deba@1423
  2903
    ///
deba@1423
  2904
    /// Gives back the names of the attributes in the indiced section.
deba@1423
  2905
    const std::vector<std::string>& attributesItems(int index) const {
deba@1423
  2906
      return attributes[index].items;
deba@1423
  2907
    }
deba@1423
  2908
deba@1423
  2909
    const std::vector<std::string>& otherSections() const {
deba@1423
  2910
      return sections;
deba@1423
  2911
    }
deba@1423
  2912
deba@1423
  2913
  protected:
deba@1423
  2914
    
deba@1423
  2915
    /// \brief Gives back true when the SectionReader can process 
deba@1423
  2916
    /// the section with the given header line.
deba@1423
  2917
    ///
deba@1423
  2918
    /// It gives back true when the section is common section.
deba@1423
  2919
    bool header(const std::string& line) {
deba@1423
  2920
      std::istringstream ls(line);
deba@1423
  2921
      std::string command, name;
deba@1423
  2922
      ls >> command >> name;
deba@1423
  2923
      if (command == "@nodeset") {
deba@1423
  2924
	current = command;
deba@1423
  2925
	nodesets.push_back(SectionInfo(name));
deba@1423
  2926
      } else if (command == "@edgeset") {
deba@1423
  2927
	current = command;
deba@1423
  2928
	edgesets.push_back(SectionInfo(name));
klao@1909
  2929
      } else if (command == "@uedgeset") {
deba@1423
  2930
	current = command;
klao@1909
  2931
	uedgesets.push_back(SectionInfo(name));
deba@1423
  2932
      } else if (command == "@nodes") {
deba@1423
  2933
	current = command;
deba@1423
  2934
	nodes.push_back(SectionInfo(name));
deba@1423
  2935
      } else if (command == "@edges") {
deba@1423
  2936
	current = command;
deba@1423
  2937
	edges.push_back(SectionInfo(name));
klao@1909
  2938
      } else if (command == "@uedges") {
deba@1423
  2939
	current = command;
klao@1909
  2940
	uedges.push_back(SectionInfo(name));
deba@1423
  2941
      } else if (command == "@attributes") {
deba@1423
  2942
	current = command;
deba@1423
  2943
	attributes.push_back(SectionInfo(name));
deba@1423
  2944
      } else {
deba@1423
  2945
	sections.push_back(line);
deba@1423
  2946
	return false;
deba@1423
  2947
      }
deba@1423
  2948
      return true;
deba@1423
  2949
    }
deba@1423
  2950
deba@1423
  2951
    /// \brief Retrieve the items from various sections.
deba@1423
  2952
    ///
deba@1423
  2953
    /// Retrieve the items from various sections.
deba@1423
  2954
    void read(std::istream& is) {
deba@1423
  2955
      if (current == "@nodeset") {
deba@1423
  2956
	readMapNames(is, nodesets.back().items);
deba@1423
  2957
      } else if (current == "@edgeset") {
deba@1423
  2958
	readMapNames(is, edgesets.back().items);
klao@1909
  2959
      } else if (current == "@uedgeset") {
klao@1909
  2960
	readMapNames(is, uedgesets.back().items);
deba@1423
  2961
      } else if (current == "@nodes") {
deba@1423
  2962
	readItemNames(is, nodes.back().items);
deba@1423
  2963
      } else if (current == "@edges") {
deba@1423
  2964
	readItemNames(is, edges.back().items);
klao@1909
  2965
      } else if (current == "@uedges") {
klao@1909
  2966
	readItemNames(is, uedges.back().items);
deba@1423
  2967
      } else if (current == "@attributes") {
deba@1423
  2968
	readItemNames(is, attributes.back().items);
deba@1423
  2969
      }
deba@1423
  2970
    }    
deba@1423
  2971
deba@1423
  2972
  private:
deba@1423
  2973
deba@1423
  2974
    void readMapNames(std::istream& is, std::vector<std::string>& maps) {
deba@1901
  2975
      std::string line, name;
deba@1423
  2976
      std::getline(is, line);
deba@1423
  2977
      std::istringstream ls(line);
deba@1901
  2978
      while (ls >> name) {
deba@1901
  2979
	maps.push_back(name);
deba@1423
  2980
      }
deba@1423
  2981
      while (getline(is, line));
deba@1423
  2982
    }
deba@1423
  2983
deba@1423
  2984
    void readItemNames(std::istream& is, std::vector<std::string>& maps) {
deba@1901
  2985
      std::string line, name;
deba@1423
  2986
      while (std::getline(is, line)) {
deba@1423
  2987
	std::istringstream ls(line);
deba@1901
  2988
	ls >> name;
deba@1901
  2989
	maps.push_back(name);
deba@1423
  2990
      }
deba@1423
  2991
    }
deba@1423
  2992
deba@1423
  2993
    struct SectionInfo {
deba@1423
  2994
      std::string name;
deba@1423
  2995
      std::vector<std::string> items;
deba@1423
  2996
deba@1423
  2997
      SectionInfo(const std::string& _name) : name(_name) {}
deba@1423
  2998
    };
deba@1423
  2999
deba@1423
  3000
    std::vector<SectionInfo> nodesets;
deba@1423
  3001
    std::vector<SectionInfo> edgesets;
klao@1909
  3002
    std::vector<SectionInfo> uedgesets;
deba@1423
  3003
deba@1423
  3004
    std::vector<SectionInfo> nodes;
deba@1423
  3005
    std::vector<SectionInfo> edges;
klao@1909
  3006
    std::vector<SectionInfo> uedges;
deba@1423
  3007
deba@1423
  3008
    std::vector<SectionInfo> attributes;
deba@1423
  3009
deba@1423
  3010
    std::vector<std::string> sections;
deba@1423
  3011
deba@1423
  3012
    std::string current;
deba@1423
  3013
deba@1423
  3014
  };
deba@1423
  3015
deba@1408
  3016
}
deba@1408
  3017
#endif