lemon/lemon_reader.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1722 2acb5f9bfa72
child 1845 f8bbfed86036
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
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