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