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 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
39 /// \brief Standard ReaderTraits for the GraphReader class.
41 /// Standard ReaderTraits for the GraphReader class.
42 /// It defines standard reading method for all type of value.
43 struct DefaultReaderTraits {
45 /// \brief Template class for reading an value.
47 /// Template class for reading an value.
48 template <typename _Value>
52 /// \brief Reads a value from the given stream.
54 /// Reads a value from the given stream.
55 void read(std::istream& is, Value& value) {
57 throw DataFormatError("Default reader format exception");
61 /// The reader class for the not needed maps.
62 typedef Reader<std::string> DefaultReader;
66 /// \brief Reader class for quoted strings.
68 /// Reader class for quoted strings. It can process the escape
69 /// sequences in the string.
70 class QuotedStringReader {
72 typedef std::string Value;
74 /// \brief Constructor for the reader.
76 /// Constructor for the reader. If the given parameter is true
77 /// the reader processes the escape sequences.
78 QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}
80 /// \brief Reads a quoted string from the given stream.
82 /// Reads a quoted string from the given stream.
83 void read(std::istream& is, std::string& value) {
87 if (!is.get(c) || c != '\"')
88 throw DataFormatError("Quoted string format error");
89 while (is.get(c) && c != '\"') {
90 if (escaped && c == '\\') {
91 value += readEscape(is);
96 if (!is) throw DataFormatError("Quoted string format error");
101 static char readEscape(std::istream& is) {
103 switch (is.get(c), c) {
129 if (!is.get(c) || !isHex(c))
130 throw DataFormatError("Escape format error");
131 else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
132 else code = code * 16 + valueHex(c);
139 throw DataFormatError("Escape format error");
140 else if (code = valueOct(c), !is.get(c) || !isOct(c))
142 else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
144 else code = code * 8 + valueOct(c);
150 static bool isOct(char c) {
151 return '0' <= c && c <='7';
154 static int valueOct(char c) {
158 static bool isHex(char c) {
159 return ('0' <= c && c <= '9') ||
160 ('a' <= c && c <= 'z') ||
161 ('A' <= c && c <= 'Z');
164 static int valueHex(char c) {
165 if ('0' <= c && c <= '9') return c - '0';
166 if ('a' <= c && c <= 'z') return c - 'a' + 10;
173 /// \brief The graph reader class.
175 /// The reader class for the graph input.
176 /// \see \ref GraphWriter
177 /// \see \ref graph-io-page
178 template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits>
182 typedef _Graph Graph;
183 typedef typename Graph::Node Node;
184 typedef typename Graph::Edge Edge;
186 typedef _ReaderTraits ReaderTraits;
187 typedef typename ReaderTraits::DefaultReader DefaultReader;
189 /// \brief Construct a new GraphReader.
191 /// Construct a new GraphReader. It reads into the given graph
192 /// and it use the given reader as the default skipper.
193 GraphReader(std::istream& _is, Graph& _graph,
194 const DefaultReader& _reader = DefaultReader())
195 : is(_is), graph(_graph), nodeSkipper(_reader), edgeSkipper(_reader) {}
197 /// \brief Destruct the graph reader.
199 /// Destruct the graph reader.
202 for (typename NodeMapReaders::iterator it = node_map_readers.begin();
203 it != node_map_readers.end(); ++it) {
207 for (typename EdgeMapReaders::iterator it = edge_map_readers.begin();
208 it != edge_map_readers.end(); ++it) {
214 /// \brief Add a new node map reader command for the reader.
216 /// Add a new node map reader command for the reader.
217 template <typename Map>
218 GraphReader& addNodeMap(std::string name, Map& map) {
219 return addNodeMap<typename ReaderTraits::template
220 Reader<typename Map::Value>, Map>(name, map);
223 /// \brief Add a new node map reader command for the reader.
225 /// Add a new node map reader command for the reader.
226 template <typename Reader, typename Map>
227 GraphReader& addNodeMap(std::string name, Map& map,
228 const Reader& reader = Reader()) {
229 if (node_map_readers.find(name) != node_map_readers.end()) {
231 msg << "Multiple read rule for node map: " << name;
232 throw IOLogicError(msg.message());
234 node_map_readers.insert(
235 make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
239 /// \brief Add a new node map skipper command for the reader.
241 /// Add a new node map skipper command for the reader.
242 template <typename Reader>
243 GraphReader& skipNodeMap(std::string name,
244 const Reader& reader = Reader()) {
245 if (node_map_readers.find(name) != node_map_readers.end()) {
247 msg << "Multiple read rule for node map: " << name;
248 throw IOLogicError(msg.message());
250 node_map_readers.insert(
251 make_pair(name, new SkipReader<Node, Reader>(reader)));
255 /// \brief Add a new edge map reader command for the reader.
257 /// Add a new edge map reader command for the reader.
258 template <typename Map>
259 GraphReader& addEdgeMap(std::string name, Map& map) {
260 return addEdgeMap<typename ReaderTraits::template
261 Reader<typename Map::Value>, Map>(name, map);
265 /// \brief Add a new edge map reader command for the reader.
267 /// Add a new edge map reader command for the reader.
268 template <typename Reader, typename Map>
269 GraphReader& addEdgeMap(std::string name, Map& map,
270 const Reader& reader = Reader()) {
271 if (edge_map_readers.find(name) != edge_map_readers.end()) {
273 msg << "Multiple read rule for edge map: " << name;
274 throw IOLogicError(msg.message());
276 edge_map_readers.insert(
277 make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
281 /// \brief Add a new edge map skipper command for the reader.
283 /// Add a new edge map skipper command for the reader.
284 template <typename Reader>
285 GraphReader& skipEdgeMap(std::string name,
286 const Reader& reader = Reader()) {
287 if (edge_map_readers.find(name) != edge_map_readers.end()) {
289 msg << "Multiple read rule for edge map: " << name;
290 throw IOLogicError(msg.message());
292 edge_map_readers.insert(
293 make_pair(name, new SkipReader<Edge, Reader>(reader)));
297 /// \brief Add a new labeled node reader for the reader.
299 /// Add a new labeled node reader for the reader.
300 GraphReader& addNode(std::string name, Node& node) {
301 if (node_readers.find(name) != node_readers.end()) {
303 msg << "Multiple read rule for node: " << name;
304 throw IOLogicError(msg.message());
306 node_readers.insert(make_pair(name, &node));
310 /// \brief Add a new labeled edge reader for the reader.
312 /// Add a new labeled edge reader for the reader.
313 GraphReader& addEdge(std::string name, Edge& edge) {
314 if (edge_readers.find(name) != edge_readers.end()) {
316 msg << "Multiple read rule for edge: " << name;
317 throw IOLogicError(msg.message());
319 edge_readers.insert(make_pair(name, &edge));
323 /// \brief Executes the reader commands.
325 /// Executes the reader commands.
328 std::auto_ptr<InverterBase<Node> > nodeInverter;
329 std::auto_ptr<InverterBase<Edge> > edgeInverter;
331 std::string line = readNotEmptyLine(is, line_num);
332 if (line.find("@nodeset") == 0) {
333 line = readNodeSet(line_num, nodeInverter);
335 if (line.find("@edgeset") == 0) {
336 line = readEdgeSet(line_num, edgeInverter, nodeInverter);
338 if (line.find("@nodes") == 0) {
339 line = readNodes(line_num, nodeInverter);
341 if (line.find("@edges") == 0) {
342 line = readEdges(line_num, edgeInverter);
344 if (line.find("@end") != 0) {
345 throw DataFormatError("Invalid control sequence error");
347 } catch (DataFormatError e) {
355 template <typename Item> class InverterBase;
357 std::string readNodeSet(int& line_num,
358 auto_ptr<InverterBase<Node> > & nodeInverter) {
359 std::vector<ReaderBase<Node>* > index;
361 std::string line = readNotEmptyLine(is, line_num);
363 std::istringstream ls(line);
365 if (id[0] == '#') break;
366 typename NodeMapReaders::iterator it = node_map_readers.find(id);
367 if (it != node_map_readers.end()) {
368 index.push_back(it->second);
369 node_map_readers.erase(it);
371 index.push_back(&nodeSkipper);
376 if (index.size() == 0) {
377 throw DataFormatError("Cannot find node id map");
380 nodeInverter = auto_ptr<InverterBase<Node> >(index[0]->getInverter());
382 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
383 Node node = graph.addNode();
384 std::istringstream ls(line);
385 nodeInverter->read(ls, node);
386 for (int i = 1; i < (int)index.size(); ++i) {
387 index[i]->read(ls, node);
393 std::string readEdgeSet(int& line_num,
394 auto_ptr<InverterBase<Edge> > & edgeInverter,
395 auto_ptr<InverterBase<Node> > & nodeInverter) {
396 std::vector<ReaderBase<Edge>*> index;
398 std::string line = readNotEmptyLine(is, line_num);
400 std::istringstream ls(line);
402 if (id[0] == '#') break;
403 typename EdgeMapReaders::iterator it = edge_map_readers.find(id);
404 if (it != edge_map_readers.end()) {
405 index.push_back(it->second);
406 edge_map_readers.erase(it);
408 index.push_back(&edgeSkipper);
413 if (index.size() == 0) {
414 throw DataFormatError("Cannot find edge id map");
417 edgeInverter = auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
419 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
420 std::istringstream ls(line);
421 Node source = nodeInverter->read(ls);
422 Node target = nodeInverter->read(ls);
423 Edge edge = graph.addEdge(source, target);
424 edgeInverter->read(ls, edge);
425 for (int i = 1; i < (int)index.size(); ++i) {
426 index[i]->read(ls, edge);
432 std::string readNodes(int& line_num,
433 auto_ptr<InverterBase<Node> >& nodeInverter) {
435 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
436 std::istringstream ls(line);
439 typename NodeReaders::iterator it = node_readers.find(name);
440 if (it != node_readers.end()) {
441 *(it -> second) = nodeInverter->read(ls);
447 std::string readEdges(int& line_num,
448 auto_ptr<InverterBase<Edge> >& edgeInverter) {
450 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
451 std::istringstream ls(line);
454 typename EdgeReaders::iterator it = edge_readers.find(name);
455 if (it != edge_readers.end()) {
456 *(it -> second) = edgeInverter->read(ls);
462 std::string readNotEmptyLine(std::istream& is, int& line_num) {
464 while (++line_num, getline(is, line)) {
465 int vi = line.find_first_not_of(" \t");
466 if (vi != (int)string::npos && line[vi] != '#') {
467 return line.substr(vi);
470 throw DataFormatError("End of stream error");
473 // Inverters store and give back the Item from the id,
474 // and may put the ids into a map.
476 template <typename _Item>
480 virtual void read(std::istream&, const Item&) = 0;
481 virtual Item read(std::istream&) = 0;
484 template <typename _Item, typename _Map, typename _Reader>
485 class MapReaderInverter : public InverterBase<_Item> {
488 typedef _Reader Reader;
489 typedef typename Reader::Value Value;
491 typedef std::map<Value, Item> Inverse;
497 MapReaderInverter(Map& _map, const Reader& _reader)
498 : map(_map), reader(_reader) {}
500 virtual ~MapReaderInverter() {}
502 virtual void read(std::istream& is, const Item& item) {
504 reader.read(is, value);
505 map.set(item, value);
506 typename Inverse::iterator it = inverse.find(value);
507 if (it == inverse.end()) {
508 inverse.insert(make_pair(value, item));
510 throw DataFormatError("Multiple ID occurence");
514 virtual Item read(std::istream& is) {
516 reader.read(is, value);
517 typename Inverse::const_iterator it = inverse.find(value);
518 if (it != inverse.end()) {
521 throw DataFormatError("Invalid ID error");
526 template <typename _Item, typename _Reader>
527 class SkipReaderInverter : public InverterBase<_Item> {
530 typedef _Reader Reader;
531 typedef typename Reader::Value Value;
532 typedef std::map<Value, Item> Inverse;
536 SkipReaderInverter(const Reader& _reader)
539 virtual ~SkipReaderInverter() {}
541 virtual void read(std::istream& is, const Item& item) {
543 reader.read(is, value);
544 typename Inverse::iterator it = inverse.find(value);
545 if (it == inverse.end()) {
546 inverse.insert(make_pair(value, item));
548 throw DataFormatError("Multiple ID occurence error");
552 virtual Item read(std::istream& is) {
554 reader.read(is, value);
555 typename Inverse::const_iterator it = inverse.find(value);
556 if (it != inverse.end()) {
559 throw DataFormatError("Invalid ID error");
568 template <typename _Item>
573 // virtual ~ReaderBase() {}
575 virtual void read(std::istream& is, const Item& item) = 0;
576 virtual InverterBase<_Item>* getInverter() = 0;
579 template <typename _Item, typename _Map, typename _Reader>
580 class MapReader : public ReaderBase<_Item> {
583 typedef _Reader Reader;
584 typedef typename Reader::Value Value;
590 MapReader(Map& _map, const Reader& _reader)
591 : map(_map), reader(_reader) {}
593 virtual ~MapReader() {}
595 virtual void read(std::istream& is, const Item& item) {
597 reader.read(is, value);
598 map.set(item, value);
601 virtual InverterBase<_Item>* getInverter() {
602 return new MapReaderInverter<Item, Map, Reader>(map, reader);
607 template <typename _Item, typename _Reader>
608 class SkipReader : public ReaderBase<_Item> {
610 typedef _Reader Reader;
611 typedef typename Reader::Value Value;
615 SkipReader(const Reader& _reader) : reader(_reader) {}
617 virtual ~SkipReader() {}
619 virtual void read(std::istream& is, const Item& item) {
621 reader.read(is, value);
624 virtual InverterBase<Item>* getInverter() {
625 return new SkipReaderInverter<Item, Reader>(reader);
630 typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders;
631 NodeMapReaders node_map_readers;
633 typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders;
634 EdgeMapReaders edge_map_readers;
636 typedef std::map<std::string, Node*> NodeReaders;
637 NodeReaders node_readers;
639 typedef std::map<std::string, Edge*> EdgeReaders;
640 EdgeReaders edge_readers;
645 SkipReader<Node, DefaultReader> nodeSkipper;
646 SkipReader<Edge, DefaultReader> edgeSkipper;
650 /// Ready to use reader function.
651 template<typename Graph, typename CapacityMap, typename CostMap>
652 void readGraph(std::istream& is, Graph &g, CapacityMap& capacity,
653 typename Graph::Node &s, typename Graph::Node &t,
655 GraphReader<Graph> reader(is, g);
656 reader.addEdgeMap("capacity", capacity);
657 reader.addEdgeMap("cost", cost);
658 reader.addNode("source", s);
659 reader.addNode("target", t);
663 template<typename Graph, typename CapacityMap>
664 void readGraph(std::istream& is, Graph &g, CapacityMap& capacity,
665 typename Graph::Node &s, typename Graph::Node &t) {
666 GraphReader<Graph> reader(is, g);
667 reader.addEdgeMap("capacity", capacity);
668 reader.addNode("source", s);
669 reader.addNode("target", t);
673 template<typename Graph, typename CapacityMap>
674 void readGraph(std::istream& is, Graph &g, CapacityMap& capacity,
675 typename Graph::Node &s) {
676 GraphReader<Graph> reader(is, g);
677 reader.addEdgeMap("capacity", capacity);
678 reader.addNode("source", s);
682 template<typename Graph, typename CapacityMap>
683 void readGraph(std::istream& is, Graph &g, CapacityMap& capacity) {
684 GraphReader<Graph> reader(is, g);
685 reader.addEdgeMap("capacity", capacity);
689 template<typename Graph>
690 void readGraph(std::istream& is, Graph &g) {
691 GraphReader<Graph> reader(is, g);