lemon/bits/item_reader.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 1956 a055123339d5
child 2254 50cb2b90daa9
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

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