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