src/lemon/bits/item_reader.h
author deba
Wed, 11 May 2005 13:48:39 +0000
changeset 1410 dcfad73b3965
child 1415 2a5810c2f806
permissions -rw-r--r--
Bug fixes.
deba@1408
     1
/* -*- C++ -*-
deba@1408
     2
 * src/lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
deba@1408
     3
 *
deba@1408
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1408
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1408
     6
 *
deba@1408
     7
 * Permission to use, modify and distribute this software is granted
deba@1408
     8
 * provided that this copyright notice appears in all copies. For
deba@1408
     9
 * precise terms see the accompanying LICENSE file.
deba@1408
    10
 *
deba@1408
    11
 * This software is provided "AS IS" with no warranty of any kind,
deba@1408
    12
 * express or implied, and with no claim as to its suitability for any
deba@1408
    13
 * purpose.
deba@1408
    14
 *
deba@1408
    15
 */
deba@1408
    16
deba@1408
    17
/// \ingroup io_group
deba@1408
    18
/// \file
deba@1408
    19
/// \brief Item reader bits for lemon input.
deba@1408
    20
deba@1408
    21
#ifndef LEMON_BITS_ITEM_READER_H
deba@1408
    22
#define LEMON_BITS_ITEM_READER_H
deba@1408
    23
deba@1408
    24
#include <iostream>
deba@1408
    25
#include <string>
deba@1408
    26
deba@1408
    27
#include <vector>
deba@1408
    28
#include <deque>
deba@1408
    29
#include <list>
deba@1408
    30
#include <set>
deba@1408
    31
deba@1408
    32
