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