src/work/deba/graph_reader.h
author alpar
Fri, 14 Jan 2005 08:02:10 +0000
changeset 1080 568ce2be7fe0
parent 1036 2f514b5c7122
child 1115 444f69240539
permissions -rw-r--r--
Changes in doc.
deba@1032
     1
/* -*- C++ -*-
deba@1032
     2
 * src/lemon/graph_reader.h - Part of LEMON, a generic C++ optimization library
deba@1032
     3
 *
deba@1032
     4
 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1032
     5
 * (Egervary Combinatorial Optimization Research Group, EGRES).
deba@1032
     6
 *
deba@1032
     7
 * Permission to use, modify and distribute this software is granted
deba@1032
     8
 * provided that this copyright notice appears in all copies. For
deba@1032
     9
 * precise terms see the accompanying LICENSE file.
deba@1032
    10
 *
deba@1032
    11
 * This software is provided "AS IS" with no warranty of any kind,
deba@1032
    12
 * express or implied, and with no claim as to its suitability for any
deba@1032
    13
 * purpose.
deba@1032
    14
 *
deba@1032
    15
 */
deba@1032
    16
deba@1032
    17
///\ingroup gio
deba@1032
    18
///\file
deba@1036
    19
///\brief Graph reader.
deba@1032
    20
deba@1032
    21
#include <iostream>
deba@1032
    22
#include <sstream>
deba@1032
    23
deba@1032
    24
#include <map>
deba@1032
    25
#include <vector>
deba@1032
    26
deba@1037
    27
#include <memory>
deba@1037
    28
deba@1032
    29
#include <lemon/error.h>
deba@1032
    30
deba@1032
    31
/// \todo fix exceptions
deba@1032
    32
deba@1032
    33
deba@1032
    34
