New graph reader interface.
1.1 --- a/src/lemon/Makefile.am Fri May 06 15:39:33 2005 +0000
1.2 +++ b/src/lemon/Makefile.am Mon May 09 11:24:26 2005 +0000
1.3 @@ -52,6 +52,7 @@
1.4 xy.h \
1.5 concept_check.h \
1.6 utility.h \
1.7 + lemon_reader.h \
1.8 graph_reader.h \
1.9 graph_writer.h \
1.10 bits/alteration_notifier.h \
1.11 @@ -64,7 +65,8 @@
1.12 bits/extendable_graph_extender.h \
1.13 bits/clearable_graph_extender.h \
1.14 bits/erasable_graph_extender.h \
1.15 - bits/undir_graph_extender.h
1.16 + bits/undir_graph_extender.h \
1.17 + bits/item_reader.h
1.18
1.19 noinst_HEADERS = \
1.20 concept/graph.h \
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/src/lemon/bits/item_reader.h Mon May 09 11:24:26 2005 +0000
2.3 @@ -0,0 +1,395 @@
2.4 +/* -*- C++ -*-
2.5 + * src/lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
2.6 + *
2.7 + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
2.8 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
2.9 + *
2.10 + * Permission to use, modify and distribute this software is granted
2.11 + * provided that this copyright notice appears in all copies. For
2.12 + * precise terms see the accompanying LICENSE file.
2.13 + *
2.14 + * This software is provided "AS IS" with no warranty of any kind,
2.15 + * express or implied, and with no claim as to its suitability for any
2.16 + * purpose.
2.17 + *
2.18 + */
2.19 +
2.20 +/// \ingroup io_group
2.21 +/// \file
2.22 +/// \brief Item reader bits for lemon input.
2.23 +
2.24 +#ifndef LEMON_BITS_ITEM_READER_H
2.25 +#define LEMON_BITS_ITEM_READER_H
2.26 +
2.27 +#include <iostream>
2.28 +#include <string>
2.29 +
2.30 +#include <vector>
2.31 +#include <deque>
2.32 +#include <list>
2.33 +#include <set>
2.34 +
2.35 +namespace lemon {
2.36 +
2.37 + template <typename Value>
2.38 + class DefaultReader;
2.39 +
2.40 + /// \ingroup io_group
2.41 + ///
2.42 + /// \brief Reader class for quoted strings.
2.43 + ///
2.44 + /// Reader class for quoted strings. It can process the escape
2.45 + /// sequences in the string.
2.46 + ///
2.47 + /// \author Balazs Dezso
2.48 + class QuotedStringReader {
2.49 + public:
2.50 + /// \brief The value type of reader.
2.51 + ///
2.52 + /// The value type of reader.
2.53 + typedef std::string Value;
2.54 +
2.55 + /// \brief Constructor for the reader.
2.56 + ///
2.57 + /// Constructor for the reader. If the given parameter is true
2.58 + /// the reader processes the escape sequences.
2.59 + QuotedStringReader(bool _escaped = true)
2.60 + : escaped(_escaped) {}
2.61 +
2.62 + /// \brief Reads a quoted string from the given stream.
2.63 + ///
2.64 + /// Reads a quoted string from the given stream.
2.65 + void read(std::istream& is, std::string& value) const {
2.66 + char c;
2.67 + value.clear();
2.68 + is >> std::ws;
2.69 + if (!is.get(c) || c != '\"')
2.70 + throw DataFormatError("Quoted string format error");
2.71 + while (is.get(c) && c != '\"') {
2.72 + if (escaped && c == '\\') {
2.73 + value += readEscape(is);
2.74 + } else {
2.75 + value += c;
2.76 + }
2.77 + }
2.78 + if (!is) throw DataFormatError("Quoted string format error");
2.79 + }
2.80 +
2.81 + private:
2.82 +
2.83 + static char readEscape(std::istream& is) {
2.84 + char c;
2.85 + switch (is.get(c), c) {
2.86 + case '\\':
2.87 + return '\\';
2.88 + case '\"':
2.89 + return '\"';
2.90 + case '\'':
2.91 + return '\'';
2.92 + case '\?':
2.93 + return '\?';
2.94 + case 'a':
2.95 + return '\a';
2.96 + case 'b':
2.97 + return '\b';
2.98 + case 'f':
2.99 + return '\f';
2.100 + case 'n':
2.101 + return '\n';
2.102 + case 'r':
2.103 + return '\r';
2.104 + case 't':
2.105 + return '\t';
2.106 + case 'v':
2.107 + return '\v';
2.108 + case 'x':
2.109 + {
2.110 + int code;
2.111 + if (!is.get(c) || !isHex(c))
2.112 + throw DataFormatError("Escape format error");
2.113 + else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
2.114 + else code = code * 16 + valueHex(c);
2.115 + return code;
2.116 + }
2.117 + default:
2.118 + {
2.119 + int code;
2.120 + if (!isOct(c))
2.121 + throw DataFormatError("Escape format error");
2.122 + else if (code = valueOct(c), !is.get(c) || !isOct(c))
2.123 + is.putback(c);
2.124 + else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
2.125 + is.putback(c);
2.126 + else code = code * 8 + valueOct(c);
2.127 + return code;
2.128 + }
2.129 + }
2.130 + }
2.131 +
2.132 + static bool isOct(char c) {
2.133 + return '0' <= c && c <='7';
2.134 + }
2.135 +
2.136 + static int valueOct(char c) {
2.137 + return c - '0';
2.138 + }
2.139 +
2.140 + static bool isHex(char c) {
2.141 + return ('0' <= c && c <= '9') ||
2.142 + ('a' <= c && c <= 'z') ||
2.143 + ('A' <= c && c <= 'Z');
2.144 + }
2.145 +
2.146 + static int valueHex(char c) {
2.147 + if ('0' <= c && c <= '9') return c - '0';
2.148 + if ('a' <= c && c <= 'z') return c - 'a' + 10;
2.149 + return c - 'A' + 10;
2.150 + }
2.151 +
2.152 + bool escaped;
2.153 + };
2.154 +
2.155 + /// \ingroup io_group
2.156 + /// \brief Reader for standard containers.
2.157 + ///
2.158 + /// Reader for back insertable standard containers. The representation
2.159 + /// of the container is the values enumerated between an open and a
2.160 + /// close parse.
2.161 + ///
2.162 + /// \author Balazs Dezso
2.163 + template <
2.164 + typename _Container,
2.165 + typename _ItemReader = DefaultReader<typename _Container::value_type>
2.166 + >
2.167 + class PushBackReader {
2.168 + public:
2.169 + typedef _Container Value;
2.170 + typedef _ItemReader ItemReader;
2.171 +
2.172 + private:
2.173 +
2.174 + ItemReader item_reader;
2.175 +
2.176 + public:
2.177 +
2.178 + /// \brief Reads the values into the container from the given stream.
2.179 + ///
2.180 + /// Reads the values into the container from the given stream.
2.181 + void read(std::istream& is, Value& value) const {
2.182 + char c;
2.183 + if (!(is >> c) || c != '(')
2.184 + throw DataFormatError("PushBackReader format error");
2.185 + while (is >> c && c != ')') {
2.186 + is.putback(c);
2.187 + typename ItemReader::Value item;
2.188 + item_reader.read(is, item);
2.189 + value.push_back(item);
2.190 + }
2.191 + if (!is) throw DataFormatError("PushBackReader format error");
2.192 + is.putback(c);
2.193 + }
2.194 +
2.195 + };
2.196 +
2.197 + /// \ingroup io_group
2.198 + ///
2.199 + /// \brief Reader for standard containers.
2.200 + ///
2.201 + /// Reader for insertable standard containers. The representation
2.202 + /// of the container is the values enumerated between an open and a
2.203 + /// close parse.
2.204 + ///
2.205 + /// \author Balazs Dezso
2.206 + template <
2.207 + typename _Container,
2.208 + typename _ItemReader = DefaultReader<typename _Container::value_type>
2.209 + >
2.210 + class InsertReader {
2.211 + public:
2.212 + typedef _Container Value;
2.213 + typedef _ItemReader ItemReader;
2.214 +
2.215 + private:
2.216 +
2.217 + ItemReader item_reader;
2.218 +
2.219 + public:
2.220 +
2.221 + /// \brief Reads the values into the container from the given stream.
2.222 + ///
2.223 + /// Reads the values into the container from the given stream.
2.224 + void read(std::istream& is, Value& value) const {
2.225 + char c;
2.226 + if (!(is >> c) || c != '(')
2.227 + throw DataFormatError("InsertReader format error");
2.228 + while (is >> c && c != ')') {
2.229 + is.putback(c);
2.230 + typename ItemReader::Value item;
2.231 + item_reader.read(is, item);
2.232 + value.insert(item);
2.233 + }
2.234 + if (!is) throw DataFormatError("PushBackReader format error");
2.235 + is.putback(c);
2.236 + }
2.237 +
2.238 + };
2.239 +
2.240 + /// \ingroup io_group
2.241 + /// \brief Reader for parsed string.
2.242 + ///
2.243 + /// Reader for parsed strings. You can give the open and close
2.244 + /// parse characters.
2.245 + ///
2.246 + /// \author Balazs Dezso
2.247 + class ParsedStringReader {
2.248 + public:
2.249 + typedef std::string Value;
2.250 +
2.251 + /// \brief Constructor.
2.252 + ///
2.253 + /// Constructor for ParsedStringReader. You can give as parameter
2.254 + /// the open and close parse characters.
2.255 + ParsedStringReader(char _open = '(', char _close = ')')
2.256 + : open(_open), close(_close) {}
2.257 +
2.258 +
2.259 + /// \brief Reads the parsed string from the given stream.
2.260 + ///
2.261 + /// Reads the parsed string from the given stream.
2.262 + void read(std::istream& is, Value& value) const {
2.263 + char c;
2.264 + if (!(is >> c) || c != open) {
2.265 + throw DataFormatError("ParsedStringReader format error");
2.266 + }
2.267 + value += c;
2.268 + int counter = 1;
2.269 + while (counter > 0 && is >> c) {
2.270 + if (c == close) {
2.271 + --counter;
2.272 + } else if (c == open) {
2.273 + ++counter;
2.274 + }
2.275 + value += c;
2.276 + }
2.277 + if (!is) {
2.278 + throw DataFormatError("ParsedStrinReader format error");
2.279 + }
2.280 + }
2.281 +
2.282 + private:
2.283 + char open, close;
2.284 +
2.285 + };
2.286 +
2.287 + /// \ingroup io_group
2.288 + /// \brief Reader for read the whole line.
2.289 + ///
2.290 + /// Reader for read the whole line.
2.291 + ///
2.292 + /// \author Balazs Dezso
2.293 + class LineReader {
2.294 + public:
2.295 + typedef std::string Value;
2.296 +
2.297 + /// \brief Constructor.
2.298 + ///
2.299 + /// Constructor for the LineReader. If the given parameter is
2.300 + /// true then the spaces before the first not space character are
2.301 + /// skipped.
2.302 + LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
2.303 +
2.304 + /// \brief Reads the line from the given stream.
2.305 + ///
2.306 + /// Reads the line from the given stream.
2.307 + void read(std::istream& is, Value& value) {
2.308 + if (skipSpaces) is >> std::ws;
2.309 + if (!getline(is, value)) {
2.310 + throw DataFormatError("LineReader forma error");
2.311 + }
2.312 + }
2.313 + private:
2.314 + bool skipSpaces;
2.315 + };
2.316 +
2.317 + /// \ingroup io_group
2.318 + ///
2.319 + /// \brief The default item reader template class.
2.320 + ///
2.321 + /// The default item reader template class. If some section reader
2.322 + /// needs to read a value from a stream it will give the default way for it.
2.323 + ///
2.324 + /// \author Balazs Dezso
2.325 + template <typename _Value>
2.326 + class DefaultReader {
2.327 + public:
2.328 + /// The value type.
2.329 + typedef _Value Value;
2.330 + /// \brief Reads a value from the given stream.
2.331 + ///
2.332 + /// Reads a value from the given stream.
2.333 + void read(std::istream& is, Value& value) const {
2.334 + if (!(is >> value))
2.335 + throw DataFormatError("DefaultReader format error");
2.336 + }
2.337 + };
2.338 +
2.339 + template <typename Item>
2.340 + class DefaultReader<std::vector<Item> >
2.341 + : public PushBackReader<std::vector<Item> > {};
2.342 +
2.343 + template <typename Item>
2.344 + class DefaultReader<std::deque<Item> >
2.345 + : public PushBackReader<std::deque<Item> > {};
2.346 +
2.347 + template <typename Item>
2.348 + class DefaultReader<std::list<Item> >
2.349 + : public PushBackReader<std::list<Item> > {};
2.350 +
2.351 + template <typename Item>
2.352 + class DefaultReader<std::set<Item> >
2.353 + : public InsertReader<std::set<Item> > {};
2.354 +
2.355 + template <typename Item>
2.356 + class DefaultReader<std::multiset<Item> >
2.357 + : public InsertReader<std::multiset<Item> > {};
2.358 +
2.359 + /// \ingroup io_group
2.360 + class DefaultSkipper {
2.361 + public:
2.362 + typedef std::string Value;
2.363 +
2.364 + void read(std::istream& is, Value& value) const {
2.365 + char c;
2.366 + if (!(is >> c)) return;
2.367 + is.putback(c);
2.368 + switch (c) {
2.369 + case '\"':
2.370 + QuotedStringReader().read(is, value);
2.371 + break;
2.372 + case '(':
2.373 + ParsedStringReader().read(is, value);
2.374 + break;
2.375 + default:
2.376 + DefaultReader<std::string>().read(is, value);
2.377 + break;
2.378 + }
2.379 + }
2.380 + };
2.381 +
2.382 + /// \brief Standard ReaderTraits for the GraphReader class.
2.383 + ///
2.384 + /// Standard ReaderTraits for the GraphReader class.
2.385 + /// It defines standard reading method for all type of value.
2.386 + /// \author Balazs Dezso
2.387 + struct DefaultReaderTraits {
2.388 +
2.389 + template <typename _Value>
2.390 + struct Reader : DefaultReader<_Value> {};
2.391 +
2.392 + typedef DefaultSkipper Skipper;
2.393 +
2.394 + };
2.395 +
2.396 +}
2.397 +
2.398 +#endif
3.1 --- a/src/lemon/graph_reader.h Fri May 06 15:39:33 2005 +0000
3.2 +++ b/src/lemon/graph_reader.h Mon May 09 11:24:26 2005 +0000
3.3 @@ -22,173 +22,17 @@
3.4 #define LEMON_GRAPH_READER_H
3.5
3.6 #include <iostream>
3.7 -#include <sstream>
3.8 -
3.9 -#include <map>
3.10 -#include <vector>
3.11 -
3.12 -#include <memory>
3.13
3.14 #include <lemon/error.h>
3.15 -
3.16 +#include <lemon/lemon_reader.h>
3.17
3.18 namespace lemon {
3.19
3.20 /// \addtogroup io_group
3.21 /// @{
3.22
3.23 - /// \brief Standard ReaderTraits for the GraphReader class.
3.24 - ///
3.25 - /// Standard ReaderTraits for the GraphReader class.
3.26 - /// It defines standard reading method for all type of value.
3.27 - /// \author Balazs Dezso
3.28 - struct DefaultReaderTraits {
3.29 -
3.30 - /// \brief Template class for reading an value.
3.31 - ///
3.32 - /// Template class for reading an value.
3.33 - /// \author Balazs Dezso
3.34 - template <typename _Value>
3.35 - struct Reader {
3.36 - /// The value type.
3.37 - typedef _Value Value;
3.38 - /// \brief Reads a value from the given stream.
3.39 - ///
3.40 - /// Reads a value from the given stream.
3.41 - void read(std::istream& is, Value& value) {
3.42 - if (!(is >> value))
3.43 - throw DataFormatError("Default reader format exception");
3.44 - }
3.45 - };
3.46 -
3.47 - /// \brief Returns wheter this name is an ID map name.
3.48 - ///
3.49 - /// Returns wheter this name is an ID map name.
3.50 - static bool idMapName(const std::string& name) {
3.51 - return name == "id";
3.52 - }
3.53 -
3.54 - /// The reader class for the not needed maps.
3.55 - typedef Reader<std::string> DefaultReader;
3.56 -
3.57 - };
3.58 -
3.59 - /// \brief Reader class for quoted strings.
3.60 - ///
3.61 - /// Reader class for quoted strings. It can process the escape
3.62 - /// sequences in the string.
3.63 - /// \author Balazs Dezso
3.64 - class QuotedStringReader {
3.65 - public:
3.66 - typedef std::string Value;
3.67 -
3.68 - /// \brief Constructor for the reader.
3.69 - ///
3.70 - /// Constructor for the reader. If the given parameter is true
3.71 - /// the reader processes the escape sequences.
3.72 - QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}
3.73 -
3.74 - /// \brief Reads a quoted string from the given stream.
3.75 - ///
3.76 - /// Reads a quoted string from the given stream.
3.77 - void read(std::istream& is, std::string& value) {
3.78 - char c;
3.79 - value.clear();
3.80 - is >> std::ws;
3.81 - if (!is.get(c) || c != '\"')
3.82 - throw DataFormatError("Quoted string format error");
3.83 - while (is.get(c) && c != '\"') {
3.84 - if (escaped && c == '\\') {
3.85 - value += readEscape(is);
3.86 - } else {
3.87 - value += c;
3.88 - }
3.89 - }
3.90 - if (!is) throw DataFormatError("Quoted string format error");
3.91 - }
3.92 -
3.93 - private:
3.94 -
3.95 - static char readEscape(std::istream& is) {
3.96 - char c;
3.97 - switch (is.get(c), c) {
3.98 - case '\\':
3.99 - return '\\';
3.100 - case '\"':
3.101 - return '\"';
3.102 - case '\'':
3.103 - return '\'';
3.104 - case '\?':
3.105 - return '\?';
3.106 - case 'a':
3.107 - return '\a';
3.108 - case 'b':
3.109 - return '\b';
3.110 - case 'f':
3.111 - return '\f';
3.112 - case 'n':
3.113 - return '\n';
3.114 - case 'r':
3.115 - return '\r';
3.116 - case 't':
3.117 - return '\t';
3.118 - case 'v':
3.119 - return '\v';
3.120 - case 'x':
3.121 - {
3.122 - int code;
3.123 - if (!is.get(c) || !isHex(c))
3.124 - throw DataFormatError("Escape format error");
3.125 - else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
3.126 - else code = code * 16 + valueHex(c);
3.127 - return code;
3.128 - }
3.129 - default:
3.130 - {
3.131 - int code;
3.132 - if (!isOct(c))
3.133 - throw DataFormatError("Escape format error");
3.134 - else if (code = valueOct(c), !is.get(c) || !isOct(c))
3.135 - is.putback(c);
3.136 - else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
3.137 - is.putback(c);
3.138 - else code = code * 8 + valueOct(c);
3.139 - return code;
3.140 - }
3.141 - }
3.142 - }
3.143 -
3.144 - static bool isOct(char c) {
3.145 - return '0' <= c && c <='7';
3.146 - }
3.147 -
3.148 - static int valueOct(char c) {
3.149 - return c - '0';
3.150 - }
3.151 -
3.152 - static bool isHex(char c) {
3.153 - return ('0' <= c && c <= '9') ||
3.154 - ('a' <= c && c <= 'z') ||
3.155 - ('A' <= c && c <= 'Z');
3.156 - }
3.157 -
3.158 - static int valueHex(char c) {
3.159 - if ('0' <= c && c <= '9') return c - '0';
3.160 - if ('a' <= c && c <= 'z') return c - 'a' + 10;
3.161 - return c - 'A' + 10;
3.162 - }
3.163 -
3.164 - bool escaped;
3.165 - };
3.166 -
3.167 - class GUIReader {
3.168 - public:
3.169 - virtual void read(std::istream& is) = 0;
3.170 - };
3.171 -
3.172 /// \brief The graph reader class.
3.173 ///
3.174 - ///
3.175 /// The given file format may contain several maps and labeled nodes or
3.176 /// edges.
3.177 ///
3.178 @@ -229,8 +73,8 @@
3.179 /// reader.readEdgeMap("label", labelMap);
3.180 /// \endcode
3.181 ///
3.182 - /// With \c readNode() and \c readEdge() functions you can read labeled Nodes
3.183 - /// and Edges.
3.184 + /// With \c readNode() and \c readEdge() functions you can read
3.185 + /// labeled Nodes and Edges.
3.186 ///
3.187 /// \code
3.188 /// reader.readNode("source", sourceNode);
3.189 @@ -239,6 +83,10 @@
3.190 /// reader.readEdge("observed", edge);
3.191 /// \endcode
3.192 ///
3.193 + /// With the \c readAttribute() functions you can read an attribute
3.194 + /// in a variable. You can specify the reader for the attribute as
3.195 + /// the nodemaps.
3.196 + ///
3.197 /// After you give all read commands you must call the \c run() member
3.198 /// function, which execute all the commands.
3.199 ///
3.200 @@ -260,31 +108,56 @@
3.201 typedef typename Graph::Edge Edge;
3.202
3.203 typedef _ReaderTraits ReaderTraits;
3.204 - typedef typename ReaderTraits::DefaultReader DefaultReader;
3.205 + typedef typename ReaderTraits::Skipper DefaultSkipper;
3.206
3.207 /// \brief Construct a new GraphReader.
3.208 ///
3.209 /// Construct a new GraphReader. It reads into the given graph
3.210 /// and it use the given reader as the default skipper.
3.211 GraphReader(std::istream& _is, Graph& _graph,
3.212 - const DefaultReader& _reader = DefaultReader())
3.213 - : gui_reader(0), is(_is), graph(_graph),
3.214 - nodeSkipper(_reader), edgeSkipper(_reader) {}
3.215 + const DefaultSkipper& _skipper = DefaultSkipper())
3.216 + : reader(new LemonReader(_is)), own_reader(true),
3.217 + graph(_graph), skipper(_skipper),
3.218 + nodeset_reader(*reader, graph, std::string(), skipper),
3.219 + edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
3.220 + node_reader(*reader, nodeset_reader, std::string()),
3.221 + edge_reader(*reader, edgeset_reader, std::string()),
3.222 + attribute_reader(*reader, std::string()) {}
3.223 +
3.224 + /// \brief Construct a new GraphReader.
3.225 + ///
3.226 + /// Construct a new GraphReader. It reads into the given graph
3.227 + /// and it use the given reader as the default skipper.
3.228 + GraphReader(const std::string& _filename, Graph& _graph,
3.229 + const DefaultSkipper& _skipper = DefaultSkipper())
3.230 + : reader(new LemonReader(_filename)), own_reader(true),
3.231 + graph(_graph), skipper(_skipper),
3.232 + nodeset_reader(*reader, graph, std::string(), skipper),
3.233 + edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
3.234 + node_reader(*reader, nodeset_reader, std::string()),
3.235 + edge_reader(*reader, edgeset_reader, std::string()),
3.236 + attribute_reader(*reader, std::string()) {}
3.237 +
3.238 + /// \brief Construct a new GraphReader.
3.239 + ///
3.240 + /// Construct a new GraphReader. It reads into the given graph
3.241 + /// and it use the given reader as the default skipper.
3.242 + GraphReader(LemonReader& _reader, Graph& _graph,
3.243 + const DefaultSkipper& _skipper = DefaultSkipper())
3.244 + : reader(_reader), own_reader(false),
3.245 + graph(_graph), skipper(_skipper),
3.246 + nodeset_reader(*reader, graph, std::string(), skipper),
3.247 + edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
3.248 + node_reader(*reader, nodeset_reader, std::string()),
3.249 + edge_reader(*reader, edgeset_reader, std::string()),
3.250 + attribute_reader(*reader, std::string()) {}
3.251
3.252 /// \brief Destruct the graph reader.
3.253 ///
3.254 /// Destruct the graph reader.
3.255 ~GraphReader() {
3.256 - for (typename NodeMapReaders::iterator it = node_map_readers.begin();
3.257 - it != node_map_readers.end(); ++it) {
3.258 - delete it->second;
3.259 - }
3.260 -
3.261 - for (typename EdgeMapReaders::iterator it = edge_map_readers.begin();
3.262 - it != edge_map_readers.end(); ++it) {
3.263 - delete it->second;
3.264 - }
3.265 -
3.266 + if (own_reader)
3.267 + delete reader;
3.268 }
3.269
3.270 /// \brief Add a new node map reader command for the reader.
3.271 @@ -292,8 +165,8 @@
3.272 /// Add a new node map reader command for the reader.
3.273 template <typename Map>
3.274 GraphReader& readNodeMap(std::string name, Map& map) {
3.275 - return readNodeMap<typename ReaderTraits::template
3.276 - Reader<typename Map::Value>, Map>(name, map);
3.277 + nodeset_reader.readMap(name, map);
3.278 + return *this;
3.279 }
3.280
3.281 /// \brief Add a new node map reader command for the reader.
3.282 @@ -302,13 +175,7 @@
3.283 template <typename Reader, typename Map>
3.284 GraphReader& readNodeMap(std::string name, Map& map,
3.285 const Reader& reader = Reader()) {
3.286 - if (node_map_readers.find(name) != node_map_readers.end()) {
3.287 - ErrorMessage msg;
3.288 - msg << "Multiple read rule for node map: " << name;
3.289 - throw IOParameterError(msg.message());
3.290 - }
3.291 - node_map_readers.insert(
3.292 - make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
3.293 + nodeset_reader.readMap(name, map, reader);
3.294 return *this;
3.295 }
3.296
3.297 @@ -318,13 +185,7 @@
3.298 template <typename Reader>
3.299 GraphReader& skipNodeMap(std::string name,
3.300 const Reader& reader = Reader()) {
3.301 - if (node_map_readers.find(name) != node_map_readers.end()) {
3.302 - ErrorMessage msg;
3.303 - msg << "Multiple read rule for node map: " << name;
3.304 - throw IOParameterError(msg.message());
3.305 - }
3.306 - node_map_readers.insert(
3.307 - make_pair(name, new SkipReader<Node, Reader>(reader)));
3.308 + nodeset_reader.skipMap(name, reader);
3.309 return *this;
3.310 }
3.311
3.312 @@ -333,8 +194,8 @@
3.313 /// Add a new edge map reader command for the reader.
3.314 template <typename Map>
3.315 GraphReader& readEdgeMap(std::string name, Map& map) {
3.316 - return readEdgeMap<typename ReaderTraits::template
3.317 - Reader<typename Map::Value>, Map>(name, map);
3.318 + edgeset_reader.readMap(name, map);
3.319 + return *this;
3.320 }
3.321
3.322
3.323 @@ -344,13 +205,7 @@
3.324 template <typename Reader, typename Map>
3.325 GraphReader& readEdgeMap(std::string name, Map& map,
3.326 const Reader& reader = Reader()) {
3.327 - if (edge_map_readers.find(name) != edge_map_readers.end()) {
3.328 - ErrorMessage msg;
3.329 - msg << "Multiple read rule for edge map: " << name;
3.330 - throw IOParameterError(msg.message());
3.331 - }
3.332 - edge_map_readers.insert(
3.333 - make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
3.334 + edgeset_reader.readMap(name, map, reader);
3.335 return *this;
3.336 }
3.337
3.338 @@ -360,13 +215,8 @@
3.339 template <typename Reader>
3.340 GraphReader& skipEdgeMap(std::string name,
3.341 const Reader& reader = Reader()) {
3.342 - if (edge_map_readers.find(name) != edge_map_readers.end()) {
3.343 - ErrorMessage msg;
3.344 - msg << "Multiple read rule for edge map: " << name;
3.345 - throw IOParameterError(msg.message());
3.346 - }
3.347 - edge_map_readers.insert(
3.348 - make_pair(name, new SkipReader<Edge, Reader>(reader)));
3.349 +
3.350 + edgeset_reader.skipMap(name, reader);
3.351 return *this;
3.352 }
3.353
3.354 @@ -374,12 +224,7 @@
3.355 ///
3.356 /// Add a new labeled node reader for the reader.
3.357 GraphReader& readNode(std::string name, Node& node) {
3.358 - if (node_readers.find(name) != node_readers.end()) {
3.359 - ErrorMessage msg;
3.360 - msg << "Multiple read rule for node: " << name;
3.361 - throw IOParameterError(msg.message());
3.362 - }
3.363 - node_readers.insert(make_pair(name, &node));
3.364 + node_reader.readNode(name, node);
3.365 return *this;
3.366 }
3.367
3.368 @@ -387,385 +232,61 @@
3.369 ///
3.370 /// Add a new labeled edge reader for the reader.
3.371 GraphReader& readEdge(std::string name, Edge& edge) {
3.372 - if (edge_readers.find(name) != edge_readers.end()) {
3.373 - ErrorMessage msg;
3.374 - msg << "Multiple read rule for edge: " << name;
3.375 - throw IOParameterError(msg.message());
3.376 - }
3.377 - edge_readers.insert(make_pair(name, &edge));
3.378 + edge_reader.readEdge(name, edge);
3.379 + }
3.380 +
3.381 + /// \brief Add a new attribute reader command.
3.382 + ///
3.383 + /// Add a new attribute reader command.
3.384 + template <typename Value>
3.385 + GraphReader& readAttribute(std::string name, Value& value) {
3.386 + attribute_reader.readAttribute(name, value);
3.387 return *this;
3.388 }
3.389 +
3.390 + /// \brief Add a new attribute reader command.
3.391 + ///
3.392 + /// Add a new attribute reader command.
3.393 + template <typename Reader, typename Value>
3.394 + GraphReader& readAttribute(std::string name, Value& value,
3.395 + const Reader& reader) {
3.396 + attribute_reader.readAttribute<Reader>(name, value, reader);
3.397 + return *this;
3.398 + }
3.399 +
3.400 + /// \brief Conversion operator to LemonReader.
3.401 + ///
3.402 + /// Conversion operator to LemonReader. It make possible
3.403 + /// to access the encapsulated \e LemonReader, this way
3.404 + /// you can attach to this reader new instances of
3.405 + /// \e LemonReader::SectionReader.
3.406 + operator LemonReader&() {
3.407 + return *reader;
3.408 + }
3.409
3.410 /// \brief Executes the reader commands.
3.411 ///
3.412 /// Executes the reader commands.
3.413 void run() {
3.414 - int line_num = 0;
3.415 - std::auto_ptr<InverterBase<Node> > nodeInverter;
3.416 - std::auto_ptr<InverterBase<Edge> > edgeInverter;
3.417 - try {
3.418 - std::string line = readNotEmptyLine(is, line_num);
3.419 - if (line.find("@nodeset") == 0) {
3.420 - line = readNodeSet(line_num, nodeInverter);
3.421 - }
3.422 - if (line.find("@edgeset") == 0) {
3.423 - line = readEdgeSet(line_num, edgeInverter, nodeInverter);
3.424 - }
3.425 - if (line.find("@nodes") == 0) {
3.426 - line = readNodes(line_num, nodeInverter);
3.427 - }
3.428 - if (line.find("@edges") == 0) {
3.429 - line = readEdges(line_num, edgeInverter);
3.430 - }
3.431 - if (line.find("@gui") == 0) {
3.432 - line = readGUI(line_num);
3.433 - }
3.434 - if (line.find("@end") != 0) {
3.435 - throw DataFormatError("Invalid control sequence error");
3.436 - }
3.437 - } catch (DataFormatError e) {
3.438 - e.line(line_num);
3.439 - throw e;
3.440 - }
3.441 - }
3.442 -
3.443 - GraphReader& readGUI(GUIReader& reader) {
3.444 - gui_reader = &reader;
3.445 - return *this;
3.446 + reader->run();
3.447 }
3.448
3.449 private:
3.450
3.451 - template <typename Item> class InverterBase;
3.452 + LemonReader* reader;
3.453 + bool own_reader;
3.454
3.455 - std::string readNodeSet(int& line_num,
3.456 - std::auto_ptr<InverterBase<Node> >& nodeInverter) {
3.457 - std::vector<ReaderBase<Node>* > index;
3.458 - {
3.459 - std::string line = readNotEmptyLine(is, line_num);
3.460 - std::string id;
3.461 - std::istringstream ls(line);
3.462 - while (ls >> id) {
3.463 - typename NodeMapReaders::iterator it = node_map_readers.find(id);
3.464 - if (it != node_map_readers.end()) {
3.465 - index.push_back(it->second);
3.466 - node_map_readers.erase(it);
3.467 - } else {
3.468 - index.push_back(&nodeSkipper);
3.469 - }
3.470 - if (ReaderTraits::idMapName(id) && nodeInverter.get() == 0) {
3.471 - nodeInverter.reset(index.back()->getInverter());
3.472 - index.back() = nodeInverter.get();
3.473 - }
3.474 - }
3.475 - }
3.476 -
3.477 -// if (index.size() == 0) {
3.478 -// throw DataFormatError("Cannot find node id map");
3.479 -// }
3.480 -
3.481 -// nodeInverter =
3.482 -// std::auto_ptr<InverterBase<Node> >(index[0]->getInverter());
3.483 - std::string line;
3.484 - while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
3.485 - Node node = graph.addNode();
3.486 - std::istringstream ls(line);
3.487 - for (int i = 0; i < (int)index.size(); ++i) {
3.488 - index[i]->read(ls, node);
3.489 - }
3.490 - }
3.491 - return line;
3.492 - }
3.493 -
3.494 - std::string readEdgeSet(int& line_num,
3.495 - std::auto_ptr<InverterBase<Edge> >& edgeInverter,
3.496 - std::auto_ptr<InverterBase<Node> >& nodeInverter) {
3.497 - std::vector<ReaderBase<Edge>*> index;
3.498 - {
3.499 - std::string line = readNotEmptyLine(is, line_num);
3.500 - std::string id;
3.501 - std::istringstream ls(line);
3.502 - while (ls >> id) {
3.503 - typename EdgeMapReaders::iterator it = edge_map_readers.find(id);
3.504 - if (it != edge_map_readers.end()) {
3.505 - index.push_back(it->second);
3.506 - edge_map_readers.erase(it);
3.507 - } else {
3.508 - index.push_back(&edgeSkipper);
3.509 - }
3.510 - if (ReaderTraits::idMapName(id) && edgeInverter.get() == 0) {
3.511 - edgeInverter.reset(index.back()->getInverter());
3.512 - index.back() = edgeInverter.get();
3.513 - }
3.514 - }
3.515 - }
3.516 -
3.517 - if (nodeInverter.get() == 0) {
3.518 - throw DataFormatError("Cannot find node id map");
3.519 - }
3.520 -// if (index.size() == 0) {
3.521 -// throw DataFormatError("Cannot find edge id map");
3.522 -// }
3.523 -
3.524 -// edgeInverter =
3.525 -// std::auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
3.526 - std::string line;
3.527 - while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
3.528 - std::istringstream ls(line);
3.529 - Node source = nodeInverter->read(ls);
3.530 - Node target = nodeInverter->read(ls);
3.531 - Edge edge = graph.addEdge(source, target);
3.532 - for (int i = 0; i < (int)index.size(); ++i) {
3.533 - index[i]->read(ls, edge);
3.534 - }
3.535 - }
3.536 - return line;
3.537 - }
3.538 -
3.539 - std::string readNodes(int& line_num,
3.540 - std::auto_ptr<InverterBase<Node> >& nodeInverter) {
3.541 - std::string line;
3.542 - if (nodeInverter.get() == 0) {
3.543 - throw DataFormatError("Cannot find node id map");
3.544 - }
3.545 - while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
3.546 - std::istringstream ls(line);
3.547 - std::string name;
3.548 - ls >> name;
3.549 - typename NodeReaders::iterator it = node_readers.find(name);
3.550 - if (it != node_readers.end()) {
3.551 - *(it -> second) = nodeInverter->read(ls);
3.552 - }
3.553 - }
3.554 - return line;
3.555 - }
3.556 -
3.557 - std::string readEdges(int& line_num,
3.558 - std::auto_ptr<InverterBase<Edge> >& edgeInverter) {
3.559 - std::string line;
3.560 - if (edgeInverter.get() == 0) {
3.561 - throw DataFormatError("Cannot find edge id map");
3.562 - }
3.563 - while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
3.564 - std::istringstream ls(line);
3.565 - std::string name;
3.566 - ls >> name;
3.567 - typename EdgeReaders::iterator it = edge_readers.find(name);
3.568 - if (it != edge_readers.end()) {
3.569 - *(it -> second) = edgeInverter->read(ls);
3.570 - }
3.571 - }
3.572 - return line;
3.573 - }
3.574 -
3.575 - std::string readGUI(int& line_num) {
3.576 - std::stringstream section;
3.577 - std::string line;
3.578 - while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
3.579 - section << line << std::endl;
3.580 - }
3.581 - if (gui_reader != 0) {
3.582 - gui_reader->read(section);
3.583 - }
3.584 - return line;
3.585 - }
3.586 -
3.587 - std::string readNotEmptyLine(std::istream& is, int& line_num) {
3.588 - std::string line;
3.589 - while (++line_num, getline(is, line)) {
3.590 - int vi = line.find('#');
3.591 - if (vi != (int)::std::string::npos) {
3.592 - line = line.substr(0, vi);
3.593 - }
3.594 - vi = line.find_first_not_of(" \t");
3.595 - if (vi != (int)std::string::npos) {
3.596 - return line.substr(vi);
3.597 - }
3.598 - }
3.599 - throw DataFormatError("End of stream error");
3.600 - }
3.601 -
3.602 - template <typename _Item>
3.603 - class ReaderBase;
3.604 -
3.605 - template <typename _Item>
3.606 - class InverterBase : public ReaderBase<_Item> {
3.607 - public:
3.608 - typedef _Item Item;
3.609 - virtual void read(std::istream&, const Item&) = 0;
3.610 - virtual Item read(std::istream&) = 0;
3.611 -
3.612 - virtual InverterBase<_Item>* getInverter() {
3.613 - return this;
3.614 - }
3.615 - };
3.616 -
3.617 - template <typename _Item, typename _Map, typename _Reader>
3.618 - class MapReaderInverter : public InverterBase<_Item> {
3.619 - public:
3.620 - typedef _Item Item;
3.621 - typedef _Reader Reader;
3.622 - typedef typename Reader::Value Value;
3.623 - typedef _Map Map;
3.624 - typedef std::map<Value, Item> Inverse;
3.625 -
3.626 - Map& map;
3.627 - Reader reader;
3.628 - Inverse inverse;
3.629 -
3.630 - MapReaderInverter(Map& _map, const Reader& _reader)
3.631 - : map(_map), reader(_reader) {}
3.632 -
3.633 - virtual ~MapReaderInverter() {}
3.634 -
3.635 - virtual void read(std::istream& is, const Item& item) {
3.636 - Value value;
3.637 - reader.read(is, value);
3.638 - map.set(item, value);
3.639 - typename Inverse::iterator it = inverse.find(value);
3.640 - if (it == inverse.end()) {
3.641 - inverse.insert(std::make_pair(value, item));
3.642 - } else {
3.643 - throw DataFormatError("Multiple ID occurence");
3.644 - }
3.645 - }
3.646 -
3.647 - virtual Item read(std::istream& is) {
3.648 - Value value;
3.649 - reader.read(is, value);
3.650 - typename Inverse::const_iterator it = inverse.find(value);
3.651 - if (it != inverse.end()) {
3.652 - return it->second;
3.653 - } else {
3.654 - throw DataFormatError("Invalid ID error");
3.655 - }
3.656 - }
3.657 - };
3.658 -
3.659 - template <typename _Item, typename _Reader>
3.660 - class SkipReaderInverter : public InverterBase<_Item> {
3.661 - public:
3.662 - typedef _Item Item;
3.663 - typedef _Reader Reader;
3.664 - typedef typename Reader::Value Value;
3.665 - typedef std::map<Value, Item> Inverse;
3.666 -
3.667 - Reader reader;
3.668 -
3.669 - SkipReaderInverter(const Reader& _reader)
3.670 - : reader(_reader) {}
3.671 -
3.672 - virtual ~SkipReaderInverter() {}
3.673 -
3.674 - virtual void read(std::istream& is, const Item& item) {
3.675 - Value value;
3.676 - reader.read(is, value);
3.677 - typename Inverse::iterator it = inverse.find(value);
3.678 - if (it == inverse.end()) {
3.679 - inverse.insert(std::make_pair(value, item));
3.680 - } else {
3.681 - throw DataFormatError("Multiple ID occurence error");
3.682 - }
3.683 - }
3.684 -
3.685 - virtual Item read(std::istream& is) {
3.686 - Value value;
3.687 - reader.read(is, value);
3.688 - typename Inverse::const_iterator it = inverse.find(value);
3.689 - if (it != inverse.end()) {
3.690 - return it->second;
3.691 - } else {
3.692 - throw DataFormatError("Invalid ID error");
3.693 - }
3.694 - }
3.695 - private:
3.696 - Inverse inverse;
3.697 - };
3.698 -
3.699 - // Readers
3.700 -
3.701 - template <typename _Item>
3.702 - class ReaderBase {
3.703 - public:
3.704 - typedef _Item Item;
3.705 -
3.706 - // virtual ~ReaderBase() {}
3.707 -
3.708 - virtual void read(std::istream& is, const Item& item) = 0;
3.709 - virtual InverterBase<_Item>* getInverter() = 0;
3.710 - };
3.711 -
3.712 - template <typename _Item, typename _Map, typename _Reader>
3.713 - class MapReader : public ReaderBase<_Item> {
3.714 - public:
3.715 - typedef _Map Map;
3.716 - typedef _Reader Reader;
3.717 - typedef typename Reader::Value Value;
3.718 - typedef _Item Item;
3.719 -
3.720 - Map& map;
3.721 - Reader reader;
3.722 -
3.723 - MapReader(Map& _map, const Reader& _reader)
3.724 - : map(_map), reader(_reader) {}
3.725 -
3.726 - virtual ~MapReader() {}
3.727 -
3.728 - virtual void read(std::istream& is, const Item& item) {
3.729 - Value value;
3.730 - reader.read(is, value);
3.731 - map.set(item, value);
3.732 - }
3.733 -
3.734 - virtual InverterBase<_Item>* getInverter() {
3.735 - return new MapReaderInverter<Item, Map, Reader>(map, reader);
3.736 - }
3.737 - };
3.738 -
3.739 -
3.740 - template <typename _Item, typename _Reader>
3.741 - class SkipReader : public ReaderBase<_Item> {
3.742 - public:
3.743 - typedef _Reader Reader;
3.744 - typedef typename Reader::Value Value;
3.745 - typedef _Item Item;
3.746 -
3.747 - Reader reader;
3.748 - SkipReader(const Reader& _reader) : reader(_reader) {}
3.749 -
3.750 - virtual ~SkipReader() {}
3.751 -
3.752 - virtual void read(std::istream& is, const Item&) {
3.753 - Value value;
3.754 - reader.read(is, value);
3.755 - }
3.756 -
3.757 - virtual InverterBase<Item>* getInverter() {
3.758 - return new SkipReaderInverter<Item, Reader>(reader);
3.759 - }
3.760 - };
3.761 -
3.762 -
3.763 - typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders;
3.764 - NodeMapReaders node_map_readers;
3.765 -
3.766 - typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders;
3.767 - EdgeMapReaders edge_map_readers;
3.768 -
3.769 - typedef std::map<std::string, Node*> NodeReaders;
3.770 - NodeReaders node_readers;
3.771 -
3.772 - typedef std::map<std::string, Edge*> EdgeReaders;
3.773 - EdgeReaders edge_readers;
3.774 -
3.775 - GUIReader* gui_reader;
3.776 -
3.777 - std::istream& is;
3.778 Graph& graph;
3.779
3.780 - SkipReader<Node, DefaultReader> nodeSkipper;
3.781 - SkipReader<Edge, DefaultReader> edgeSkipper;
3.782 + DefaultSkipper skipper;
3.783
3.784 + NodeSetReader<Graph, ReaderTraits> nodeset_reader;
3.785 + EdgeSetReader<Graph, ReaderTraits> edgeset_reader;
3.786 +
3.787 + NodeReader<Graph> node_reader;
3.788 + EdgeReader<Graph> edge_reader;
3.789 +
3.790 + AttributeReader<ReaderTraits> attribute_reader;
3.791 };
3.792
3.793 /// \brief Read a graph from the input.
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/src/lemon/lemon_reader.h Mon May 09 11:24:26 2005 +0000
4.3 @@ -0,0 +1,977 @@
4.4 +/* -*- C++ -*-
4.5 + * src/lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library
4.6 + *
4.7 + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
4.8 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
4.9 + *
4.10 + * Permission to use, modify and distribute this software is granted
4.11 + * provided that this copyright notice appears in all copies. For
4.12 + * precise terms see the accompanying LICENSE file.
4.13 + *
4.14 + * This software is provided "AS IS" with no warranty of any kind,
4.15 + * express or implied, and with no claim as to its suitability for any
4.16 + * purpose.
4.17 + *
4.18 + */
4.19 +
4.20 +///\ingroup io_group
4.21 +///\file
4.22 +///\brief Lemon Format reader.
4.23 +
4.24 +#ifndef LEMON_LEMON_READER_H
4.25 +#define LEMON_LEMON_READER_H
4.26 +
4.27 +#include <iostream>
4.28 +#include <fstream>
4.29 +#include <string>
4.30 +#include <vector>
4.31 +#include <algorithm>
4.32 +#include <map>
4.33 +#include <memory>
4.34 +
4.35 +#include <lemon/error.h>
4.36 +#include "item_reader.h"
4.37 +
4.38 +
4.39 +namespace lemon {
4.40 +
4.41 + /// \addtogroup io_group
4.42 + /// @{
4.43 +
4.44 + /// \brief Lemon Format reader class.
4.45 + ///
4.46 + class LemonReader {
4.47 + private:
4.48 +
4.49 + class FilterStreamBuf : public std::streambuf {
4.50 + public:
4.51 +
4.52 + typedef std::streambuf Parent;
4.53 + typedef Parent::char_type char_type;
4.54 + FilterStreamBuf(std::istream& is, int& num)
4.55 + : _is(is), _base(0), _eptr(0),
4.56 + _num(num), skip_state(after_endl) {}
4.57 +
4.58 + protected:
4.59 +
4.60 + enum skip_state_type {
4.61 + no_skip,
4.62 + after_comment,
4.63 + after_endl,
4.64 + empty_line
4.65 + };
4.66 +
4.67 + char_type small_buf[1];
4.68 +
4.69 +
4.70 + std::istream& _is;
4.71 +
4.72 + char_type* _base;
4.73 + char_type* _eptr;
4.74 +
4.75 + int& _num;
4.76 +
4.77 + skip_state_type skip_state;
4.78 +
4.79 +
4.80 + char_type* base() { return _base; }
4.81 +
4.82 + char_type* eptr() { return _eptr; }
4.83 +
4.84 + int blen() { return _eptr - _base; }
4.85 +
4.86 + void setb(char_type* buf, int len) {
4.87 + _base = buf;
4.88 + _eptr = buf + len;
4.89 + }
4.90 +
4.91 + virtual std::streambuf* setbuf(char *buf, int len) {
4.92 + if (base()) return 0;
4.93 + if (buf != 0 && len >= (int)sizeof(small_buf)) {
4.94 + setb(buf, len);
4.95 + } else {
4.96 + setb(small_buf, sizeof(small_buf));
4.97 + }
4.98 + setg(0, 0, 0);
4.99 + return this;
4.100 + }
4.101 +
4.102 + bool put_char(char c) {
4.103 + switch (skip_state) {
4.104 + case no_skip:
4.105 + switch (c) {
4.106 + case '\n':
4.107 + skip_state = after_endl;
4.108 + return true;
4.109 + case '#':
4.110 + skip_state = after_comment;
4.111 + return false;
4.112 + default:
4.113 + return true;
4.114 + }
4.115 + case after_comment:
4.116 + switch (c) {
4.117 + case '\n':
4.118 + skip_state = after_endl;
4.119 + return true;
4.120 + default:
4.121 + return false;
4.122 + }
4.123 + case after_endl:
4.124 + switch (c) {
4.125 + case '@':
4.126 + return false;
4.127 + case '\n':
4.128 + return false;
4.129 + case '#':
4.130 + skip_state = empty_line;
4.131 + return false;
4.132 + default:
4.133 + if (!isspace(c)) {
4.134 + skip_state = no_skip;
4.135 + return true;
4.136 + } else {
4.137 + return false;
4.138 + }
4.139 + }
4.140 + break;
4.141 + case empty_line:
4.142 + switch (c) {
4.143 + case '\n':
4.144 + skip_state = after_endl;
4.145 + return false;
4.146 + default:
4.147 + return false;
4.148 + }
4.149 + }
4.150 + return false;
4.151 + }
4.152 +
4.153 + virtual int underflow() {
4.154 + char c;
4.155 + if (_is.read(&c, 1)) {
4.156 + _is.putback(c);
4.157 + if (c == '@') {
4.158 + return EOF;
4.159 + }
4.160 + } else {
4.161 + return EOF;
4.162 + }
4.163 + char_type *ptr;
4.164 + for (ptr = base(); ptr != eptr(); ++ptr) {
4.165 + if (_is.read(&c, 1)) {
4.166 + if (c == '\n') ++_num;
4.167 + if (put_char(c)) {
4.168 + *ptr = c;
4.169 + } else {
4.170 + if (skip_state == after_endl && c == '@') {
4.171 + _is.putback('@');
4.172 + break;
4.173 + }
4.174 + --ptr;
4.175 + }
4.176 + } else {
4.177 + break;
4.178 + }
4.179 + }
4.180 + setg(base(), base(), ptr);
4.181 + return *base();
4.182 + }
4.183 +
4.184 + virtual int sync() {
4.185 + return EOF;
4.186 + }
4.187 + };
4.188 +
4.189 + public:
4.190 +
4.191 + class SectionReader {
4.192 + public:
4.193 + /// \e
4.194 + virtual bool header(const std::string& line) = 0;
4.195 + /// \e
4.196 + virtual void read(std::istream& is) = 0;
4.197 + };
4.198 +
4.199 + /// \e
4.200 + LemonReader(std::istream& _is)
4.201 + : is(&_is), own_is(false) {}
4.202 +
4.203 + LemonReader(const std::string& filename)
4.204 + : is(0), own_is(true) {
4.205 + is = new std::ifstream(filename.c_str());
4.206 + }
4.207 +
4.208 +
4.209 + ~LemonReader() {
4.210 + if (own_is) {
4.211 + delete is;
4.212 + }
4.213 + }
4.214 +
4.215 + private:
4.216 + LemonReader(const LemonReader&);
4.217 + void operator=(const LemonReader&);
4.218 +
4.219 + public:
4.220 +
4.221 + /// \e
4.222 + void attach(SectionReader& reader) {
4.223 + readers.push_back(&reader);
4.224 + }
4.225 +
4.226 + /// \e
4.227 + void detach(SectionReader& reader) {
4.228 + std::vector<SectionReader*>::iterator it =
4.229 + std::find(readers.begin(), readers.end(), &reader);
4.230 + if (it != readers.end()) {
4.231 + readers.erase(it);
4.232 + }
4.233 + }
4.234 +
4.235 + /// \e
4.236 + void run() {
4.237 + int line_num = 0;
4.238 + std::string line;
4.239 + try {
4.240 + while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
4.241 + SectionReaders::iterator it;
4.242 + for (it = readers.begin(); it != readers.end(); ++it) {
4.243 + if ((*it)->header(line)) {
4.244 + char buf[2048];
4.245 + FilterStreamBuf buffer(*is, line_num);
4.246 + buffer.pubsetbuf(buf, sizeof(buf));
4.247 + std::istream is(&buffer);
4.248 + (*it)->read(is);
4.249 + break;
4.250 + }
4.251 + }
4.252 + }
4.253 + } catch (DataFormatError& error) {
4.254 + error.line(line_num);
4.255 + throw error;
4.256 + }
4.257 + }
4.258 +
4.259 +
4.260 + private:
4.261 +
4.262 + std::istream* is;
4.263 + bool own_is;
4.264 +
4.265 + typedef std::vector<SectionReader*> SectionReaders;
4.266 + SectionReaders readers;
4.267 +
4.268 + };
4.269 +
4.270 +
4.271 + /// \e
4.272 + class CommonSectionReaderBase : public LemonReader::SectionReader {
4.273 + protected:
4.274 + template <typename _Item>
4.275 + class ReaderBase;
4.276 +
4.277 + template <typename _Item>
4.278 + class InverterBase : public ReaderBase<_Item> {
4.279 + public:
4.280 + typedef _Item Item;
4.281 + virtual void read(std::istream&, const Item&) = 0;
4.282 + virtual Item read(std::istream&) const = 0;
4.283 +
4.284 + virtual InverterBase<_Item>* getInverter() {
4.285 + return this;
4.286 + }
4.287 +
4.288 +
4.289 + };
4.290 +
4.291 + template <typename _Item, typename _Map, typename _Reader>
4.292 + class MapReaderInverter : public InverterBase<_Item> {
4.293 + public:
4.294 + typedef _Item Item;
4.295 + typedef _Reader Reader;
4.296 + typedef typename Reader::Value Value;
4.297 + typedef _Map Map;
4.298 + typedef std::map<Value, Item> Inverse;
4.299 +
4.300 + Map& map;
4.301 + Reader reader;
4.302 + Inverse inverse;
4.303 +
4.304 + MapReaderInverter(Map& _map, const Reader& _reader)
4.305 + : map(_map), reader(_reader) {}
4.306 +
4.307 + virtual ~MapReaderInverter() {}
4.308 +
4.309 + virtual void read(std::istream& is, const Item& item) {
4.310 + Value value;
4.311 + reader.read(is, value);
4.312 + map.set(item, value);
4.313 + typename Inverse::iterator it = inverse.find(value);
4.314 + if (it == inverse.end()) {
4.315 + inverse.insert(std::make_pair(value, item));
4.316 + } else {
4.317 + throw DataFormatError("Multiple ID occurence");
4.318 + }
4.319 + }
4.320 +
4.321 + virtual Item read(std::istream& is) const {
4.322 + Value value;
4.323 + reader.read(is, value);
4.324 + typename Inverse::const_iterator it = inverse.find(value);
4.325 + if (it != inverse.end()) {
4.326 + return it->second;
4.327 + } else {
4.328 + throw DataFormatError("Invalid ID error");
4.329 + }
4.330 + }
4.331 +
4.332 + };
4.333 +
4.334 + template <typename _Item, typename _Reader>
4.335 + class SkipReaderInverter : public InverterBase<_Item> {
4.336 + public:
4.337 + typedef _Item Item;
4.338 + typedef _Reader Reader;
4.339 + typedef typename Reader::Value Value;
4.340 + typedef std::map<Value, Item> Inverse;
4.341 +
4.342 + Reader reader;
4.343 +
4.344 + SkipReaderInverter(const Reader& _reader)
4.345 + : reader(_reader) {}
4.346 +
4.347 + virtual ~SkipReaderInverter() {}
4.348 +
4.349 + virtual void read(std::istream& is, const Item& item) {
4.350 + Value value;
4.351 + reader.read(is, value);
4.352 + typename Inverse::iterator it = inverse.find(value);
4.353 + if (it == inverse.end()) {
4.354 + inverse.insert(std::make_pair(value, item));
4.355 + } else {
4.356 + throw DataFormatError("Multiple ID occurence error");
4.357 + }
4.358 + }
4.359 +
4.360 + virtual Item read(std::istream& is) const {
4.361 + Value value;
4.362 + reader.read(is, value);
4.363 + typename Inverse::const_iterator it = inverse.find(value);
4.364 + if (it != inverse.end()) {
4.365 + return it->second;
4.366 + } else {
4.367 + throw DataFormatError("Invalid ID error");
4.368 + }
4.369 + }
4.370 +
4.371 + private:
4.372 + Inverse inverse;
4.373 + };
4.374 +
4.375 + // Readers
4.376 +
4.377 + template <typename _Item>
4.378 + class ReaderBase {
4.379 + public:
4.380 + typedef _Item Item;
4.381 +
4.382 + virtual ~ReaderBase() {}
4.383 +
4.384 + virtual void read(std::istream& is, const Item& item) = 0;
4.385 + virtual InverterBase<_Item>* getInverter() = 0;
4.386 + };
4.387 +
4.388 + template <typename _Item, typename _Map, typename _Reader>
4.389 + class MapReader : public ReaderBase<_Item> {
4.390 + public:
4.391 + typedef _Map Map;
4.392 + typedef _Reader Reader;
4.393 + typedef typename Reader::Value Value;
4.394 + typedef _Item Item;
4.395 +
4.396 + Map& map;
4.397 + Reader reader;
4.398 +
4.399 + MapReader(Map& _map, const Reader& _reader)
4.400 + : map(_map), reader(_reader) {}
4.401 +
4.402 + virtual ~MapReader() {}
4.403 +
4.404 + virtual void read(std::istream& is, const Item& item) {
4.405 + Value value;
4.406 + reader.read(is, value);
4.407 + map.set(item, value);
4.408 + }
4.409 +
4.410 + virtual InverterBase<_Item>* getInverter() {
4.411 + return new MapReaderInverter<Item, Map, Reader>(map, reader);
4.412 + }
4.413 + };
4.414 +
4.415 +
4.416 + template <typename _Item, typename _Reader>
4.417 + class SkipReader : public ReaderBase<_Item> {
4.418 + public:
4.419 + typedef _Reader Reader;
4.420 + typedef typename Reader::Value Value;
4.421 + typedef _Item Item;
4.422 +
4.423 + Reader reader;
4.424 + SkipReader(const Reader& _reader) : reader(_reader) {}
4.425 +
4.426 + virtual ~SkipReader() {}
4.427 +
4.428 + virtual void read(std::istream& is, const Item&) {
4.429 + Value value;
4.430 + reader.read(is, value);
4.431 + }
4.432 +
4.433 + virtual InverterBase<Item>* getInverter() {
4.434 + return new SkipReaderInverter<Item, Reader>(reader);
4.435 + }
4.436 + };
4.437 +
4.438 + template <typename _Item>
4.439 + class ResolverReaderBase {
4.440 + public:
4.441 + typedef _Item Item;
4.442 + virtual Item resolve(std::istream& is) const = 0;
4.443 + };
4.444 +
4.445 + template <typename _Item, typename _Resolver>
4.446 + class ResolverReader : public ResolverReaderBase<_Item> {
4.447 + public:
4.448 + typedef _Item Item;
4.449 + typedef _Resolver Resolver;
4.450 +
4.451 + const Resolver& resolver;
4.452 +
4.453 + ResolverReader(const Resolver& _resolver)
4.454 + : resolver(_resolver) {}
4.455 +
4.456 + virtual Item resolve(std::istream& is) const {
4.457 + return resolver.resolve(is);
4.458 + }
4.459 + };
4.460 +
4.461 + class ValueReaderBase {
4.462 + public:
4.463 + virtual void read(std::istream&) {};
4.464 + };
4.465 +
4.466 + template <typename _Value, typename _Reader>
4.467 + class ValueReader : public ValueReaderBase {
4.468 + public:
4.469 + typedef _Value Value;
4.470 + typedef _Reader Reader;
4.471 +
4.472 + ValueReader(Value& _value, const Reader& _reader)
4.473 + : value(_value), reader(_reader) {}
4.474 +
4.475 + virtual void read(std::istream& is) {
4.476 + reader.read(is, value);
4.477 + }
4.478 + private:
4.479 + Value& value;
4.480 + Reader reader;
4.481 + };
4.482 +
4.483 + };
4.484 +
4.485 +
4.486 + template <typename _Graph, typename _Traits = DefaultReaderTraits>
4.487 + class NodeSetReader : public CommonSectionReaderBase {
4.488 + typedef CommonSectionReaderBase Parent;
4.489 + public:
4.490 +
4.491 + typedef _Graph Graph;
4.492 + typedef _Traits Traits;
4.493 + typedef typename Graph::Node Item;
4.494 + typedef typename Traits::Skipper DefaultSkipper;
4.495 +
4.496 + NodeSetReader(LemonReader& _reader, Graph& _graph,
4.497 + const std::string& _id = std::string(),
4.498 + const DefaultSkipper& _defreader = DefaultSkipper())
4.499 + : graph(_graph), id(_id), skipper(_defreader) {
4.500 + _reader.attach(*this);
4.501 + }
4.502 +
4.503 + virtual ~NodeSetReader() {
4.504 + for (typename MapReaders::iterator it = readers.begin();
4.505 + it != readers.end(); ++it) {
4.506 + delete it->second;
4.507 + }
4.508 + }
4.509 +
4.510 + private:
4.511 + NodeSetReader(const NodeSetReader&);
4.512 + void operator=(const NodeSetReader&);
4.513 +
4.514 + public:
4.515 +
4.516 + /// \brief Add a new node map reader command for the reader.
4.517 + ///
4.518 + /// Add a new node map reader command for the reader.
4.519 + template <typename Map>
4.520 + NodeSetReader& readMap(std::string name, Map& map) {
4.521 + return readMap<typename Traits::
4.522 + template Reader<typename Map::Value>, Map>(name, map);
4.523 + }
4.524 +
4.525 + /// \brief Add a new node map reader command for the reader.
4.526 + ///
4.527 + /// Add a new node map reader command for the reader.
4.528 + template <typename Reader, typename Map>
4.529 + NodeSetReader& readMap(std::string name, Map& map,
4.530 + const Reader& reader = Reader()) {
4.531 + if (readers.find(name) != readers.end()) {
4.532 + ErrorMessage msg;
4.533 + msg << "Multiple read rule for node map: " << name;
4.534 + throw IOParameterError(msg.message());
4.535 + }
4.536 + readers.insert(
4.537 + make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
4.538 + return *this;
4.539 + }
4.540 +
4.541 + /// \brief Add a new node map skipper command for the reader.
4.542 + ///
4.543 + /// Add a new node map skipper command for the reader.
4.544 + template <typename Reader>
4.545 + NodeSetReader& skipMap(std::string name,
4.546 + const Reader& reader = Reader()) {
4.547 + if (readers.find(name) != readers.end()) {
4.548 + ErrorMessage msg;
4.549 + msg << "Multiple read rule for node map: " << name;
4.550 + throw IOParameterError(msg.message());
4.551 + }
4.552 + readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
4.553 + return *this;
4.554 + }
4.555 +
4.556 + /// \e
4.557 + virtual bool header(const std::string& line) {
4.558 + std::istringstream ls(line);
4.559 + std::string command;
4.560 + std::string name;
4.561 + ls >> command >> name;
4.562 + return command == "@nodeset" && name == id;
4.563 + }
4.564 +
4.565 + /// \e
4.566 + virtual void read(std::istream& is) {
4.567 + std::vector<ReaderBase<Item>* > index;
4.568 + std::string line;
4.569 +
4.570 + getline(is, line);
4.571 + std::istringstream ls(line);
4.572 + while (ls >> id) {
4.573 + typename MapReaders::iterator it = readers.find(id);
4.574 + if (it != readers.end()) {
4.575 + index.push_back(it->second);
4.576 + } else {
4.577 + index.push_back(&skipper);
4.578 + }
4.579 + if (id == "id" && inverter.get() == 0) {
4.580 + inverter.reset(index.back()->getInverter());
4.581 + index.back() = inverter.get();
4.582 + }
4.583 + }
4.584 + while (getline(is, line)) {
4.585 + typename Graph::Node node = graph.addNode();
4.586 + std::istringstream ls(line);
4.587 + for (int i = 0; i < (int)index.size(); ++i) {
4.588 + index[i]->read(ls, node);
4.589 + }
4.590 + }
4.591 + }
4.592 +
4.593 + bool isResolver() const {
4.594 + return inverter.get() != 0;
4.595 + }
4.596 +
4.597 + typename Graph::Node resolve(std::istream& is) const {
4.598 + return inverter->read(is);
4.599 + }
4.600 +
4.601 + private:
4.602 +
4.603 + typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
4.604 + MapReaders readers;
4.605 +
4.606 + Graph& graph;
4.607 + std::string id;
4.608 + SkipReader<Item, DefaultSkipper> skipper;
4.609 +
4.610 + std::auto_ptr<InverterBase<Item> > inverter;
4.611 + };
4.612 +
4.613 +
4.614 +
4.615 + /// \e
4.616 + template <typename _Graph, typename _Traits = DefaultReaderTraits>
4.617 + class EdgeSetReader : public CommonSectionReaderBase {
4.618 + typedef CommonSectionReaderBase Parent;
4.619 + public:
4.620 +
4.621 + typedef _Graph Graph;
4.622 + typedef _Traits Traits;
4.623 + typedef typename Graph::Edge Item;
4.624 + typedef typename Traits::Skipper DefaultSkipper;
4.625 +
4.626 + template <typename Resolver>
4.627 + EdgeSetReader(LemonReader& _reader, Graph& _graph,
4.628 + const Resolver& _nodeResolver,
4.629 + const std::string& _id = std::string(),
4.630 + const DefaultSkipper& _defreader = DefaultSkipper())
4.631 + : graph(_graph), id(_id), skipper(_defreader),
4.632 + nodeResolver(new ResolverReader<typename Graph::Node, Resolver>
4.633 + (_nodeResolver)) {
4.634 + _reader.attach(*this);
4.635 + }
4.636 +
4.637 + virtual ~EdgeSetReader() {
4.638 + for (typename MapReaders::iterator it = readers.begin();
4.639 + it != readers.end(); ++it) {
4.640 + delete it->second;
4.641 + }
4.642 + }
4.643 +
4.644 + private:
4.645 + EdgeSetReader(const EdgeSetReader&);
4.646 + void operator=(const EdgeSetReader&);
4.647 +
4.648 + public:
4.649 +
4.650 + /// \brief Add a new node map reader command for the reader.
4.651 + ///
4.652 + /// Add a new node map reader command for the reader.
4.653 + template <typename Map>
4.654 + EdgeSetReader& readMap(std::string name, Map& map) {
4.655 + return readMap<typename Traits::
4.656 + template Reader<typename Map::Value>, Map>(name, map);
4.657 + }
4.658 +
4.659 + /// \brief Add a new node map reader command for the reader.
4.660 + ///
4.661 + /// Add a new node map reader command for the reader.
4.662 + template <typename Reader, typename Map>
4.663 + EdgeSetReader& readMap(std::string name, Map& map,
4.664 + const Reader& reader = Reader()) {
4.665 + if (readers.find(name) != readers.end()) {
4.666 + ErrorMessage msg;
4.667 + msg << "Multiple read rule for edge map: " << name;
4.668 + throw IOParameterError(msg.message());
4.669 + }
4.670 + readers.insert(
4.671 + make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
4.672 + return *this;
4.673 + }
4.674 +
4.675 + /// \brief Add a new node map skipper command for the reader.
4.676 + ///
4.677 + /// Add a new node map skipper command for the reader.
4.678 + template <typename Reader>
4.679 + EdgeSetReader& skipMap(std::string name,
4.680 + const Reader& reader = Reader()) {
4.681 + if (readers.find(name) != readers.end()) {
4.682 + ErrorMessage msg;
4.683 + msg << "Multiple read rule for node map: " << name;
4.684 + throw IOParameterError(msg.message());
4.685 + }
4.686 + readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
4.687 + return *this;
4.688 + }
4.689 +
4.690 + /// \e
4.691 + virtual bool header(const std::string& line) {
4.692 + std::istringstream ls(line);
4.693 + std::string command;
4.694 + std::string name;
4.695 + ls >> command >> name;
4.696 + return command == "@edgeset" && name == id;
4.697 + }
4.698 +
4.699 + /// \e
4.700 + virtual void read(std::istream& is) {
4.701 + std::vector<ReaderBase<Item>* > index;
4.702 + std::string line;
4.703 +
4.704 + getline(is, line);
4.705 + std::istringstream ls(line);
4.706 + while (ls >> id) {
4.707 + typename MapReaders::iterator it = readers.find(id);
4.708 + if (it != readers.end()) {
4.709 + index.push_back(it->second);
4.710 + } else {
4.711 + index.push_back(&skipper);
4.712 + }
4.713 + if (id == "id" && inverter.get() == 0) {
4.714 + inverter.reset(index.back()->getInverter());
4.715 + index.back() = inverter.get();
4.716 + }
4.717 + }
4.718 + while (getline(is, line)) {
4.719 + std::istringstream ls(line);
4.720 + typename Graph::Node from = nodeResolver->resolve(ls);
4.721 + typename Graph::Node to = nodeResolver->resolve(ls);
4.722 + typename Graph::Edge edge = graph.addEdge(from, to);
4.723 + for (int i = 0; i < (int)index.size(); ++i) {
4.724 + index[i]->read(ls, edge);
4.725 + }
4.726 + }
4.727 + }
4.728 +
4.729 + bool isResolver() const {
4.730 + return inverter.get() != 0;
4.731 + }
4.732 +
4.733 + typename Graph::Edge resolve(std::istream& is) {
4.734 + return inverter->read(is);
4.735 + }
4.736 +
4.737 + private:
4.738 +
4.739 + typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
4.740 + MapReaders readers;
4.741 +
4.742 + Graph& graph;
4.743 + std::string id;
4.744 + SkipReader<Item, DefaultSkipper> skipper;
4.745 +
4.746 + std::auto_ptr<InverterBase<Item> > inverter;
4.747 + std::auto_ptr<ResolverReaderBase<typename Graph::Node> > nodeResolver;
4.748 + };
4.749 +
4.750 +
4.751 + /// \e
4.752 + template <typename _Traits = DefaultReaderTraits>
4.753 + class AttributeReader : public CommonSectionReaderBase {
4.754 + typedef CommonSectionReaderBase Parent;
4.755 + typedef _Traits Traits;
4.756 + public:
4.757 + /// \e
4.758 + AttributeReader(LemonReader& _reader,
4.759 + const std::string& _id = std::string()) : id(_id) {
4.760 + _reader.attach(*this);
4.761 + }
4.762 +
4.763 + /// \e
4.764 + virtual ~AttributeReader() {
4.765 + for (typename Readers::iterator it = readers.begin();
4.766 + it != readers.end(); ++it) {
4.767 + delete it->second;
4.768 + }
4.769 + }
4.770 +
4.771 + private:
4.772 + AttributeReader(const AttributeReader&);
4.773 + void operator=(AttributeReader&);
4.774 +
4.775 + public:
4.776 + /// \e
4.777 + template <typename Value>
4.778 + AttributeReader& readAttribute(const std::string& id, Value& value) {
4.779 + return readAttribute<typename Traits::template Reader<Value> >
4.780 + (id, value);
4.781 + }
4.782 +
4.783 + /// \e
4.784 + template <typename Reader, typename Value>
4.785 + AttributeReader& readAttribute(const std::string& name, Value& value,
4.786 + const Reader& reader = Reader()) {
4.787 + if (readers.find(name) != readers.end()) {
4.788 + ErrorMessage msg;
4.789 + msg << "Multiple read rule for attribute: " << name;
4.790 + throw IOParameterError(msg.message());
4.791 + }
4.792 + readers.insert(make_pair(name, new ValueReader<Value, Reader>
4.793 + (value, reader)));
4.794 + return *this;
4.795 + }
4.796 +
4.797 + /// \e
4.798 + bool header(const std::string& line) {
4.799 + std::istringstream ls(line);
4.800 + std::string command;
4.801 + std::string name;
4.802 + ls >> command >> name;
4.803 + return command == "@attributes" && name == id;
4.804 + }
4.805 +
4.806 + /// \e
4.807 + void read(std::istream& is) {
4.808 + std::string line;
4.809 + while (getline(is, line)) {
4.810 + std::istringstream ls(line);
4.811 + std::string id;
4.812 + ls >> id;
4.813 + typename Readers::iterator it = readers.find(id);
4.814 + if (it != readers.end()) {
4.815 + it->second->read(ls);
4.816 + }
4.817 + }
4.818 + }
4.819 +
4.820 + private:
4.821 + std::string id;
4.822 +
4.823 + typedef std::map<std::string, ValueReaderBase*> Readers;
4.824 + Readers readers;
4.825 +
4.826 + };
4.827 +
4.828 + template <typename _Graph>
4.829 + class NodeReader : public CommonSectionReaderBase {
4.830 + typedef CommonSectionReaderBase Parent;
4.831 + typedef _Graph Graph;
4.832 + typedef typename Graph::Node Item;
4.833 + public:
4.834 +
4.835 + template <typename Resolver>
4.836 + NodeReader(LemonReader& _reader, const Resolver& _resolver,
4.837 + const std::string& _id = std::string())
4.838 + : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
4.839 + (_resolver)) {
4.840 + _reader.attach(*this);
4.841 + }
4.842 +
4.843 + virtual ~NodeReader() {}
4.844 +
4.845 + private:
4.846 + NodeReader(const NodeReader&);
4.847 + void operator=(const NodeReader&);
4.848 +
4.849 + public:
4.850 +
4.851 + void readNode(const std::string& name, Item& item) {
4.852 + if (readers.find(name) != readers.end()) {
4.853 + ErrorMessage msg;
4.854 + msg << "Multiple read rule for node: " << name;
4.855 + throw IOParameterError(msg.message());
4.856 + }
4.857 + readers.insert(make_pair(name, &item));
4.858 + }
4.859 +
4.860 + virtual bool header(const std::string& line) {
4.861 + std::istringstream ls(line);
4.862 + std::string command;
4.863 + std::string name;
4.864 + ls >> command >> name;
4.865 + return command == "@nodes" && name == id;
4.866 + }
4.867 +
4.868 + virtual void read(std::istream& is) {
4.869 + std::string line;
4.870 + while (getline(is, line)) {
4.871 + std::istringstream ls(line);
4.872 + std::string id;
4.873 + ls >> id;
4.874 + typename ItemReaders::iterator it = readers.find(id);
4.875 + if (it != readers.end()) {
4.876 + *(it->second) = resolver->resolve(ls);
4.877 + }
4.878 + }
4.879 + }
4.880 +
4.881 + private:
4.882 +
4.883 + std::string id;
4.884 +
4.885 + typedef std::map<std::string, Item*> ItemReaders;
4.886 + ItemReaders readers;
4.887 + std::auto_ptr<ResolverReaderBase<Item> > resolver;
4.888 + };
4.889 +
4.890 + template <typename _Graph>
4.891 + class EdgeReader : public CommonSectionReaderBase {
4.892 + typedef CommonSectionReaderBase Parent;
4.893 + typedef _Graph Graph;
4.894 + typedef typename Graph::Edge Item;
4.895 + public:
4.896 +
4.897 + template <typename Resolver>
4.898 + EdgeReader(LemonReader& _reader, const Resolver& _resolver,
4.899 + const std::string& _id = std::string())
4.900 + : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
4.901 + (_resolver)) {
4.902 + _reader.attach(*this);
4.903 + }
4.904 +
4.905 + virtual ~EdgeReader() {}
4.906 + private:
4.907 + EdgeReader(const EdgeReader&);
4.908 + void operator=(const EdgeReader&);
4.909 +
4.910 + public:
4.911 +
4.912 + void readEdge(const std::string& name, Item& item) {
4.913 + if (readers.find(name) != readers.end()) {
4.914 + ErrorMessage msg;
4.915 + msg << "Multiple read rule for edge: " << name;
4.916 + throw IOParameterError(msg.message());
4.917 + }
4.918 + readers.insert(make_pair(name, &item));
4.919 + }
4.920 +
4.921 +
4.922 + virtual bool header(const std::string& line) {
4.923 + std::istringstream ls(line);
4.924 + std::string command;
4.925 + std::string name;
4.926 + ls >> command >> name;
4.927 + return command == "@nodes" && name == id;
4.928 + }
4.929 +
4.930 + virtual void read(std::istream& is) {
4.931 + std::string line;
4.932 + while (getline(is, line)) {
4.933 + std::istringstream ls(line);
4.934 + std::string id;
4.935 + ls >> id;
4.936 + typename ItemReaders::iterator it = readers.find(id);
4.937 + if (it != readers.end()) {
4.938 + *(it->second) = resolver->resolve(ls);
4.939 + }
4.940 + }
4.941 + }
4.942 +
4.943 + private:
4.944 +
4.945 + std::string id;
4.946 +
4.947 + typedef std::map<std::string, Item*> ItemReaders;
4.948 + ItemReaders readers;
4.949 + std::auto_ptr<ResolverReaderBase<Item> > resolver;
4.950 + };
4.951 +
4.952 + /// \e
4.953 + class PrintReader : public LemonReader::SectionReader {
4.954 + typedef LemonReader::SectionReader Parent;
4.955 + public:
4.956 +
4.957 + /// \e
4.958 + PrintReader(LemonReader& reader) {
4.959 + reader.attach(*this);
4.960 + }
4.961 +
4.962 + /// \e
4.963 + bool header(const std::string& line) {
4.964 + std::cout << "Asked header: " << line << std::endl;
4.965 + return true;
4.966 + }
4.967 +
4.968 + /// \e
4.969 + void read(std::istream& is) {
4.970 + std::string line;
4.971 + while (std::getline(is, line)) {
4.972 + std::cout << line << std::endl;
4.973 + }
4.974 + }
4.975 +
4.976 + };
4.977 +
4.978 + /// @}
4.979 +}
4.980 +#endif