2 * src/lemon/graph_reader.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, 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 Lemon Graph Format reader.
21 #ifndef LEMON_GRAPH_READER_H
22 #define LEMON_GRAPH_READER_H
32 #include <lemon/error.h>
37 /// \addtogroup io_group
40 /// \brief Standard ReaderTraits for the GraphReader class.
42 /// Standard ReaderTraits for the GraphReader class.
43 /// It defines standard reading method for all type of value.
44 /// \author Balazs Dezso
45 struct DefaultReaderTraits {
47 /// \brief Template class for reading an value.
49 /// Template class for reading an value.
50 /// \author Balazs Dezso
51 template <typename _Value>
55 /// \brief Reads a value from the given stream.
57 /// Reads a value from the given stream.
58 void read(std::istream& is, Value& value) {
60 throw DataFormatError("Default reader format exception");
64 /// \brief Returns wheter this name is an ID map name.
66 /// Returns wheter this name is an ID map name.
67 static bool idMapName(const std::string& name) {
71 /// The reader class for the not needed maps.
72 typedef Reader<std::string> DefaultReader;
76 /// \brief Reader class for quoted strings.
78 /// Reader class for quoted strings. It can process the escape
79 /// sequences in the string.
80 /// \author Balazs Dezso
81 class QuotedStringReader {
83 typedef std::string Value;
85 /// \brief Constructor for the reader.
87 /// Constructor for the reader. If the given parameter is true
88 /// the reader processes the escape sequences.
89 QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}
91 /// \brief Reads a quoted string from the given stream.
93 /// Reads a quoted string from the given stream.
94 void read(std::istream& is, std::string& value) {
98 if (!is.get(c) || c != '\"')
99 throw DataFormatError("Quoted string format error");
100 while (is.get(c) && c != '\"') {
101 if (escaped && c == '\\') {
102 value += readEscape(is);
107 if (!is) throw DataFormatError("Quoted string format error");
112 static char readEscape(std::istream& is) {
114 switch (is.get(c), c) {
140 if (!is.get(c) || !isHex(c))
141 throw DataFormatError("Escape format error");
142 else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
143 else code = code * 16 + valueHex(c);
150 throw DataFormatError("Escape format error");
151 else if (code = valueOct(c), !is.get(c) || !isOct(c))
153 else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
155 else code = code * 8 + valueOct(c);
161 static bool isOct(char c) {
162 return '0' <= c && c <='7';
165 static int valueOct(char c) {
169 static bool isHex(char c) {
170 return ('0' <= c && c <= '9') ||
171 ('a' <= c && c <= 'z') ||
172 ('A' <= c && c <= 'Z');
175 static int valueHex(char c) {
176 if ('0' <= c && c <= '9') return c - '0';
177 if ('a' <= c && c <= 'z') return c - 'a' + 10;
186 virtual void read(std::istream& is) = 0;
189 /// \brief The graph reader class.
192 /// The given file format may contain several maps and labeled nodes or
195 /// If you read a graph you need not read all the maps and items just those
196 /// that you need. The interface of the \c GraphReader is very similar to
197 /// the GraphWriter but the reading method does not depend on the order the
200 /// The reader object suppose that each not readed value does not contain
201 /// whitespaces, therefore it has some extra possibilities to control how
202 /// it should skip the values when the string representation contains spaces.
205 /// GraphReader<ListGraph> reader(std::cin, graph);
208 /// The \c readNodeMap() function reads a map from the \c \@nodeset section.
209 /// If there is a map that you do not want to read from the file and there is
210 /// whitespace in the string represenation of the values then you should
211 /// call the \c skipNodeMap() template member function with proper
215 /// reader.readNodeMap("x-coord", xCoordMap);
216 /// reader.readNodeMap("y-coord", yCoordMap);
218 /// reader.readNodeMap<QuotedStringReader>("label", labelMap);
219 /// reader.skipNodeMap<QuotedStringReader>("description");
221 /// reader.readNodeMap("color", colorMap);
224 /// With the \c readEdgeMap() member function you can give an edge map
225 /// reading command similar to the NodeMaps.
228 /// reader.readEdgeMap("weight", weightMap);
229 /// reader.readEdgeMap("label", labelMap);
232 /// With \c readNode() and \c readEdge() functions you can read labeled Nodes
236 /// reader.readNode("source", sourceNode);
237 /// reader.readNode("target", targetNode);
239 /// reader.readEdge("observed", edge);
242 /// After you give all read commands you must call the \c run() member
243 /// function, which execute all the commands.
249 /// \see DefaultReaderTraits
250 /// \see QuotedStringReader
251 /// \see \ref GraphWriter
252 /// \see \ref graph-io-page
253 /// \author Balazs Dezso
254 template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits>
258 typedef _Graph Graph;
259 typedef typename Graph::Node Node;
260 typedef typename Graph::Edge Edge;
262 typedef _ReaderTraits ReaderTraits;
263 typedef typename ReaderTraits::DefaultReader DefaultReader;
265 /// \brief Construct a new GraphReader.
267 /// Construct a new GraphReader. It reads into the given graph
268 /// and it use the given reader as the default skipper.
269 GraphReader(std::istream& _is, Graph& _graph,
270 const DefaultReader& _reader = DefaultReader())
271 : gui_reader(0), is(_is), graph(_graph),
272 nodeSkipper(_reader), edgeSkipper(_reader) {}
274 /// \brief Destruct the graph reader.
276 /// Destruct the graph reader.
278 for (typename NodeMapReaders::iterator it = node_map_readers.begin();
279 it != node_map_readers.end(); ++it) {
283 for (typename EdgeMapReaders::iterator it = edge_map_readers.begin();
284 it != edge_map_readers.end(); ++it) {
290 /// \brief Add a new node map reader command for the reader.
292 /// Add a new node map reader command for the reader.
293 template <typename Map>
294 GraphReader& readNodeMap(std::string name, Map& map) {
295 return readNodeMap<typename ReaderTraits::template
296 Reader<typename Map::Value>, Map>(name, map);
299 /// \brief Add a new node map reader command for the reader.
301 /// Add a new node map reader command for the reader.
302 template <typename Reader, typename Map>
303 GraphReader& readNodeMap(std::string name, Map& map,
304 const Reader& reader = Reader()) {
305 if (node_map_readers.find(name) != node_map_readers.end()) {
307 msg << "Multiple read rule for node map: " << name;
308 throw IOParameterError(msg.message());
310 node_map_readers.insert(
311 make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
315 /// \brief Add a new node map skipper command for the reader.
317 /// Add a new node map skipper command for the reader.
318 template <typename Reader>
319 GraphReader& skipNodeMap(std::string name,
320 const Reader& reader = Reader()) {
321 if (node_map_readers.find(name) != node_map_readers.end()) {
323 msg << "Multiple read rule for node map: " << name;
324 throw IOParameterError(msg.message());
326 node_map_readers.insert(
327 make_pair(name, new SkipReader<Node, Reader>(reader)));
331 /// \brief Add a new edge map reader command for the reader.
333 /// Add a new edge map reader command for the reader.
334 template <typename Map>
335 GraphReader& readEdgeMap(std::string name, Map& map) {
336 return readEdgeMap<typename ReaderTraits::template
337 Reader<typename Map::Value>, Map>(name, map);
341 /// \brief Add a new edge map reader command for the reader.
343 /// Add a new edge map reader command for the reader.
344 template <typename Reader, typename Map>
345 GraphReader& readEdgeMap(std::string name, Map& map,
346 const Reader& reader = Reader()) {
347 if (edge_map_readers.find(name) != edge_map_readers.end()) {
349 msg << "Multiple read rule for edge map: " << name;
350 throw IOParameterError(msg.message());
352 edge_map_readers.insert(
353 make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
357 /// \brief Add a new edge map skipper command for the reader.
359 /// Add a new edge map skipper command for the reader.
360 template <typename Reader>
361 GraphReader& skipEdgeMap(std::string name,
362 const Reader& reader = Reader()) {
363 if (edge_map_readers.find(name) != edge_map_readers.end()) {
365 msg << "Multiple read rule for edge map: " << name;
366 throw IOParameterError(msg.message());
368 edge_map_readers.insert(
369 make_pair(name, new SkipReader<Edge, Reader>(reader)));
373 /// \brief Add a new labeled node reader for the reader.
375 /// Add a new labeled node reader for the reader.
376 GraphReader& readNode(std::string name, Node& node) {
377 if (node_readers.find(name) != node_readers.end()) {
379 msg << "Multiple read rule for node: " << name;
380 throw IOParameterError(msg.message());
382 node_readers.insert(make_pair(name, &node));
386 /// \brief Add a new labeled edge reader for the reader.
388 /// Add a new labeled edge reader for the reader.
389 GraphReader& readEdge(std::string name, Edge& edge) {
390 if (edge_readers.find(name) != edge_readers.end()) {
392 msg << "Multiple read rule for edge: " << name;
393 throw IOParameterError(msg.message());
395 edge_readers.insert(make_pair(name, &edge));
399 /// \brief Executes the reader commands.
401 /// Executes the reader commands.
404 std::auto_ptr<InverterBase<Node> > nodeInverter;
405 std::auto_ptr<InverterBase<Edge> > edgeInverter;
407 std::string line = readNotEmptyLine(is, line_num);
408 if (line.find("@nodeset") == 0) {
409 line = readNodeSet(line_num, nodeInverter);
411 if (line.find("@edgeset") == 0) {
412 line = readEdgeSet(line_num, edgeInverter, nodeInverter);
414 if (line.find("@nodes") == 0) {
415 line = readNodes(line_num, nodeInverter);
417 if (line.find("@edges") == 0) {
418 line = readEdges(line_num, edgeInverter);
420 if (line.find("@gui") == 0) {
421 line = readGUI(line_num);
423 if (line.find("@end") != 0) {
424 throw DataFormatError("Invalid control sequence error");
426 } catch (DataFormatError e) {
432 GraphReader& readGUI(GUIReader& reader) {
433 gui_reader = &reader;
439 template <typename Item> class InverterBase;
441 std::string readNodeSet(int& line_num,
442 std::auto_ptr<InverterBase<Node> >& nodeInverter) {
443 std::vector<ReaderBase<Node>* > index;
445 std::string line = readNotEmptyLine(is, line_num);
447 std::istringstream ls(line);
449 typename NodeMapReaders::iterator it = node_map_readers.find(id);
450 if (it != node_map_readers.end()) {
451 index.push_back(it->second);
452 node_map_readers.erase(it);
454 index.push_back(&nodeSkipper);
456 if (ReaderTraits::idMapName(id) && nodeInverter.get() == 0) {
457 nodeInverter.reset(index.back()->getInverter());
458 index.back() = nodeInverter.get();
463 // if (index.size() == 0) {
464 // throw DataFormatError("Cannot find node id map");
468 // std::auto_ptr<InverterBase<Node> >(index[0]->getInverter());
470 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
471 Node node = graph.addNode();
472 std::istringstream ls(line);
473 for (int i = 0; i < (int)index.size(); ++i) {
474 index[i]->read(ls, node);
480 std::string readEdgeSet(int& line_num,
481 std::auto_ptr<InverterBase<Edge> >& edgeInverter,
482 std::auto_ptr<InverterBase<Node> >& nodeInverter) {
483 std::vector<ReaderBase<Edge>*> index;
485 std::string line = readNotEmptyLine(is, line_num);
487 std::istringstream ls(line);
489 typename EdgeMapReaders::iterator it = edge_map_readers.find(id);
490 if (it != edge_map_readers.end()) {
491 index.push_back(it->second);
492 edge_map_readers.erase(it);
494 index.push_back(&edgeSkipper);
496 if (ReaderTraits::idMapName(id) && edgeInverter.get() == 0) {
497 edgeInverter.reset(index.back()->getInverter());
498 index.back() = edgeInverter.get();
503 if (nodeInverter.get() == 0) {
504 throw DataFormatError("Cannot find node id map");
506 // if (index.size() == 0) {
507 // throw DataFormatError("Cannot find edge id map");
511 // std::auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
513 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
514 std::istringstream ls(line);
515 Node source = nodeInverter->read(ls);
516 Node target = nodeInverter->read(ls);
517 Edge edge = graph.addEdge(source, target);
518 for (int i = 0; i < (int)index.size(); ++i) {
519 index[i]->read(ls, edge);
525 std::string readNodes(int& line_num,
526 std::auto_ptr<InverterBase<Node> >& nodeInverter) {
528 if (nodeInverter.get() == 0) {
529 throw DataFormatError("Cannot find node id map");
531 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
532 std::istringstream ls(line);
535 typename NodeReaders::iterator it = node_readers.find(name);
536 if (it != node_readers.end()) {
537 *(it -> second) = nodeInverter->read(ls);
543 std::string readEdges(int& line_num,
544 std::auto_ptr<InverterBase<Edge> >& edgeInverter) {
546 if (edgeInverter.get() == 0) {
547 throw DataFormatError("Cannot find edge id map");
549 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
550 std::istringstream ls(line);
553 typename EdgeReaders::iterator it = edge_readers.find(name);
554 if (it != edge_readers.end()) {
555 *(it -> second) = edgeInverter->read(ls);
561 std::string readGUI(int& line_num) {
562 std::stringstream section;
564 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
565 section << line << std::endl;
567 if (gui_reader != 0) {
568 gui_reader->read(section);
573 std::string readNotEmptyLine(std::istream& is, int& line_num) {
575 while (++line_num, getline(is, line)) {
576 int vi = line.find('#');
577 if (vi != (int)::std::string::npos) {
578 line = line.substr(0, vi);
580 vi = line.find_first_not_of(" \t");
581 if (vi != (int)std::string::npos) {
582 return line.substr(vi);
585 throw DataFormatError("End of stream error");
588 template <typename _Item>
591 template <typename _Item>
592 class InverterBase : public ReaderBase<_Item> {
595 virtual void read(std::istream&, const Item&) = 0;
596 virtual Item read(std::istream&) = 0;
598 virtual InverterBase<_Item>* getInverter() {
603 template <typename _Item, typename _Map, typename _Reader>
604 class MapReaderInverter : public InverterBase<_Item> {
607 typedef _Reader Reader;
608 typedef typename Reader::Value Value;
610 typedef std::map<Value, Item> Inverse;
616 MapReaderInverter(Map& _map, const Reader& _reader)
617 : map(_map), reader(_reader) {}
619 virtual ~MapReaderInverter() {}
621 virtual void read(std::istream& is, const Item& item) {
623 reader.read(is, value);
624 map.set(item, value);
625 typename Inverse::iterator it = inverse.find(value);
626 if (it == inverse.end()) {
627 inverse.insert(std::make_pair(value, item));
629 throw DataFormatError("Multiple ID occurence");
633 virtual Item read(std::istream& is) {
635 reader.read(is, value);
636 typename Inverse::const_iterator it = inverse.find(value);
637 if (it != inverse.end()) {
640 throw DataFormatError("Invalid ID error");
645 template <typename _Item, typename _Reader>
646 class SkipReaderInverter : public InverterBase<_Item> {
649 typedef _Reader Reader;
650 typedef typename Reader::Value Value;
651 typedef std::map<Value, Item> Inverse;
655 SkipReaderInverter(const Reader& _reader)
658 virtual ~SkipReaderInverter() {}
660 virtual void read(std::istream& is, const Item& item) {
662 reader.read(is, value);
663 typename Inverse::iterator it = inverse.find(value);
664 if (it == inverse.end()) {
665 inverse.insert(std::make_pair(value, item));
667 throw DataFormatError("Multiple ID occurence error");
671 virtual Item read(std::istream& is) {
673 reader.read(is, value);
674 typename Inverse::const_iterator it = inverse.find(value);
675 if (it != inverse.end()) {
678 throw DataFormatError("Invalid ID error");
687 template <typename _Item>
692 // virtual ~ReaderBase() {}
694 virtual void read(std::istream& is, const Item& item) = 0;
695 virtual InverterBase<_Item>* getInverter() = 0;
698 template <typename _Item, typename _Map, typename _Reader>
699 class MapReader : public ReaderBase<_Item> {
702 typedef _Reader Reader;
703 typedef typename Reader::Value Value;
709 MapReader(Map& _map, const Reader& _reader)
710 : map(_map), reader(_reader) {}
712 virtual ~MapReader() {}
714 virtual void read(std::istream& is, const Item& item) {
716 reader.read(is, value);
717 map.set(item, value);
720 virtual InverterBase<_Item>* getInverter() {
721 return new MapReaderInverter<Item, Map, Reader>(map, reader);
726 template <typename _Item, typename _Reader>
727 class SkipReader : public ReaderBase<_Item> {
729 typedef _Reader Reader;
730 typedef typename Reader::Value Value;
734 SkipReader(const Reader& _reader) : reader(_reader) {}
736 virtual ~SkipReader() {}
738 virtual void read(std::istream& is, const Item&) {
740 reader.read(is, value);
743 virtual InverterBase<Item>* getInverter() {
744 return new SkipReaderInverter<Item, Reader>(reader);
749 typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders;
750 NodeMapReaders node_map_readers;
752 typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders;
753 EdgeMapReaders edge_map_readers;
755 typedef std::map<std::string, Node*> NodeReaders;
756 NodeReaders node_readers;
758 typedef std::map<std::string, Edge*> EdgeReaders;
759 EdgeReaders edge_readers;
761 GUIReader* gui_reader;
766 SkipReader<Node, DefaultReader> nodeSkipper;
767 SkipReader<Edge, DefaultReader> edgeSkipper;
771 /// \brief Read a graph from the input.
773 /// Read a graph from the input.
774 /// \param is The input stream.
775 /// \param g The graph.
776 /// \param capacity The capacity map.
777 /// \param s The source node.
778 /// \param t The target node.
779 /// \param cost The cost map.
780 template<typename Graph, typename CapacityMap, typename CostMap>
781 void readGraph(std::istream& is, Graph &g, CapacityMap& capacity,
782 typename Graph::Node &s, typename Graph::Node &t,
784 GraphReader<Graph> reader(is, g);
785 reader.readEdgeMap("capacity", capacity);
786 reader.readEdgeMap("cost", cost);
787 reader.readNode("source", s);
788 reader.readNode("target", t);
792 /// \brief Read a graph from the input.
794 /// Read a graph from the input.
795 /// \param is The input stream.
796 /// \param g The graph.
797 /// \param capacity The capacity map.
798 /// \param s The source node.
799 /// \param t The target node.
800 template<typename Graph, typename CapacityMap>
801 void readGraph(std::istream& is, Graph &g, CapacityMap& capacity,
802 typename Graph::Node &s, typename Graph::Node &t) {
803 GraphReader<Graph> reader(is, g);
804 reader.readEdgeMap("capacity", capacity);
805 reader.readNode("source", s);
806 reader.readNode("target", t);
810 /// \brief Read a graph from the input.
812 /// Read a graph from the input.
813 /// \param is The input stream.
814 /// \param g The graph.
815 /// \param capacity The capacity map.
816 /// \param s The source node.
817 template<typename Graph, typename CapacityMap>
818 void readGraph(std::istream& is, Graph &g, CapacityMap& capacity,
819 typename Graph::Node &s) {
820 GraphReader<Graph> reader(is, g);
821 reader.readEdgeMap("capacity", capacity);
822 reader.readNode("source", s);
826 /// \brief Read a graph from the input.
828 /// Read a graph from the input.
829 /// \param is The input stream.
830 /// \param g The graph.
831 /// \param capacity The capacity map.
832 template<typename Graph, typename CapacityMap>
833 void readGraph(std::istream& is, Graph &g, CapacityMap& capacity) {
834 GraphReader<Graph> reader(is, g);
835 reader.readEdgeMap("capacity", capacity);
839 /// \brief Read a graph from the input.
841 /// Read a graph from the input.
842 /// \param is The input stream.
843 /// \param g The graph.
844 template<typename Graph>
845 void readGraph(std::istream& is, Graph &g) {
846 GraphReader<Graph> reader(is, g);