namespace lemon {
deba@1036
    35
deba@1036
    36
  // Exceptions
deba@1036
    37
deba@1036
    38
  class IOException {
deba@1036
    39
  public:
deba@1036
    40
    virtual string what() const = 0;
deba@1036
    41
  };
deba@1036
    42
deba@1036
    43
  class DataFormatException : public IOException {
deba@1036
    44
    std::string message;
deba@1036
    45
  public:
deba@1036
    46
    DataFormatException(const std::string& _message) 
deba@1036
    47
      : message(_message) {}
deba@1036
    48
    std::string what() const {
deba@1036
    49
      return "DataFormatException: " + message; 
deba@1036
    50
    }
deba@1036
    51
  };
deba@1036
    52
deba@1037
    53
  template <typename _Exception>
deba@1037
    54
  class StreamException : public _Exception {
deba@1036
    55
  public:
deba@1037
    56
    typedef _Exception Exception;
deba@1037
    57
    StreamException(int _line, Exception _exception) 
deba@1037
    58
      : line_num(_line), Exception(_exception) {}
deba@1037
    59
    virtual int line() const {
deba@1037
    60
      return line_num;
deba@1037
    61
    }
deba@1037
    62
    virtual std::string what() const {
deba@1037
    63
      ostringstream os;
deba@1037
    64
      os << Exception::what() << " in line " << line();
deba@1037
    65
      return os.str();
deba@1037
    66
    }
deba@1036
    67
  private:
deba@1036
    68
    int line_num;
deba@1036
    69
  };  
deba@1036
    70
deba@1036
    71
deba@1036
    72
  // Readers and ReaderTraits
deba@1032
    73
  
deba@1032
    74
  struct DefaultReaderTraits {
deba@1032
    75
deba@1032
    76
    template <typename _Value>
deba@1032
    77
    struct Reader {
deba@1032
    78
      typedef _Value Value;
deba@1032
    79
      void read(std::istream& is, Value& value) {
deba@1036
    80
	if (!(is >> value)) 
deba@1036
    81
	  throw DataFormatException("Default Reader format exception");
deba@1032
    82
      }
deba@1032
    83
    };
deba@1032
    84
deba@1036
    85
    typedef Reader<std::string> DefaultReader;
deba@1032
    86
deba@1032
    87
  };
deba@1032
    88
deba@1036
    89
  class QuotedStringReader {
deba@1036
    90
  public:
deba@1036
    91
    typedef std::string Value;
deba@1036
    92
deba@1036
    93
    QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}
deba@1036
    94
deba@1036
    95
    void read(std::istream& is, std::string& value) {
deba@1036
    96
      char c;
deba@1036
    97
      value.clear();
deba@1036
    98
      is >> ws;
deba@1037
    99
      if (!is.get(c) || c != '\"') throw DataFormatException("Quoted string format");
deba@1036
   100
      while (is.get(c) && c != '\"') {
deba@1036
   101
	if (escaped && c == '\\') {
deba@1036
   102
	  value += readEscape(is);
deba@1036
   103
	} else {
deba@1036
   104
	  value += c;
deba@1036
   105
	}
deba@1036
   106
      }
deba@1037
   107
      if (!is) throw DataFormatException("Quoted string format");
deba@1036
   108
    }
deba@1036
   109
deba@1036
   110
  private:
deba@1036
   111
    
deba@1036
   112
    static char readEscape(std::istream& is) {
deba@1036
   113
      char c;
deba@1036
   114
      switch (is.get(c), c) {
deba@1036
   115
      case '\\':
deba@1036
   116
	return '\\';
deba@1036
   117
      case '\"':
deba@1036
   118
	return '\"';
deba@1036
   119
      case '\'':
deba@1036
   120
	return '\'';
deba@1036
   121
      case '\?':
deba@1036
   122
	return '\?';
deba@1036
   123
      case 'a':
deba@1036
   124
	return '\a';
deba@1036
   125
      case 'b':
deba@1036
   126
	return '\b';
deba@1036
   127
      case 'f':
deba@1036
   128
	return '\f';
deba@1036
   129
      case 'n':
deba@1036
   130
	return '\n';
deba@1036
   131
      case 'r':
deba@1036
   132
	return '\r';
deba@1036
   133
      case 't':
deba@1036
   134
	return '\t';
deba@1036
   135
      case 'v':
deba@1036
   136
	return '\v';
deba@1036
   137
      case 'x':
deba@1036
   138
	{
deba@1036
   139
	  int code;
deba@1036
   140
	  if (!is.get(c) || !isHex(c)) throw DataFormatException("Escape format exception");
deba@1036
   141
	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
deba@1036
   142
	  else code = code * 16 + valueHex(c);
deba@1036
   143
	  return code;
deba@1036
   144
	}
deba@1036
   145
      default:
deba@1036
   146
	{
deba@1036
   147
	  int code;
deba@1036
   148
	  if (!isOct(c)) throw DataFormatException("Escape format exception");
deba@1036
   149
	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) is.putback(c);
deba@1036
   150
	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) is.putback(c);
deba@1036
   151
	  else code = code * 8 + valueOct(c);
deba@1036
   152
	  return code;
deba@1036
   153
	}	      
deba@1036
   154
      } 
deba@1036
   155
    }
deba@1036
   156
deba@1036
   157
    static bool isOct(char c) {
deba@1036
   158
      return '0' <= c && c <='7'; 
deba@1036
   159
    }
deba@1036
   160
    
deba@1036
   161
    static int valueOct(char c) {
deba@1036
   162
      return c - '0';
deba@1036
   163
    }
deba@1036
   164
deba@1036
   165
   static bool isHex(char c) {
deba@1036
   166
      return ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); 
deba@1036
   167
    }
deba@1036
   168
    
deba@1036
   169
    static int valueHex(char c) {
deba@1036
   170
      if ('0' <= c && c <= '9') return c - '0';
deba@1036
   171
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
deba@1036
   172
      return c - 'A' + 10;
deba@1036
   173
    }
deba@1036
   174
deba@1036
   175
    bool escaped;
deba@1032
   176
  };
deba@1032
   177
deba@1032
   178
deba@1036
   179
deba@1036
   180
deba@1036
   181
deba@1036
   182
  // Graph reader
deba@1032
   183
  
deba@1032
   184
  template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits> 
