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