lemon/bits/item_reader.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@1408
     1
/* -*- C++ -*-
deba@1408
     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@1408
     8
 *
deba@1408
     9
 * Permission to use, modify and distribute this software is granted
deba@1408
    10
 * provided that this copyright notice appears in all copies. For
deba@1408
    11
 * precise terms see the accompanying LICENSE file.
deba@1408
    12
 *
deba@1408
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@1408
    14
 * express or implied, and with no claim as to its suitability for any
deba@1408
    15
 * purpose.
deba@1408
    16
 *
deba@1408
    17
 */
deba@1408
    18
alpar@1946
    19
/// \ingroup item_io
deba@1408
    20
/// \file
deba@1408
    21
/// \brief Item reader bits for lemon input.
deba@1408
    22
deba@1408
    23
#ifndef LEMON_BITS_ITEM_READER_H
deba@1408
    24
#define LEMON_BITS_ITEM_READER_H
deba@1408
    25
deba@1408
    26
#include <iostream>
deba@1408
    27
#include <string>
deba@1408
    28
deba@1408
    29
#include <vector>
deba@1408
    30
#include <deque>
deba@1408
    31
#include <list>
deba@1408
    32
#include <set>
deba@2426
    33
#include <map>
deba@2426
    34
deba@2426
    35
#include <lemon/error.h>
deba@1408
    36
deba@1408
    37