deba@1032
   185
  class GraphReader {
deba@1032
   186
  public:
deba@1032
   187
    
deba@1032
   188
    typedef _Graph Graph;
deba@1032
   189
    typedef typename Graph::Node Node;
deba@1032
   190
    typedef typename Graph::Edge Edge;
deba@1032
   191
deba@1032
   192
    typedef _ReaderTraits ReaderTraits;
deba@1036
   193
    typedef typename ReaderTraits::DefaultReader DefaultReader;
deba@1032
   194
deba@1037
   195
    GraphReader(std::istream& _is, Graph& _graph, const DefaultReader& _reader = DefaultReader()) 
deba@1036
   196
      : is(_is), graph(_graph), nodeSkipper(_reader), edgeSkipper(_reader) {}
deba@1036
   197
deba@1036
   198
deba@1036
   199
    ~GraphReader() {
deba@1036
   200
deba@1037
   201
      for (typename NodeMapReaders::iterator it = node_map_readers.begin(); it != node_map_readers.end(); ++it) {
deba@1036
   202
	delete it->second;
deba@1036
   203
      }
deba@1036
   204
deba@1037
   205
      for (typename EdgeMapReaders::iterator it = edge_map_readers.begin(); it != edge_map_readers.end(); ++it) {
deba@1036
   206
	delete it->second;
deba@1036
   207
      }
deba@1036
   208
deba@1036
   209
    }
deba@1032
   210
deba@1037
   211
    // Node map rules
deba@1037
   212
deba@1032
   213
    template <typename Map>
deba@1036
   214
    GraphReader& readNodeMap(std::string name, Map& map) {
deba@1036
   215
      return readNodeMap<typename ReaderTraits::template Reader<typename Map::Value>, Map>(name, map);
deba@1032
   216
    }
deba@1032
   217
deba@1036
   218
    template <typename Reader, typename Map>
deba@1032
   219
    GraphReader& readNodeMap(std::string name, Map& map, const Reader& reader = Reader()) {
deba@1037
   220
      if (node_map_readers.find(name) != node_map_readers.end()) {
deba@1037
   221
	throw Exception() << "Multiple read rule for node map: " << name;
deba@1036
   222
      }
deba@1037
   223
      node_map_readers.insert(make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
deba@1032
   224
      return *this;
deba@1032
   225
    }
deba@1032
   226
deba@1036
   227
    template <typename Reader>
deba@1036
   228
    GraphReader& skipNodeMap(std::string name, const Reader& reader = Reader()) {
deba@1037
   229
      if (node_map_readers.find(name) != node_map_readers.end()) {
deba@1037
   230
	throw Exception() << "Multiple read rule for node map: " << name;
deba@1036
   231
      }
deba@1037
   232
      node_map_readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
deba@1036
   233
      return *this;
deba@1032
   234
    }
deba@1032
   235
deba@1037
   236
    // Edge map rules
deba@1037
   237
deba@1036
   238
    template <typename Map>
deba@1036
   239
    GraphReader& readEdgeMap(std::string name, Map& map) { 
deba@1036
   240
      return readEdgeMap<typename ReaderTraits::template Reader<typename Map::Value>, Map>(name, map);
deba@1036
   241
    }
deba@1036
   242
deba@1036
   243
deba@1036
   244
    template <typename Reader, typename Map>
deba@1032
   245
    GraphReader& readEdgeMap(std::string name, Map& map, const Reader& reader = Reader()) {
deba@1037
   246
      if (edge_map_readers.find(name) != edge_map_readers.end()) {
deba@1037
   247
	throw Exception() << "Multiple read rule for edge map: " << name;
deba@1036
   248
      }
deba@1037
   249
      edge_map_readers.insert(make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
deba@1032
   250
      return *this;
deba@1032
   251
    }
deba@1032
   252
deba@1036
   253
    template <typename Reader>
deba@1036
   254
    GraphReader& skipEdgeMap(std::string name, const Reader& reader = Reader()) {
deba@1037
   255
      if (edge_map_readers.find(name) != edge_map_readers.end()) {
deba@1037
   256
	throw Exception() << "Multiple read rule for edge map: " << name;
deba@1037
   257
      }
deba@1037
   258
      edge_map_readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
deba@1037
   259
      return *this;
deba@1037
   260
    }
deba@1037
   261
deba@1037
   262
    // Node rules
deba@1037
   263
    GraphReader& readNode(std::string name, Node& node) {
deba@1037
   264
      if (node_readers.find(name) != node_readers.end()) {
deba@1037
   265
	throw Exception() << "Multiple read rule for node";
deba@1037
   266
      }
deba@1037
   267
      node_readers.insert(make_pair(name, &node));
deba@1037
   268
    }
deba@1037
   269
deba@1037
   270
    // Edge rules
deba@1037
   271
deba@1037
   272
    GraphReader& readEdge(std::string name, Edge& edge) {
deba@1036
   273
      if (edge_readers.find(name) != edge_readers.end()) {
deba@1037
   274
	throw Exception() << "Multiple read rule for edge";
deba@1036
   275
      }
deba@1037
   276
      edge_readers.insert(make_pair(name, &edge));
deba@1036
   277
    }
deba@1036
   278
deba@1032
   279
    void read() {
deba@1032
   280
      int line_num = 0;
deba@1037
   281
      std::auto_ptr<InverterBase<Node> > nodeInverter;
deba@1037
   282
      std::auto_ptr<InverterBase<Edge> > edgeInverter;
deba@1037
   283
      try {
deba@1037
   284
	std::string line = readNotEmptyLine(is, line_num);
deba@1037
   285
	if (line.find("@nodeset") == 0) {
deba@1037
   286
	  line = readNodeSet(line_num, nodeInverter);
deba@1037
   287
	} 
deba@1037
   288
	if (line.find("@edgeset") == 0) {
deba@1037
   289
	  line = readEdgeSet(line_num, edgeInverter, nodeInverter);
deba@1036
   290
	}
deba@1037
   291
	if (line.find("@nodes") == 0) {
deba@1037
   292
	  line = readNodes(line_num, nodeInverter);
deba@1037
   293
	}
deba@1037
   294
	if (line.find("@edges") == 0) {
deba@1037
   295
	  line = readEdges(line_num, edgeInverter);
deba@1037
   296
	}
deba@1037
   297
	if (line.find("@end") != 0) {
deba@1037
   298
	  throw DataFormatException("Invalid control sequence: " + line);
deba@1037
   299
	}
deba@1037
   300
      } catch (DataFormatException e) {
deba@1037
   301
	throw StreamException<DataFormatException>(line_num, e);
deba@1037
   302
      }
deba@1032
   303
    }
deba@1032
   304
deba@1032
   305
  private:
deba@1032
   306
deba@1036
   307
    template <typename Item> class InverterBase;
deba@1036
   308
deba@1037
   309
    std::string readNodeSet(int& line_num, auto_ptr<InverterBase<Node> > & nodeInverter) {
deba@1037
   310
      std::vector<ReaderBase<Node>* > index;
deba@1032
   311
      {
deba@1032
   312
	std::string line = readNotEmptyLine(is, line_num);    
deba@1032
   313
	std::string id;
deba@1032
   314
	std::istringstream ls(line);	
deba@1032
   315
	while (ls >> id) {
deba@1036
   316
	  if (id[0] == '#') break;
deba@1037
   317
	  typename NodeMapReaders::iterator it = node_map_readers.find(id);
deba@1037
   318
	  if (it != node_map_readers.end()) {
deba@1032
   319
	    index.push_back(it->second);
deba@1037
   320
	    node_map_readers.erase(it);
deba@1032
   321
	  } else {
deba@1036
   322
	    index.push_back(&nodeSkipper);
deba@1032
   323
	  }
deba@1032
   324
	}
deba@1032
   325
      }
deba@1036
   326
deba@1037
   327
      if (index.size() == 0) {
deba@1037
   328
	throw DataFormatException("No node map found");
deba@1037
   329
      }
deba@1037
   330
deba@1037
   331
      nodeInverter = auto_ptr<InverterBase<Node> >(index[0]->getInverter());
deba@1032
   332
      std::string line;
deba@1032
   333
      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
deba@1032
   334
	Node node = graph.addNode();
deba@1032
   335
	std::istringstream ls(line);
deba@1036
   336
	nodeInverter->read(ls, node);
deba@1037
   337
	for (int i = 1; i < index.size(); ++i) {
deba@1036
   338
	  index[i]->read(ls, node);
deba@1032
   339
	}
deba@1032
   340
      }
deba@1037
   341
      return line;
deba@1032
   342
    }
deba@1032
   343
deba@1037
   344
    std::string readEdgeSet(int& line_num, 
deba@1037
   345
		     auto_ptr<InverterBase<Edge> > & edgeInverter, auto_ptr<InverterBase<Node> > & nodeInverter) {
deba@1036
   346
      std::vector<ReaderBase<Edge>*> index;
deba@1036
   347
      {
deba@1036
   348
	std::string line = readNotEmptyLine(is, line_num);    
deba@1036
   349
	std::string id;
deba@1036
   350
	std::istringstream ls(line);	
deba@1036
   351
	while (ls >> id) {
deba@1036
   352
	  if (id[0] == '#') break;
deba@1037
   353
	  typename EdgeMapReaders::iterator it = edge_map_readers.find(id);
deba@1037
   354
	  if (it != edge_map_readers.end()) {
deba@1036
   355
	    index.push_back(it->second);
deba@1037
   356
	    edge_map_readers.erase(it);
deba@1036
   357
	  } else {
deba@1036
   358
	    index.push_back(&edgeSkipper);
deba@1036
   359
	  }
deba@1036
   360
	}
deba@1036
   361
      }
deba@1037
   362
deba@1037
   363
      if (index.size() == 0) {
deba@1037
   364
	throw DataFormatException("No edge map found");
deba@1037
   365
      }
deba@1037
   366
deba@1037
   367
      edgeInverter = auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
deba@1036
   368
      std::string line;
deba@1036
   369
      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {	
deba@1036
   370
	std::istringstream ls(line);
deba@1036
   371
	Node source = nodeInverter->read(ls);
deba@1036
   372
	Node target = nodeInverter->read(ls);
deba@1036
   373
	Edge edge = graph.addEdge(source, target);
deba@1036
   374
	edgeInverter->read(ls, edge);
deba@1037
   375
	for (int i = 1; i < index.size(); ++i) {
deba@1036
   376
	  index[i]->read(ls, edge);
deba@1036
   377
	}
deba@1036
   378
      }      
deba@1037
   379
      return line;
deba@1037
   380
    }
deba@1037
   381
deba@1037
   382
    std::string readNodes(int& line_num, auto_ptr<InverterBase<Node> >& nodeInverter) {
deba@1037
   383
      std::string line;
deba@1037
   384
      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
deba@1037
   385
	std::istringstream ls(line);
deba@1037
   386
	std::string name;
deba@1037
   387
	ls >> name;
deba@1037
   388
	typename NodeReaders::iterator it = node_readers.find(name);
deba@1037
   389
	if (it != node_readers.end()) {
deba@1037
   390
	  *(it -> second) = nodeInverter->read(ls);
deba@1037
   391
	} 
deba@1037
   392
      }        
deba@1037
   393
      return line;
deba@1037
   394
    }
deba@1037
   395
deba@1037
   396
    std::string readEdges(int& line_num, auto_ptr<InverterBase<Edge> >& edgeInverter) {
deba@1037
   397
      std::string line;
deba@1037
   398
      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
deba@1037
   399
	std::istringstream ls(line);
deba@1037
   400
	std::string name;
deba@1037
   401
	ls >> name;
deba@1037
   402
	typename EdgeReaders::iterator it = edge_readers.find(name);
deba@1037
   403
	if (it != edge_readers.end()) {
deba@1037
   404
	  *(it -> second) = edgeInverter->read(ls);
deba@1037
   405
	} 
deba@1037
   406
      }        
deba@1037
   407
      return line;    
deba@1032
   408
    }
