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