deba@1409: /* -*- C++ -*- deba@1409: * alpar@1956: * This file is a part of LEMON, a generic C++ optimization library alpar@1956: * alpar@2391: * Copyright (C) 2003-2007 alpar@1956: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@1956: * (Egervary Research Group on Combinatorial Optimization, EGRES). deba@1409: * deba@1409: * Permission to use, modify and distribute this software is granted deba@1409: * provided that this copyright notice appears in all copies. For deba@1409: * precise terms see the accompanying LICENSE file. deba@1409: * deba@1409: * This software is provided "AS IS" with no warranty of any kind, deba@1409: * express or implied, and with no claim as to its suitability for any deba@1409: * purpose. deba@1409: * deba@1409: */ deba@1409: alpar@1946: /// \ingroup item_io deba@1409: /// \file deba@1409: /// \brief Item writer bits for lemon output. deba@1409: deba@1409: #ifndef LEMON_BITS_ITEM_WRITER_H deba@1409: #define LEMON_BITS_ITEM_WRITER_H deba@1409: deba@1409: #include deba@2254: #include deba@1409: #include deba@1409: deba@1409: #include deba@1409: #include deba@1409: #include deba@1409: #include deba@1409: deba@1409: namespace lemon { deba@1409: deba@1409: template deba@1409: class DefaultWriter; deba@1409: alpar@1946: /// \ingroup item_io deba@1409: /// \brief Writer class for quoted strings. deba@1409: /// deba@2254: /// Writer class for unformatted strings. deba@2254: /// \author Balazs Dezso deba@2254: class UnformattedWriter { deba@2254: public: deba@2254: typedef std::string Value; deba@2254: deba@2254: /// \brief Constructor for the writer. deba@2254: /// deba@2254: /// Constructor for the writer. deba@2254: UnformattedWriter() {} deba@2254: deba@2254: /// \brief Writes an unformatted string to the given stream. deba@2254: /// deba@2254: /// Writes an unformatted string to the given stream. deba@2254: void write(std::ostream& os, const std::string& value) const { deba@2254: os << value; deba@2254: } deba@2254: deba@2254: bool readable(const std::string& value) const { deba@2254: std::istringstream is(value); deba@2254: char c; deba@2254: while (is.get(c) && !whiteSpace(c)) { deba@2254: if (!processChar(c, is)) return false; deba@2254: } deba@2254: if (is) return false; deba@2254: return true; deba@2254: } deba@2254: deba@2254: private: deba@2254: deba@2254: bool processChar(char c, std::istream& is) const { deba@2254: switch (c) { deba@2254: case '(': deba@2254: is.putback(c); deba@2254: if (!readableParsed('(', ')', is)) return false; deba@2254: break; deba@2254: case '[': deba@2254: is.putback(c); deba@2254: if (!readableParsed('[', ']', is)) return false; deba@2254: break; deba@2254: case '{': deba@2254: is.putback(c); deba@2254: if (!readableParsed('{', '}', is)) return false; deba@2254: break; deba@2255: case '/': deba@2255: is.putback(c); deba@2255: if (!readableParsed('/', '/', is)) return false; deba@2255: break; deba@2254: case '\"': deba@2254: is.putback(c); deba@2254: if (!readableQuoted('\"', is)) return false; deba@2254: break; deba@2254: case '\'': deba@2254: is.putback(c); deba@2254: if (!readableQuoted('\'', is)) return false; deba@2254: break; deba@2254: default: deba@2254: break; deba@2254: } deba@2254: return true; deba@2254: } deba@2254: deba@2254: bool readableParsed(char open, char close, std::istream& is) const { deba@2254: char c; deba@2254: if (!is.get(c) || c != open) return false; deba@2254: while (is.get(c) && c != close) { deba@2254: if (!processChar(c, is)) return false; deba@2254: } deba@2254: if (!is) return false; deba@2254: return true; deba@2254: } deba@2254: deba@2254: bool readableQuoted(char quote, std::istream& is) const { deba@2254: char c; deba@2254: bool esc = false; deba@2254: if (!is.get(c) || c != quote) return false; deba@2255: while (is.get(c) && (c != quote || esc)) { deba@2254: if (c == '\\') esc = !esc; deba@2254: else esc = false; deba@2254: } deba@2254: if (!is) return false; deba@2254: return true; deba@2254: } deba@2254: deba@2254: static bool whiteSpace(char c) { deba@2254: return c == ' ' || c == '\t' || c == '\v' || deba@2254: c == '\n' || c == '\r' || c == '\f'; deba@2254: } deba@2254: deba@2254: }; deba@2254: deba@2254: /// \ingroup item_io deba@2254: /// \brief Writer class for quoted strings. deba@2254: /// deba@1409: /// Writer class for quoted strings. It can process the escape deba@1409: /// sequences in the string. deba@1409: /// \author Balazs Dezso deba@1409: class QuotedStringWriter { deba@2254: friend class QuotedCharWriter; deba@1409: public: deba@1409: typedef std::string Value; deba@1409: deba@1409: /// \brief Constructor for the writer. deba@1409: /// deba@1409: /// Constructor for the writer. If the given parameter is true deba@1409: /// the writer creates escape sequences from special characters. deba@1409: QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {} deba@1409: deba@1409: /// \brief Writes a quoted string to the given stream. deba@1409: /// deba@1409: /// Writes a quoted string to the given stream. deba@1852: void write(std::ostream& os, const std::string& value) const { deba@1409: os << "\""; deba@1409: if (escaped) { klao@1535: std::ostringstream ls; deba@2386: for (int i = 0; i < int(value.size()); ++i) { deba@1409: writeEscape(ls, value[i]); deba@1409: } deba@1409: os << ls.str(); deba@1409: } else { deba@1409: os << value; deba@1409: } deba@1409: os << "\""; deba@1409: } deba@1409: deba@1409: private: deba@1409: deba@1409: static void writeEscape(std::ostream& os, char c) { deba@1409: switch (c) { deba@1409: case '\\': deba@1409: os << "\\\\"; deba@1409: return; deba@1409: case '\"': deba@1409: os << "\\\""; deba@1409: return; deba@1409: case '\'': deba@1409: os << "\\\'"; deba@1409: return; deba@1409: case '\?': deba@1409: os << "\\\?"; deba@1409: return; deba@1409: case '\a': deba@1409: os << "\\a"; deba@1409: return; deba@1409: case '\b': deba@1409: os << "\\b"; deba@1409: return; deba@1409: case '\f': deba@1409: os << "\\f"; deba@1409: return; deba@1409: case '\r': deba@1409: os << "\\r"; deba@1409: return; deba@1409: case '\n': deba@1409: os << "\\n"; deba@1409: return; deba@1409: case '\t': deba@1409: os << "\\t"; deba@1409: return; deba@1409: case '\v': deba@1409: os << "\\v"; deba@1409: return; deba@1409: default: deba@1409: if (c < 0x20) { deba@2386: os << '\\' << std::oct << static_cast(c); deba@1409: } else { deba@1409: os << c; deba@1409: } deba@1409: return; deba@1409: } deba@1409: } deba@1409: private: deba@1409: bool escaped; deba@1409: }; deba@1409: alpar@1946: /// \ingroup item_io deba@2254: /// \brief Writer class for quoted chars. deba@2254: /// deba@2254: /// Writer class for quoted char. It can process the escape deba@2254: /// sequences in the string. deba@2254: /// \author Balazs Dezso deba@2254: class QuotedCharWriter { deba@2254: public: deba@2254: typedef char Value; deba@2254: deba@2254: /// \brief Constructor for the writer. deba@2254: /// deba@2254: /// Constructor for the writer. If the given parameter is true deba@2254: /// the writer creates escape sequences from special characters. deba@2254: QuotedCharWriter(bool _escaped = true) : escaped(_escaped) {} deba@2254: deba@2254: /// \brief Writes a quoted char to the given stream. deba@2254: /// deba@2254: /// Writes a quoted char to the given stream. deba@2254: void write(std::ostream& os, const char& value) const { deba@2254: os << "\'"; deba@2254: if (escaped) { deba@2254: std::ostringstream ls; deba@2254: QuotedStringWriter::writeEscape(ls, value); deba@2254: os << ls.str(); deba@2254: } else { deba@2254: os << value; deba@2254: } deba@2254: os << "\'"; deba@2254: } deba@2254: deba@2254: private: deba@2254: bool escaped; deba@2254: }; deba@2254: deba@2254: /// \ingroup item_io deba@1533: /// \brief Writer class for quoted char array. deba@1533: /// deba@1533: /// Writer class for quoted char array. It can process the escape deba@1533: /// sequences in the char array. deba@1533: /// \author Balazs Dezso deba@1533: class QuotedCharArrayWriter { deba@1533: public: deba@1533: typedef const char* Value; deba@1533: deba@1533: /// \brief Constructor for the writer. deba@1533: /// deba@1533: /// Constructor for the writer. If the given parameter is true deba@1533: /// the writer creates escape sequences from special characters. deba@1533: QuotedCharArrayWriter(bool _escaped = true) : escaped(_escaped) {} deba@1533: deba@1533: /// \brief Writes a quoted char array to the given stream. deba@1533: /// deba@1533: /// Writes a quoted char array to the given stream. deba@1852: void write(std::ostream& os, const char* value) const { deba@1533: QuotedStringWriter(escaped).write(os, std::string(value)); deba@1533: } deba@1533: deba@1533: private: deba@1533: bool escaped; deba@1533: }; deba@1533: deba@1533: alpar@1946: /// \ingroup item_io deba@1409: /// deba@1409: /// \brief Writer for standard containers. deba@1409: /// deba@1409: /// Writer for each iterable standard containers. The representation deba@1409: /// of the container is the values enumerated between an open and a deba@1409: /// close parse. deba@1409: /// deba@1409: /// \author Balazs Dezso deba@1409: template < deba@1409: typename _Container, deba@1409: typename _ItemWriter = DefaultWriter deba@1409: > deba@1409: class IterableWriter { deba@1409: public: deba@1409: typedef _Container Value; deba@1409: typedef _ItemWriter ItemWriter; deba@1409: deba@1409: private: deba@1409: deba@1409: ItemWriter item_writer; deba@1409: deba@1409: public: deba@1409: deba@1852: IterableWriter(const ItemWriter& _item_writer = ItemWriter()) deba@1852: : item_writer(_item_writer) {} deba@1852: deba@1409: /// \brief Writes the values of the container to the given stream. deba@1409: /// deba@1409: /// Writes the values of the container to the given stream. deba@1409: void write(std::ostream& os, const Value& value) const { deba@1409: typename Value::const_iterator it; deba@1409: os << '('; deba@1409: for (it = value.begin(); it != value.end(); ++it) { deba@1409: item_writer.write(os, *it); deba@1409: os << ' '; deba@1409: } deba@1409: os << ')'; deba@1409: } deba@1409: deba@1409: }; deba@1409: alpar@1946: /// \ingroup item_io deba@1852: /// deba@1852: /// \brief Writer for standard pairs. deba@1852: /// deba@1852: /// Writer for standard pairs. The representation of a pair is alpar@1946: ///\code ( first_value => second_value ) \endcode. deba@1852: /// \author Balazs Dezso deba@1852: template , deba@1852: typename _SecondWriter = deba@1852: DefaultWriter > deba@1852: class PairWriter { deba@1852: public: deba@1852: deba@1852: typedef _Pair Value; deba@1852: deba@1852: typedef _FirstWriter FirstWriter; deba@1852: typedef _SecondWriter SecondWriter; deba@1852: deba@1852: private: deba@1852: deba@1852: FirstWriter first_writer; deba@1852: SecondWriter second_writer; deba@1852: deba@1852: public: deba@1852: deba@1852: /// \brief Constructor. deba@1852: /// deba@1852: /// Constructor for the PairWriter. deba@1852: PairWriter(const FirstWriter& _first_writer = FirstWriter(), deba@1852: const SecondWriter& _second_writer = SecondWriter()) deba@1852: : first_writer(_first_writer), second_writer(_second_writer) {} deba@1852: deba@1852: /// \brief Writes the pair from the given stream. deba@1852: /// deba@1852: /// Writes the pair from the given stream. deba@1852: void write(std::ostream& os, const Value& value) const { deba@1852: os << "( "; deba@1852: first_writer.write(os, value.first); deba@1852: os << " => "; deba@1852: second_writer.write(os, value.second); deba@1852: os << " )"; deba@1852: } deba@1852: deba@1852: }; deba@1852: alpar@1946: /// \ingroup item_io deba@1409: /// deba@1409: /// \brief The default item writer template class. deba@1409: /// deba@1409: /// The default item writer template class. If some section writer deba@1409: /// needs to write a value to the stream it will give the default way for it. deba@1409: /// deba@1409: /// \author Balazs Dezso deba@1409: template deba@1409: class DefaultWriter { deba@1409: public: deba@1409: /// The value type. deba@1409: typedef _Value Value; deba@1409: /// \brief Writes the value to the given stream. deba@1409: /// deba@1409: /// Writes the value to the given stream. deba@1409: void write(std::ostream& os, const Value& value) const { deba@1409: os << value; deba@1409: } deba@1409: }; deba@1409: deba@1429: template <> deba@2254: class DefaultWriter { deba@2254: public: deba@2254: typedef std::string Value; deba@2254: deba@2254: void write(std::ostream& os, const Value& value) const { deba@2254: if (UnformattedWriter().readable(value)) { deba@2254: UnformattedWriter().write(os, value); deba@2254: } else { deba@2254: QuotedStringWriter().write(os, value); deba@2254: } deba@2254: } deba@2254: deba@2254: }; deba@2254: deba@2254: template <> deba@2254: class DefaultWriter deba@2254: : public QuotedCharWriter {}; deba@2254: deba@2254: template <> deba@2254: class DefaultWriter { deba@2254: public: deba@2254: typedef bool Value; deba@2254: deba@2254: void write(std::ostream& os, const Value& value) const { deba@2254: os << (value ? "1" : "0"); deba@2254: } deba@2254: deba@2254: }; deba@1429: deba@1533: template deba@1533: class DefaultWriter deba@1533: : public QuotedCharArrayWriter {}; deba@1533: deba@1533: template deba@1533: class DefaultWriter deba@1533: : public QuotedCharArrayWriter {}; deba@1533: deba@1852: template <> deba@1852: class DefaultWriter deba@1852: : public QuotedCharArrayWriter {}; deba@1852: deba@1852: template <> deba@1852: class DefaultWriter deba@1852: : public QuotedCharArrayWriter {}; deba@1852: deba@1409: template deba@1409: class DefaultWriter > deba@1409: : public IterableWriter > {}; deba@1409: deba@1409: template deba@1409: class DefaultWriter > deba@1409: : public IterableWriter > {}; deba@1409: deba@1409: template deba@1409: class DefaultWriter > deba@1409: : public IterableWriter > {}; deba@1409: deba@1409: template deba@1409: class DefaultWriter > deba@1409: : public IterableWriter > {}; deba@1409: deba@1852: template deba@1852: class DefaultWriter > deba@1852: : public IterableWriter > {}; deba@1852: deba@1409: template deba@1409: class DefaultWriter > deba@1409: : public IterableWriter > {}; deba@1409: deba@1852: template deba@1852: class DefaultWriter > deba@1852: : public IterableWriter > {}; deba@1852: deba@1852: template deba@1852: class DefaultWriter > deba@1852: : public PairWriter > {}; deba@1852: alpar@1946: /// \ingroup item_io deba@1409: /// \brief Standard WriterTraits for the section writers. deba@1409: /// deba@1409: /// Standard WriterTraits for the section writers. deba@1409: /// It defines standard writing method for all type of value. deba@1409: /// \author Balazs Dezso deba@1409: struct DefaultWriterTraits { deba@1409: deba@1409: template deba@1533: struct Writer : DefaultWriter<_Value> { deba@1533: typedef DefaultWriter<_Value> Parent; deba@1533: }; deba@1409: deba@1409: }; deba@1409: deba@1409: } deba@1409: deba@1409: #endif