Changes in doc.
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 string what() const = 0;
43 class DataFormatException : public IOException {
46 DataFormatException(const std::string& _message)
47 : message(_message) {}
48 std::string what() const {
49 return "DataFormatException: " + message;
53 template <typename _Exception>
54 class StreamException : public _Exception {
56 typedef _Exception Exception;
57 StreamException(int _line, Exception _exception)
58 : line_num(_line), Exception(_exception) {}
59 virtual int line() const {
62 virtual std::string what() const {
64 os << Exception::what() << " in line " << line();
72 // Readers and ReaderTraits
74 struct DefaultReaderTraits {
76 template <typename _Value>
79 void read(std::istream& is, Value& value) {
81 throw DataFormatException("Default Reader format exception");
85 typedef Reader<std::string> DefaultReader;
89 class QuotedStringReader {
91 typedef std::string Value;
93 QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}
95 void read(std::istream& is, std::string& value) {
99 if (!is.get(c) || c != '\"') throw DataFormatException("Quoted string format");
100 while (is.get(c) && c != '\"') {
101 if (escaped && c == '\\') {
102 value += readEscape(is);
107 if (!is) throw DataFormatException("Quoted string format");
112 static char readEscape(std::istream& is) {
114 switch (is.get(c), c) {
140 if (!is.get(c) || !isHex(c)) throw DataFormatException("Escape format exception");
141 else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
142 else code = code * 16 + valueHex(c);
148 if (!isOct(c)) throw DataFormatException("Escape format exception");
149 else if (code = valueOct(c), !is.get(c) || !isOct(c)) is.putback(c);
150 else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) is.putback(c);
151 else code = code * 8 + valueOct(c);
157 static bool isOct(char c) {
158 return '0' <= c && c <='7';
161 static int valueOct(char c) {
165 static bool isHex(char c) {
166 return ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
169 static int valueHex(char c) {
170 if ('0' <= c && c <= '9') return c - '0';
171 if ('a' <= c && c <= 'z') return c - 'a' + 10;
184 template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits>
188 typedef _Graph Graph;
189 typedef typename Graph::Node Node;
190 typedef typename Graph::Edge Edge;
192 typedef _ReaderTraits ReaderTraits;
193 typedef typename ReaderTraits::DefaultReader DefaultReader;
195 GraphReader(std::istream& _is, Graph& _graph, const DefaultReader& _reader = DefaultReader())
196 : is(_is), graph(_graph), nodeSkipper(_reader), edgeSkipper(_reader) {}
201 for (typename NodeMapReaders::iterator it = node_map_readers.begin(); it != node_map_readers.end(); ++it) {
205 for (typename EdgeMapReaders::iterator it = edge_map_readers.begin(); it != edge_map_readers.end(); ++it) {
213 template <typename Map>
214 GraphReader& readNodeMap(std::string name, Map& map) {
215 return readNodeMap<typename ReaderTraits::template Reader<typename Map::Value>, Map>(name, map);
218 template <typename Reader, typename Map>
219 GraphReader& readNodeMap(std::string name, Map& map, const Reader& reader = Reader()) {
220 if (node_map_readers.find(name) != node_map_readers.end()) {
221 throw Exception() << "Multiple read rule for node map: " << name;
223 node_map_readers.insert(make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
227 template <typename Reader>
228 GraphReader& skipNodeMap(std::string name, const Reader& reader = Reader()) {
229 if (node_map_readers.find(name) != node_map_readers.end()) {
230 throw Exception() << "Multiple read rule for node map: " << name;
232 node_map_readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
238 template <typename Map>
239 GraphReader& readEdgeMap(std::string name, Map& map) {
240 return readEdgeMap<typename ReaderTraits::template Reader<typename Map::Value>, Map>(name, map);
244 template <typename Reader, typename Map>
245 GraphReader& readEdgeMap(std::string name, Map& map, const Reader& reader = Reader()) {
246 if (edge_map_readers.find(name) != edge_map_readers.end()) {
247 throw Exception() << "Multiple read rule for edge map: " << name;
249 edge_map_readers.insert(make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
253 template <typename Reader>
254 GraphReader& skipEdgeMap(std::string name, const Reader& reader = Reader()) {
255 if (edge_map_readers.find(name) != edge_map_readers.end()) {
256 throw Exception() << "Multiple read rule for edge map: " << name;
258 edge_map_readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
263 GraphReader& readNode(std::string name, Node& node) {
264 if (node_readers.find(name) != node_readers.end()) {
265 throw Exception() << "Multiple read rule for node";
267 node_readers.insert(make_pair(name, &node));
272 GraphReader& readEdge(std::string name, Edge& edge) {
273 if (edge_readers.find(name) != edge_readers.end()) {
274 throw Exception() << "Multiple read rule for edge";
276 edge_readers.insert(make_pair(name, &edge));
281 std::auto_ptr<InverterBase<Node> > nodeInverter;
282 std::auto_ptr<InverterBase<Edge> > edgeInverter;
284 std::string line = readNotEmptyLine(is, line_num);
285 if (line.find("@nodeset") == 0) {
286 line = readNodeSet(line_num, nodeInverter);
288 if (line.find("@edgeset") == 0) {
289 line = readEdgeSet(line_num, edgeInverter, nodeInverter);
291 if (line.find("@nodes") == 0) {
292 line = readNodes(line_num, nodeInverter);
294 if (line.find("@edges") == 0) {
295 line = readEdges(line_num, edgeInverter);
297 if (line.find("@end") != 0) {
298 throw DataFormatException("Invalid control sequence: " + line);
300 } catch (DataFormatException e) {
301 throw StreamException<DataFormatException>(line_num, e);
307 template <typename Item> class InverterBase;
309 std::string readNodeSet(int& line_num, auto_ptr<InverterBase<Node> > & nodeInverter) {
310 std::vector<ReaderBase<Node>* > index;
312 std::string line = readNotEmptyLine(is, line_num);
314 std::istringstream ls(line);
316 if (id[0] == '#') break;
317 typename NodeMapReaders::iterator it = node_map_readers.find(id);
318 if (it != node_map_readers.end()) {
319 index.push_back(it->second);
320 node_map_readers.erase(it);
322 index.push_back(&nodeSkipper);
327 if (index.size() == 0) {
328 throw DataFormatException("No node map found");
331 nodeInverter = auto_ptr<InverterBase<Node> >(index[0]->getInverter());
333 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
334 Node node = graph.addNode();
335 std::istringstream ls(line);
336 nodeInverter->read(ls, node);
337 for (int i = 1; i < index.size(); ++i) {
338 index[i]->read(ls, node);
344 std::string readEdgeSet(int& line_num,
345 auto_ptr<InverterBase<Edge> > & edgeInverter, auto_ptr<InverterBase<Node> > & nodeInverter) {
346 std::vector<ReaderBase<Edge>*> index;
348 std::string line = readNotEmptyLine(is, line_num);
350 std::istringstream ls(line);
352 if (id[0] == '#') break;
353 typename EdgeMapReaders::iterator it = edge_map_readers.find(id);
354 if (it != edge_map_readers.end()) {
355 index.push_back(it->second);
356 edge_map_readers.erase(it);
358 index.push_back(&edgeSkipper);
363 if (index.size() == 0) {
364 throw DataFormatException("No edge map found");
367 edgeInverter = auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
369 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
370 std::istringstream ls(line);
371 Node source = nodeInverter->read(ls);
372 Node target = nodeInverter->read(ls);
373 Edge edge = graph.addEdge(source, target);
374 edgeInverter->read(ls, edge);
375 for (int i = 1; i < index.size(); ++i) {
376 index[i]->read(ls, edge);
382 std::string readNodes(int& line_num, auto_ptr<InverterBase<Node> >& nodeInverter) {
384 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
385 std::istringstream ls(line);
388 typename NodeReaders::iterator it = node_readers.find(name);
389 if (it != node_readers.end()) {
390 *(it -> second) = nodeInverter->read(ls);
396 std::string readEdges(int& line_num, auto_ptr<InverterBase<Edge> >& edgeInverter) {
398 while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
399 std::istringstream ls(line);
402 typename EdgeReaders::iterator it = edge_readers.find(name);
403 if (it != edge_readers.end()) {
404 *(it -> second) = edgeInverter->read(ls);
410 std::string readNotEmptyLine(std::istream& is, int& line_num) {
412 while (++line_num, getline(is, line)) {
413 int vi = line.find_first_not_of(" \t");
414 if (vi != string::npos && line[vi] != '#') {
415 return line.substr(vi);
418 throw DataFormatException("End of stream");
421 // Inverters store and give back the Item from the id,
422 // and may put the ids into a map.
424 template <typename _Item>
428 virtual void read(std::istream&, const Item&) = 0;
429 virtual Item read(std::istream&) = 0;
432 template <typename _Item, typename _Map, typename _Reader>
433 class MapReaderInverter : public InverterBase<_Item> {
436 typedef _Reader Reader;
437 typedef typename Reader::Value Value;
439 typedef std::map<Value, Item> Inverse;
445 MapReaderInverter(Map& _map, const Reader& _reader)
446 : map(_map), reader(_reader) {}
448 virtual void read(std::istream& is, const Item& item) {
450 reader.read(is, value);
451 map.set(item, value);
452 typename Inverse::iterator it = inverse.find(value);
453 if (it == inverse.end()) {
454 inverse.insert(make_pair(value, item));
456 throw DataFormatException("Multiple ID occurence");
460 virtual Item read(std::istream& is) {
462 reader.read(is, value);
463 typename Inverse::const_iterator it = inverse.find(value);
464 if (it != inverse.end()) {
467 throw DataFormatException("Invalid ID");
472 template <typename _Item, typename _Reader>
473 class SkipReaderInverter : public InverterBase<_Item> {
476 typedef _Reader Reader;
477 typedef typename Reader::Value Value;
478 typedef std::map<Value, Item> Inverse;
482 SkipReaderInverter(const Reader& _reader)
485 virtual void read(std::istream& is, const Item& item) {
487 reader.read(is, value);
488 typename Inverse::iterator it = inverse.find(value);
489 if (it == inverse.end()) {
490 inverse.insert(make_pair(value, item));
492 throw DataFormatException("Multiple ID occurence");
496 virtual Item read(std::istream& is) {
498 reader.read(is, value);
499 typename Inverse::const_iterator it = inverse.find(value);
500 if (it != inverse.end()) {
503 throw DataFormatException("Invalid ID");
512 template <typename _Item>
517 virtual void read(std::istream& is, const Item& item) = 0;
518 virtual InverterBase<_Item>* getInverter() = 0;
521 template <typename _Item, typename _Map, typename _Reader>
522 class MapReader : public ReaderBase<_Item> {
525 typedef _Reader Reader;
526 typedef typename Reader::Value Value;
532 MapReader(Map& _map, const Reader& _reader)
533 : map(_map), reader(_reader) {}
536 virtual void read(std::istream& is, const Item& item) {
538 reader.read(is, value);
539 map.set(item, value);
542 virtual InverterBase<_Item>* getInverter() {
543 return new MapReaderInverter<Item, Map, Reader>(map, reader);
548 template <typename _Item, typename _Reader>
549 class SkipReader : public ReaderBase<_Item> {
551 typedef _Reader Reader;
552 typedef typename Reader::Value Value;
556 SkipReader(const Reader& _reader) : reader(_reader) {}
558 virtual void read(std::istream& is, const Item& item) {
560 reader.read(is, value);
563 virtual InverterBase<Item>* getInverter() {
564 return new SkipReaderInverter<Item, Reader>(reader);
569 typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders;
570 NodeMapReaders node_map_readers;
572 typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders;
573 EdgeMapReaders edge_map_readers;
575 typedef std::map<std::string, Node*> NodeReaders;
576 NodeReaders node_readers;
578 typedef std::map<std::string, Edge*> EdgeReaders;
579 EdgeReaders edge_readers;
584 SkipReader<Node, DefaultReader> nodeSkipper;
585 SkipReader<Edge, DefaultReader> edgeSkipper;