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