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