namespace lemon {
deba@1408
    33
  
deba@1408
    34
  template <typename Value>
deba@1408
    35
  class DefaultReader;
deba@1408
    36
deba@1408
    37
  /// \ingroup io_group
deba@1408
    38
  ///
deba@1408
    39
  /// \brief Reader class for quoted strings.
deba@1408
    40
  ///
deba@1408
    41
  /// Reader class for quoted strings. It can process the escape
deba@1408
    42
  /// sequences in the string.
deba@1408
    43
  ///
deba@1408
    44
  /// \author Balazs Dezso
deba@1408
    45
  class QuotedStringReader {
deba@1408
    46
  public:
deba@1408
    47
    /// \brief The value type of reader.
deba@1408
    48
    ///
deba@1408
    49
    /// The value type of reader.
deba@1408
    50
    typedef std::string Value;
deba@1408
    51
    
deba@1408
    52
    /// \brief Constructor for the reader.
deba@1408
    53
    ///
deba@1408
    54
    /// Constructor for the reader. If the given parameter is true
deba@1408
    55
    /// the reader processes the escape sequences.
deba@1408
    56
    QuotedStringReader(bool _escaped = true) 
deba@1408
    57
      : escaped(_escaped) {}
deba@1408
    58
    
deba@1408
    59
    /// \brief Reads a quoted string from the given stream.
deba@1408
    60
    ///
deba@1408
    61
    /// Reads a quoted string from the given stream.
deba@1408
    62
    void read(std::istream& is, std::string& value) const {
deba@1408
    63
      char c;
deba@1408
    64
      value.clear();
deba@1408
    65
      is >> std::ws;
deba@1408
    66
      if (!is.get(c) || c != '\"') 
deba@1408
    67
	throw DataFormatError("Quoted string format error");
deba@1408
    68
      while (is.get(c) && c != '\"') {
deba@1408
    69
	if (escaped && c == '\\') {
deba@1408
    70
	  value += readEscape(is);
deba@1408
    71
	} else {
deba@1408
    72
	  value += c;
deba@1408
    73
	}
deba@1408
    74
      }
deba@1408
    75
      if (!is) throw DataFormatError("Quoted string format error");
deba@1408
    76
    }
deba@1408
    77
deba@1408
    78
  private:
deba@1408
    79
    
deba@1408
    80
    static char readEscape(std::istream& is) {
deba@1408
    81
      char c;
deba@1408
    82
      switch (is.get(c), c) {
deba@1408
    83
      case '\\':
deba@1408
    84
	return '\\';
deba@1408
    85
      case '\"':
deba@1408
    86
	return '\"';
deba@1408
    87
      case '\'':
deba@1408
    88
	return '\'';
deba@1408
    89
      case '\?':
deba@1408
    90
	return '\?';
deba@1408
    91
      case 'a':
deba@1408
    92
	return '\a';
deba@1408
    93
      case 'b':
deba@1408
    94
	return '\b';
deba@1408
    95
      case 'f':
deba@1408
    96
	return '\f';
deba@1408
    97
      case 'n':
deba@1408
    98
	return '\n';
deba@1408
    99
      case 'r':
deba@1408
   100
	return '\r';
deba@1408
   101
      case 't':
deba@1408
   102
	return '\t';
deba@1408
   103
      case 'v':
deba@1408
   104
	return '\v';
deba@1408
   105
      case 'x':
deba@1408
   106
	{
deba@1408
   107
	  int code;
deba@1408
   108
	  if (!is.get(c) || !isHex(c)) 
deba@1408
   109
	    throw DataFormatError("Escape format error");
deba@1408
   110
	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
deba@1408
   111
	  else code = code * 16 + valueHex(c);
deba@1408
   112
	  return code;
deba@1408
   113
	}
deba@1408
   114
      default:
deba@1408
   115
	{
deba@1408
   116
	  int code;
deba@1408
   117
	  if (!isOct(c)) 
deba@1408
   118
	    throw DataFormatError("Escape format error");
deba@1408
   119
	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
deba@1408
   120
	    is.putback(c);
deba@1408
   121
	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
deba@1408
   122
	    is.putback(c);
deba@1408
   123
	  else code = code * 8 + valueOct(c);
deba@1408
   124
	  return code;
deba@1408
   125
	}	      
deba@1408
   126
      } 
deba@1408
   127
    }
deba@1408
   128
deba@1408
   129
    static bool isOct(char c) {
deba@1408
   130
      return '0' <= c && c <='7'; 
deba@1408
   131
    }
deba@1408
   132
    
deba@1408
   133
    static int valueOct(char c) {
deba@1408
   134
      return c - '0';
deba@1408
   135
    }
deba@1408
   136
deba@1408
   137
   static bool isHex(char c) {
deba@1408
   138
      return ('0' <= c && c <= '9') || 
deba@1408
   139
	('a' <= c && c <= 'z') || 
deba@1408
   140
	('A' <= c && c <= 'Z'); 
deba@1408
   141
    }
deba@1408
   142
    
deba@1408
   143
    static int valueHex(char c) {
deba@1408
   144
      if ('0' <= c && c <= '9') return c - '0';
deba@1408
   145
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
deba@1408
   146
      return c - 'A' + 10;
deba@1408
   147
    }
deba@1408
   148
deba@1408
   149
    bool escaped;
deba@1408
   150
  };
deba@1408
   151
deba@1408
   152
  /// \ingroup io_group
deba@1408
   153
  /// \brief Reader for standard containers.
deba@1408
   154
  ///
deba@1408
   155
  /// Reader for back insertable standard containers. The representation
deba@1408
   156
  /// of the container is the values enumerated between an open and a
deba@1408
   157
  /// close parse. 
deba@1408
   158
  ///
deba@1408
   159
  /// \author Balazs Dezso
deba@1408
   160
  template <
deba@1408
   161
    typename _Container, 
deba@1408
   162
    typename _ItemReader = DefaultReader<typename _Container::value_type> 
deba@1408
   163
  >
deba@1408
   164
  class PushBackReader {
deba@1408
   165
  public:
deba@1408
   166
    typedef _Container Value;
deba@1408
   167
    typedef _ItemReader ItemReader;
deba@1408
   168
deba@1408
   169
  private:
deba@1408
   170
deba@1408
   171
    ItemReader item_reader;
deba@1408
   172
deba@1408
   173
  public:
deba@1408
   174
deba@1408
   175
    /// \brief Reads the values into the container from the given stream.
deba@1408
   176
    ///
deba@1408
   177
    /// Reads the values into the container from the given stream.
deba@1408
   178
    void read(std::istream& is, Value& value) const {
deba@1408
   179
      char c;
deba@1408
   180
      if (!(is >> c) || c != '(') 
deba@1408
   181
	throw DataFormatError("PushBackReader format error");
deba@1408
   182
      while (is >> c && c != ')') {
deba@1408
   183
	is.putback(c);
deba@1408
   184
	typename ItemReader::Value item;
deba@1408
   185
	item_reader.read(is, item);
deba@1408
   186
	value.push_back(item);
deba@1408
   187
      }
deba@1408
   188
      if (!is) throw DataFormatError("PushBackReader format error");
deba@1408
   189
      is.putback(c);
deba@1408
   190
    }
deba@1408
   191
deba@1408
   192
  };
deba@1408
   193
deba@1408
   194
  /// \ingroup io_group
deba@1408
   195
  ///
deba@1408
   196
  /// \brief Reader for standard containers.
deba@1408
   197
  ///
deba@1408
   198
  /// Reader for insertable standard containers. The representation
deba@1408
   199
  /// of the container is the values enumerated between an open and a
deba@1408
   200
  /// close parse. 
deba@1408
   201
  ///
deba@1408
   202
  /// \author Balazs Dezso
deba@1408
   203
  template <
deba@1408
   204
    typename _Container, 
deba@1408
   205
    typename _ItemReader = DefaultReader<typename _Container::value_type> 
deba@1408
   206
  >
deba@1408
   207
  class InsertReader {
deba@1408
   208
  public:
deba@1408
   209
    typedef _Container Value;
deba@1408
   210
    typedef _ItemReader ItemReader;
deba@1408
   211
deba@1408
   212
  private:
deba@1408
   213
deba@1408
   214
    ItemReader item_reader;
deba@1408
   215
deba@1408
   216
  public:
deba@1408
   217
deba@1408
   218
    /// \brief Reads the values into the container from the given stream.
deba@1408
   219
    ///
deba@1408
   220
    /// Reads the values into the container from the given stream.
deba@1408
   221
    void read(std::istream& is, Value& value) const {
deba@1408
   222
      char c;
deba@1408
   223
      if (!(is >> c) || c != '(') 
deba@1408
   224
	throw DataFormatError("InsertReader format error");
deba@1408
   225
      while (is >> c && c != ')') {
deba@1408
   226
	is.putback(c);
deba@1408
   227
	typename ItemReader::Value item;
deba@1408
   228
	item_reader.read(is, item);
deba@1408
   229
	value.insert(item);
deba@1408
   230
      }
deba@1408
   231
      if (!is) throw DataFormatError("PushBackReader format error");
deba@1408
   232
      is.putback(c);
deba@1408
   233
    }
deba@1408
   234
deba@1408
   235
  };
deba@1408
   236
deba@1408
   237
  /// \ingroup io_group
deba@1408
   238
  /// \brief Reader for parsed string.
deba@1408
   239
  ///
deba@1408
   240
  /// Reader for parsed strings. You can give the open and close
deba@1408
   241
  /// parse characters.
deba@1408
   242
  ///
deba@1408
   243
  /// \author Balazs Dezso
deba@1408
   244
  class ParsedStringReader {
deba@1408
   245
  public:
deba@1408
   246
    typedef std::string Value;
deba@1408
   247
deba@1408
   248
    /// \brief Constructor.
deba@1408
   249
    ///
deba@1408
   250
    /// Constructor for ParsedStringReader. You can give as parameter
deba@1408
   251
    /// the open and close parse characters.
deba@1408
   252
    ParsedStringReader(char _open = '(', char _close = ')')
deba@1408
   253
      : open(_open), close(_close) {}
deba@1408
   254
    
deba@1408
   255
    
deba@1408
   256
    /// \brief Reads the parsed string from the given stream.
deba@1408
   257
    ///
deba@1408
   258
    /// Reads the parsed string from the given stream.
deba@1408
   259
    void read(std::istream& is, Value& value) const {
deba@1408
   260
      char c;
deba@1408
   261
      if (!(is >> c) || c != open) {
deba@1408
   262
	throw DataFormatError("ParsedStringReader format error");
deba@1408
   263
      }
deba@1408
   264
      value += c;
deba@1408
   265
      int counter = 1;
deba@1408
   266
      while (counter > 0 && is >> c) {
deba@1408
   267
	if (c == close) {
deba@1408
   268
	  --counter;
deba@1408
   269
	} else if (c == open) {
deba@1408
   270
	  ++counter;
deba@1408
   271
	}
deba@1408
   272
	value += c;
deba@1408
   273
      }
deba@1408
   274
      if (!is) {
deba@1408
   275
	throw DataFormatError("ParsedStrinReader format error");
deba@1408
   276
      }
deba@1408
   277
    }
deba@1408
   278
deba@1408
   279
  private:
deba@1408
   280
    char open, close;
deba@1408
   281
deba@1408
   282
  };
deba@1408
   283
deba@1408
   284
  /// \ingroup io_group
deba@1408
   285
  /// \brief Reader for read the whole line.
deba@1408
   286
  ///
deba@1408
   287
  /// Reader for read the whole line.
deba@1408
   288
  ///
deba@1408
   289
  /// \author Balazs Dezso
deba@1408
   290
  class LineReader {
deba@1408
   291
  public:
deba@1408
   292
    typedef std::string Value;
deba@1408
   293
deba@1408
   294
    /// \brief Constructor.
deba@1408
   295
    ///
deba@1408
   296
    /// Constructor for the LineReader. If the given parameter is
deba@1408
   297
    /// true then the spaces before the first not space character are
deba@1408
   298
    /// skipped.
deba@1408
   299
    LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
deba@1408
   300
    
deba@1408
   301
    /// \brief Reads the line from the given stream.
deba@1408
   302
    ///
deba@1408
   303
    /// Reads the line from the given stream.
deba@1408
   304
    void read(std::istream& is, Value& value) {
deba@1408
   305
      if (skipSpaces) is >> std::ws;
deba@1408
   306
      if (!getline(is, value)) {
deba@1408
   307
	throw DataFormatError("LineReader forma error");
deba@1408
   308
      }
deba@1408
   309
    }
deba@1408
   310
  private:
deba@1408
   311
    bool skipSpaces;
deba@1408
   312
  };
deba@1408
   313
deba@1408
   314
  /// \ingroup io_group
deba@1408
   315
  /// 
deba@1408
   316
  /// \brief The default item reader template class.
deba@1408
   317
  ///
deba@1408
   318
  /// The default item reader template class. If some section reader
deba@1408
   319
  /// needs to read a value from a stream it will give the default way for it.
deba@1408
   320
  ///
deba@1408
   321
  /// \author Balazs Dezso
deba@1408
   322
  template <typename _Value>
deba@1408
   323
  class DefaultReader {
deba@1408
   324
  public:
deba@1408
   325
    /// The value type.
deba@1408
   326
    typedef _Value Value;
deba@1408
   327
    /// \brief Reads a value from the given stream.
deba@1408
   328
    ///
deba@1408
   329
    /// Reads a value from the given stream.
deba@1408
   330
    void read(std::istream& is, Value& value) const {
deba@1408
   331
      if (!(is >> value)) 
deba@1408
   332
	throw DataFormatError("DefaultReader format error");
deba@1408
   333
    }
deba@1408
   334
  };
deba@1408
   335
deba@1408
   336
  template <typename Item>
deba@1408
   337
  class DefaultReader<std::vector<Item> > 
deba@1408
   338
    : public PushBackReader<std::vector<Item> > {};
deba@1408
   339
deba@1408
   340
  template <typename Item>
deba@1408
   341
  class DefaultReader<std::deque<Item> > 
deba@1408
   342
    : public PushBackReader<std::deque<Item> > {};
deba@1408
   343
deba@1408
   344
  template <typename Item>
deba@1408
   345
  class DefaultReader<std::list<Item> > 
deba@1408
   346
    : public PushBackReader<std::list<Item> > {};
deba@1408
   347
deba@1408
   348
  template <typename Item>
deba@1408
   349
  class DefaultReader<std::set<Item> > 
deba@1408
   350
    : public InsertReader<std::set<Item> > {};
deba@1408
   351
deba@1408
   352
  template <typename Item>
deba@1408
   353
  class DefaultReader<std::multiset<Item> > 
deba@1408
   354
    : public InsertReader<std::multiset<Item> > {};
deba@1408
   355
deba@1408
   356
  /// \ingroup io_group
deba@1408
   357
  class DefaultSkipper {
deba@1408
   358
  public:
deba@1408
   359
    typedef std::string Value;
deba@1408
   360
    
deba@1408
   361
    void read(std::istream& is, Value& value) const {
deba@1408
   362
      char c;
deba@1408
   363
      if (!(is >> c)) return;
deba@1408
   364
      is.putback(c);
deba@1408
   365
      switch (c) {
deba@1408
   366
      case '\"':
deba@1408
   367
	QuotedStringReader().read(is, value);
deba@1408
   368
	break;
deba@1408
   369
      case '(':
deba@1408
   370
	ParsedStringReader().read(is, value);
deba@1408
   371
	break;
deba@1408
   372
      default:
deba@1408
   373
	DefaultReader<std::string>().read(is, value); 
deba@1408
   374
	break;
deba@1408
   375
      }
deba@1408
   376
    }
deba@1408
   377
  };
deba@1408
   378
  
deba@1408
   379
  /// \brief Standard ReaderTraits for the GraphReader class.
deba@1408
   380
  ///
deba@1408
   381
  /// Standard ReaderTraits for the GraphReader class.
deba@1408
   382
  /// It defines standard reading method for all type of value. 
deba@1408
   383
  /// \author Balazs Dezso
deba@1408
   384
  struct DefaultReaderTraits {
deba@1408
   385
deba@1408
   386
    template <typename _Value>
deba@1408
   387
    struct Reader : DefaultReader<_Value> {};
deba@1408
   388
deba@1408
   389
    typedef DefaultSkipper Skipper;
deba@1408
   390
deba@1408
   391
  };
deba@1408
   392
deba@1408
   393
}
deba@1408
   394
deba@1408
   395
#endif