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