1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/lemon/bits/item_reader.h Mon May 23 04:48:14 2005 +0000
1.3 @@ -0,0 +1,414 @@
1.4 +/* -*- C++ -*-
1.5 + * lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
1.6 + *
1.7 + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
1.8 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
1.9 + *
1.10 + * Permission to use, modify and distribute this software is granted
1.11 + * provided that this copyright notice appears in all copies. For
1.12 + * precise terms see the accompanying LICENSE file.
1.13 + *
1.14 + * This software is provided "AS IS" with no warranty of any kind,
1.15 + * express or implied, and with no claim as to its suitability for any
1.16 + * purpose.
1.17 + *
1.18 + */
1.19 +
1.20 +/// @defgroup item_io Item Readers and Writers
1.21 +/// @ingroup io_group
1.22 +/// \brief Item Readers and Writers
1.23 +///
1.24 +/// The Input-Output classes can handle more data type by example
1.25 +/// as map or attribute value. Each of these should be written and
1.26 +/// read some way. The module make possible to do this.
1.27 +
1.28 +/// \ingroup item_io
1.29 +/// \file
1.30 +/// \brief Item reader bits for lemon input.
1.31 +
1.32 +#ifndef LEMON_BITS_ITEM_READER_H
1.33 +#define LEMON_BITS_ITEM_READER_H
1.34 +
1.35 +#include <iostream>
1.36 +#include <string>
1.37 +
1.38 +#include <vector>
1.39 +#include <deque>
1.40 +#include <list>
1.41 +#include <set>
1.42 +
1.43 +namespace lemon {
1.44 +
1.45 + template <typename Value>
1.46 + class DefaultReader;
1.47 +
1.48 + /// \ingroup item_io
1.49 + ///
1.50 + /// \brief Reader class for quoted strings.
1.51 + ///
1.52 + /// Reader class for quoted strings. It can process the escape
1.53 + /// sequences in the string.
1.54 + ///
1.55 + /// \author Balazs Dezso
1.56 + class QuotedStringReader {
1.57 + public:
1.58 + /// \brief The value type of reader.
1.59 + ///
1.60 + /// The value type of reader.
1.61 + typedef std::string Value;
1.62 +
1.63 + /// \brief Constructor for the reader.
1.64 + ///
1.65 + /// Constructor for the reader. If the given parameter is true
1.66 + /// the reader processes the escape sequences.
1.67 + QuotedStringReader(bool _escaped = true)
1.68 + : escaped(_escaped) {}
1.69 +
1.70 + /// \brief Reads a quoted string from the given stream.
1.71 + ///
1.72 + /// Reads a quoted string from the given stream.
1.73 + void read(std::istream& is, std::string& value) const {
1.74 + char c;
1.75 + value.clear();
1.76 + is >> std::ws;
1.77 + if (!is.get(c) || c != '\"')
1.78 + throw DataFormatError("Quoted string format error");
1.79 + while (is.get(c) && c != '\"') {
1.80 + if (escaped && c == '\\') {
1.81 + value += readEscape(is);
1.82 + } else {
1.83 + value += c;
1.84 + }
1.85 + }
1.86 + if (!is) throw DataFormatError("Quoted string format error");
1.87 + }
1.88 +
1.89 + private:
1.90 +
1.91 + static char readEscape(std::istream& is) {
1.92 + char c;
1.93 + switch (is.get(c), c) {
1.94 + case '\\':
1.95 + return '\\';
1.96 + case '\"':
1.97 + return '\"';
1.98 + case '\'':
1.99 + return '\'';
1.100 + case '\?':
1.101 + return '\?';
1.102 + case 'a':
1.103 + return '\a';
1.104 + case 'b':
1.105 + return '\b';
1.106 + case 'f':
1.107 + return '\f';
1.108 + case 'n':
1.109 + return '\n';
1.110 + case 'r':
1.111 + return '\r';
1.112 + case 't':
1.113 + return '\t';
1.114 + case 'v':
1.115 + return '\v';
1.116 + case 'x':
1.117 + {
1.118 + int code;
1.119 + if (!is.get(c) || !isHex(c))
1.120 + throw DataFormatError("Escape format error");
1.121 + else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
1.122 + else code = code * 16 + valueHex(c);
1.123 + return code;
1.124 + }
1.125 + default:
1.126 + {
1.127 + int code;
1.128 + if (!isOct(c))
1.129 + throw DataFormatError("Escape format error");
1.130 + else if (code = valueOct(c), !is.get(c) || !isOct(c))
1.131 + is.putback(c);
1.132 + else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
1.133 + is.putback(c);
1.134 + else code = code * 8 + valueOct(c);
1.135 + return code;
1.136 + }
1.137 + }
1.138 + }
1.139 +
1.140 + static bool isOct(char c) {
1.141 + return '0' <= c && c <='7';
1.142 + }
1.143 +
1.144 + static int valueOct(char c) {
1.145 + return c - '0';
1.146 + }
1.147 +
1.148 + static bool isHex(char c) {
1.149 + return ('0' <= c && c <= '9') ||
1.150 + ('a' <= c && c <= 'z') ||
1.151 + ('A' <= c && c <= 'Z');
1.152 + }
1.153 +
1.154 + static int valueHex(char c) {
1.155 + if ('0' <= c && c <= '9') return c - '0';
1.156 + if ('a' <= c && c <= 'z') return c - 'a' + 10;
1.157 + return c - 'A' + 10;
1.158 + }
1.159 +
1.160 + bool escaped;
1.161 + };
1.162 +
1.163 + /// \ingroup item_io
1.164 + /// \brief Reader for standard containers.
1.165 + ///
1.166 + /// Reader for back insertable standard containers. The representation
1.167 + /// of the container is the values enumerated between an open and a
1.168 + /// close parse.
1.169 + ///
1.170 + /// \author Balazs Dezso
1.171 + template <
1.172 + typename _Container,
1.173 + typename _ItemReader = DefaultReader<typename _Container::value_type>
1.174 + >
1.175 + class PushBackReader {
1.176 + public:
1.177 + typedef _Container Value;
1.178 + typedef _ItemReader ItemReader;
1.179 +
1.180 + private:
1.181 +
1.182 + ItemReader item_reader;
1.183 +
1.184 + public:
1.185 +
1.186 + /// \brief Reads the values into the container from the given stream.
1.187 + ///
1.188 + /// Reads the values into the container from the given stream.
1.189 + void read(std::istream& is, Value& value) const {
1.190 + char c;
1.191 + if (!(is >> c) || c != '(')
1.192 + throw DataFormatError("PushBackReader format error");
1.193 + while (is >> c && c != ')') {
1.194 + is.putback(c);
1.195 + typename ItemReader::Value item;
1.196 + item_reader.read(is, item);
1.197 + value.push_back(item);
1.198 + }
1.199 + if (!is) throw DataFormatError("PushBackReader format error");
1.200 + is.putback(c);
1.201 + }
1.202 +
1.203 + };
1.204 +
1.205 + /// \ingroup item_io
1.206 + ///
1.207 + /// \brief Reader for standard containers.
1.208 + ///
1.209 + /// Reader for insertable standard containers. The representation
1.210 + /// of the container is the values enumerated between an open and a
1.211 + /// close parse.
1.212 + ///
1.213 + /// \author Balazs Dezso
1.214 + template <
1.215 + typename _Container,
1.216 + typename _ItemReader = DefaultReader<typename _Container::value_type>
1.217 + >
1.218 + class InsertReader {
1.219 + public:
1.220 + typedef _Container Value;
1.221 + typedef _ItemReader ItemReader;
1.222 +
1.223 + private:
1.224 +
1.225 + ItemReader item_reader;
1.226 +
1.227 + public:
1.228 +
1.229 + /// \brief Reads the values into the container from the given stream.
1.230 + ///
1.231 + /// Reads the values into the container from the given stream.
1.232 + void read(std::istream& is, Value& value) const {
1.233 + char c;
1.234 + if (!(is >> c) || c != '(')
1.235 + throw DataFormatError("InsertReader format error");
1.236 + while (is >> c && c != ')') {
1.237 + is.putback(c);
1.238 + typename ItemReader::Value item;
1.239 + item_reader.read(is, item);
1.240 + value.insert(item);
1.241 + }
1.242 + if (!is) throw DataFormatError("PushBackReader format error");
1.243 + is.putback(c);
1.244 + }
1.245 +
1.246 + };
1.247 +
1.248 + /// \ingroup item_io
1.249 + /// \brief Reader for parsed string.
1.250 + ///
1.251 + /// Reader for parsed strings. You can give the open and close
1.252 + /// parse characters.
1.253 + ///
1.254 + /// \author Balazs Dezso
1.255 + class ParsedStringReader {
1.256 + public:
1.257 + typedef std::string Value;
1.258 +
1.259 + /// \brief Constructor.
1.260 + ///
1.261 + /// Constructor for ParsedStringReader. You can give as parameter
1.262 + /// the open and close parse characters.
1.263 + ParsedStringReader(char _open = '(', char _close = ')')
1.264 + : open(_open), close(_close) {}
1.265 +
1.266 +
1.267 + /// \brief Reads the parsed string from the given stream.
1.268 + ///
1.269 + /// Reads the parsed string from the given stream.
1.270 + void read(std::istream& is, Value& value) const {
1.271 + char c;
1.272 + if (!(is >> c) || c != open) {
1.273 + throw DataFormatError("ParsedStringReader format error");
1.274 + }
1.275 + value += c;
1.276 + int counter = 1;
1.277 + while (counter > 0 && is >> c) {
1.278 + if (c == close) {
1.279 + --counter;
1.280 + } else if (c == open) {
1.281 + ++counter;
1.282 + }
1.283 + value += c;
1.284 + }
1.285 + if (!is) {
1.286 + throw DataFormatError("ParsedStrinReader format error");
1.287 + }
1.288 + }
1.289 +
1.290 + private:
1.291 + char open, close;
1.292 +
1.293 + };
1.294 +
1.295 + /// \ingroup item_io
1.296 + /// \brief Reader for read the whole line.
1.297 + ///
1.298 + /// Reader for read the whole line.
1.299 + ///
1.300 + /// \author Balazs Dezso
1.301 + class LineReader {
1.302 + public:
1.303 + typedef std::string Value;
1.304 +
1.305 + /// \brief Constructor.
1.306 + ///
1.307 + /// Constructor for the LineReader. If the given parameter is
1.308 + /// true then the spaces before the first not space character are
1.309 + /// skipped.
1.310 + LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
1.311 +
1.312 + /// \brief Reads the line from the given stream.
1.313 + ///
1.314 + /// Reads the line from the given stream.
1.315 + void read(std::istream& is, Value& value) {
1.316 + if (skipSpaces) is >> std::ws;
1.317 + if (!getline(is, value)) {
1.318 + throw DataFormatError("LineReader forma error");
1.319 + }
1.320 + }
1.321 + private:
1.322 + bool skipSpaces;
1.323 + };
1.324 +
1.325 + /// \ingroup item_io
1.326 + ///
1.327 + /// \brief The default item reader template class.
1.328 + ///
1.329 + /// The default item reader template class. If some section reader
1.330 + /// needs to read a value from a stream it will give the default way for it.
1.331 + ///
1.332 + /// \author Balazs Dezso
1.333 + template <typename _Value>
1.334 + class DefaultReader {
1.335 + public:
1.336 + /// The value type.
1.337 + typedef _Value Value;
1.338 + /// \brief Reads a value from the given stream.
1.339 + ///
1.340 + /// Reads a value from the given stream.
1.341 + void read(std::istream& is, Value& value) const {
1.342 + if (!(is >> value))
1.343 + throw DataFormatError("DefaultReader format error");
1.344 + }
1.345 + };
1.346 +
1.347 + template <>
1.348 + class DefaultReader<std::string> {
1.349 + public:
1.350 + typedef std::string Value;
1.351 +
1.352 + void read(std::istream& is, Value& value) const {
1.353 + char c;
1.354 + if (!(is >> std::ws >> c)) return;
1.355 + is.putback(c);
1.356 + switch (c) {
1.357 + case '\"':
1.358 + QuotedStringReader().read(is, value);
1.359 + break;
1.360 + case '(':
1.361 + ParsedStringReader().read(is, value);
1.362 + break;
1.363 + default:
1.364 + is >> value;
1.365 + break;
1.366 + }
1.367 + }
1.368 +
1.369 + };
1.370 +
1.371 + template <typename Item>
1.372 + class DefaultReader<std::vector<Item> >
1.373 + : public PushBackReader<std::vector<Item> > {};
1.374 +
1.375 + template <typename Item>
1.376 + class DefaultReader<std::deque<Item> >
1.377 + : public PushBackReader<std::deque<Item> > {};
1.378 +
1.379 + template <typename Item>
1.380 + class DefaultReader<std::list<Item> >
1.381 + : public PushBackReader<std::list<Item> > {};
1.382 +
1.383 + template <typename Item>
1.384 + class DefaultReader<std::set<Item> >
1.385 + : public InsertReader<std::set<Item> > {};
1.386 +
1.387 + template <typename Item>
1.388 + class DefaultReader<std::multiset<Item> >
1.389 + : public InsertReader<std::multiset<Item> > {};
1.390 +
1.391 + /// \ingroup item_io
1.392 + ///
1.393 + /// \brief The default item reader for skipping a value in the stream.
1.394 + ///
1.395 + /// The default item reader for skipping a value in the stream.
1.396 + ///
1.397 + /// \author Balazs Dezso
1.398 + class DefaultSkipper : public DefaultReader<std::string> {};
1.399 +
1.400 + /// \ingroup item_io
1.401 + /// \brief Standard ReaderTraits for the GraphReader class.
1.402 + ///
1.403 + /// Standard ReaderTraits for the GraphReader class.
1.404 + /// It defines standard reading method for all type of value.
1.405 + /// \author Balazs Dezso
1.406 + struct DefaultReaderTraits {
1.407 +
1.408 + template <typename _Value>
1.409 + struct Reader : DefaultReader<_Value> {};
1.410 +
1.411 + typedef DefaultSkipper Skipper;
1.412 +
1.413 + };
1.414 +
1.415 +}
1.416 +
1.417 +#endif