deba@1032
   409
deba@1032
   410
    std::string readNotEmptyLine(std::istream& is, int& line_num) {
deba@1032
   411
      std::string line;
deba@1032
   412
      while (++line_num, getline(is, line)) {	
deba@1032
   413
	int vi = line.find_first_not_of(" \t");
deba@1032
   414
	if (vi != string::npos && line[vi] != '#') {
deba@1032
   415
	  return line.substr(vi);
deba@1032
   416
	}
deba@1032
   417
      }
deba@1037
   418
      throw DataFormatException("End of stream");
deba@1032
   419
    }
deba@1032
   420
    
deba@1037
   421
    // Inverters store and give back the Item from the id,
deba@1037
   422
    // and may put the ids into a map.
deba@1037
   423
    
deba@1036
   424
    template <typename _Item>
deba@1036
   425
    class InverterBase {
deba@1036
   426
    public:
deba@1036
   427
      typedef _Item Item;
deba@1037
   428
      virtual void read(std::istream&, const Item&) = 0;
deba@1037
   429
      virtual Item read(std::istream&) = 0;
deba@1036
   430
    };
deba@1032
   431
deba@1036
   432
    template <typename _Item, typename _Map, typename _Reader>
deba@1036
   433
    class MapReaderInverter : public InverterBase<_Item> {
deba@1036
   434
    public:
deba@1036
   435
      typedef _Item Item;
deba@1036
   436
      typedef _Reader Reader;
deba@1036
   437
      typedef typename Reader::Value Value;
deba@1036
   438
      typedef _Map Map;
deba@1036
   439
      typedef std::map<Value, Item> Inverse;
deba@1036
   440
deba@1036
   441
      Map& map;
deba@1036
   442
      Reader reader;
deba@1036
   443
      Inverse inverse;
deba@1036
   444
deba@1036
   445
      MapReaderInverter(Map& _map, const Reader& _reader) 
deba@1036
   446
	: map(_map), reader(_reader) {}
deba@1036
   447
deba@1037
   448
      virtual void read(std::istream& is, const Item& item) {
deba@1036
   449
	Value value;
deba@1036
   450
	reader.read(is, value);
deba@1036
   451
	map.set(item, value);
deba@1036
   452
	typename Inverse::iterator it = inverse.find(value);
deba@1036
   453
	if (it == inverse.end()) {
deba@1036
   454
	  inverse.insert(make_pair(value, item));
deba@1036
   455
	} else {
deba@1036
   456
	  throw DataFormatException("Multiple ID occurence");
deba@1036
   457
	}
deba@1036
   458
      }
deba@1036
   459
deba@1037
   460
      virtual Item read(std::istream& is) {
deba@1036
   461
	Value value;
deba@1036
   462
	reader.read(is, value);	
deba@1036
   463
	typename Inverse::const_iterator it = inverse.find(value);
deba@1036
   464
	if (it != inverse.end()) {
deba@1036
   465
	  return it->second;
deba@1036
   466
	} else {
deba@1036
   467
	  throw DataFormatException("Invalid ID");
deba@1036
   468
	}
deba@1036
   469
      }      
deba@1036
   470
    };