namespace lemon {
deba@1408
    38
  
deba@1408
    39
  template <typename Value>
deba@1408
    40
  class DefaultReader;
deba@1408
    41
alpar@1946
    42
  /// \ingroup item_io
deba@1408
    43
  ///
deba@2254
    44
  /// \brief Reader class for unformatted strings.
deba@2254
    45
  ///
deba@2254
    46
  /// Reader class for unformatted strings. This class want to be
deba@2254
    47
  /// a general reader type which can read the most 
deba@2254
    48
  ///
deba@2254
    49
  /// \author Balazs Dezso
deba@2254
    50
  class UnformattedReader {
deba@2254
    51
  public:
deba@2254
    52
    /// \brief The value type of reader.
deba@2254
    53
    ///
deba@2254
    54
    /// The value type of reader.
deba@2254
    55
    typedef std::string Value;
deba@2254
    56
    
deba@2254
    57
    /// \brief Constructor for the reader.
deba@2254
    58
    ///
deba@2254
    59
    /// Constructor for the reader.
deba@2254
    60
    UnformattedReader() {} 
deba@2254
    61
    
deba@2254
    62
    /// \brief Reads an unformatted string from the given stream.
deba@2254
    63
    ///
deba@2254
    64
    /// Reads an unformatted string from the given stream.
deba@2254
    65
    void read(std::istream& is, std::string& value) const {
deba@2254
    66
      char c;
deba@2254
    67
      value.clear();
deba@2254
    68
      is >> std::ws;
deba@2254
    69
      while (is.get(c) && !whiteSpace(c)) {
deba@2254
    70
        processChar(c, is, value);
deba@2254
    71
      }
deba@2254
    72
    }
deba@2254
    73
deba@2254
    74
  private:
deba@2254
    75
deba@2254
    76
    void processChar(char c, std::istream& is, Value& value) const {
deba@2254
    77
      switch (c) {
deba@2254
    78
      case '(':
deba@2254
    79
        is.putback(c);
deba@2254
    80
        readParsed('(', ')', is, value);
deba@2254
    81
        break;
deba@2254
    82
      case '[':
deba@2254
    83
        is.putback(c);
deba@2254
    84
        readParsed('[', ']', is, value);
deba@2254
    85
        break;
deba@2254
    86
      case '{':
deba@2254
    87
        is.putback(c);
deba@2254
    88
        readParsed('{', '}', is, value);
deba@2254
    89
        break;
deba@2254
    90
      case '/':
deba@2254
    91
        is.putback(c);
deba@2254
    92
        readParsed('/', '/', is, value);
deba@2254
    93
        break;
deba@2254
    94
      case '\"':
deba@2254
    95
        is.putback(c);
deba@2254
    96
        readQuoted('\"', is, value);
deba@2254
    97
        break;
deba@2254
    98
      case '\'':
deba@2254
    99
        is.putback(c);
deba@2254
   100
        readQuoted('\'', is, value);
deba@2254
   101
        break;
deba@2254
   102
      default:
deba@2254
   103
        value += c;
deba@2254
   104
        break;
deba@2254
   105
      }
deba@2254
   106
    }
deba@2254
   107
deba@2254
   108
    void readParsed(char open, char close, 
deba@2254
   109
                    std::istream& is, Value& value) const {
deba@2254
   110
      char c;
deba@2254
   111
      if (!is.get(c) || c != open)
deba@2254
   112
	throw DataFormatError("Unformatted string format error");
deba@2254
   113
      value += c;
deba@2254
   114
      while (is.get(c) && c != close) {
deba@2254
   115
        processChar(c, is, value);
deba@2254
   116
      }
deba@2254
   117
      if (!is) 
deba@2254
   118
        throw DataFormatError("Unformatted string format error");
deba@2254
   119
      value += c;      
deba@2254
   120
    }
deba@2254
   121
deba@2254
   122
    void readQuoted(char quote, std::istream& is, Value& value) const {
deba@2254
   123
      char c;
deba@2254
   124
      bool esc = false;
deba@2254
   125
      if (!is.get(c) || c != quote)
deba@2254
   126
	throw DataFormatError("Unformatted string format error");
deba@2254
   127
      value += c;
deba@2254
   128
      while (is.get(c) && (c != quote || esc)) {
deba@2254
   129
        if (c == '\\') esc = !esc;
deba@2254
   130
        else esc = false;
deba@2254
   131
        value += c;
deba@2254
   132
      }
deba@2254
   133
      if (!is) 
deba@2254
   134
        throw DataFormatError("Unformatted string format error");
deba@2254
   135
      value += c;
deba@2254
   136
    }
deba@2254
   137
deba@2254
   138
deba@2254
   139
deba@2254
   140
    static bool whiteSpace(char c) {
deba@2254
   141
      return c == ' ' || c == '\t' || c == '\v' || 
deba@2254
   142
        c == '\n' || c == '\r' || c == '\f'; 
deba@2254
   143
    }
deba@2254
   144
deba@2254
   145
    
deba@2254
   146
  };
deba@2254
   147
deba@2254
   148
  /// \ingroup item_io
deba@2254
   149
  ///
deba@1408
   150
  /// \brief Reader class for quoted strings.
deba@1408
   151
  ///
deba@1408
   152
  /// Reader class for quoted strings. It can process the escape
deba@1408
   153
  /// sequences in the string.
deba@1408
   154
  ///
deba@1408
   155
  /// \author Balazs Dezso
deba@1408
   156
  class QuotedStringReader {
deba@2254
   157
    friend class QuotedCharReader;
deba@1408
   158
  public:
deba@1408
   159
    /// \brief The value type of reader.
deba@1408
   160
    ///
deba@1408
   161
    /// The value type of reader.
deba@1408
   162
    typedef std::string Value;
deba@1408
   163
    
deba@1408
   164
    /// \brief Constructor for the reader.
deba@1408
   165
    ///
deba@1408
   166
    /// Constructor for the reader. If the given parameter is true
deba@1408
   167
    /// the reader processes the escape sequences.
deba@1408
   168
    QuotedStringReader(bool _escaped = true) 
deba@1408
   169
      : escaped(_escaped) {}
deba@1408
   170
    
deba@1408
   171
    /// \brief Reads a quoted string from the given stream.
deba@1408
   172
    ///
deba@1408
   173
    /// Reads a quoted string from the given stream.
deba@1408
   174
    void read(std::istream& is, std::string& value) const {
deba@1408
   175
      char c;
deba@1408
   176
      value.clear();
deba@1408
   177
      is >> std::ws;
deba@2426
   178
      if (!is.get(c) || (c != '\"' && c != '\'')) 
deba@2254
   179
	throw DataFormatError("Quoted format error");
deba@2426
   180
      char quote = c;
deba@2426
   181
      while (is.get(c) && c != quote) {
deba@1408
   182
	if (escaped && c == '\\') {
deba@1408
   183
	  value += readEscape(is);
deba@1408
   184
	} else {
deba@1408
   185
	  value += c;
deba@1408
   186
	}
deba@1408
   187
      }
deba@2254
   188
      if (!is) throw DataFormatError("Quoted format error");
deba@1408
   189
    }
deba@1408
   190
deba@1408
   191
  private:
deba@1408
   192
    
deba@1408
   193
    static char readEscape(std::istream& is) {
deba@1408
   194
      char c;
deba@1408
   195
      switch (is.get(c), c) {
deba@1408
   196
      case '\\':
deba@1408
   197
	return '\\';
deba@1408
   198
      case '\"':
deba@1408
   199
	return '\"';
deba@1408
   200
      case '\'':
deba@1408
   201
	return '\'';
deba@1408
   202
      case '\?':
deba@1408
   203
	return '\?';
deba@1408
   204
      case 'a':
deba@1408
   205
	return '\a';
deba@1408
   206
      case 'b':
deba@1408
   207
	return '\b';
deba@1408
   208
      case 'f':
deba@1408
   209
	return '\f';
deba@1408
   210
      case 'n':
deba@1408
   211
	return '\n';
deba@1408
   212
      case 'r':
deba@1408
   213
	return '\r';
deba@1408
   214
      case 't':
deba@1408
   215
	return '\t';
deba@1408
   216
      case 'v':
deba@1408
   217
	return '\v';
deba@1408
   218
      case 'x':
deba@1408
   219
	{
deba@1408
   220
	  int code;
deba@1408
   221
	  if (!is.get(c) || !isHex(c)) 
deba@1408
   222
	    throw DataFormatError("Escape format error");
deba@1408
   223
	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
deba@1408
   224
	  else code = code * 16 + valueHex(c);
deba@1408
   225
	  return code;
deba@1408
   226
	}
deba@1408
   227
      default:
deba@1408
   228
	{
deba@1408
   229
	  int code;
deba@1408
   230
	  if (!isOct(c)) 
deba@1408
   231
	    throw DataFormatError("Escape format error");
deba@1408
   232
	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
deba@1408
   233
	    is.putback(c);
deba@1408
   234
	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
deba@1408
   235
	    is.putback(c);
deba@1408
   236
	  else code = code * 8 + valueOct(c);
deba@1408
   237
	  return code;
deba@1408
   238
	}	      
deba@1408
   239
      } 
deba@1408
   240
    }
deba@1408
   241
deba@1408
   242
    static bool isOct(char c) {
deba@1408
   243
      return '0' <= c && c <='7'; 
deba@1408
   244
    }
deba@1408
   245
    
deba@1408
   246
    static int valueOct(char c) {
deba@1408
   247
      return c - '0';
deba@1408
   248
    }
deba@1408
   249
deba@1408
   250
   static bool isHex(char c) {
deba@1408
   251
      return ('0' <= c && c <= '9') || 
deba@1408
   252
	('a' <= c && c <= 'z') || 
deba@1408
   253
	('A' <= c && c <= 'Z'); 
deba@1408
   254
    }
deba@1408
   255
    
deba@1408
   256
    static int valueHex(char c) {
deba@1408
   257
      if ('0' <= c && c <= '9') return c - '0';
deba@1408
   258
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
deba@1408
   259
      return c - 'A' + 10;
deba@1408
   260
    }
deba@1408
   261
deba@1408
   262
    bool escaped;
deba@1408
   263
  };
deba@1408
   264
alpar@1946
   265
  /// \ingroup item_io
deba@2254
   266
  ///
deba@2254
   267
  /// \brief Reader class for quoted strings.
deba@2254
   268
  ///
deba@2254
   269
  /// Reader class for quoted strings. It can process the escape
deba@2254
   270
  /// sequences in the string.
deba@2254
   271
  ///
deba@2254
   272
  /// \author Balazs Dezso
deba@2254
   273
  class QuotedCharReader {
deba@2254
   274
  public:
deba@2254
   275
    /// \brief The value type of reader.
deba@2254
   276
    ///
deba@2254
   277
    /// The value type of reader.
deba@2254
   278
    typedef char Value;
deba@2254
   279
    
deba@2254
   280
    /// \brief Constructor for the reader.
deba@2254
   281
    ///
deba@2254
   282
    /// Constructor for the reader. If the given parameter is true
deba@2254
   283
    /// the reader processes the escape sequences.
deba@2254
   284
    QuotedCharReader(bool _escaped = true) 
deba@2254
   285
      : escaped(_escaped) {}
deba@2254
   286
    
deba@2254
   287
    /// \brief Reads a quoted string from the given stream.
deba@2254
   288
    ///
deba@2254
   289
    /// Reads a quoted string from the given stream.
deba@2254
   290
    void read(std::istream& is, char& value) const {
deba@2254
   291
      char c;
deba@2254
   292
      is >> std::ws;
deba@2254
   293
      if (!is.get(c) || c != '\'') 
deba@2254
   294
	throw DataFormatError("Quoted format error");
deba@2254
   295
      if (!is.get(c)) 
deba@2254
   296
        throw DataFormatError("Quoted format error");
deba@2254
   297
      if (escaped && c == '\\') {
deba@2254
   298
        value = QuotedStringReader::readEscape(is);
deba@2254
   299
      } else {
deba@2254
   300
        value = c;
deba@2254
   301
      }
deba@2254
   302
      if (!is.get(c) || c != '\'') 
deba@2254
   303
	throw DataFormatError("Quoted format error");
deba@2254
   304
    }
deba@2254
   305
deba@2254
   306
  private:
deba@2254
   307
    bool escaped;
deba@2254
   308
  };
deba@2254
   309
deba@2254
   310
  /// \ingroup item_io
deba@1408
   311
  /// \brief Reader for standard containers.
deba@1408
   312
  ///
deba@1408
   313
  /// Reader for back insertable standard containers. The representation
deba@1408
   314
  /// of the container is the values enumerated between an open and a
deba@1408
   315
  /// close parse. 
deba@1408
   316
  ///
deba@1408
   317
  /// \author Balazs Dezso
deba@1408
   318
  template <
deba@1408
   319
    typename _Container, 
deba@1408
   320
    typename _ItemReader = DefaultReader<typename _Container::value_type> 
deba@1408
   321
  >
deba@1408
   322
  class PushBackReader {
deba@1408
   323
  public:
deba@1408
   324
    typedef _Container Value;
deba@1408
   325
    typedef _ItemReader ItemReader;
deba@1408
   326
deba@1408
   327
  private:
deba@1408
   328
deba@1408
   329
    ItemReader item_reader;
deba@1408
   330
deba@1408
   331
  public:
deba@1408
   332
deba@1852
   333
    /// \brief Constructor for InsertReader
deba@1852
   334
    ///
deba@1852
   335
    /// Constructor for InsertReader
deba@1852
   336
    PushBackReader(const ItemReader& _item_reader = ItemReader())
deba@1852
   337
      : item_reader(_item_reader) {}
deba@1852
   338
deba@1408
   339
    /// \brief Reads the values into the container from the given stream.
deba@1408
   340
    ///
deba@1408
   341
    /// Reads the values into the container from the given stream.
deba@1408
   342
    void read(std::istream& is, Value& value) const {
deba@1408
   343
      char c;
deba@1408
   344
      if (!(is >> c) || c != '(') 
deba@1408
   345
	throw DataFormatError("PushBackReader format error");
deba@1408
   346
      while (is >> c && c != ')') {
deba@1408
   347
	is.putback(c);
deba@1408
   348
	typename ItemReader::Value item;
deba@1408
   349
	item_reader.read(is, item);
deba@1408
   350
	value.push_back(item);
deba@1408
   351
      }
deba@1408
   352
      if (!is) throw DataFormatError("PushBackReader format error");
deba@1408
   353
    }
deba@1408
   354
deba@1408
   355
  };
deba@1408
   356
alpar@1946
   357
  /// \ingroup item_io
deba@1408
   358
  ///
deba@1408
   359
  /// \brief Reader for standard containers.
deba@1408
   360
  ///
deba@1408
   361
  /// Reader for insertable standard containers. The representation
deba@1408
   362
  /// of the container is the values enumerated between an open and a
deba@1408
   363
  /// close parse. 
deba@1408
   364
  ///
deba@1408
   365
  /// \author Balazs Dezso
deba@1408
   366
  template <
deba@1408
   367
    typename _Container, 
deba@1408
   368
    typename _ItemReader = DefaultReader<typename _Container::value_type> 
deba@1408
   369
  >
deba@1408
   370
  class InsertReader {
deba@1408
   371
  public:
deba@1408
   372
    typedef _Container Value;
deba@1408
   373
    typedef _ItemReader ItemReader;
deba@1408
   374
deba@1408
   375
  private:
deba@1408
   376
deba@1408
   377
    ItemReader item_reader;
deba@1408
   378
deba@1408
   379
  public:
deba@1408
   380
deba@1852
   381
    /// \brief Constructor for InsertReader
deba@1852
   382
    ///
deba@1852
   383
    /// Constructor for InsertReader
deba@1852
   384
    InsertReader(const ItemReader& _item_reader = ItemReader())
deba@1852
   385
      : item_reader(_item_reader) {}
deba@1852
   386
deba@1408
   387
    /// \brief Reads the values into the container from the given stream.
deba@1408
   388
    ///
deba@1408
   389
    /// Reads the values into the container from the given stream.
deba@1408
   390
    void read(std::istream& is, Value& value) const {
deba@1408
   391
      char c;
deba@1408
   392
      if (!(is >> c) || c != '(') 
deba@1408
   393
	throw DataFormatError("InsertReader format error");
deba@1408
   394
      while (is >> c && c != ')') {
deba@1408
   395
	is.putback(c);
deba@1408
   396
	typename ItemReader::Value item;
deba@1408
   397
	item_reader.read(is, item);
deba@1408
   398
	value.insert(item);
deba@1408
   399
      }
deba@1408
   400
      if (!is) throw DataFormatError("PushBackReader format error");
deba@1408
   401
    }
deba@1408
   402
deba@1408
   403
  };
deba@1408
   404
alpar@1946
   405
  /// \ingroup item_io
deba@1408
   406
  /// \brief Reader for parsed string.
deba@1408
   407
  ///
deba@1744
   408
  /// Reader for parsed strings. You can define the open and close
deba@1744
   409
  /// parse characters. It reads from the input a character sequence
deba@1744
   410
  /// which is right parsed.
deba@1408
   411
  ///
deba@1408
   412
  /// \author Balazs Dezso
deba@1408
   413
  class ParsedStringReader {
deba@1408
   414
  public:
deba@1408
   415
    typedef std::string Value;
deba@1408
   416
deba@1408
   417
    /// \brief Constructor.
deba@1408
   418
    ///
deba@1408
   419
    /// Constructor for ParsedStringReader. You can give as parameter
deba@1408
   420
    /// the open and close parse characters.
deba@1408
   421
    ParsedStringReader(char _open = '(', char _close = ')')
deba@1408
   422
      : open(_open), close(_close) {}
deba@1408
   423
    
deba@1408
   424
    
deba@1408
   425
    /// \brief Reads the parsed string from the given stream.
deba@1408
   426
    ///
deba@1408
   427
    /// Reads the parsed string from the given stream.
deba@1408
   428
    void read(std::istream& is, Value& value) const {
deba@1408
   429
      char c;
deba@2254
   430
      value.clear();
deba@1408
   431
      if (!(is >> c) || c != open) {
deba@1408
   432
	throw DataFormatError("ParsedStringReader format error");
deba@1408
   433
      }
deba@1408
   434
      value += c;
deba@1408
   435
      int counter = 1;
deba@1408
   436
      while (counter > 0 && is >> c) {
deba@1408
   437
	if (c == close) {
deba@1408
   438
	  --counter;
deba@1408
   439
	} else if (c == open) {
deba@1408
   440
	  ++counter;
deba@1408
   441
	}
deba@1408
   442
	value += c;
deba@1408
   443
      }
deba@1408
   444
      if (!is) {
deba@1408
   445
	throw DataFormatError("ParsedStrinReader format error");
deba@1408
   446
      }
deba@1408
   447
    }
deba@1408
   448
deba@1408
   449
  private:
deba@1408
   450
    char open, close;
deba@1408
   451
deba@1408
   452
  };
deba@1408
   453
alpar@1946
   454
  /// \ingroup item_io
deba@1408
   455
  /// \brief Reader for read the whole line.
deba@1408
   456
  ///
deba@1408
   457
  /// Reader for read the whole line.
deba@1408
   458
  ///
deba@1408
   459
  /// \author Balazs Dezso
deba@1408
   460
  class LineReader {
deba@1408
   461
  public:
deba@1408
   462
    typedef std::string Value;
deba@1408
   463
deba@1408
   464
    /// \brief Constructor.
deba@1408
   465
    ///
deba@1408
   466
    /// Constructor for the LineReader. If the given parameter is
deba@1408
   467
    /// true then the spaces before the first not space character are
deba@1408
   468
    /// skipped.
deba@1408
   469
    LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
deba@1408
   470
    
deba@1408
   471
    /// \brief Reads the line from the given stream.
deba@1408
   472
    ///
deba@1408
   473
    /// Reads the line from the given stream.
deba@1852
   474
    void read(std::istream& is, Value& value) const {
deba@1408
   475
      if (skipSpaces) is >> std::ws;
deba@1408
   476
      if (!getline(is, value)) {
deba@1852
   477
	throw DataFormatError("LineReader format error");
deba@1408
   478
      }
deba@1408
   479
    }
deba@1408
   480
  private:
deba@1408
   481
    bool skipSpaces;
deba@1408
   482
  };
deba@1408
   483
alpar@1946
   484
  /// \ingroup item_io
deba@1852
   485
  /// \brief Reader for std::pair.
deba@1852
   486
  ///
deba@1852
   487
  /// Reader for std::pair.
deba@1852
   488
  ///
deba@1852
   489
  /// \author Balazs Dezso
deba@1852
   490
  template <typename _Pair, 
deba@1852
   491
	    typename _FirstReader = 
deba@1852
   492
	    DefaultReader<typename _Pair::first_type>,
deba@1852
   493
	    typename _SecondReader = 
deba@1852
   494
	    DefaultReader<typename _Pair::second_type> >
deba@1852
   495
  class PairReader {
deba@1852
   496
  public:
deba@1852
   497
    typedef _Pair Value;
deba@1852
   498
deba@1852
   499
    typedef _FirstReader FirstReader;
deba@1852
   500
    typedef _SecondReader SecondReader;
deba@1852
   501
deba@1852
   502
  private:
deba@1852
   503
deba@1852
   504
    FirstReader first_reader;
deba@1852
   505
    SecondReader second_reader;
deba@1852
   506
deba@1852
   507
  public:
deba@1852
   508
    
deba@1852
   509
    /// \brief Constructor.
deba@1852
   510
    ///
deba@1852
   511
    /// Constructor for the PairReader.
deba@1852
   512
    PairReader(const FirstReader& _first_reader = FirstReader(), 
deba@1852
   513
	       const SecondReader& _second_reader = SecondReader()) 
deba@1852
   514
      : first_reader(_first_reader), second_reader(_second_reader) {}
deba@1852
   515
    
deba@1852
   516
    /// \brief Reads the pair from the given stream.
deba@1852
   517
    ///
deba@1852
   518
    /// Reads the pair from the given stream.
deba@1852
   519
    void read(std::istream& is, Value& value) const {
deba@1852
   520
      char c;
deba@1852
   521
      if (!(is >> c) || c != '(') {
deba@1852
   522
	throw DataFormatError("PairReader format error");
deba@1852
   523
      }
deba@1852
   524
      first_reader.read(is, value.first);
deba@1852
   525
      if (!(is >> c) || c != '=') {
deba@1852
   526
	throw DataFormatError("PairReader format error");
deba@1852
   527
      }
deba@1852
   528
      if (!(is >> c) || c != '>') {
deba@1852
   529
	throw DataFormatError("PairReader format error");
deba@1852
   530
      }
deba@1852
   531
      second_reader.read(is, value.second);
deba@1852
   532
      if (!(is >> c) || c != ')') {
deba@1852
   533
	throw DataFormatError("PairReader format error");
deba@1852
   534
      }
deba@1852
   535
    }
deba@1852
   536
  };
deba@1852
   537
alpar@1946
   538
  /// \ingroup item_io
deba@1408
   539
  /// 
deba@1408
   540
  /// \brief The default item reader template class.
deba@1408
   541
  ///
deba@1408
   542
  /// The default item reader template class. If some section reader
deba@1408
   543
  /// needs to read a value from a stream it will give the default way for it.
deba@1408
   544
  ///
deba@1408
   545
  /// \author Balazs Dezso
deba@1408
   546
  template <typename _Value>
deba@1408
   547
  class DefaultReader {
deba@1408
   548
  public:
deba@1408
   549
    /// The value type.
deba@1408
   550
    typedef _Value Value;
deba@1408
   551
    /// \brief Reads a value from the given stream.
deba@1408
   552
    ///
deba@1408
   553
    /// Reads a value from the given stream.
deba@1408
   554
    void read(std::istream& is, Value& value) const {
deba@1408
   555
      if (!(is >> value)) 
deba@1408
   556
	throw DataFormatError("DefaultReader format error");
deba@1408
   557
    }
deba@1408
   558
  };
deba@1408
   559
deba@1427
   560
  template <>
deba@1427
   561
  class DefaultReader<std::string> {
deba@1427
   562
  public:
deba@1427
   563
    typedef std::string Value;
deba@1427
   564
    
deba@1427
   565
    void read(std::istream& is, Value& value) const {
deba@1427
   566
      char c;
deba@2254
   567
      if (!(is >> std::ws >> c)) 
deba@2254
   568
        throw DataFormatError("DefaultReader<string> format error");
deba@1427
   569
      is.putback(c);
deba@1427
   570
      switch (c) {
deba@1427
   571
      case '\"':
deba@1427
   572
	QuotedStringReader().read(is, value);
deba@1427
   573
	break;
deba@1427
   574
      default:
deba@2254
   575
        UnformattedReader().read(is, value);
deba@1427
   576
	break;
deba@1427
   577
      }
deba@1427
   578
    }
deba@1427
   579
    
deba@1427
   580
  };
deba@1427
   581
deba@2254
   582
  template <>
deba@2254
   583
  class DefaultReader<char> {
deba@2254
   584
  public:
deba@2254
   585
    typedef char Value;
deba@2254
   586
    
deba@2254
   587
    void read(std::istream& is, Value& value) const {
deba@2254
   588
      char c;
deba@2254
   589
      if (!(is >> std::ws >> c))
deba@2254
   590
        throw DataFormatError("DefaultReader<char> format error");
deba@2254
   591
      is.putback(c);
deba@2254
   592
      switch (c) {
deba@2254
   593
      case '\'':
deba@2254
   594
	QuotedCharReader().read(is, value);
deba@2254
   595
	break;
deba@2254
   596
      default:
deba@2254
   597
        { 
deba@2254
   598
          int temp;          
deba@2254
   599
          if (!(is >> temp)) 
deba@2254
   600
            throw DataFormatError("DefaultReader<char> format error");
deba@2386
   601
          value = static_cast<char>(temp);
deba@2254
   602
          break;
deba@2254
   603
        }
deba@2254
   604
      }
deba@2254
   605
    }    
deba@2254
   606
  };
deba@2254
   607
deba@2254
   608
  template <>
deba@2254
   609
  class DefaultReader<bool> {
deba@2254
   610
  public:
deba@2254
   611
    typedef bool Value;
deba@2254
   612
    
deba@2254
   613
    void read(std::istream& is, Value& value) const {
deba@2254
   614
      std::string rep;
deba@2254
   615
      if (!(is >> rep))
deba@2254
   616
        throw DataFormatError("DefaultReader<bool> format error");
deba@2254
   617
      if (rep == "true" || rep == "t" || rep == "1") {
deba@2254
   618
        value = true;
deba@2254
   619
      } else if (rep == "false" || rep == "f" || rep == "0") {
deba@2254
   620
        value = false;
deba@2254
   621
      } else throw DataFormatError("DefaultReader<bool> format error");
deba@2254
   622
    }    
deba@2254
   623
  };
deba@2254
   624
deba@1408
   625
  template <typename Item>
deba@1408
   626
  class DefaultReader<std::vector<Item> > 
deba@1408
   627
    : public PushBackReader<std::vector<Item> > {};
deba@1408
   628
deba@1408
   629
  template <typename Item>
deba@1408
   630
  class DefaultReader<std::deque<Item> > 
deba@1408
   631
    : public PushBackReader<std::deque<Item> > {};
deba@1408
   632
deba@1408
   633
  template <typename Item>
deba@1408
   634
  class DefaultReader<std::list<Item> > 
deba@1408
   635
    : public PushBackReader<std::list<Item> > {};
deba@1408
   636
deba@1408
   637
  template <typename Item>
deba@1408
   638
  class DefaultReader<std::set<Item> > 
deba@1408
   639
    : public InsertReader<std::set<Item> > {};
deba@1408
   640
deba@1852
   641
  template <typename Key, typename Value>
deba@1852
   642
  class DefaultReader<std::map<Key, Value> > 
deba@1852
   643
    : public InsertReader<std::map<Key, Value>,
deba@1852
   644
			  DefaultReader<std::pair<Key, Value> > > {};
deba@1852
   645
deba@1408
   646
  template <typename Item>
deba@1408
   647
  class DefaultReader<std::multiset<Item> > 
deba@1408
   648
    : public InsertReader<std::multiset<Item> > {};
deba@1408
   649
deba@1852
   650
  template <typename Key, typename Value>
deba@1852
   651
  class DefaultReader<std::multimap<Key, Value> > 
deba@1852
   652
    : public InsertReader<std::multimap<Key, Value>,
deba@1852
   653
			  DefaultReader<std::pair<Key, Value> > > {};
deba@1852
   654
deba@1852
   655
  template <typename First, typename Second>
deba@1852
   656
  class DefaultReader<std::pair<First, Second> > 
deba@1852
   657
    : public PairReader<std::pair<First, Second> > {};
deba@1852
   658
alpar@1946
   659
  /// \ingroup item_io
deba@1415
   660
  /// 
deba@1415
   661
  /// \brief The default item reader for skipping a value in the stream.
deba@1415
   662
  ///
deba@1415
   663
  /// The default item reader for skipping a value in the stream.
deba@1415
   664
  ///
deba@1415
   665
  /// \author Balazs Dezso
deba@2254
   666
  class DefaultSkipper : public UnformattedReader {};
deba@1415
   667
alpar@1946
   668
  /// \ingroup item_io  
deba@1408
   669
  /// \brief Standard ReaderTraits for the GraphReader class.
deba@1408
   670
  ///
deba@1408
   671
  /// Standard ReaderTraits for the GraphReader class.
deba@1408
   672
  /// It defines standard reading method for all type of value. 
deba@1408
   673
  /// \author Balazs Dezso
deba@1408
   674
  struct DefaultReaderTraits {
deba@1408
   675
deba@1408
   676
    template <typename _Value>
deba@1408
   677
    struct Reader : DefaultReader<_Value> {};
deba@1408
   678
deba@1408
   679
    typedef DefaultSkipper Skipper;
deba@1408
   680
deba@1408
   681
  };
deba@1408
   682
deba@1408
   683
}
deba@1408
   684
deba@1408
   685
#endif