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