src/lemon/graph_reader.h
author alpar
Fri, 15 Apr 2005 22:12:51 +0000
changeset 1363 a32f990b73d9
parent 1343 a81f9cfc9775
child 1394 f0c48d7fa73d
permissions -rw-r--r--
An unnecessary duplicate removed.
     1 /* -*- C++ -*-
     2  * src/lemon/graph_reader.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Research Group on Combinatorial Optimization, 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 io_group
    18 ///\file
    19 ///\brief Lemon Graph Format reader.
    20 
    21 #ifndef LEMON_GRAPH_READER_H
    22 #define LEMON_GRAPH_READER_H
    23 
    24 #include <iostream>
    25 #include <sstream>
    26 
    27 #include <map>
    28 #include <vector>
    29 
    30 #include <memory>
    31 
    32 #include <lemon/error.h>
    33 
    34 
    35 namespace lemon {
    36 
    37   /// \addtogroup io_group
    38   /// @{
    39 
    40   /// \brief Standard ReaderTraits for the GraphReader class.
    41   ///
    42   /// Standard ReaderTraits for the GraphReader class.
    43   /// It defines standard reading method for all type of value. 
    44   /// \author Balazs Dezso
    45   struct DefaultReaderTraits {
    46 
    47     /// \brief Template class for reading an value.
    48     ///
    49     /// Template class for reading an value.
    50     /// \author Balazs Dezso
    51     template <typename _Value>
    52     struct Reader {
    53       /// The value type.
    54       typedef _Value Value;
    55       /// \brief Reads a value from the given stream.
    56       ///
    57       /// Reads a value from the given stream.
    58       void read(std::istream& is, Value& value) {
    59 	if (!(is >> value)) 
    60 	  throw DataFormatError("Default reader format exception");
    61       }
    62     };
    63 
    64     /// \brief Returns wheter this name is an ID map name.
    65     ///
    66     /// Returns wheter this name is an ID map name.
    67     static bool idMapName(const std::string& name) {
    68       return name == "id";
    69     }
    70 
    71     /// The reader class for the not needed maps.
    72     typedef Reader<std::string> DefaultReader;
    73 
    74   };
    75 
    76   /// \brief Reader class for quoted strings.
    77   ///
    78   /// Reader class for quoted strings. It can process the escape
    79   /// sequences in the string.
    80   /// \author Balazs Dezso
    81   class QuotedStringReader {
    82   public:
    83     typedef std::string Value;
    84     
    85     /// \brief Constructor for the reader.
    86     ///
    87     /// Constructor for the reader. If the given parameter is true
    88     /// the reader processes the escape sequences.
    89     QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}
    90     
    91     /// \brief Reads a quoted string from the given stream.
    92     ///
    93     /// Reads a quoted string from the given stream.
    94     void read(std::istream& is, std::string& value) {
    95       char c;
    96       value.clear();
    97       is >> std::ws;
    98       if (!is.get(c) || c != '\"') 
    99 	throw DataFormatError("Quoted string format error");
   100       while (is.get(c) && c != '\"') {
   101 	if (escaped && c == '\\') {
   102 	  value += readEscape(is);
   103 	} else {
   104 	  value += c;
   105 	}
   106       }
   107       if (!is) throw DataFormatError("Quoted string format error");
   108     }
   109 
   110   private:
   111     
   112     static char readEscape(std::istream& is) {
   113       char c;
   114       switch (is.get(c), c) {
   115       case '\\':
   116 	return '\\';
   117       case '\"':
   118 	return '\"';
   119       case '\'':
   120 	return '\'';
   121       case '\?':
   122 	return '\?';
   123       case 'a':
   124 	return '\a';
   125       case 'b':
   126 	return '\b';
   127       case 'f':
   128 	return '\f';
   129       case 'n':
   130 	return '\n';
   131       case 'r':
   132 	return '\r';
   133       case 't':
   134 	return '\t';
   135       case 'v':
   136 	return '\v';
   137       case 'x':
   138 	{
   139 	  int code;
   140 	  if (!is.get(c) || !isHex(c)) 
   141 	    throw DataFormatError("Escape format error");
   142 	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
   143 	  else code = code * 16 + valueHex(c);
   144 	  return code;
   145 	}
   146       default:
   147 	{
   148 	  int code;
   149 	  if (!isOct(c)) 
   150 	    throw DataFormatError("Escape format error");
   151 	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
   152 	    is.putback(c);
   153 	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
   154 	    is.putback(c);
   155 	  else code = code * 8 + valueOct(c);
   156 	  return code;
   157 	}	      
   158       } 
   159     }
   160 
   161     static bool isOct(char c) {
   162       return '0' <= c && c <='7'; 
   163     }
   164     
   165     static int valueOct(char c) {
   166       return c - '0';
   167     }
   168 
   169    static bool isHex(char c) {
   170       return ('0' <= c && c <= '9') || 
   171 	('a' <= c && c <= 'z') || 
   172 	('A' <= c && c <= 'Z'); 
   173     }
   174     
   175     static int valueHex(char c) {
   176       if ('0' <= c && c <= '9') return c - '0';
   177       if ('a' <= c && c <= 'z') return c - 'a' + 10;
   178       return c - 'A' + 10;
   179     }
   180 
   181     bool escaped;
   182   };
   183 
   184   /// \brief The graph reader class.
   185   ///
   186   ///
   187   /// The given file format may contain several maps and labeled nodes or 
   188   /// edges.
   189   ///
   190   /// If you read a graph you need not read all the maps and items just those
   191   /// that you need. The interface of the \c GraphReader is very similar to
   192   /// the GraphWriter but the reading method does not depend on the order the
   193   /// given commands.
   194   ///
   195   /// The reader object suppose that each not readed value does not contain 
   196   /// whitespaces, therefore it has some extra possibilities to control how
   197   /// it should skip the values when the string representation contains spaces.
   198   ///
   199   /// \code
   200   /// GraphReader<ListGraph> reader(std::cin, graph);
   201   /// \endcode
   202   ///
   203   /// The \c addNodeMap() function reads a map from the \c \@nodeset section.
   204   /// If there is a map that you do not want to read from the file and there is
   205   /// whitespace in the string represenation of the values then you should
   206   /// call the \c skipNodeMap() template member function with proper 
   207   /// parameters.
   208   ///
   209   /// \code
   210   /// reader.addNodeMap("x-coord", xCoordMap);
   211   /// reader.addNodeMap("y-coord", yCoordMap);
   212   ///
   213   /// reader.addNodeMap<QuotedStringReader>("label", labelMap);
   214   /// reader.skipNodeMap<QuotedStringReader>("description");
   215   ///
   216   /// reader.addNodeMap("color", colorMap);
   217   /// \endcode
   218   ///
   219   /// With the \c addEdgeMap() member function you can give an edge map
   220   /// reading command similar to the NodeMaps. 
   221   ///
   222   /// \code
   223   /// reader.addEdgeMap("weight", weightMap);
   224   /// reader.addEdgeMap("label", labelMap);
   225   /// \endcode
   226   ///
   227   /// With \c addNode() and \c addEdge() functions you can read labeled Nodes 
   228   /// and Edges.
   229   ///
   230   /// \code
   231   /// reader.addNode("source", sourceNode);
   232   /// reader.addNode("target", targetNode);
   233   ///
   234   /// reader.addEdge("observed", edge);
   235   /// \endcode
   236   ///
   237   /// After you give all read commands you must call the \c run() member
   238   /// function, which execute all the commands.
   239   ///
   240   /// \code
   241   /// reader.run();
   242   /// \endcode
   243   ///
   244   /// \see DefaultReaderTraits
   245   /// \see QuotedStringReader
   246   /// \see \ref GraphWriter
   247   /// \see \ref graph-io-page
   248   /// \author Balazs Dezso
   249   template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits> 
   250   class GraphReader {
   251   public:
   252     
   253     typedef _Graph Graph;
   254     typedef typename Graph::Node Node;
   255     typedef typename Graph::Edge Edge;
   256 
   257     typedef _ReaderTraits ReaderTraits;
   258     typedef typename ReaderTraits::DefaultReader DefaultReader;
   259 
   260     /// \brief Construct a new GraphReader.
   261     ///
   262     /// Construct a new GraphReader. It reads into the given graph
   263     /// and it use the given reader as the default skipper.
   264     GraphReader(std::istream& _is, Graph& _graph, 
   265 		const DefaultReader& _reader = DefaultReader()) 
   266       : is(_is), graph(_graph), nodeSkipper(_reader), edgeSkipper(_reader) {}
   267 
   268     /// \brief Destruct the graph reader.
   269     ///
   270     /// Destruct the graph reader.
   271     ~GraphReader() {
   272       for (typename NodeMapReaders::iterator it = node_map_readers.begin(); 
   273 	   it != node_map_readers.end(); ++it) {
   274 	delete it->second;
   275       }
   276 
   277       for (typename EdgeMapReaders::iterator it = edge_map_readers.begin(); 
   278 	   it != edge_map_readers.end(); ++it) {
   279 	delete it->second;
   280       }
   281 
   282     }
   283 
   284     /// \brief Add a new node map reader command for the reader.
   285     ///
   286     /// Add a new node map reader command for the reader.
   287     template <typename Map>
   288     GraphReader& addNodeMap(std::string name, Map& map) {
   289       return addNodeMap<typename ReaderTraits::template 
   290 	Reader<typename Map::Value>, Map>(name, map);
   291     }
   292 
   293     /// \brief Add a new node map reader command for the reader.
   294     ///
   295     /// Add a new node map reader command for the reader.
   296     template <typename Reader, typename Map>
   297     GraphReader& addNodeMap(std::string name, Map& map, 
   298 			     const Reader& reader = Reader()) {
   299       if (node_map_readers.find(name) != node_map_readers.end()) {
   300 	ErrorMessage msg;
   301 	msg << "Multiple read rule for node map: " << name;
   302 	throw IOParameterError(msg.message());
   303       }
   304       node_map_readers.insert(
   305         make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
   306       return *this;
   307     }
   308 
   309     /// \brief Add a new node map skipper command for the reader.
   310     ///
   311     /// Add a new node map skipper command for the reader.
   312     template <typename Reader>
   313     GraphReader& skipNodeMap(std::string name, 
   314 			     const Reader& reader = Reader()) {
   315       if (node_map_readers.find(name) != node_map_readers.end()) {
   316 	ErrorMessage msg;
   317 	msg << "Multiple read rule for node map: " << name;
   318 	throw IOParameterError(msg.message());
   319       }
   320       node_map_readers.insert(
   321         make_pair(name, new SkipReader<Node, Reader>(reader)));
   322       return *this;
   323     }
   324 
   325     /// \brief Add a new edge map reader command for the reader.
   326     ///
   327     /// Add a new edge map reader command for the reader.
   328     template <typename Map>
   329     GraphReader& addEdgeMap(std::string name, Map& map) { 
   330       return addEdgeMap<typename ReaderTraits::template
   331 	Reader<typename Map::Value>, Map>(name, map);
   332     }
   333 
   334 
   335     /// \brief Add a new edge map reader command for the reader.
   336     ///
   337     /// Add a new edge map reader command for the reader.
   338     template <typename Reader, typename Map>
   339     GraphReader& addEdgeMap(std::string name, Map& map,
   340 			     const Reader& reader = Reader()) {
   341       if (edge_map_readers.find(name) != edge_map_readers.end()) {
   342 	ErrorMessage msg;
   343 	msg << "Multiple read rule for edge map: " << name;
   344 	throw IOParameterError(msg.message());
   345       }
   346       edge_map_readers.insert(
   347         make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
   348       return *this;
   349     }
   350 
   351     /// \brief Add a new edge map skipper command for the reader.
   352     ///
   353     /// Add a new edge map skipper command for the reader.
   354     template <typename Reader>
   355     GraphReader& skipEdgeMap(std::string name,
   356 			     const Reader& reader = Reader()) {
   357       if (edge_map_readers.find(name) != edge_map_readers.end()) {
   358 	ErrorMessage msg;
   359 	msg << "Multiple read rule for edge map: " << name;
   360 	throw IOParameterError(msg.message());
   361       }
   362       edge_map_readers.insert(
   363         make_pair(name, new SkipReader<Edge, Reader>(reader)));
   364       return *this;
   365     }
   366 
   367     /// \brief Add a new labeled node reader for the reader.
   368     ///
   369     /// Add a new labeled node reader for the reader.
   370     GraphReader& addNode(std::string name, Node& node) {
   371       if (node_readers.find(name) != node_readers.end()) {
   372 	ErrorMessage msg;
   373 	msg << "Multiple read rule for node: " << name;
   374 	throw IOParameterError(msg.message());
   375       }
   376       node_readers.insert(make_pair(name, &node));
   377       return *this;
   378     }
   379 
   380     /// \brief Add a new labeled edge reader for the reader.
   381     ///
   382     /// Add a new labeled edge reader for the reader.
   383     GraphReader& addEdge(std::string name, Edge& edge) {
   384       if (edge_readers.find(name) != edge_readers.end()) {
   385 	ErrorMessage msg;
   386 	msg << "Multiple read rule for edge: " << name;
   387 	throw IOParameterError(msg.message());
   388       }
   389       edge_readers.insert(make_pair(name, &edge));
   390       return *this;
   391     }
   392 
   393     /// \brief Executes the reader commands.
   394     ///
   395     /// Executes the reader commands.
   396     void run() {
   397       int line_num = 0;
   398       std::auto_ptr<InverterBase<Node> > nodeInverter;
   399       std::auto_ptr<InverterBase<Edge> > edgeInverter;
   400       try {
   401 	std::string line = readNotEmptyLine(is, line_num);
   402 	if (line.find("@nodeset") == 0) {
   403 	  line = readNodeSet(line_num, nodeInverter);
   404 	} 
   405 	if (line.find("@edgeset") == 0) {
   406 	  line = readEdgeSet(line_num, edgeInverter, nodeInverter);
   407 	}
   408 	if (line.find("@nodes") == 0) {
   409 	  line = readNodes(line_num, nodeInverter);
   410 	}
   411 	if (line.find("@edges") == 0) {
   412 	  line = readEdges(line_num, edgeInverter);
   413 	}
   414 	if (line.find("@end") != 0) {
   415 	  throw DataFormatError("Invalid control sequence error");
   416 	}
   417       } catch (DataFormatError e) {
   418 	e.line(line_num);
   419 	throw e;
   420       }
   421     }
   422 
   423   private:
   424 
   425     template <typename Item> class InverterBase;
   426 
   427     std::string readNodeSet(int& line_num, 
   428 			    std::auto_ptr<InverterBase<Node> >& nodeInverter) {
   429       std::vector<ReaderBase<Node>* > index;
   430       {
   431 	std::string line = readNotEmptyLine(is, line_num);    
   432 	std::string id;
   433 	std::istringstream ls(line);	
   434 	while (ls >> id) {
   435 	  typename NodeMapReaders::iterator it = node_map_readers.find(id);
   436 	  if (it != node_map_readers.end()) {
   437 	    index.push_back(it->second);
   438 	    node_map_readers.erase(it);
   439 	  } else {
   440 	    index.push_back(&nodeSkipper);
   441 	  }
   442 	  if (ReaderTraits::idMapName(id) && nodeInverter.get() == 0) {
   443 	    nodeInverter.reset(index.back()->getInverter());
   444 	    index.back() = nodeInverter.get();
   445 	  }
   446 	}
   447       }
   448 
   449 //       if (index.size() == 0) {
   450 // 	throw DataFormatError("Cannot find node id map");
   451 //       }
   452 
   453 //       nodeInverter = 
   454 // 	std::auto_ptr<InverterBase<Node> >(index[0]->getInverter());
   455       std::string line;
   456       while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   457 	Node node = graph.addNode();
   458 	std::istringstream ls(line);
   459 	for (int i = 0; i < (int)index.size(); ++i) {
   460 	  index[i]->read(ls, node);
   461 	}
   462       }
   463       return line;
   464     }
   465 
   466     std::string readEdgeSet(int& line_num, 
   467 			    std::auto_ptr<InverterBase<Edge> >& edgeInverter, 
   468 			    std::auto_ptr<InverterBase<Node> >& nodeInverter) {
   469       std::vector<ReaderBase<Edge>*> index;
   470       {
   471 	std::string line = readNotEmptyLine(is, line_num);    
   472 	std::string id;
   473 	std::istringstream ls(line);	
   474 	while (ls >> id) {
   475 	  typename EdgeMapReaders::iterator it = edge_map_readers.find(id);
   476 	  if (it != edge_map_readers.end()) {
   477 	    index.push_back(it->second);
   478 	    edge_map_readers.erase(it);
   479 	  } else {
   480 	    index.push_back(&edgeSkipper);
   481 	  }
   482 	  if (ReaderTraits::idMapName(id) && edgeInverter.get() == 0) {
   483 	    edgeInverter.reset(index.back()->getInverter());
   484 	    index.back() = edgeInverter.get();
   485 	  }
   486 	}
   487       }
   488       
   489       if (nodeInverter.get() == 0) {
   490  	throw DataFormatError("Cannot find node id map");
   491       }
   492 //       if (index.size() == 0) {
   493 // 	throw DataFormatError("Cannot find edge id map");
   494 //       }
   495 
   496 //       edgeInverter = 
   497 // 	std::auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
   498       std::string line;
   499       while (line = readNotEmptyLine(is, line_num), line[0] != '@') {	
   500 	std::istringstream ls(line);
   501 	Node source = nodeInverter->read(ls);
   502 	Node target = nodeInverter->read(ls);
   503 	Edge edge = graph.addEdge(source, target);
   504 	for (int i = 0; i < (int)index.size(); ++i) {
   505 	  index[i]->read(ls, edge);
   506 	}
   507       }      
   508       return line;
   509     }
   510 
   511     std::string readNodes(int& line_num, 
   512 			  std::auto_ptr<InverterBase<Node> >& nodeInverter) {
   513       std::string line;
   514       if (nodeInverter.get() == 0) {
   515  	throw DataFormatError("Cannot find node id map");
   516       }
   517       while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   518 	std::istringstream ls(line);
   519 	std::string name;
   520 	ls >> name;
   521 	typename NodeReaders::iterator it = node_readers.find(name);
   522 	if (it != node_readers.end()) {
   523 	  *(it -> second) = nodeInverter->read(ls);
   524 	} 
   525       }        
   526       return line;
   527     }
   528 
   529     std::string readEdges(int& line_num, 
   530 			  std::auto_ptr<InverterBase<Edge> >& edgeInverter) {
   531       std::string line;
   532       if (edgeInverter.get() == 0) {
   533  	throw DataFormatError("Cannot find edge id map");
   534       }
   535       while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   536 	std::istringstream ls(line);
   537 	std::string name;
   538 	ls >> name;
   539 	typename EdgeReaders::iterator it = edge_readers.find(name);
   540 	if (it != edge_readers.end()) {
   541 	  *(it -> second) = edgeInverter->read(ls);
   542 	} 
   543       }        
   544       return line;    
   545     }
   546 
   547     std::string readNotEmptyLine(std::istream& is, int& line_num) {
   548       std::string line;
   549       while (++line_num, getline(is, line)) {	
   550 	int vi = line.find('#');
   551 	if (vi != (int)::std::string::npos) {
   552 	  line = line.substr(0, vi);
   553 	}
   554 	vi = line.find_first_not_of(" \t");
   555 	if (vi != (int)std::string::npos) { 
   556 	  return line.substr(vi);
   557 	}
   558       }
   559       throw DataFormatError("End of stream error");
   560     }
   561     
   562     template <typename _Item>
   563     class ReaderBase;
   564     
   565     template <typename _Item>
   566     class InverterBase : public ReaderBase<_Item> {
   567     public:
   568       typedef _Item Item;
   569       virtual void read(std::istream&, const Item&) = 0;
   570       virtual Item read(std::istream&) = 0;
   571 
   572       virtual InverterBase<_Item>* getInverter() {
   573 	return this;
   574       }
   575     };
   576 
   577     template <typename _Item, typename _Map, typename _Reader>
   578     class MapReaderInverter : public InverterBase<_Item> {
   579     public:
   580       typedef _Item Item;
   581       typedef _Reader Reader;
   582       typedef typename Reader::Value Value;
   583       typedef _Map Map;
   584       typedef std::map<Value, Item> Inverse;
   585 
   586       Map& map;
   587       Reader reader;
   588       Inverse inverse;
   589 
   590       MapReaderInverter(Map& _map, const Reader& _reader) 
   591 	: map(_map), reader(_reader) {}
   592 
   593       virtual ~MapReaderInverter() {}
   594 
   595       virtual void read(std::istream& is, const Item& item) {
   596 	Value value;
   597 	reader.read(is, value);
   598 	map.set(item, value);
   599 	typename Inverse::iterator it = inverse.find(value);
   600 	if (it == inverse.end()) {
   601 	  inverse.insert(std::make_pair(value, item));
   602 	} else {
   603 	  throw DataFormatError("Multiple ID occurence");
   604 	}
   605       }
   606 
   607       virtual Item read(std::istream& is) {
   608 	Value value;
   609 	reader.read(is, value);	
   610 	typename Inverse::const_iterator it = inverse.find(value);
   611 	if (it != inverse.end()) {
   612 	  return it->second;
   613 	} else {
   614 	  throw DataFormatError("Invalid ID error");
   615 	}
   616       }      
   617     };
   618 
   619     template <typename _Item, typename _Reader>
   620     class SkipReaderInverter : public InverterBase<_Item> {
   621     public:
   622       typedef _Item Item;
   623       typedef _Reader Reader;
   624       typedef typename Reader::Value Value;
   625       typedef std::map<Value, Item> Inverse;
   626 
   627       Reader reader;
   628 
   629       SkipReaderInverter(const Reader& _reader) 
   630 	: reader(_reader) {}
   631 
   632       virtual ~SkipReaderInverter() {}
   633 
   634       virtual void read(std::istream& is, const Item& item) {
   635 	Value value;
   636 	reader.read(is, value);
   637 	typename Inverse::iterator it = inverse.find(value);
   638 	if (it == inverse.end()) {
   639 	  inverse.insert(std::make_pair(value, item));
   640 	} else {
   641 	  throw DataFormatError("Multiple ID occurence error");
   642 	}
   643       }
   644 
   645       virtual Item read(std::istream& is) {
   646 	Value value;
   647 	reader.read(is, value);	
   648 	typename Inverse::const_iterator it = inverse.find(value);
   649 	if (it != inverse.end()) {
   650 	  return it->second;
   651 	} else {
   652 	  throw DataFormatError("Invalid ID error");
   653 	}
   654       }      
   655     private:
   656       Inverse inverse;
   657     };
   658 
   659     // Readers
   660 
   661     template <typename _Item>    
   662     class ReaderBase {
   663     public:
   664       typedef _Item Item;
   665 
   666       //      virtual ~ReaderBase() {}
   667 
   668       virtual void read(std::istream& is, const Item& item) = 0;
   669       virtual InverterBase<_Item>* getInverter() = 0;
   670     };
   671 
   672     template <typename _Item, typename _Map, typename _Reader>
   673     class MapReader : public ReaderBase<_Item> {
   674     public:
   675       typedef _Map Map;
   676       typedef _Reader Reader;
   677       typedef typename Reader::Value Value;
   678       typedef _Item Item;
   679       
   680       Map& map;
   681       Reader reader;
   682 
   683       MapReader(Map& _map, const Reader& _reader) 
   684 	: map(_map), reader(_reader) {}
   685 
   686       virtual ~MapReader() {}
   687 
   688       virtual void read(std::istream& is, const Item& item) {
   689 	Value value;
   690 	reader.read(is, value);
   691 	map.set(item, value);
   692       }
   693 
   694       virtual InverterBase<_Item>* getInverter() {
   695 	return new MapReaderInverter<Item, Map, Reader>(map, reader);
   696       }
   697     };
   698 
   699 
   700     template <typename _Item, typename _Reader>
   701     class SkipReader : public ReaderBase<_Item> {
   702     public:
   703       typedef _Reader Reader;
   704       typedef typename Reader::Value Value;
   705       typedef _Item Item;
   706 
   707       Reader reader;
   708       SkipReader(const Reader& _reader) : reader(_reader) {}
   709 
   710       virtual ~SkipReader() {}
   711 
   712       virtual void read(std::istream& is, const Item&) {
   713 	Value value;
   714 	reader.read(is, value);
   715       }      
   716 
   717       virtual InverterBase<Item>* getInverter() {
   718 	return new SkipReaderInverter<Item, Reader>(reader);
   719       }
   720     };
   721 
   722 
   723     typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders;
   724     NodeMapReaders node_map_readers;
   725 
   726     typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders;
   727     EdgeMapReaders edge_map_readers;
   728 
   729     typedef std::map<std::string, Node*> NodeReaders;
   730     NodeReaders node_readers;
   731 
   732     typedef std::map<std::string, Edge*> EdgeReaders;
   733     EdgeReaders edge_readers;
   734 
   735     std::istream& is;
   736     Graph& graph;
   737 
   738     SkipReader<Node, DefaultReader> nodeSkipper;
   739     SkipReader<Edge, DefaultReader> edgeSkipper;
   740 
   741   };
   742 
   743   /// \brief Read a graph from the input.
   744   ///
   745   /// Read a graph from the input.
   746   /// \param is The input stream.
   747   /// \param g The graph.
   748   /// \param capacity The capacity map.
   749   /// \param s The source node.
   750   /// \param t The target node.
   751   /// \param cost The cost map.
   752   template<typename Graph, typename CapacityMap, typename CostMap>
   753   void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, 
   754 		  typename Graph::Node &s, typename Graph::Node &t, 
   755 		  CostMap& cost) {
   756     GraphReader<Graph> reader(is, g);
   757     reader.addEdgeMap("capacity", capacity);
   758     reader.addEdgeMap("cost", cost);
   759     reader.addNode("source", s);
   760     reader.addNode("target", t);
   761     reader.run();
   762   }
   763 
   764   /// \brief Read a graph from the input.
   765   ///
   766   /// Read a graph from the input.
   767   /// \param is The input stream.
   768   /// \param g The graph.
   769   /// \param capacity The capacity map.
   770   /// \param s The source node.
   771   /// \param t The target node.
   772   template<typename Graph, typename CapacityMap>
   773   void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, 
   774 		  typename Graph::Node &s, typename Graph::Node &t) {
   775     GraphReader<Graph> reader(is, g);
   776     reader.addEdgeMap("capacity", capacity);
   777     reader.addNode("source", s);
   778     reader.addNode("target", t);
   779     reader.run();
   780   }
   781 
   782   /// \brief Read a graph from the input.
   783   ///
   784   /// Read a graph from the input.
   785   /// \param is The input stream.
   786   /// \param g The graph.
   787   /// \param capacity The capacity map.
   788   /// \param s The source node.
   789   template<typename Graph, typename CapacityMap>
   790   void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, 
   791 		  typename Graph::Node &s) {
   792     GraphReader<Graph> reader(is, g);
   793     reader.addEdgeMap("capacity", capacity);
   794     reader.addNode("source", s);
   795     reader.run();
   796   }
   797 
   798   /// \brief Read a graph from the input.
   799   ///
   800   /// Read a graph from the input.
   801   /// \param is The input stream.
   802   /// \param g The graph.
   803   /// \param capacity The capacity map.
   804   template<typename Graph, typename CapacityMap>
   805   void readGraph(std::istream& is, Graph &g, CapacityMap& capacity) {
   806     GraphReader<Graph> reader(is, g);
   807     reader.addEdgeMap("capacity", capacity);
   808     reader.run();
   809   }
   810 
   811   /// \brief Read a graph from the input.
   812   ///
   813   /// Read a graph from the input.
   814   /// \param is The input stream.
   815   /// \param g The graph.
   816   template<typename Graph>
   817   void readGraph(std::istream& is, Graph &g) {
   818     GraphReader<Graph> reader(is, g);
   819     reader.run();
   820   }
   821 
   822   /// @}
   823 }
   824 
   825 #endif