deba@1036
   471
deba@1036
   472
    template <typename _Item, typename _Reader>
deba@1036
   473
    class SkipReaderInverter : public InverterBase<_Item> {
deba@1036
   474
    public:
deba@1036
   475
      typedef _Item Item;
deba@1036
   476
      typedef _Reader Reader;
deba@1036
   477
      typedef typename Reader::Value Value;
deba@1036
   478
      typedef std::map<Value, Item> Inverse;
deba@1036
   479
deba@1036
   480
      Reader reader;
deba@1036
   481
deba@1036
   482
      SkipReaderInverter(const Reader& _reader) 
deba@1036
   483
	: reader(_reader) {}
deba@1036
   484
deba@1037
   485
      virtual void read(std::istream& is, const Item& item) {
deba@1036
   486
	Value value;
deba@1036
   487
	reader.read(is, value);
deba@1036
   488
	typename Inverse::iterator it = inverse.find(value);
deba@1036
   489
	if (it == inverse.end()) {
deba@1036
   490
	  inverse.insert(make_pair(value, item));
deba@1036
   491
	} else {
deba@1036
   492
	  throw DataFormatException("Multiple ID occurence");
deba@1036
   493
	}
deba@1036
   494
      }
deba@1036
   495
deba@1037
   496
      virtual Item read(std::istream& is) {
deba@1036
   497
	Value value;
deba@1036
   498
	reader.read(is, value);	
deba@1036
   499
	typename Inverse::const_iterator it = inverse.find(value);
deba@1036
   500
	if (it != inverse.end()) {
deba@1036
   501
	  return it->second;
deba@1036
   502
	} else {
deba@1036
   503
	  throw DataFormatException("Invalid ID");
deba@1036
   504
	}
deba@1036
   505
      }      
deba@1036
   506
    private:
deba@1036
   507
      Inverse inverse;
deba@1036
   508
    };
