src/lemon/graph_reader.h
author alpar
Tue, 12 Apr 2005 14:24:06 +0000
changeset 1340 80da1eadcaa7
parent 1311 b810a07248a0
child 1341 bda966891ea0
permissions -rw-r--r--
Missing header added
     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 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 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 	  std::cerr << "Line: " << line.substr(vi) << std::endl;
   557 	  return line.substr(vi);
   558 	}
   559       }
   560       throw DataFormatError("End of stream error");
   561     }
   562     
   563     template <typename _Item>
   564     class ReaderBase;
   565     
   566     template <typename _Item>
   567     class InverterBase : public ReaderBase<_Item> {
   568     public:
   569       typedef _Item Item;
   570       virtual void read(std::istream&, const Item&) = 0;
   571       virtual Item read(std::istream&) = 0;
   572 
   573       virtual InverterBase<_Item>* getInverter() {
   574 	return this;
   575       }
   576     };
   577 
   578     template <typename _Item, typename _Map, typename _Reader>
   579     class MapReaderInverter : public InverterBase<_Item> {
   580     public:
   581       typedef _Item Item;
   582       typedef _Reader Reader;
   583       typedef typename Reader::Value Value;
   584       typedef _Map Map;
   585       typedef std::map<Value, Item> Inverse;
   586 
   587       Map& map;
   588       Reader reader;
   589       Inverse inverse;
   590 
   591       MapReaderInverter(Map& _map, const Reader& _reader) 
   592 	: map(_map), reader(_reader) {}
   593 
   594       virtual ~MapReaderInverter() {}
   595 
   596       virtual void read(std::istream& is, const Item& item) {
   597 	Value value;
   598 	reader.read(is, value);
   599 	map.set(item, value);
   600 	typename Inverse::iterator it = inverse.find(value);
   601 	if (it == inverse.end()) {
   602 	  inverse.insert(std::make_pair(value, item));
   603 	} else {
   604 	  throw DataFormatError("Multiple ID occurence");
   605 	}
   606       }
   607 
   608       virtual Item read(std::istream& is) {
   609 	Value value;
   610 	reader.read(is, value);	
   611 	typename Inverse::const_iterator it = inverse.find(value);
   612 	if (it != inverse.end()) {
   613 	  return it->second;
   614 	} else {
   615 	  throw DataFormatError("Invalid ID error");
   616 	}
   617       }      
   618     };
   619 
   620     template <typename _Item, typename _Reader>
   621     class SkipReaderInverter : public InverterBase<_Item> {
   622     public:
   623       typedef _Item Item;
   624       typedef _Reader Reader;
   625       typedef typename Reader::Value Value;
   626       typedef std::map<Value, Item> Inverse;
   627 
   628       Reader reader;
   629 
   630       SkipReaderInverter(const Reader& _reader) 
   631 	: reader(_reader) {}
   632 
   633       virtual ~SkipReaderInverter() {}
   634 
   635       virtual void read(std::istream& is, const Item& item) {
   636 	Value value;
   637 	reader.read(is, value);
   638 	typename Inverse::iterator it = inverse.find(value);
   639 	if (it == inverse.end()) {
   640 	  inverse.insert(std::make_pair(value, item));
   641 	} else {
   642 	  throw DataFormatError("Multiple ID occurence error");
   643 	}
   644       }
   645 
   646       virtual Item read(std::istream& is) {
   647 	Value value;
   648 	reader.read(is, value);	
   649 	typename Inverse::const_iterator it = inverse.find(value);
   650 	if (it != inverse.end()) {
   651 	  return it->second;
   652 	} else {
   653 	  throw DataFormatError("Invalid ID error");
   654 	}
   655       }      
   656     private:
   657       Inverse inverse;
   658     };
   659 
   660     // Readers
   661 
   662     template <typename _Item>    
   663     class ReaderBase {
   664     public:
   665       typedef _Item Item;
   666 
   667       //      virtual ~ReaderBase() {}
   668 
   669       virtual void read(std::istream& is, const Item& item) = 0;
   670       virtual InverterBase<_Item>* getInverter() = 0;
   671     };
   672 
   673     template <typename _Item, typename _Map, typename _Reader>
   674     class MapReader : public ReaderBase<_Item> {
   675     public:
   676       typedef _Map Map;
   677       typedef _Reader Reader;
   678       typedef typename Reader::Value Value;
   679       typedef _Item Item;
   680       
   681       Map& map;
   682       Reader reader;
   683 
   684       MapReader(Map& _map, const Reader& _reader) 
   685 	: map(_map), reader(_reader) {}
   686 
   687       virtual ~MapReader() {}
   688 
   689       virtual void read(std::istream& is, const Item& item) {
   690 	Value value;
   691 	reader.read(is, value);
   692 	map.set(item, value);
   693       }
   694 
   695       virtual InverterBase<_Item>* getInverter() {
   696 	return new MapReaderInverter<Item, Map, Reader>(map, reader);
   697       }
   698     };
   699 
   700 
   701     template <typename _Item, typename _Reader>
   702     class SkipReader : public ReaderBase<_Item> {
   703     public:
   704       typedef _Reader Reader;
   705       typedef typename Reader::Value Value;
   706       typedef _Item Item;
   707 
   708       Reader reader;
   709       SkipReader(const Reader& _reader) : reader(_reader) {}
   710 
   711       virtual ~SkipReader() {}
   712 
   713       virtual void read(std::istream& is, const Item&) {
   714 	Value value;
   715 	reader.read(is, value);
   716       }      
   717 
   718       virtual InverterBase<Item>* getInverter() {
   719 	return new SkipReaderInverter<Item, Reader>(reader);
   720       }
   721     };
   722 
   723 
   724     typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders;
   725     NodeMapReaders node_map_readers;
   726 
   727     typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders;
   728     EdgeMapReaders edge_map_readers;
   729 
   730     typedef std::map<std::string, Node*> NodeReaders;
   731     NodeReaders node_readers;
   732 
   733     typedef std::map<std::string, Edge*> EdgeReaders;
   734     EdgeReaders edge_readers;
   735 
   736     std::istream& is;
   737     Graph& graph;
   738 
   739     SkipReader<Node, DefaultReader> nodeSkipper;
   740     SkipReader<Edge, DefaultReader> edgeSkipper;
   741 
   742   };
   743 
   744   /// \brief Read a graph from the input.
   745   ///
   746   /// Read a graph from the input.
   747   /// \param is The input stream.
   748   /// \param g The graph.
   749   /// \param capacity The capacity map.
   750   /// \param s The source node.
   751   /// \param t The target node.
   752   /// \param cost The cost map.
   753   template<typename Graph, typename CapacityMap, typename CostMap>
   754   void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, 
   755 		  typename Graph::Node &s, typename Graph::Node &t, 
   756 		  CostMap& cost) {
   757     GraphReader<Graph> reader(is, g);
   758     reader.addEdgeMap("capacity", capacity);
   759     reader.addEdgeMap("cost", cost);
   760     reader.addNode("source", s);
   761     reader.addNode("target", t);
   762     reader.run();
   763   }
   764 
   765   /// \brief Read a graph from the input.
   766   ///
   767   /// Read a graph from the input.
   768   /// \param is The input stream.
   769   /// \param g The graph.
   770   /// \param capacity The capacity map.
   771   /// \param s The source node.
   772   /// \param t The target node.
   773   template<typename Graph, typename CapacityMap>
   774   void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, 
   775 		  typename Graph::Node &s, typename Graph::Node &t) {
   776     GraphReader<Graph> reader(is, g);
   777     reader.addEdgeMap("capacity", capacity);
   778     reader.addNode("source", s);
   779     reader.addNode("target", t);
   780     reader.run();
   781   }
   782 
   783   /// \brief Read a graph from the input.
   784   ///
   785   /// Read a graph from the input.
   786   /// \param is The input stream.
   787   /// \param g The graph.
   788   /// \param capacity The capacity map.
   789   /// \param s The source node.
   790   template<typename Graph, typename CapacityMap>
   791   void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, 
   792 		  typename Graph::Node &s) {
   793     GraphReader<Graph> reader(is, g);
   794     reader.addEdgeMap("capacity", capacity);
   795     reader.addNode("source", s);
   796     reader.run();
   797   }
   798 
   799   /// \brief Read a graph from the input.
   800   ///
   801   /// Read a graph from the input.
   802   /// \param is The input stream.
   803   /// \param g The graph.
   804   /// \param capacity The capacity map.
   805   template<typename Graph, typename CapacityMap>
   806   void readGraph(std::istream& is, Graph &g, CapacityMap& capacity) {
   807     GraphReader<Graph> reader(is, g);
   808     reader.addEdgeMap("capacity", capacity);
   809     reader.run();
   810   }
   811 
   812   /// \brief Read a graph from the input.
   813   ///
   814   /// Read a graph from the input.
   815   /// \param is The input stream.
   816   /// \param g The graph.
   817   template<typename Graph>
   818   void readGraph(std::istream& is, Graph &g) {
   819     GraphReader<Graph> reader(is, g);
   820     reader.run();
   821   }
   822 
   823   /// @}
   824 }
   825 
   826 #endif