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