2 * src/lemon/graph_reader.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Combinatorial Optimization Research Group, EGRES).
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.
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
19 ///\brief Graph reader.
29 #include <lemon/error.h>
31 /// \todo fix exceptions
40 virtual ~IOException() {}
41 virtual string what() const = 0;
44 class DataFormatException : public IOException {
47 DataFormatException(const std::string& _message)
48 : message(_message) {}
49 std::string what() const {
50 return "DataFormatException: " + message;
54 template <typename _Exception>
55 class StreamException : public _Exception {
57 typedef _Exception Exception;
58 StreamException(int _line, Exception _exception)
59 : Exception(_exception), line_num(_line) {}
60 virtual int line() const {
64 virtual ~StreamException() {}
66 virtual std::string what() const {
68 os << Exception::what() << " in line " << line();
76 // Readers and ReaderTraits
77 /// \brief Standard ReaderTraits for the GraphReader class.
81 struct DefaultReaderTraits {
83 template <typename _Value>
86 void read(std::istream& is, Value& value) {
88 throw DataFormatException("Default Reader format exception");
92 typedef Reader<std::string> DefaultReader;
96 class QuotedStringReader {
98 typedef std::string Value;
100 QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}
102 void read(std::istream& is, std::string& value) {
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);
115 if (!is) throw DataFormatException("Quoted string format");
120 static char readEscape(std::istream& is) {
122 switch (is.get(c), c) {
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);
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);
165 static bool isOct(char c) {
166 return '0' <= c && c <='7';
169 static int valueOct(char c) {
173 static bool isHex(char c) {
174 return ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
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;
192 template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits>
196 typedef _Graph Graph;
197 typedef typename Graph::Node Node;
198 typedef typename Graph::Edge Edge;
200 typedef _ReaderTraits ReaderTraits;
201 typedef typename ReaderTraits::DefaultReader DefaultReader;
203 GraphReader(std::istream& _is, Graph& _graph,
204 const DefaultReader& _reader = DefaultReader())
205 : is(_is), graph(_graph), nodeSkipper(_reader), edgeSkipper(_reader) {}
210 for (typename NodeMapReaders::iterator it = node_map_readers.begin();
211 it != node_map_readers.end(); ++it) {
215 for (typename EdgeMapReaders::iterator it = edge_map_readers.begin();
216 it != edge_map_readers.end(); ++it) {
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);
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;
236 node_map_readers.insert(
237 make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
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;
247 node_map_readers.insert(
248 make_pair(name, new SkipReader<Node, Reader>(reader)));
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);
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;
267 edge_map_readers.insert(
268 make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
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;
278 edge_map_readers.insert(
279 make_pair(name, new SkipReader<Edge, Reader>(reader)));
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";
288 node_readers.insert(make_pair(name, &node));
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";
298 edge_readers.insert(make_pair(name, &edge));
304 std::auto_ptr<InverterBase<Node> > nodeInverter;
305 std::auto_ptr<InverterBase<Edge> > edgeInverter;
307 std::string line = readNotEmptyLine(is, line_num);
308 if (line.find("@nodeset") == 0) {
309 line = readNodeSet(line_num, nodeInverter);
311 if (line.find("@edgeset") == 0) {
312 line = readEdgeSet(line_num, edgeInverter, nodeInverter);
314 if (line.find("@nodes") == 0) {
315 line = readNodes(line_num, nodeInverter);
317 if (line.find("@edges") == 0) {
318 line = readEdges(line_num, edgeInverter);
320 if (line.find("@end") != 0) {
321 throw DataFormatException("Invalid control sequence: " + line);
323 } catch (DataFormatException e) {
324 throw StreamException<DataFormatException>(line_num, e);
330 template <typename Item> class InverterBase;
332 std::string readNodeSet(int& line_num,
333 auto_ptr<InverterBase<Node> > & nodeInverter) {
334 std::vector<ReaderBase<Node>* > index;
336 std::string line = readNotEmptyLine(is, line_num);
338 std::istringstream ls(line);
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);
346 index.push_back(&nodeSkipper);
351 if (index.size() == 0) {
352 throw DataFormatException("No node map found");
355 nodeInverter = auto_ptr<InverterBase<Node> >(index[0]->getInverter());
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);
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;
373 std::string line = readNotEmptyLine(is, line_num);
375 std::istringstream ls(line);
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);
383 index.push_back(&edgeSkipper);
388 if (index.size() == 0) {
389 throw DataFormatException("No edge map found");
392 edgeInverter = auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
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);
407 std::string readNodes(int& line_num,
408 auto_ptr<InverterBase<Node> >& nodeInverter) {
410 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
411 std::istringstream ls(line);
414 typename NodeReaders::iterator it = node_readers.find(name);
415 if (it != node_readers.end()) {
416 *(it -> second) = nodeInverter->read(ls);
422 std::string readEdges(int& line_num,
423 auto_ptr<InverterBase<Edge> >& edgeInverter) {
425 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
426 std::istringstream ls(line);
429 typename EdgeReaders::iterator it = edge_readers.find(name);
430 if (it != edge_readers.end()) {
431 *(it -> second) = edgeInverter->read(ls);
437 std::string readNotEmptyLine(std::istream& is, int& line_num) {
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);
445 throw DataFormatException("End of stream");
448 // Inverters store and give back the Item from the id,
449 // and may put the ids into a map.
451 template <typename _Item>
455 virtual void read(std::istream&, const Item&) = 0;
456 virtual Item read(std::istream&) = 0;
459 template <typename _Item, typename _Map, typename _Reader>
460 class MapReaderInverter : public InverterBase<_Item> {
463 typedef _Reader Reader;
464 typedef typename Reader::Value Value;
466 typedef std::map<Value, Item> Inverse;
472 MapReaderInverter(Map& _map, const Reader& _reader)
473 : map(_map), reader(_reader) {}
475 virtual ~MapReaderInverter() {}
477 virtual void read(std::istream& is, const Item& item) {
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));
485 throw DataFormatException("Multiple ID occurence");
489 virtual Item read(std::istream& is) {
491 reader.read(is, value);
492 typename Inverse::const_iterator it = inverse.find(value);
493 if (it != inverse.end()) {
496 throw DataFormatException("Invalid ID");
501 template <typename _Item, typename _Reader>
502 class SkipReaderInverter : public InverterBase<_Item> {
505 typedef _Reader Reader;
506 typedef typename Reader::Value Value;
507 typedef std::map<Value, Item> Inverse;
511 SkipReaderInverter(const Reader& _reader)
514 virtual ~SkipReaderInverter() {}
516 virtual void read(std::istream& is, const Item& item) {
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));
523 throw DataFormatException("Multiple ID occurence");
527 virtual Item read(std::istream& is) {
529 reader.read(is, value);
530 typename Inverse::const_iterator it = inverse.find(value);
531 if (it != inverse.end()) {
534 throw DataFormatException("Invalid ID");
543 template <typename _Item>
548 // virtual ~ReaderBase() {}
550 virtual void read(std::istream& is, const Item& item) = 0;
551 virtual InverterBase<_Item>* getInverter() = 0;
554 template <typename _Item, typename _Map, typename _Reader>
555 class MapReader : public ReaderBase<_Item> {
558 typedef _Reader Reader;
559 typedef typename Reader::Value Value;
565 MapReader(Map& _map, const Reader& _reader)
566 : map(_map), reader(_reader) {}
568 virtual ~MapReader() {}
570 virtual void read(std::istream& is, const Item& item) {
572 reader.read(is, value);
573 map.set(item, value);
576 virtual InverterBase<_Item>* getInverter() {
577 return new MapReaderInverter<Item, Map, Reader>(map, reader);
582 template <typename _Item, typename _Reader>
583 class SkipReader : public ReaderBase<_Item> {
585 typedef _Reader Reader;
586 typedef typename Reader::Value Value;
590 SkipReader(const Reader& _reader) : reader(_reader) {}
592 virtual ~SkipReader() {}
594 virtual void read(std::istream& is, const Item& item) {
596 reader.read(is, value);
599 virtual InverterBase<Item>* getInverter() {
600 return new SkipReaderInverter<Item, Reader>(reader);
605 typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders;
606 NodeMapReaders node_map_readers;
608 typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders;
609 EdgeMapReaders edge_map_readers;
611 typedef std::map<std::string, Node*> NodeReaders;
612 NodeReaders node_readers;
614 typedef std::map<std::string, Edge*> EdgeReaders;
615 EdgeReaders edge_readers;
620 SkipReader<Node, DefaultReader> nodeSkipper;
621 SkipReader<Edge, DefaultReader> edgeSkipper;