diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/item_reader.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/item_reader.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,414 @@ +/* -*- C++ -*- + * lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +/// @defgroup item_io Item Readers and Writers +/// @ingroup io_group +/// \brief Item Readers and Writers +/// +/// The Input-Output classes can handle more data type by example +/// as map or attribute value. Each of these should be written and +/// read some way. The module make possible to do this. + +/// \ingroup item_io +/// \file +/// \brief Item reader bits for lemon input. + +#ifndef LEMON_BITS_ITEM_READER_H +#define LEMON_BITS_ITEM_READER_H + +#include +#include + +#include +#include +#include +#include + +namespace lemon { + + template + class DefaultReader; + + /// \ingroup item_io + /// + /// \brief Reader class for quoted strings. + /// + /// Reader class for quoted strings. It can process the escape + /// sequences in the string. + /// + /// \author Balazs Dezso + class QuotedStringReader { + public: + /// \brief The value type of reader. + /// + /// The value type of reader. + typedef std::string Value; + + /// \brief Constructor for the reader. + /// + /// Constructor for the reader. If the given parameter is true + /// the reader processes the escape sequences. + QuotedStringReader(bool _escaped = true) + : escaped(_escaped) {} + + /// \brief Reads a quoted string from the given stream. + /// + /// Reads a quoted string from the given stream. + void read(std::istream& is, std::string& value) const { + char c; + value.clear(); + is >> std::ws; + if (!is.get(c) || c != '\"') + throw DataFormatError("Quoted string format error"); + while (is.get(c) && c != '\"') { + if (escaped && c == '\\') { + value += readEscape(is); + } else { + value += c; + } + } + if (!is) throw DataFormatError("Quoted string format error"); + } + + 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 DataFormatError("Escape format error"); + 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 DataFormatError("Escape format error"); + 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; + }; + + /// \ingroup item_io + /// \brief Reader for standard containers. + /// + /// Reader for back insertable standard containers. The representation + /// of the container is the values enumerated between an open and a + /// close parse. + /// + /// \author Balazs Dezso + template < + typename _Container, + typename _ItemReader = DefaultReader + > + class PushBackReader { + public: + typedef _Container Value; + typedef _ItemReader ItemReader; + + private: + + ItemReader item_reader; + + public: + + /// \brief Reads the values into the container from the given stream. + /// + /// Reads the values into the container from the given stream. + void read(std::istream& is, Value& value) const { + char c; + if (!(is >> c) || c != '(') + throw DataFormatError("PushBackReader format error"); + while (is >> c && c != ')') { + is.putback(c); + typename ItemReader::Value item; + item_reader.read(is, item); + value.push_back(item); + } + if (!is) throw DataFormatError("PushBackReader format error"); + is.putback(c); + } + + }; + + /// \ingroup item_io + /// + /// \brief Reader for standard containers. + /// + /// Reader for insertable standard containers. The representation + /// of the container is the values enumerated between an open and a + /// close parse. + /// + /// \author Balazs Dezso + template < + typename _Container, + typename _ItemReader = DefaultReader + > + class InsertReader { + public: + typedef _Container Value; + typedef _ItemReader ItemReader; + + private: + + ItemReader item_reader; + + public: + + /// \brief Reads the values into the container from the given stream. + /// + /// Reads the values into the container from the given stream. + void read(std::istream& is, Value& value) const { + char c; + if (!(is >> c) || c != '(') + throw DataFormatError("InsertReader format error"); + while (is >> c && c != ')') { + is.putback(c); + typename ItemReader::Value item; + item_reader.read(is, item); + value.insert(item); + } + if (!is) throw DataFormatError("PushBackReader format error"); + is.putback(c); + } + + }; + + /// \ingroup item_io + /// \brief Reader for parsed string. + /// + /// Reader for parsed strings. You can give the open and close + /// parse characters. + /// + /// \author Balazs Dezso + class ParsedStringReader { + public: + typedef std::string Value; + + /// \brief Constructor. + /// + /// Constructor for ParsedStringReader. You can give as parameter + /// the open and close parse characters. + ParsedStringReader(char _open = '(', char _close = ')') + : open(_open), close(_close) {} + + + /// \brief Reads the parsed string from the given stream. + /// + /// Reads the parsed string from the given stream. + void read(std::istream& is, Value& value) const { + char c; + if (!(is >> c) || c != open) { + throw DataFormatError("ParsedStringReader format error"); + } + value += c; + int counter = 1; + while (counter > 0 && is >> c) { + if (c == close) { + --counter; + } else if (c == open) { + ++counter; + } + value += c; + } + if (!is) { + throw DataFormatError("ParsedStrinReader format error"); + } + } + + private: + char open, close; + + }; + + /// \ingroup item_io + /// \brief Reader for read the whole line. + /// + /// Reader for read the whole line. + /// + /// \author Balazs Dezso + class LineReader { + public: + typedef std::string Value; + + /// \brief Constructor. + /// + /// Constructor for the LineReader. If the given parameter is + /// true then the spaces before the first not space character are + /// skipped. + LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {} + + /// \brief Reads the line from the given stream. + /// + /// Reads the line from the given stream. + void read(std::istream& is, Value& value) { + if (skipSpaces) is >> std::ws; + if (!getline(is, value)) { + throw DataFormatError("LineReader forma error"); + } + } + private: + bool skipSpaces; + }; + + /// \ingroup item_io + /// + /// \brief The default item reader template class. + /// + /// The default item reader template class. If some section reader + /// needs to read a value from a stream it will give the default way for it. + /// + /// \author Balazs Dezso + template + class DefaultReader { + public: + /// The value type. + typedef _Value Value; + /// \brief Reads a value from the given stream. + /// + /// Reads a value from the given stream. + void read(std::istream& is, Value& value) const { + if (!(is >> value)) + throw DataFormatError("DefaultReader format error"); + } + }; + + template <> + class DefaultReader { + public: + typedef std::string Value; + + void read(std::istream& is, Value& value) const { + char c; + if (!(is >> std::ws >> c)) return; + is.putback(c); + switch (c) { + case '\"': + QuotedStringReader().read(is, value); + break; + case '(': + ParsedStringReader().read(is, value); + break; + default: + is >> value; + break; + } + } + + }; + + template + class DefaultReader > + : public PushBackReader > {}; + + template + class DefaultReader > + : public PushBackReader > {}; + + template + class DefaultReader > + : public PushBackReader > {}; + + template + class DefaultReader > + : public InsertReader > {}; + + template + class DefaultReader > + : public InsertReader > {}; + + /// \ingroup item_io + /// + /// \brief The default item reader for skipping a value in the stream. + /// + /// The default item reader for skipping a value in the stream. + /// + /// \author Balazs Dezso + class DefaultSkipper : public DefaultReader {}; + + /// \ingroup item_io + /// \brief Standard ReaderTraits for the GraphReader class. + /// + /// Standard ReaderTraits for the GraphReader class. + /// It defines standard reading method for all type of value. + /// \author Balazs Dezso + struct DefaultReaderTraits { + + template + struct Reader : DefaultReader<_Value> {}; + + typedef DefaultSkipper Skipper; + + }; + +} + +#endif