deba@1036
   509
deba@1037
   510
    // Readers
deba@1032
   511
deba@1032
   512
    template <typename _Item>    
deba@1036
   513
    class ReaderBase {
deba@1032
   514
    public:
deba@1032
   515
      typedef _Item Item;
deba@1037
   516
deba@1037
   517
      virtual void read(std::istream& is, const Item& item) = 0;
deba@1036
   518
      virtual InverterBase<_Item>* getInverter() = 0;
deba@1032
   519
    };
deba@1036
   520
deba@1032
   521
    template <typename _Item, typename _Map, typename _Reader>
deba@1036
   522
    class MapReader : public ReaderBase<_Item> {
deba@1032
   523
    public:
deba@1032
   524
      typedef _Map Map;
deba@1032
   525
      typedef _Reader Reader;
deba@1036
   526
      typedef typename Reader::Value Value;
deba@1032
   527
      typedef _Item Item;
deba@1032
   528
      
deba@1032
   529
      Map& map;
deba@1032
   530
      Reader reader;
deba@1032
   531
deba@1032
   532
      MapReader(Map& _map, const Reader& _reader) 
deba@1032
   533
	: map(_map), reader(_reader) {}
deba@1032
   534
deba@1032
   535
deba@1037
   536
      virtual void read(std::istream& is, const Item& item) {
deba@1036
   537
	Value value;
deba@1032
   538
	reader.read(is, value);
deba@1032
   539
	map.set(item, value);
deba@1032
   540
      }
deba@1036
   541
deba@1036
   542
      virtual InverterBase<_Item>* getInverter() {
deba@1036
   543
	return new MapReaderInverter<Item, Map, Reader>(map, reader);
deba@1036
   544
      }
deba@1032
   545
    };
