lemon/bits/item_reader.h
author deba
Wed, 01 Mar 2006 10:25:30 +0000
changeset 1991 d7442141d9ef
parent 1946 17eb3eaad9f8
child 2016 ecb067198349
permissions -rw-r--r--
The graph adadptors can be alteration observed.
In most cases it uses the adapted graph alteration notifiers.
Only special case is now the UndirGraphAdaptor, where
we have to proxy the signals from the graph.

The SubBidirGraphAdaptor is removed, because it doest not
gives more feature than the EdgeSubGraphAdaptor<UndirGraphAdaptor<Graph>>.

The ResGraphAdaptor is based on this composition.
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@1956
     5
 * Copyright (C) 2003-2006
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
deba@1910
    19
/// @defgroin item_io Item Readers and Writers
alpar@1946
    20
/// @ingroup io_groin
deba@1415
    21
/// \brief Item Readers and Writers
deba@1415
    22
/// 
deba@1415
    23
/// The Input-Output classes can handle more data type by example
deba@1415
    24
/// as map or attribute value. Each of these should be written and
deba@1415
    25
/// read some way. The module make possible to do this.  
deba@1415
    26
alpar@1946
    27
/// \ingroup item_io
deba@1408
    28
/// \file
deba@1408
    29
/// \brief Item reader bits for lemon input.
deba@1408
    30
deba@1408
    31
#ifndef LEMON_BITS_ITEM_READER_H
deba@1408
    32
#define LEMON_BITS_ITEM_READER_H
deba@1408
    33
deba@1408
    34
#include <iostream>
deba@1408
    35
#include <string>
deba@1408
    36
deba@1408
    37
#include <vector>
deba@1408
    38
#include <deque>
deba@1408
    39
#include <list>
deba@1408
    40
#include <set>
deba@1408
    41
deba@1408
    42
