lemon/bits/item_writer.h
author deba
Sat, 20 Dec 2008 22:45:48 +0000
changeset 2631 212ea31bf6b9
parent 2426 6e1027a05d73
permissions -rw-r--r--
Backport hg commit [52c04a2a652c] (ticket #197)
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2008
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 /// \ingroup item_io
    20 /// \file
    21 /// \brief Item writer bits for lemon output.
    22 
    23 #ifndef LEMON_BITS_ITEM_WRITER_H
    24 #define LEMON_BITS_ITEM_WRITER_H
    25 
    26 #include <iostream>
    27 #include <sstream>
    28 #include <string>
    29 
    30 #include <vector>
    31 #include <deque>
    32 #include <list>
    33 #include <set>
    34 #include <map>
    35 
    36 #include <lemon/error.h>
    37 
    38 namespace lemon {
    39   
    40   template <typename Value>
    41   class DefaultWriter;
    42 
    43   /// \ingroup item_io
    44   /// \brief Writer class for quoted strings.
    45   ///
    46   /// Writer class for unformatted strings.
    47   /// \author Balazs Dezso
    48   class UnformattedWriter {
    49   public:
    50     typedef std::string Value;
    51 
    52     /// \brief Constructor for the writer.
    53     ///
    54     /// Constructor for the writer.
    55     UnformattedWriter() {}
    56 
    57     /// \brief Writes an unformatted string to the given stream.
    58     ///
    59     /// Writes an unformatted string to the given stream.
    60     void write(std::ostream& os, const std::string& value) const {
    61       os << value;
    62     }
    63 
    64     bool readable(const std::string& value) const {
    65       std::istringstream is(value);
    66       char c;
    67       while (is.get(c) && !whiteSpace(c)) {
    68         if (!processChar(c, is)) return false;
    69       }
    70       if (is) return false;
    71       return true;
    72     }
    73 
    74   private:
    75 
    76     bool processChar(char c, std::istream& is) const {
    77       switch (c) {
    78       case '(':
    79         is.putback(c);
    80         if (!readableParsed('(', ')', is)) return false;
    81         break;
    82       case '[':
    83         is.putback(c);
    84         if (!readableParsed('[', ']', is)) return false;
    85         break;
    86       case '{':
    87         is.putback(c);
    88         if (!readableParsed('{', '}', is)) return false;
    89         break;
    90       case '/':
    91         is.putback(c);
    92         if (!readableParsed('/', '/', is)) return false;
    93         break;
    94       case '\"':
    95         is.putback(c);
    96         if (!readableQuoted('\"', is)) return false;
    97         break;
    98       case '\'':
    99         is.putback(c);
   100         if (!readableQuoted('\'', is)) return false;
   101         break;
   102       default:
   103         break;
   104       }
   105       return true;
   106     }
   107 
   108     bool readableParsed(char open, char close, std::istream& is) const {
   109       char c;
   110       if (!is.get(c) || c != open) return false;
   111       while (is.get(c) && c != close) {
   112         if (!processChar(c, is)) return false;
   113       }
   114       if (!is) return false;
   115       return true;
   116     }
   117 
   118     bool readableQuoted(char quote, std::istream& is) const {
   119       char c;
   120       bool esc = false;
   121       if (!is.get(c) || c != quote) return false;
   122       while (is.get(c) && (c != quote || esc)) {
   123         if (c == '\\') esc = !esc;
   124         else esc = false;
   125       }
   126       if (!is) return false;
   127       return true;
   128     }
   129 
   130     static bool whiteSpace(char c) {
   131       return c == ' ' || c == '\t' || c == '\v' || 
   132         c == '\n' || c == '\r' || c == '\f'; 
   133     }
   134 
   135   };
   136 
   137   /// \ingroup item_io
   138   /// \brief Writer class for quoted strings.
   139   ///
   140   /// Writer class for quoted strings. It can process the escape
   141   /// sequences in the string.
   142   /// \author Balazs Dezso
   143   class QuotedStringWriter {
   144     friend class QuotedCharWriter;
   145   public:
   146     typedef std::string Value;
   147 
   148     /// \brief Constructor for the writer.
   149     ///
   150     /// Constructor for the writer. If the given parameter is true
   151     /// the writer creates escape sequences from special characters.
   152     QuotedStringWriter(bool _escaped = true, char _quote = '\"') 
   153       : escaped(_escaped), quote(_quote) {}
   154 
   155     /// \brief Writes a quoted string to the given stream.
   156     ///
   157     /// Writes a quoted string to the given stream.
   158     void write(std::ostream& os, const std::string& value) const {
   159       os << quote;
   160       if (escaped) {
   161 	std::ostringstream ls;
   162 	for (int i = 0; i < int(value.size()); ++i) {
   163 	  writeEscape(ls, value[i]);
   164 	}
   165 	os << ls.str();
   166       } else {
   167 	os << value;
   168       }
   169       os << quote;
   170     }
   171 
   172   private:
   173     
   174     static void writeEscape(std::ostream& os, char c) {
   175       switch (c) {
   176       case '\\':
   177 	os << "\\\\";
   178 	return;
   179       case '\"':
   180 	os << "\\\"";
   181 	return;
   182       case '\'':
   183 	os << "\\\'";
   184 	return;
   185       case '\?':
   186 	os << "\\\?";
   187 	return;
   188       case '\a':
   189 	os << "\\a";
   190 	return;
   191       case '\b':
   192 	os << "\\b";
   193 	return;
   194       case '\f':
   195 	os << "\\f";
   196 	return;
   197       case '\r':
   198 	os << "\\r";
   199 	return;
   200       case '\n':
   201 	os << "\\n";
   202 	return;
   203       case '\t':
   204 	os << "\\t";
   205 	return;
   206       case '\v':
   207 	os << "\\v";
   208 	return;
   209       default:
   210 	if (c < 0x20) {
   211 	  os << '\\' << std::oct << static_cast<int>(c);
   212 	} else {
   213 	  os << c;
   214 	}
   215 	return;
   216       }     
   217     }
   218   private:
   219     bool escaped;
   220     char quote;
   221   };
   222 
   223   /// \ingroup item_io
   224   /// \brief Writer class for quoted chars.
   225   ///
   226   /// Writer class for quoted char. It can process the escape
   227   /// sequences in the string.
   228   /// \author Balazs Dezso
   229   class QuotedCharWriter {
   230   public:
   231     typedef char Value;
   232 
   233     /// \brief Constructor for the writer.
   234     ///
   235     /// Constructor for the writer. If the given parameter is true
   236     /// the writer creates escape sequences from special characters.
   237     QuotedCharWriter(bool _escaped = true) : escaped(_escaped) {}
   238 
   239     /// \brief Writes a quoted char to the given stream.
   240     ///
   241     /// Writes a quoted char to the given stream.
   242     void write(std::ostream& os, const char& value) const {
   243       os << "\'";
   244       if (escaped) {
   245 	std::ostringstream ls;
   246         QuotedStringWriter::writeEscape(ls, value);
   247 	os << ls.str();
   248       } else {
   249 	os << value;
   250       }
   251       os << "\'";
   252     }
   253 
   254   private:
   255     bool escaped;
   256   };
   257 
   258   /// \ingroup item_io
   259   /// \brief Writer class for quoted char array.
   260   ///
   261   /// Writer class for quoted char array. It can process the escape
   262   /// sequences in the char array.
   263   /// \author Balazs Dezso
   264   class QuotedCharArrayWriter {
   265   public:
   266     typedef const char* Value;
   267 
   268     /// \brief Constructor for the writer.
   269     ///
   270     /// Constructor for the writer. If the given parameter is true
   271     /// the writer creates escape sequences from special characters.
   272     QuotedCharArrayWriter(bool _escaped = true) : escaped(_escaped) {}
   273 
   274     /// \brief Writes a quoted char array to the given stream.
   275     ///
   276     /// Writes a quoted char array to the given stream.
   277     void write(std::ostream& os, const char* value) const {
   278       QuotedStringWriter(escaped).write(os, std::string(value));
   279     }
   280 
   281   private:    
   282     bool escaped;
   283   };
   284 
   285 
   286   /// \ingroup item_io
   287   ///
   288   /// \brief Writer for standard containers.
   289   ///
   290   /// Writer for each iterable standard containers. The representation
   291   /// of the container is the values enumerated between an open and a
   292   /// close parse. 
   293   ///
   294   /// \author Balazs Dezso
   295   template <
   296     typename _Container, 
   297     typename _ItemWriter = DefaultWriter<typename _Container::value_type> 
   298   >
   299   class IterableWriter {
   300   public:
   301     typedef _Container Value;
   302     typedef _ItemWriter ItemWriter;
   303 
   304   private:
   305 
   306     ItemWriter item_writer;
   307 
   308   public:
   309 
   310     IterableWriter(const ItemWriter& _item_writer = ItemWriter())
   311       : item_writer(_item_writer) {}
   312 
   313     /// \brief Writes the values of the container to the given stream.
   314     ///
   315     /// Writes the values of the container to the given stream.
   316     void write(std::ostream& os, const Value& value) const {
   317       typename Value::const_iterator it;
   318       os << '(';
   319       for (it = value.begin(); it != value.end(); ++it) {
   320 	item_writer.write(os, *it);
   321 	os << ' ';
   322       }
   323       os << ')';
   324     }
   325 
   326   };
   327 
   328   /// \ingroup item_io
   329   ///
   330   /// \brief Writer for standard pairs.
   331   ///
   332   /// Writer for standard pairs. The representation of a pair is
   333   ///\code ( first_value => second_value ) \endcode.
   334   /// \author Balazs Dezso
   335   template <typename _Pair, 
   336 	    typename _FirstWriter = 
   337 	    DefaultWriter<typename _Pair::first_type>,
   338 	    typename _SecondWriter = 
   339 	    DefaultWriter<typename _Pair::second_type> >
   340   class PairWriter {
   341   public:
   342 
   343     typedef _Pair Value;
   344 
   345     typedef _FirstWriter FirstWriter;
   346     typedef _SecondWriter SecondWriter;
   347 
   348   private:
   349 
   350     FirstWriter first_writer;
   351     SecondWriter second_writer;
   352 
   353   public:
   354     
   355     /// \brief Constructor.
   356     ///
   357     /// Constructor for the PairWriter.
   358     PairWriter(const FirstWriter& _first_writer = FirstWriter(), 
   359 	       const SecondWriter& _second_writer = SecondWriter()) 
   360       : first_writer(_first_writer), second_writer(_second_writer) {}
   361     
   362     /// \brief Writes the pair from the given stream.
   363     ///
   364     /// Writes the pair from the given stream.
   365     void write(std::ostream& os, const Value& value) const {
   366       os << "( ";
   367       first_writer.write(os, value.first);
   368       os << " => ";
   369       second_writer.write(os, value.second);
   370       os << " )";
   371     }
   372 
   373   };
   374 
   375   /// \ingroup item_io
   376   /// 
   377   /// \brief The default item writer template class.
   378   ///
   379   /// The default item writer template class. If some section writer
   380   /// needs to write a value to the stream it will give the default way for it.
   381   ///
   382   /// \author Balazs Dezso
   383   template <typename _Value>
   384   class DefaultWriter {
   385   public:
   386     /// The value type.
   387     typedef _Value Value;
   388     /// \brief Writes the value to the given stream.
   389     ///
   390     /// Writes the value to the given stream.
   391     void write(std::ostream& os, const Value& value) const {
   392       os << value;
   393     }
   394   };
   395 
   396   template <>
   397   class DefaultWriter<std::string> {
   398   public:
   399     typedef std::string Value;
   400     
   401     void write(std::ostream& os, const Value& value) const {
   402       if (UnformattedWriter().readable(value)) {
   403         UnformattedWriter().write(os, value);
   404       } else {
   405         QuotedStringWriter().write(os, value);
   406       }
   407     }
   408       
   409   };
   410 
   411   template <>
   412   class DefaultWriter<char> 
   413     : public QuotedCharWriter {};
   414 
   415   template <>
   416   class DefaultWriter<bool> {
   417   public:
   418     typedef bool Value;
   419     
   420     void write(std::ostream& os, const Value& value) const {
   421       os << (value ? "1" : "0");
   422     }
   423       
   424   };
   425 
   426   template <int length>
   427   class DefaultWriter<char[length]> 
   428     : public QuotedCharArrayWriter {};
   429 
   430   template <int length>
   431   class DefaultWriter<const char[length]> 
   432     : public QuotedCharArrayWriter {};
   433 
   434   template <>
   435   class DefaultWriter<char*> 
   436     : public QuotedCharArrayWriter {};
   437 
   438   template <>
   439   class DefaultWriter<const char*> 
   440     : public QuotedCharArrayWriter {};
   441 
   442   template <typename Item>
   443   class DefaultWriter<std::vector<Item> > 
   444     : public IterableWriter<std::vector<Item> > {};
   445 
   446   template <typename Item>
   447   class DefaultWriter<std::deque<Item> > 
   448     : public IterableWriter<std::deque<Item> > {};
   449 
   450   template <typename Item>
   451   class DefaultWriter<std::list<Item> > 
   452     : public IterableWriter<std::list<Item> > {};
   453   
   454   template <typename Item>
   455   class DefaultWriter<std::set<Item> > 
   456     : public IterableWriter<std::set<Item> > {};
   457 
   458   template <typename Key, typename Value>
   459   class DefaultWriter<std::map<Key, Value> > 
   460     : public IterableWriter<std::map<Key, Value> > {};
   461 
   462   template <typename Item>
   463   class DefaultWriter<std::multiset<Item> > 
   464     : public IterableWriter<std::multiset<Item> > {};
   465 
   466   template <typename Key, typename Value>
   467   class DefaultWriter<std::multimap<Key, Value> > 
   468     : public IterableWriter<std::multimap<Key, Value> > {};
   469 
   470   template <typename First, typename Second>
   471   class DefaultWriter<std::pair<First, Second> > 
   472     : public PairWriter<std::pair<First, Second> > {};
   473 
   474   /// \ingroup item_io
   475   /// \brief Standard WriterTraits for the section writers.
   476   ///
   477   /// Standard WriterTraits for the section writers.
   478   /// It defines standard writing method for all type of value. 
   479   /// \author Balazs Dezso
   480   struct DefaultWriterTraits {
   481 
   482     template <typename _Value>
   483     struct Writer : DefaultWriter<_Value> {
   484       typedef DefaultWriter<_Value> Parent;
   485     };
   486 
   487   };
   488 
   489 }
   490 
   491 #endif