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