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