# HG changeset patch # User deba # Date 1103052410 0 # Node ID 2f514b5c7122253e865c16b6a6ba8929e2a1a9b1 # Parent f2a3426e64e6a7698a606f2904c51afdaf96c379 reader under construction diff -r f2a3426e64e6 -r 2f514b5c7122 src/work/deba/graph_io_test.cc --- a/src/work/deba/graph_io_test.cc Thu Dec 09 17:02:53 2004 +0000 +++ b/src/work/deba/graph_io_test.cc Tue Dec 14 19:26:50 2004 +0000 @@ -1,5 +1,5 @@ #include -#include +#include "graph_reader.h" #include #include @@ -11,13 +11,30 @@ ifstream input("test.lgf"); SmartGraph graph; GraphReader reader(input, graph); + SmartGraph::NodeMap id(graph); + reader.readNodeMap("id", id); SmartGraph::NodeMap cost(graph); reader.readNodeMap("cost", cost); SmartGraph::NodeMap color(graph); reader.readNodeMap("color", color); - reader.read(); + SmartGraph::NodeMap description(graph); + reader.readNodeMap("description", description); + SmartGraph::EdgeMap mmap(graph); + reader.readEdgeMap("mmap", mmap); + reader.skipEdgeMap("description"); + try { + reader.read(); + } catch (IOException& e) { + cerr << e.what() << endl; + } catch (Exception e) { + cerr << e.what() << endl; + } for (SmartGraph::NodeIt it(graph); it != INVALID; ++it) { - cout << cost[it] << color[it] << endl; + cout << cost[it] << ' ' << color[it] << ' ' << description[it] << endl; + } + + for (SmartGraph::EdgeIt it(graph); it != INVALID; ++it) { + cout << mmap[it] << ' ' << id[graph.source(it)] << ' ' << id[graph.target(it)] << endl; } return 0; } diff -r f2a3426e64e6 -r 2f514b5c7122 src/work/deba/graph_reader.h --- a/src/work/deba/graph_reader.h Thu Dec 09 17:02:53 2004 +0000 +++ b/src/work/deba/graph_reader.h Tue Dec 14 19:26:50 2004 +0000 @@ -16,7 +16,7 @@ ///\ingroup gio ///\file -///\brief Map utilities. +///\brief Graph reader. #include #include @@ -30,6 +30,34 @@ namespace lemon { + + // Exceptions + + class IOException { + public: + virtual string what() const = 0; + }; + + class DataFormatException : public IOException { + std::string message; + public: + DataFormatException(const std::string& _message) + : message(_message) {} + std::string what() const { + return "DataFormatException: " + message; + } + }; + + class StreamException : public IOException { + public: + virtual int line() = 0; + private: + IOException* exception; + int line_num; + }; + + + // Readers and ReaderTraits struct DefaultReaderTraits { @@ -37,36 +65,109 @@ struct Reader { typedef _Value Value; void read(std::istream& is, Value& value) { - is >> value; + if (!(is >> value)) + throw DataFormatException("Default Reader format exception"); } }; - template - struct Skipper { - typedef _Value Value; - void read(std::istream& is) { - Value tmp; - is >> tmp; - } - }; + typedef Reader DefaultReader; - struct DefaultSkipper { - void read(std::istream& is) { - std::string tmp; - is >> tmp; - } - }; }; - class IOException { - virtual string message() = 0; + class QuotedStringReader { + public: + typedef std::string Value; + + QuotedStringReader(bool _escaped = true) : escaped(_escaped) {} + + void read(std::istream& is, std::string& value) { + char c; + value.clear(); + is >> ws; + if (!is.get(c) || c != '\"') throw DataFormatException("Quoted string format exception"); + while (is.get(c) && c != '\"') { + if (escaped && c == '\\') { + value += readEscape(is); + } else { + value += c; + } + } + if (!is) throw DataFormatException("Quoted string format exception"); + } + + private: + + static char readEscape(std::istream& is) { + char c; + switch (is.get(c), c) { + case '\\': + return '\\'; + case '\"': + return '\"'; + case '\'': + return '\''; + case '\?': + return '\?'; + case 'a': + return '\a'; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + case 'v': + return '\v'; + case 'x': + { + int code; + if (!is.get(c) || !isHex(c)) throw DataFormatException("Escape format exception"); + else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c); + else code = code * 16 + valueHex(c); + return code; + } + default: + { + int code; + if (!isOct(c)) throw DataFormatException("Escape format exception"); + else if (code = valueOct(c), !is.get(c) || !isOct(c)) is.putback(c); + else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) is.putback(c); + else code = code * 8 + valueOct(c); + return code; + } + } + } + + static bool isOct(char c) { + return '0' <= c && c <='7'; + } + + static int valueOct(char c) { + return c - '0'; + } + + static bool isHex(char c) { + return ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); + } + + static int valueHex(char c) { + if ('0' <= c && c <= '9') return c - '0'; + if ('a' <= c && c <= 'z') return c - 'a' + 10; + return c - 'A' + 10; + } + + bool escaped; }; - class FileReaderException { - virtual int getLine() = 0; - }; - + + + + // Graph reader template class GraphReader { @@ -78,83 +179,162 @@ typedef typename Graph::Edge Edge; typedef _ReaderTraits ReaderTraits; - + typedef typename ReaderTraits::DefaultReader DefaultReader; - GraphReader(std::istream& _is, Graph& _graph) : is(_is), graph(_graph) {} + GraphReader(istream& _is, Graph& _graph, const DefaultReader& _reader = DefaultReader()) + : is(_is), graph(_graph), nodeSkipper(_reader), edgeSkipper(_reader) {} + + + ~GraphReader() { + + for (typename NodeReaders::iterator it = node_readers.begin(); it != node_readers.end(); ++it) { + delete it->second; + } + + for (typename EdgeReaders::iterator it = edge_readers.begin(); it != edge_readers.end(); ++it) { + delete it->second; + } + + } template - GraphReader& readNodeMap(std::string name, Map& map, - const typename ReaderTraits::template Reader& reader = - typename ReaderTraits::template Reader()) { - return readNodeMap >(name, map, reader); + GraphReader& readNodeMap(std::string name, Map& map) { + return readNodeMap, Map>(name, map); } - template + template GraphReader& readNodeMap(std::string name, Map& map, const Reader& reader = Reader()) { + if (node_readers.find(name) != node_readers.end()) { + Exception e; + e << "Multiple read rule for node map: " << name; + throw e; + } node_readers.insert(make_pair(name, new MapReader(map, reader))); return *this; } - template - GraphReader& readEdgeMap(std::string name, Map& map, - const typename ReaderTraits::template Reader& reader = - typename ReaderTraits::template Reader()) { - return readEdgeMap >(name, map, reader); + template + GraphReader& skipNodeMap(std::string name, const Reader& reader = Reader()) { + if (node_readers.find(name) != node_readers.end()) { + Exception e; + e << "Multiple read rule for node map: " << name; + throw e; + } + node_readers.insert(make_pair(name, new SkipReader(reader))); + return *this; } - template + template + GraphReader& readEdgeMap(std::string name, Map& map) { + return readEdgeMap, Map>(name, map); + } + + + template GraphReader& readEdgeMap(std::string name, Map& map, const Reader& reader = Reader()) { + if (edge_readers.find(name) != edge_readers.end()) { + Exception e; + e << "Multiple read rule for edge map: " << name; + throw e; + } edge_readers.insert(make_pair(name, new MapReader(map, reader))); return *this; } + template + GraphReader& skipEdgeMap(std::string name, const Reader& reader = Reader()) { + if (edge_readers.find(name) != edge_readers.end()) { + Exception e; + e << "Multiple read rule for edge map: " << name; + throw e; + } + edge_readers.insert(make_pair(name, new SkipReader(reader))); + return *this; + } + void read() { int line_num = 0; - readNodeSet(line_num); - readEdgeSet(line_num); - { - std::string line = readNotEmptyLine(is, line_num); - } + InverterBase* nodeInverter = 0; + InverterBase* edgeInverter = 0; + // \todo delete the inverters + // try { + { + std::string line = readNotEmptyLine(is, line_num); + } + readNodeSet(line_num, nodeInverter); + readEdgeSet(line_num, edgeInverter, nodeInverter); + // } catch (...){ + if (nodeInverter != 0) delete nodeInverter; + if (edgeInverter != 0) delete edgeInverter; + // } } private: - void readNodeSet(int& line_num) { + template class InverterBase; + // template class InverterBase; + + void readNodeSet(int& line_num, InverterBase* & nodeInverter) { int n = 0; - { - std::string line = readNotEmptyLine(is, line_num); - } - std::vector*> index; + std::vector*> index; { std::string line = readNotEmptyLine(is, line_num); std::string id; std::istringstream ls(line); while (ls >> id) { - typename map* >::iterator it = node_readers.find(id); + if (id[0] == '#') break; + typename NodeReaders::iterator it = node_readers.find(id); if (it != node_readers.end()) { index.push_back(it->second); } else { - index.push_back(0); + index.push_back(&nodeSkipper); } ++n; } } + + nodeInverter = index[0]->getInverter(); std::string line; while (line = readNotEmptyLine(is, line_num), line[0] != '@') { Node node = graph.addNode(); std::istringstream ls(line); - for (int i = 0; i < n; ++i) { - if (index[i] != 0) { - index[i]->read(ls, node); - } else { - default_skipper.read(ls); - } + nodeInverter->read(ls, node); + for (int i = 1; i < n; ++i) { + index[i]->read(ls, node); } } } - void readEdgeSet(int& line_num) { - + void readEdgeSet(int& line_num, InverterBase* & edgeInverter, InverterBase* & nodeInverter) { + int n = 0; + std::vector*> index; + { + std::string line = readNotEmptyLine(is, line_num); + std::string id; + std::istringstream ls(line); + while (ls >> id) { + if (id[0] == '#') break; + typename EdgeReaders::iterator it = edge_readers.find(id); + if (it != edge_readers.end()) { + index.push_back(it->second); + } else { + index.push_back(&edgeSkipper); + } + ++n; + } + } + edgeInverter = index[0]->getInverter(); + std::string line; + while (line = readNotEmptyLine(is, line_num), line[0] != '@') { + std::istringstream ls(line); + Node source = nodeInverter->read(ls); + Node target = nodeInverter->read(ls); + Edge edge = graph.addEdge(source, target); + edgeInverter->read(ls, edge); + for (int i = 1; i < n; ++i) { + index[i]->read(ls, edge); + } + } } std::string readNotEmptyLine(std::istream& is, int& line_num) { @@ -168,23 +348,107 @@ throw Exception(); } - istream& is; - Graph& graph; + template + class InverterBase { + public: + typedef _Item Item; + virtual void read(istream&, const Item&) = 0; + virtual Item read(istream&) = 0; + }; - typename ReaderTraits::DefaultSkipper default_skipper; + template + class MapReaderInverter : public InverterBase<_Item> { + public: + typedef _Item Item; + typedef _Reader Reader; + typedef typename Reader::Value Value; + typedef _Map Map; + typedef std::map Inverse; + + Map& map; + Reader reader; + Inverse inverse; + + MapReaderInverter(Map& _map, const Reader& _reader) + : map(_map), reader(_reader) {} + + virtual void read(istream& is, const Item& item) { + Value value; + reader.read(is, value); + map.set(item, value); + typename Inverse::iterator it = inverse.find(value); + if (it == inverse.end()) { + inverse.insert(make_pair(value, item)); + } else { + throw DataFormatException("Multiple ID occurence"); + } + } + + virtual Item read(istream& is) { + Value value; + reader.read(is, value); + typename Inverse::const_iterator it = inverse.find(value); + if (it != inverse.end()) { + return it->second; + } else { + throw DataFormatException("Invalid ID"); + } + } + }; + + template + class SkipReaderInverter : public InverterBase<_Item> { + public: + typedef _Item Item; + typedef _Reader Reader; + typedef typename Reader::Value Value; + typedef std::map Inverse; + + Reader reader; + + SkipReaderInverter(const Reader& _reader) + : reader(_reader) {} + + virtual void read(istream& is, const Item& item) { + Value value; + reader.read(is, value); + typename Inverse::iterator it = inverse.find(value); + if (it == inverse.end()) { + inverse.insert(make_pair(value, item)); + } else { + throw DataFormatException("Multiple ID occurence"); + } + } + + virtual Item read(istream& is) { + Value value; + reader.read(is, value); + typename Inverse::const_iterator it = inverse.find(value); + if (it != inverse.end()) { + return it->second; + } else { + throw DataFormatException("Invalid ID"); + } + } + private: + Inverse inverse; + }; + template - class MapReaderBase { + class ReaderBase { public: typedef _Item Item; virtual void read(istream& is, const Item& item) = 0; + virtual InverterBase<_Item>* getInverter() = 0; }; - + template - class MapReader : public MapReaderBase<_Item> { + class MapReader : public ReaderBase<_Item> { public: typedef _Map Map; typedef _Reader Reader; + typedef typename Reader::Value Value; typedef _Item Item; Map& map; @@ -195,18 +459,50 @@ virtual void read(istream& is, const Item& item) { - typename Reader::Value value; + Value value; reader.read(is, value); map.set(item, value); } + + virtual InverterBase<_Item>* getInverter() { + return new MapReaderInverter(map, reader); + } }; - typedef std::map* > NodeReaders; + + template + class SkipReader : public ReaderBase<_Item> { + public: + typedef _Reader Reader; + typedef typename Reader::Value Value; + typedef _Item Item; + + Reader reader; + SkipReader(const Reader& _reader) : reader(_reader) {} + + virtual void read(istream& is, const Item& item) { + Value value; + reader.read(is, value); + } + + virtual InverterBase* getInverter() { + return new SkipReaderInverter(reader); + } + }; + + + typedef std::map* > NodeReaders; NodeReaders node_readers; - typedef std::map* > EdgeReaders; + typedef std::map* > EdgeReaders; EdgeReaders edge_readers; + std::istream& is; + Graph& graph; + + SkipReader nodeSkipper; + SkipReader edgeSkipper; + }; } diff -r f2a3426e64e6 -r 2f514b5c7122 src/work/deba/test.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/work/deba/test.cpp Tue Dec 14 19:26:50 2004 +0000 @@ -0,0 +1,51 @@ +#include + +using namespace std; + + +struct _EmptyList { + void write() const {} +}; + +template +struct _AddNode { + typedef _Next Next; + typedef _Item Item; + + const Item item; + const Next& next; + + _AddNode(const Item& _item, const Next& _next) + : item(_item), next(_next) {} + + void write() const { + next.write(); + cout << item << ' '; + } +}; + +template +struct _Writer { + typedef _List List; + + const List list; + + _Writer(const List& _list = List()) : list(_list) {} + + + template _Writer<_AddNode > add(Item item) const { + return _Writer<_AddNode >(_AddNode(item, list)); + } + + void write() const { + list.write(); + cout << endl; + } +}; + + +typedef _Writer<> Writer; + +int main() { + Writer().add(3).add("alpha").add(4.53).write(); +} diff -r f2a3426e64e6 -r 2f514b5c7122 src/work/deba/test.lgf --- a/src/work/deba/test.lgf Thu Dec 09 17:02:53 2004 +0000 +++ b/src/work/deba/test.lgf Tue Dec 14 19:26:50 2004 +0000 @@ -1,30 +1,36 @@ +@nodeset +id cost color description mmap +1 1 green "A -> B \t: 10" a +2 2 blue "A -> B \t: 10" b +# hatalom dicsoseg "A -> B \t: 10" c +3 1 red "A -> B \t: 10" d #adjkhj +4 2 red "A -> B \t: 10" e +5 1 green "A -> B \t: 10" f +10 1 green "A -> B \t: 10" g + # hello - bello csucsok "A -> B \t: 10" +6 2 blue "A -> B \t: 10" h +7 1 blue "A -> B \t: 10" i +8 2 red "A -> B \t: 10" j +9 1 green "A -> B \t: 10" k + +@edgeset + id weight description mmap +1 4 1 10 "A -> B \t: 101" a +3 5 5 29 "A -> B \t: 10q" b +3 4 2 92 "A -> B \t: 10a" c +2 3 6 92 "A -> B \t: 10d" d +9 5 9 49 "A -> B \t: 10c" e +10 4 3 40 "A -> B \t: 10v" f +1 3 8 84 "A -> B \t: 10g" g +6 7 4 83 "A -> B \t: 10h" h +8 9 7 37 "A -> B \t: 10j" i +7 8 10 12 "A -> B \t: 10g" j @nodes +source 1 +target 7 -id cost color +@edges +newedge 7 -1 1 green -2 2 blue -# hatalom dicsoseg -3 1 red -4 2 red -5 1 green -10 1 green # ez nem egy igazan jo sor - # hello - bello csucsok -6 2 blue -7 1 blue -8 2 red -9 1 green -@edges -source target weight -1 4 10 -3 5 29 -3 4 92 -2 3 92 -9 5 49 -10 4 40 -1 3 84 -6 7 83 -8 9 37 -7 8 89 @end