deba@1032
   546
deba@1036
   547
deba@1036
   548
    template <typename _Item, typename _Reader>
deba@1036
   549
    class SkipReader : public ReaderBase<_Item> {
deba@1036
   550
    public:
deba@1036
   551
      typedef _Reader Reader;
deba@1036
   552
      typedef typename Reader::Value Value;
deba@1036
   553
      typedef _Item Item;
deba@1036
   554
deba@1036
   555
      Reader reader;
deba@1036
   556
      SkipReader(const Reader& _reader) : reader(_reader) {}
deba@1036
   557
deba@1037
   558
      virtual void read(std::istream& is, const Item& item) {
deba@1036
   559
	Value value;
deba@1036
   560
	reader.read(is, value);
deba@1036
   561
      }      
deba@1036
   562
deba@1036
   563
      virtual InverterBase<Item>* getInverter() {
deba@1036
   564
	return new SkipReaderInverter<Item, Reader>(reader);
deba@1036
   565
      }
deba@1036
   566
    };
deba@1036
   567
deba@1036
   568
deba@1037
   569
    typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders;
deba@1037
   570
    NodeMapReaders node_map_readers;
deba@1037
   571
deba@1037
   572
    typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders;
deba@1037
   573
    EdgeMapReaders edge_map_readers;
deba@1037
   574
deba@1037
   575
    typedef std::map<std::string, Node*> NodeReaders;
deba@1032
   576
    NodeReaders node_readers;
deba@1032
   577
deba@1037
   578
    typedef std::map<std::string, Edge*> EdgeReaders;
deba@1032
   579
    EdgeReaders edge_readers;
deba@1032
   580
deba@1036
   581
    std::istream& is;
deba@1036
   582
    Graph& graph;
deba@1036
   583
deba@1036
   584
    SkipReader<Node, DefaultReader> nodeSkipper;
deba@1036
   585
    SkipReader<Edge, DefaultReader> edgeSkipper;
deba@1036
   586
deba@1032
   587
  };
deba@1032
   588
deba@1032
   589
}