namespace lemon {
deba@1408
    43
  
deba@1408
    44
  template <typename Value>
deba@1408
    45
  class DefaultReader;
deba@1408
    46
alpar@1946
    47
  /// \ingroup item_io
deba@1408
    48
  ///
deba@1408
    49
  /// \brief Reader class for quoted strings.
deba@1408
    50
  ///
deba@1408
    51
  /// Reader class for quoted strings. It can process the escape
deba@1408
    52
  /// sequences in the string.
deba@1408
    53
  ///
deba@1408
    54
  /// \author Balazs Dezso
deba@1408
    55
  class QuotedStringReader {
deba@1408
    56
  public:
deba@1408
    57
    /// \brief The value type of reader.
deba@1408
    58
    ///
deba@1408
    59
    /// The value type of reader.
deba@1408
    60
    typedef std::string Value;
deba@1408
    61
    
deba@1408
    62
    /// \brief Constructor for the reader.
deba@1408
    63
    ///
deba@1408
    64
    /// Constructor for the reader. If the given parameter is true
deba@1408
    65
    /// the reader processes the escape sequences.
deba@1408
    66
    QuotedStringReader(bool _escaped = true) 
deba@1408
    67
      : escaped(_escaped) {}
deba@1408
    68
    
deba@1408
    69
    /// \brief Reads a quoted string from the given stream.
deba@1408
    70
    ///
deba@1408
    71
    /// Reads a quoted string from the given stream.
deba@1408
    72
    void read(std::istream& is, std::string& value) const {
deba@1408
    73
      char c;
deba@1408
    74
      value.clear();
deba@1408
    75
      is >> std::ws;
deba@1408
    76
      if (!is.get(c) || c != '\"') 
deba@1408
    77
	throw DataFormatError("Quoted string format error");
deba@1408
    78
      while (is.get(c) && c != '\"') {
deba@1408
    79
	if (escaped && c == '\\') {
deba@1408
    80
	  value += readEscape(is);
deba@1408
    81
	} else {
deba@1408
    82
	  value += c;
deba@1408
    83
	}
deba@1408
    84
      }
deba@1408
    85
      if (!is) throw DataFormatError("Quoted string format error");
deba@1408
    86
    }
deba@1408
    87
deba@1408
    88
  private:
deba@1408
    89
    
deba@1408
    90
    static char readEscape(std::istream& is) {
deba@1408
    91
      char c;
deba@1408
    92
      switch (is.get(c), c) {
deba@1408
    93
      case '\\':
deba@1408
    94
	return '\\';
deba@1408
    95
      case '\"':
deba@1408
    96
	return '\"';
deba@1408
    97
      case '\'':
deba@1408
    98
	return '\'';
deba@1408
    99
      case '\?':
deba@1408
   100
	return '\?';
deba@1408
   101
      case 'a':
deba@1408
   102
	return '\a';
deba@1408
   103
      case 'b':
deba@1408
   104
	return '\b';
deba@1408
   105
      case 'f':
deba@1408
   106
	return '\f';
deba@1408
   107
      case 'n':
deba@1408
   108
	return '\n';
deba@1408
   109
      case 'r':
deba@1408
   110
	return '\r';
deba@1408
   111
      case 't':
deba@1408
   112
	return '\t';
deba@1408
   113
      case 'v':
deba@1408
   114
	return '\v';
deba@1408
   115
      case 'x':
deba@1408
   116
	{
deba@1408
   117
	  int code;
deba@1408
   118
	  if (!is.get(c) || !isHex(c)) 
deba@1408
   119
	    throw DataFormatError("Escape format error");
deba@1408
   120
	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
deba@1408
   121
	  else code = code * 16 + valueHex(c);
deba@1408
   122
	  return code;
deba@1408
   123
	}
deba@1408
   124
      default:
deba@1408
   125
	{
deba@1408
   126
	  int code;
deba@1408
   127
	  if (!isOct(c)) 
deba@1408
   128
	    throw DataFormatError("Escape format error");
deba@1408
   129
	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
deba@1408
   130
	    is.putback(c);
deba@1408
   131
	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
deba@1408
   132
	    is.putback(c);
deba@1408
   133
	  else code = code * 8 + valueOct(c);
deba@1408
   134
	  return code;
deba@1408
   135
	}	      
deba@1408
   136
      } 
deba@1408
   137
    }
deba@1408
   138
deba@1408
   139
    static bool isOct(char c) {
deba@1408
   140
      return '0' <= c && c <='7'; 
deba@1408
   141
    }
deba@1408
   142
    
deba@1408
   143
    static int valueOct(char c) {
deba@1408
   144
      return c - '0';
deba@1408
   145
    }
deba@1408
   146
deba@1408
   147
   static bool isHex(char c) {
deba@1408
   148
      return ('0' <= c && c <= '9') || 
deba@1408
   149
	('a' <= c && c <= 'z') || 
deba@1408
   150
	('A' <= c && c <= 'Z'); 
deba@1408
   151
    }
deba@1408
   152
    
deba@1408
   153
    static int valueHex(char c) {
deba@1408
   154
      if ('0' <= c && c <= '9') return c - '0';
deba@1408
   155
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
deba@1408
   156
      return c - 'A' + 10;
deba@1408
   157
    }
deba@1408
   158
deba@1408
   159
    bool escaped;
deba@1408
   160
  };
deba@1408
   161
alpar@1946
   162
  /// \ingroup item_io
deba@1408
   163
  /// \brief Reader for standard containers.
deba@1408
   164
  ///
deba@1408
   165
  /// Reader for back insertable standard containers. The representation
deba@1408
   166
  /// of the container is the values enumerated between an open and a
deba@1408
   167
  /// close parse. 
deba@1408
   168
  ///
deba@1408
   169
  /// \author Balazs Dezso
deba@1408
   170
  template <
deba@1408
   171
    typename _Container, 
deba@1408
   172
    typename _ItemReader = DefaultReader<typename _Container::value_type> 
deba@1408
   173
  >
deba@1408
   174
  class PushBackReader {
deba@1408
   175
  public:
deba@1408
   176
    typedef _Container Value;
deba@1408
   177
    typedef _ItemReader ItemReader;
deba@1408
   178
deba@1408
   179
  private:
deba@1408
   180
deba@1408
   181
    ItemReader item_reader;
deba@1408
   182
deba@1408
   183
  public:
deba@1408
   184
deba@1852
   185
    /// \brief Constructor for InsertReader
deba@1852
   186
    ///
deba@1852
   187
    /// Constructor for InsertReader
deba@1852
   188
    PushBackReader(const ItemReader& _item_reader = ItemReader())
deba@1852
   189
      : item_reader(_item_reader) {}
deba@1852
   190
deba@1408
   191
    /// \brief Reads the values into the container from the given stream.
deba@1408
   192
    ///
deba@1408
   193
    /// Reads the values into the container from the given stream.
deba@1408
   194
    void read(std::istream& is, Value& value) const {
deba@1408
   195
      char c;
deba@1408
   196
      if (!(is >> c) || c != '(') 
deba@1408
   197
	throw DataFormatError("PushBackReader format error");
deba@1408
   198
      while (is >> c && c != ')') {
deba@1408
   199
	is.putback(c);
deba@1408
   200
	typename ItemReader::Value item;
deba@1408
   201
	item_reader.read(is, item);
deba@1408
   202
	value.push_back(item);
deba@1408
   203
      }
deba@1408
   204
      if (!is) throw DataFormatError("PushBackReader format error");
deba@1408
   205
    }
deba@1408
   206
deba@1408
   207
  };
deba@1408
   208
alpar@1946
   209
  /// \ingroup item_io
deba@1408
   210
  ///
deba@1408
   211
  /// \brief Reader for standard containers.
deba@1408
   212
  ///
deba@1408
   213
  /// Reader for insertable standard containers. The representation
deba@1408
   214
  /// of the container is the values enumerated between an open and a
deba@1408
   215
  /// close parse. 
deba@1408
   216
  ///
deba@1408
   217
  /// \author Balazs Dezso
deba@1408
   218
  template <
deba@1408
   219
    typename _Container, 
deba@1408
   220
    typename _ItemReader = DefaultReader<typename _Container::value_type> 
deba@1408
   221
  >
deba@1408
   222
  class InsertReader {
deba@1408
   223
  public:
deba@1408
   224
    typedef _Container Value;
deba@1408
   225
    typedef _ItemReader ItemReader;
deba@1408
   226
deba@1408
   227
  private:
deba@1408
   228
deba@1408
   229
    ItemReader item_reader;
deba@1408
   230
deba@1408
   231
  public:
deba@1408
   232
deba@1852
   233
    /// \brief Constructor for InsertReader
deba@1852
   234
    ///
deba@1852
   235
    /// Constructor for InsertReader
deba@1852
   236
    InsertReader(const ItemReader& _item_reader = ItemReader())
deba@1852
   237
      : item_reader(_item_reader) {}
deba@1852
   238
deba@1408
   239
    /// \brief Reads the values into the container from the given stream.
deba@1408
   240
    ///
deba@1408
   241
    /// Reads the values into the container from the given stream.
deba@1408
   242
    void read(std::istream& is, Value& value) const {
deba@1408
   243
      char c;
deba@1408
   244
      if (!(is >> c) || c != '(') 
deba@1408
   245
	throw DataFormatError("InsertReader format error");
deba@1408
   246
      while (is >> c && c != ')') {
deba@1408
   247
	is.putback(c);
deba@1408
   248
	typename ItemReader::Value item;
deba@1408
   249
	item_reader.read(is, item);
deba@1408
   250
	value.insert(item);
deba@1408
   251
      }
deba@1408
   252
      if (!is) throw DataFormatError("PushBackReader format error");
deba@1408
   253
    }
deba@1408
   254
deba@1408
   255
  };
deba@1408
   256
alpar@1946
   257
  /// \ingroup item_io
deba@1408
   258
  /// \brief Reader for parsed string.
deba@1408
   259
  ///
deba@1744
   260
  /// Reader for parsed strings. You can define the open and close
deba@1744
   261
  /// parse characters. It reads from the input a character sequence
deba@1744
   262
  /// which is right parsed.
deba@1408
   263
  ///
deba@1408
   264
  /// \author Balazs Dezso
deba@1408
   265
  class ParsedStringReader {
deba@1408
   266
  public:
deba@1408
   267
    typedef std::string Value;
deba@1408
   268
deba@1408
   269
    /// \brief Constructor.
deba@1408
   270
    ///
deba@1408
   271
    /// Constructor for ParsedStringReader. You can give as parameter
deba@1408
   272
    /// the open and close parse characters.
deba@1408
   273
    ParsedStringReader(char _open = '(', char _close = ')')
deba@1408
   274
      : open(_open), close(_close) {}
deba@1408
   275
    
deba@1408
   276
    
deba@1408
   277
    /// \brief Reads the parsed string from the given stream.
deba@1408
   278
    ///
deba@1408
   279
    /// Reads the parsed string from the given stream.
deba@1408
   280
    void read(std::istream& is, Value& value) const {
deba@1408
   281
      char c;
deba@1408
   282
      if (!(is >> c) || c != open) {
deba@1408
   283
	throw DataFormatError("ParsedStringReader format error");
deba@1408
   284
      }
deba@1408
   285
      value += c;
deba@1408
   286
      int counter = 1;
deba@1408
   287
      while (counter > 0 && is >> c) {
deba@1408
   288
	if (c == close) {
deba@1408
   289
	  --counter;
deba@1408
   290
	} else if (c == open) {
deba@1408
   291
	  ++counter;
deba@1408
   292
	}
deba@1408
   293
	value += c;
deba@1408
   294
      }
deba@1408
   295
      if (!is) {
deba@1408
   296
	throw DataFormatError("ParsedStrinReader format error");
deba@1408
   297
      }
deba@1408
   298
    }
deba@1408
   299
deba@1408
   300
  private:
deba@1408
   301
    char open, close;
deba@1408
   302
deba@1408
   303
  };
deba@1408
   304
alpar@1946
   305
  /// \ingroup item_io
deba@1408
   306
  /// \brief Reader for read the whole line.
deba@1408
   307
  ///
deba@1408
   308
  /// Reader for read the whole line.
deba@1408
   309
  ///
deba@1408
   310
  /// \author Balazs Dezso
deba@1408
   311
  class LineReader {
deba@1408
   312
  public:
deba@1408
   313
    typedef std::string Value;
deba@1408
   314
deba@1408
   315
    /// \brief Constructor.
deba@1408
   316
    ///
deba@1408
   317
    /// Constructor for the LineReader. If the given parameter is
deba@1408
   318
    /// true then the spaces before the first not space character are
deba@1408
   319
    /// skipped.
deba@1408
   320
    LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
deba@1408
   321
    
deba@1408
   322
    /// \brief Reads the line from the given stream.
deba@1408
   323
    ///
deba@1408
   324
    /// Reads the line from the given stream.
deba@1852
   325
    void read(std::istream& is, Value& value) const {
deba@1408
   326
      if (skipSpaces) is >> std::ws;
deba@1408
   327
      if (!getline(is, value)) {
deba@1852
   328
	throw DataFormatError("LineReader format error");
deba@1408
   329
      }
deba@1408
   330
    }
deba@1408
   331
  private:
deba@1408
   332
    bool skipSpaces;
deba@1408
   333
  };
deba@1408
   334
alpar@1946
   335
  /// \ingroup item_io
deba@1852
   336
  /// \brief Reader for std::pair.
deba@1852
   337
  ///
deba@1852
   338
  /// Reader for std::pair.
deba@1852
   339
  ///
deba@1852
   340
  /// \author Balazs Dezso
deba@1852
   341
  template <typename _Pair, 
deba@1852
   342
	    typename _FirstReader = 
deba@1852
   343
	    DefaultReader<typename _Pair::first_type>,
deba@1852
   344
	    typename _SecondReader = 
deba@1852
   345
	    DefaultReader<typename _Pair::second_type> >
deba@1852
   346
  class PairReader {
deba@1852
   347
  public:
deba@1852
   348
    typedef _Pair Value;
deba@1852
   349
deba@1852
   350
    typedef _FirstReader FirstReader;
deba@1852
   351
    typedef _SecondReader SecondReader;
deba@1852
   352
deba@1852
   353
  private:
deba@1852
   354
deba@1852
   355
    FirstReader first_reader;
deba@1852
   356
    SecondReader second_reader;
deba@1852
   357
deba@1852
   358
  public:
deba@1852
   359
    
deba@1852
   360
    /// \brief Constructor.
deba@1852
   361
    ///
deba@1852
   362
    /// Constructor for the PairReader.
deba@1852
   363
    PairReader(const FirstReader& _first_reader = FirstReader(), 
deba@1852
   364
	       const SecondReader& _second_reader = SecondReader()) 
deba@1852
   365
      : first_reader(_first_reader), second_reader(_second_reader) {}
deba@1852
   366
    
deba@1852
   367
    /// \brief Reads the pair from the given stream.
deba@1852
   368
    ///
deba@1852
   369
    /// Reads the pair from the given stream.
deba@1852
   370
    void read(std::istream& is, Value& value) const {
deba@1852
   371
      char c;
deba@1852
   372
      if (!(is >> c) || c != '(') {
deba@1852
   373
	throw DataFormatError("PairReader format error");
deba@1852
   374
      }
deba@1852
   375
      first_reader.read(is, value.first);
deba@1852
   376
      if (!(is >> c) || c != '=') {
deba@1852
   377
	throw DataFormatError("PairReader format error");
deba@1852
   378
      }
deba@1852
   379
      if (!(is >> c) || c != '>') {
deba@1852
   380
	throw DataFormatError("PairReader format error");
deba@1852
   381
      }
deba@1852
   382
      second_reader.read(is, value.second);
deba@1852
   383
      if (!(is >> c) || c != ')') {
deba@1852
   384
	throw DataFormatError("PairReader format error");
deba@1852
   385
      }
deba@1852
   386
    }
deba@1852
   387
  };
deba@1852
   388
alpar@1946
   389
  /// \ingroup item_io
deba@1408
   390
  /// 
deba@1408
   391
  /// \brief The default item reader template class.
deba@1408
   392
  ///
deba@1408
   393
  /// The default item reader template class. If some section reader
deba@1408
   394
  /// needs to read a value from a stream it will give the default way for it.
deba@1408
   395
  ///
deba@1408
   396
  /// \author Balazs Dezso
deba@1408
   397
  template <typename _Value>
deba@1408
   398
  class DefaultReader {
deba@1408
   399
  public:
deba@1408
   400
    /// The value type.
deba@1408
   401
    typedef _Value Value;
deba@1408
   402
    /// \brief Reads a value from the given stream.
deba@1408
   403
    ///
deba@1408
   404
    /// Reads a value from the given stream.
deba@1408
   405
    void read(std::istream& is, Value& value) const {
deba@1408
   406
      if (!(is >> value)) 
deba@1408
   407
	throw DataFormatError("DefaultReader format error");
deba@1408
   408
    }
deba@1408
   409
  };
deba@1408
   410
deba@1427
   411
  template <>
deba@1427
   412
  class DefaultReader<std::string> {
deba@1427
   413
  public:
deba@1427
   414
    typedef std::string Value;
deba@1427
   415
    
deba@1427
   416
    void read(std::istream& is, Value& value) const {
deba@1427
   417
      char c;
deba@1429
   418
      if (!(is >> std::ws >> c)) return;
deba@1427
   419
      is.putback(c);
deba@1427
   420
      switch (c) {
deba@1427
   421
      case '\"':
deba@1427
   422
	QuotedStringReader().read(is, value);
deba@1427
   423
	break;
deba@1427
   424
      case '(':
deba@1427
   425
	ParsedStringReader().read(is, value);
deba@1427
   426
	break;
deba@1744
   427
      case '[':
deba@1744
   428
	ParsedStringReader('[', ']').read(is, value);
deba@1744
   429
	break;
deba@1744
   430
      case '/':
deba@1744
   431
	ParsedStringReader('/', '/').read(is, value);
deba@1744
   432
	break;
deba@1427
   433
      default:
deba@1744
   434
	if (!(is >> value)) 
deba@1744
   435
	  throw DataFormatError("DefaultReader format error");
deba@1427
   436
	break;
deba@1427
   437
      }
deba@1427
   438
    }
deba@1427
   439
    
deba@1427
   440
  };
deba@1427
   441
deba@1408
   442
  template <typename Item>
deba@1408
   443
  class DefaultReader<std::vector<Item> > 
deba@1408
   444
    : public PushBackReader<std::vector<Item> > {};
deba@1408
   445
deba@1408
   446
  template <typename Item>
deba@1408
   447
  class DefaultReader<std::deque<Item> > 
deba@1408
   448
    : public PushBackReader<std::deque<Item> > {};
deba@1408
   449
deba@1408
   450
  template <typename Item>
deba@1408
   451
  class DefaultReader<std::list<Item> > 
deba@1408
   452
    : public PushBackReader<std::list<Item> > {};
deba@1408
   453
deba@1408
   454
  template <typename Item>
deba@1408
   455
  class DefaultReader<std::set<Item> > 
deba@1408
   456
    : public InsertReader<std::set<Item> > {};
deba@1408
   457
deba@1852
   458
  template <typename Key, typename Value>
deba@1852
   459
  class DefaultReader<std::map<Key, Value> > 
deba@1852
   460
    : public InsertReader<std::map<Key, Value>,
deba@1852
   461
			  DefaultReader<std::pair<Key, Value> > > {};
deba@1852
   462
deba@1408
   463
  template <typename Item>
deba@1408
   464
  class DefaultReader<std::multiset<Item> > 
deba@1408
   465
    : public InsertReader<std::multiset<Item> > {};
deba@1408
   466
deba@1852
   467
  template <typename Key, typename Value>
deba@1852
   468
  class DefaultReader<std::multimap<Key, Value> > 
deba@1852
   469
    : public InsertReader<std::multimap<Key, Value>,
deba@1852
   470
			  DefaultReader<std::pair<Key, Value> > > {};
deba@1852
   471
deba@1852
   472
  template <typename First, typename Second>
deba@1852
   473
  class DefaultReader<std::pair<First, Second> > 
deba@1852
   474
    : public PairReader<std::pair<First, Second> > {};
deba@1852
   475
alpar@1946
   476
  /// \ingroup item_io
deba@1415
   477
  /// 
deba@1415
   478
  /// \brief The default item reader for skipping a value in the stream.
deba@1415
   479
  ///
deba@1415
   480
  /// The default item reader for skipping a value in the stream.
deba@1415
   481
  ///
deba@1415
   482
  /// \author Balazs Dezso
deba@1427
   483
  class DefaultSkipper : public DefaultReader<std::string> {};
deba@1415
   484
alpar@1946
   485
  /// \ingroup item_io  
deba@1408
   486
  /// \brief Standard ReaderTraits for the GraphReader class.
deba@1408
   487
  ///
deba@1408
   488
  /// Standard ReaderTraits for the GraphReader class.
deba@1408
   489
  /// It defines standard reading method for all type of value. 
deba@1408
   490
  /// \author Balazs Dezso
deba@1408
   491
  struct DefaultReaderTraits {
deba@1408
   492
deba@1408
   493
    template <typename _Value>
deba@1408
   494
    struct Reader : DefaultReader<_Value> {};
deba@1408
   495
deba@1408
   496
    typedef DefaultSkipper Skipper;
deba@1408
   497
deba@1408
   498
  };
deba@1408
   499
deba@1408
   500
}
deba@1408
   501
deba@1408
   502
#endif