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