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 /// \brief Standard ReaderTraits for the GraphReader class.
78 /// Standard ReaderTraits for the GraphReader class.
79 /// It defines standard reading method for all type of value.
80 struct DefaultReaderTraits {
82 /// \brief Template class for reading an value.
84 /// Template class for reading an value.
85 template <typename _Value>
89 /// \brief Reads a value from the given stream.
91 /// Reads a value from the given stream.
92 void read(std::istream& is, Value& value) {
94 throw DataFormatException("Default Reader format exception");
98 /// The reader class for the not needed maps.
99 typedef Reader<std::string> DefaultReader;
103 /// \brief Reader class for quoted strings.
105 /// Reader class for quoted strings. It can process the escape
106 /// sequences in the string.
107 class QuotedStringReader {
109 typedef std::string Value;
111 /// \brief Constructor for the reader.
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) {}
117 /// \brief Reads a quoted string from the given stream.
119 /// Reads a quoted string from the given stream.
120 void read(std::istream& is, std::string& value) {
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);
133 if (!is) throw DataFormatException("Quoted string format");
138 static char readEscape(std::istream& is) {
140 switch (is.get(c), c) {
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);
176 throw DataFormatException("Escape format exception");
177 else if (code = valueOct(c), !is.get(c) || !isOct(c))
179 else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
181 else code = code * 8 + valueOct(c);
187 static bool isOct(char c) {
188 return '0' <= c && c <='7';
191 static int valueOct(char c) {
195 static bool isHex(char c) {
196 return ('0' <= c && c <= '9') ||
197 ('a' <= c && c <= 'z') ||
198 ('A' <= c && c <= 'Z');
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;
210 /// \brief The graph reader class.
212 /// The reader class for the graph input.
213 /// \see graph-io-page
214 template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits>
218 typedef _Graph Graph;
219 typedef typename Graph::Node Node;
220 typedef typename Graph::Edge Edge;
222 typedef _ReaderTraits ReaderTraits;
223 typedef typename ReaderTraits::DefaultReader DefaultReader;
225 /// \brief Construct a new GraphReader.
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
230 GraphReader(std::istream& _is, Graph& _graph,
231 const DefaultReader& _reader = DefaultReader())
232 : is(_is), graph(_graph), nodeSkipper(_reader), edgeSkipper(_reader) {}
234 /// \brief Destruct the graph reader.
236 /// Destruct the graph reader.
239 for (typename NodeMapReaders::iterator it = node_map_readers.begin();
240 it != node_map_readers.end(); ++it) {
244 for (typename EdgeMapReaders::iterator it = edge_map_readers.begin();
245 it != edge_map_readers.end(); ++it) {
251 /// \brief Add a new node map reader command for the reader.
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);
260 /// \brief Add a new node map reader command for the reader.
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;
269 node_map_readers.insert(
270 make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
274 /// \brief Add a new node map skipper command for the reader.
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;
283 node_map_readers.insert(
284 make_pair(name, new SkipReader<Node, Reader>(reader)));
288 /// \brief Add a new edge map reader command for the reader.
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);
298 /// \brief Add a new edge map reader command for the reader.
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;
307 edge_map_readers.insert(
308 make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
312 /// \brief Add a new edge map skipper command for the reader.
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;
321 edge_map_readers.insert(
322 make_pair(name, new SkipReader<Edge, Reader>(reader)));
326 /// \brief Add a new labeled node reader for the reader.
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";
333 node_readers.insert(make_pair(name, &node));
337 /// \brief Add a new labeled edge reader for the reader.
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";
344 edge_readers.insert(make_pair(name, &edge));
348 /// \brief Executes the reader commands.
350 /// Executes the reader commands.
353 std::auto_ptr<InverterBase<Node> > nodeInverter;
354 std::auto_ptr<InverterBase<Edge> > edgeInverter;
356 std::string line = readNotEmptyLine(is, line_num);
357 if (line.find("@nodeset") == 0) {
358 line = readNodeSet(line_num, nodeInverter);
360 if (line.find("@edgeset") == 0) {
361 line = readEdgeSet(line_num, edgeInverter, nodeInverter);
363 if (line.find("@nodes") == 0) {
364 line = readNodes(line_num, nodeInverter);
366 if (line.find("@edges") == 0) {
367 line = readEdges(line_num, edgeInverter);
369 if (line.find("@end") != 0) {
370 throw DataFormatException("Invalid control sequence: " + line);
372 } catch (DataFormatException e) {
373 throw StreamException<DataFormatException>(line_num, e);
379 template <typename Item> class InverterBase;
381 std::string readNodeSet(int& line_num,
382 auto_ptr<InverterBase<Node> > & nodeInverter) {
383 std::vector<ReaderBase<Node>* > index;
385 std::string line = readNotEmptyLine(is, line_num);
387 std::istringstream ls(line);
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);
395 index.push_back(&nodeSkipper);
400 if (index.size() == 0) {
401 throw DataFormatException("No node map found");
404 nodeInverter = auto_ptr<InverterBase<Node> >(index[0]->getInverter());
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);
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;
422 std::string line = readNotEmptyLine(is, line_num);
424 std::istringstream ls(line);
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);
432 index.push_back(&edgeSkipper);
437 if (index.size() == 0) {
438 throw DataFormatException("No edge map found");
441 edgeInverter = auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
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);
456 std::string readNodes(int& line_num,
457 auto_ptr<InverterBase<Node> >& nodeInverter) {
459 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
460 std::istringstream ls(line);
463 typename NodeReaders::iterator it = node_readers.find(name);
464 if (it != node_readers.end()) {
465 *(it -> second) = nodeInverter->read(ls);
471 std::string readEdges(int& line_num,
472 auto_ptr<InverterBase<Edge> >& edgeInverter) {
474 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
475 std::istringstream ls(line);
478 typename EdgeReaders::iterator it = edge_readers.find(name);
479 if (it != edge_readers.end()) {
480 *(it -> second) = edgeInverter->read(ls);
486 std::string readNotEmptyLine(std::istream& is, int& line_num) {
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);
494 throw DataFormatException("End of stream");
497 // Inverters store and give back the Item from the id,
498 // and may put the ids into a map.
500 template <typename _Item>
504 virtual void read(std::istream&, const Item&) = 0;
505 virtual Item read(std::istream&) = 0;
508 template <typename _Item, typename _Map, typename _Reader>
509 class MapReaderInverter : public InverterBase<_Item> {
512 typedef _Reader Reader;
513 typedef typename Reader::Value Value;
515 typedef std::map<Value, Item> Inverse;
521 MapReaderInverter(Map& _map, const Reader& _reader)
522 : map(_map), reader(_reader) {}
524 virtual ~MapReaderInverter() {}
526 virtual void read(std::istream& is, const Item& item) {
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));
534 throw DataFormatException("Multiple ID occurence");
538 virtual Item read(std::istream& is) {
540 reader.read(is, value);
541 typename Inverse::const_iterator it = inverse.find(value);
542 if (it != inverse.end()) {
545 throw DataFormatException("Invalid ID");
550 template <typename _Item, typename _Reader>
551 class SkipReaderInverter : public InverterBase<_Item> {
554 typedef _Reader Reader;
555 typedef typename Reader::Value Value;
556 typedef std::map<Value, Item> Inverse;
560 SkipReaderInverter(const Reader& _reader)
563 virtual ~SkipReaderInverter() {}
565 virtual void read(std::istream& is, const Item& item) {
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));
572 throw DataFormatException("Multiple ID occurence");
576 virtual Item read(std::istream& is) {
578 reader.read(is, value);
579 typename Inverse::const_iterator it = inverse.find(value);
580 if (it != inverse.end()) {
583 throw DataFormatException("Invalid ID");
592 template <typename _Item>
597 // virtual ~ReaderBase() {}
599 virtual void read(std::istream& is, const Item& item) = 0;
600 virtual InverterBase<_Item>* getInverter() = 0;
603 template <typename _Item, typename _Map, typename _Reader>
604 class MapReader : public ReaderBase<_Item> {
607 typedef _Reader Reader;
608 typedef typename Reader::Value Value;
614 MapReader(Map& _map, const Reader& _reader)
615 : map(_map), reader(_reader) {}
617 virtual ~MapReader() {}
619 virtual void read(std::istream& is, const Item& item) {
621 reader.read(is, value);
622 map.set(item, value);
625 virtual InverterBase<_Item>* getInverter() {
626 return new MapReaderInverter<Item, Map, Reader>(map, reader);
631 template <typename _Item, typename _Reader>
632 class SkipReader : public ReaderBase<_Item> {
634 typedef _Reader Reader;
635 typedef typename Reader::Value Value;
639 SkipReader(const Reader& _reader) : reader(_reader) {}
641 virtual ~SkipReader() {}
643 virtual void read(std::istream& is, const Item& item) {
645 reader.read(is, value);
648 virtual InverterBase<Item>* getInverter() {
649 return new SkipReaderInverter<Item, Reader>(reader);
654 typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders;
655 NodeMapReaders node_map_readers;
657 typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders;
658 EdgeMapReaders edge_map_readers;
660 typedef std::map<std::string, Node*> NodeReaders;
661 NodeReaders node_readers;
663 typedef std::map<std::string, Edge*> EdgeReaders;
664 EdgeReaders edge_readers;
669 SkipReader<Node, DefaultReader> nodeSkipper;
670 SkipReader<Edge, DefaultReader> edgeSkipper;