lemon/lgf_reader.h
author Peter Kovacs <kpeter@inf.elte.hu>
Thu, 12 Nov 2009 23:26:13 +0100
changeset 806 fa6f37d7a25b
parent 599 f63e87b9748e
child 877 141f9c0db4a3
permissions -rw-r--r--
Entirely rework CapacityScaling (#180)

- Use the new interface similarly to NetworkSimplex.
- Rework the implementation using an efficient internal structure
for handling the residual network. This improvement made the
code much faster (up to 2-5 times faster on large graphs).
- Handle GEQ supply type (LEQ is not supported).
- Handle negative costs for arcs of finite capacity.
(Note that this algorithm cannot handle arcs of negative cost
and infinite upper bound, thus it returns UNBOUNDED if such
an arc exists.)
- Extend the documentation.
alpar@209
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
deba@127
     2
 *
alpar@209
     3
 * This file is a part of LEMON, a generic C++ optimization library.
deba@127
     4
 *
alpar@440
     5
 * Copyright (C) 2003-2009
deba@127
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@127
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@127
     8
 *
deba@127
     9
 * Permission to use, modify and distribute this software is granted
deba@127
    10
 * provided that this copyright notice appears in all copies. For
deba@127
    11
 * precise terms see the accompanying LICENSE file.
deba@127
    12
 *
deba@127
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@127
    14
 * express or implied, and with no claim as to its suitability for any
deba@127
    15
 * purpose.
deba@127
    16
 *
deba@127
    17
 */
deba@127
    18
deba@127
    19
///\ingroup lemon_io
deba@127
    20
///\file
ladanyi@236
    21
///\brief \ref lgf-format "LEMON Graph Format" reader.
deba@127
    22
deba@127
    23
deba@127
    24
#ifndef LEMON_LGF_READER_H
deba@127
    25
#define LEMON_LGF_READER_H
deba@127
    26
deba@127
    27
#include <iostream>
deba@127
    28
#include <fstream>
deba@127
    29
#include <sstream>
deba@127
    30
deba@127
    31
#include <set>
deba@127
    32
#include <map>
deba@127
    33
deba@220
    34
#include <lemon/core.h>
deba@127
    35
deba@127
    36
#include <lemon/lgf_writer.h>
deba@127
    37
deba@127
    38
#include <lemon/concept_check.h>
deba@127
    39
#include <lemon/concepts/maps.h>
deba@127
    40
deba@127
    41
namespace lemon {
deba@127
    42
deba@127
    43
  namespace _reader_bits {
deba@127
    44
deba@127
    45
    template <typename Value>
deba@127
    46
    struct DefaultConverter {
deba@127
    47
      Value operator()(const std::string& str) {
alpar@209
    48
        std::istringstream is(str);
alpar@209
    49
        Value value;
deba@290
    50
        if (!(is >> value)) {
deba@290
    51
          throw FormatError("Cannot read token");
deba@290
    52
        }
alpar@209
    53
alpar@209
    54
        char c;
alpar@209
    55
        if (is >> std::ws >> c) {
deba@290
    56
          throw FormatError("Remaining characters in token");
alpar@209
    57
        }
alpar@209
    58
        return value;
deba@127
    59
      }
deba@127
    60
    };
deba@127
    61
deba@127
    62
    template <>
deba@127
    63
    struct DefaultConverter<std::string> {
deba@127
    64
      std::string operator()(const std::string& str) {
alpar@209
    65
        return str;
deba@127
    66
      }
deba@127
    67
    };
deba@127
    68
alpar@209
    69
    template <typename _Item>
deba@127
    70
    class MapStorageBase {
deba@127
    71
    public:
deba@127
    72
      typedef _Item Item;
deba@127
    73
deba@127
    74
    public:
deba@127
    75
      MapStorageBase() {}
deba@127
    76
      virtual ~MapStorageBase() {}
deba@127
    77
deba@127
    78
      virtual void set(const Item& item, const std::string& value) = 0;
deba@127
    79
deba@127
    80
    };
deba@127
    81
alpar@209
    82
    template <typename _Item, typename _Map,
alpar@209
    83
              typename _Converter = DefaultConverter<typename _Map::Value> >
deba@127
    84
    class MapStorage : public MapStorageBase<_Item> {
deba@127
    85
    public:
deba@127
    86
      typedef _Map Map;
deba@127
    87
      typedef _Converter Converter;
deba@127
    88
      typedef _Item Item;
alpar@209
    89
deba@127
    90
    private:
deba@127
    91
      Map& _map;
deba@127
    92
      Converter _converter;
deba@127
    93
deba@127
    94
    public:
alpar@209
    95
      MapStorage(Map& map, const Converter& converter = Converter())
alpar@209
    96
        : _map(map), _converter(converter) {}
deba@127
    97
      virtual ~MapStorage() {}
deba@127
    98
deba@127
    99
      virtual void set(const Item& item ,const std::string& value) {
alpar@209
   100
        _map.set(item, _converter(value));
deba@127
   101
      }
deba@127
   102
    };
deba@127
   103
deba@598
   104
    template <typename _GR, bool _dir, typename _Map,
alpar@209
   105
              typename _Converter = DefaultConverter<typename _Map::Value> >
deba@598
   106
    class GraphArcMapStorage : public MapStorageBase<typename _GR::Edge> {
deba@165
   107
    public:
deba@165
   108
      typedef _Map Map;
deba@165
   109
      typedef _Converter Converter;
deba@598
   110
      typedef _GR GR;
deba@598
   111
      typedef typename GR::Edge Item;
deba@165
   112
      static const bool dir = _dir;
alpar@209
   113
deba@165
   114
    private:
deba@598
   115
      const GR& _graph;
deba@165
   116
      Map& _map;
deba@165
   117
      Converter _converter;
deba@165
   118
deba@165
   119
    public:
deba@598
   120
      GraphArcMapStorage(const GR& graph, Map& map,
alpar@209
   121
                         const Converter& converter = Converter())
alpar@209
   122
        : _graph(graph), _map(map), _converter(converter) {}
deba@165
   123
      virtual ~GraphArcMapStorage() {}
deba@165
   124
deba@165
   125
      virtual void set(const Item& item ,const std::string& value) {
alpar@209
   126
        _map.set(_graph.direct(item, dir), _converter(value));
deba@165
   127
      }
deba@165
   128
    };
deba@165
   129
deba@127
   130
    class ValueStorageBase {
deba@127
   131
    public:
deba@127
   132
      ValueStorageBase() {}
deba@127
   133
      virtual ~ValueStorageBase() {}
deba@127
   134
deba@127
   135
      virtual void set(const std::string&) = 0;
deba@127
   136
    };
deba@127
   137
deba@127
   138
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
deba@127
   139
    class ValueStorage : public ValueStorageBase {
deba@127
   140
    public:
deba@127
   141
      typedef _Value Value;
deba@127
   142
      typedef _Converter Converter;
deba@127
   143
deba@127
   144
    private:
deba@127
   145
      Value& _value;
deba@127
   146
      Converter _converter;
deba@127
   147
deba@127
   148
    public:
deba@127
   149
      ValueStorage(Value& value, const Converter& converter = Converter())
kpeter@212
   150
        : _value(value), _converter(converter) {}
deba@127
   151
deba@127
   152
      virtual void set(const std::string& value) {
alpar@209
   153
        _value = _converter(value);
deba@127
   154
      }
deba@127
   155
    };
deba@127
   156
deba@127
   157
    template <typename Value>
deba@127
   158
    struct MapLookUpConverter {
deba@127
   159
      const std::map<std::string, Value>& _map;
deba@127
   160
deba@127
   161
      MapLookUpConverter(const std::map<std::string, Value>& map)
deba@127
   162
        : _map(map) {}
deba@127
   163
deba@127
   164
      Value operator()(const std::string& str) {
deba@127
   165
        typename std::map<std::string, Value>::const_iterator it =
deba@127
   166
          _map.find(str);
deba@127
   167
        if (it == _map.end()) {
deba@127
   168
          std::ostringstream msg;
deba@127
   169
          msg << "Item not found: " << str;
deba@290
   170
          throw FormatError(msg.str());
deba@127
   171
        }
deba@127
   172
        return it->second;
deba@127
   173
      }
deba@127
   174
    };
deba@127
   175
deba@598
   176
    template <typename GR>
deba@165
   177
    struct GraphArcLookUpConverter {
deba@598
   178
      const GR& _graph;
deba@598
   179
      const std::map<std::string, typename GR::Edge>& _map;
deba@598
   180
deba@598
   181
      GraphArcLookUpConverter(const GR& graph,
alpar@209
   182
                              const std::map<std::string,
deba@598
   183
                                             typename GR::Edge>& map)
alpar@209
   184
        : _graph(graph), _map(map) {}
alpar@209
   185
deba@598
   186
      typename GR::Arc operator()(const std::string& str) {
alpar@209
   187
        if (str.empty() || (str[0] != '+' && str[0] != '-')) {
deba@290
   188
          throw FormatError("Item must start with '+' or '-'");
alpar@209
   189
        }
deba@598
   190
        typename std::map<std::string, typename GR::Edge>
alpar@209
   191
          ::const_iterator it = _map.find(str.substr(1));
alpar@209
   192
        if (it == _map.end()) {
deba@290
   193
          throw FormatError("Item not found");
alpar@209
   194
        }
alpar@209
   195
        return _graph.direct(it->second, str[0] == '+');
deba@165
   196
      }
deba@165
   197
    };
deba@165
   198
deba@197
   199
    inline bool isWhiteSpace(char c) {
alpar@209
   200
      return c == ' ' || c == '\t' || c == '\v' ||
alpar@209
   201
        c == '\n' || c == '\r' || c == '\f';
deba@127
   202
    }
alpar@209
   203
deba@197
   204
    inline bool isOct(char c) {
alpar@209
   205
      return '0' <= c && c <='7';
deba@127
   206
    }
alpar@209
   207
deba@197
   208
    inline int valueOct(char c) {
deba@127
   209
      LEMON_ASSERT(isOct(c), "The character is not octal.");
deba@127
   210
      return c - '0';
deba@127
   211
    }
deba@127
   212
deba@197
   213
    inline bool isHex(char c) {
alpar@209
   214
      return ('0' <= c && c <= '9') ||
alpar@209
   215
        ('a' <= c && c <= 'z') ||
alpar@209
   216
        ('A' <= c && c <= 'Z');
deba@127
   217
    }
alpar@209
   218
deba@197
   219
    inline int valueHex(char c) {
deba@127
   220
      LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
deba@127
   221
      if ('0' <= c && c <= '9') return c - '0';
deba@127
   222
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
deba@127
   223
      return c - 'A' + 10;
deba@127
   224
    }
deba@127
   225
deba@197
   226
    inline bool isIdentifierFirstChar(char c) {
deba@127
   227
      return ('a' <= c && c <= 'z') ||
alpar@209
   228
        ('A' <= c && c <= 'Z') || c == '_';
deba@127
   229
    }
deba@127
   230
deba@197
   231
    inline bool isIdentifierChar(char c) {
deba@127
   232
      return isIdentifierFirstChar(c) ||
alpar@209
   233
        ('0' <= c && c <= '9');
deba@127
   234
    }
deba@127
   235
deba@197
   236
    inline char readEscape(std::istream& is) {
deba@127
   237
      char c;
deba@127
   238
      if (!is.get(c))
deba@290
   239
        throw FormatError("Escape format error");
deba@127
   240
deba@127
   241
      switch (c) {
deba@127
   242
      case '\\':
alpar@209
   243
        return '\\';
deba@127
   244
      case '\"':
alpar@209
   245
        return '\"';
deba@127
   246
      case '\'':
alpar@209
   247
        return '\'';
deba@127
   248
      case '\?':
alpar@209
   249
        return '\?';
deba@127
   250
      case 'a':
alpar@209
   251
        return '\a';
deba@127
   252
      case 'b':
alpar@209
   253
        return '\b';
deba@127
   254
      case 'f':
alpar@209
   255
        return '\f';
deba@127
   256
      case 'n':
alpar@209
   257
        return '\n';
deba@127
   258
      case 'r':
alpar@209
   259
        return '\r';
deba@127
   260
      case 't':
alpar@209
   261
        return '\t';
deba@127
   262
      case 'v':
alpar@209
   263
        return '\v';
deba@127
   264
      case 'x':
alpar@209
   265
        {
alpar@209
   266
          int code;
alpar@209
   267
          if (!is.get(c) || !isHex(c))
deba@290
   268
            throw FormatError("Escape format error");
alpar@209
   269
          else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
alpar@209
   270
          else code = code * 16 + valueHex(c);
alpar@209
   271
          return code;
alpar@209
   272
        }
deba@127
   273
      default:
alpar@209
   274
        {
alpar@209
   275
          int code;
alpar@209
   276
          if (!isOct(c))
deba@290
   277
            throw FormatError("Escape format error");
alpar@209
   278
          else if (code = valueOct(c), !is.get(c) || !isOct(c))
alpar@209
   279
            is.putback(c);
alpar@209
   280
          else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
alpar@209
   281
            is.putback(c);
alpar@209
   282
          else code = code * 8 + valueOct(c);
alpar@209
   283
          return code;
alpar@209
   284
        }
alpar@209
   285
      }
deba@127
   286
    }
alpar@209
   287
deba@197
   288
    inline std::istream& readToken(std::istream& is, std::string& str) {
deba@127
   289
      std::ostringstream os;
deba@127
   290
deba@127
   291
      char c;
deba@127
   292
      is >> std::ws;
alpar@209
   293
alpar@209
   294
      if (!is.get(c))
alpar@209
   295
        return is;
deba@127
   296
deba@127
   297
      if (c == '\"') {
alpar@209
   298
        while (is.get(c) && c != '\"') {
alpar@209
   299
          if (c == '\\')
alpar@209
   300
            c = readEscape(is);
alpar@209
   301
          os << c;
alpar@209
   302
        }
alpar@209
   303
        if (!is)
deba@290
   304
          throw FormatError("Quoted format error");
deba@127
   305
      } else {
alpar@209
   306
        is.putback(c);
alpar@209
   307
        while (is.get(c) && !isWhiteSpace(c)) {
alpar@209
   308
          if (c == '\\')
alpar@209
   309
            c = readEscape(is);
alpar@209
   310
          os << c;
alpar@209
   311
        }
alpar@209
   312
        if (!is) {
alpar@209
   313
          is.clear();
alpar@209
   314
        } else {
alpar@209
   315
          is.putback(c);
alpar@209
   316
        }
deba@127
   317
      }
deba@127
   318
      str = os.str();
deba@127
   319
      return is;
deba@127
   320
    }
deba@162
   321
deba@162
   322
    class Section {
deba@162
   323
    public:
deba@162
   324
      virtual ~Section() {}
deba@162
   325
      virtual void process(std::istream& is, int& line_num) = 0;
deba@162
   326
    };
deba@162
   327
deba@162
   328
    template <typename Functor>
deba@162
   329
    class LineSection : public Section {
deba@162
   330
    private:
deba@162
   331
deba@162
   332
      Functor _functor;
deba@162
   333
deba@162
   334
    public:
alpar@209
   335
deba@162
   336
      LineSection(const Functor& functor) : _functor(functor) {}
deba@162
   337
      virtual ~LineSection() {}
deba@162
   338
deba@162
   339
      virtual void process(std::istream& is, int& line_num) {
alpar@209
   340
        char c;
alpar@209
   341
        std::string line;
alpar@209
   342
        while (is.get(c) && c != '@') {
alpar@209
   343
          if (c == '\n') {
alpar@209
   344
            ++line_num;
alpar@209
   345
          } else if (c == '#') {
alpar@209
   346
            getline(is, line);
alpar@209
   347
            ++line_num;
alpar@209
   348
          } else if (!isWhiteSpace(c)) {
alpar@209
   349
            is.putback(c);
alpar@209
   350
            getline(is, line);
alpar@209
   351
            _functor(line);
alpar@209
   352
            ++line_num;
alpar@209
   353
          }
alpar@209
   354
        }
alpar@209
   355
        if (is) is.putback(c);
alpar@209
   356
        else if (is.eof()) is.clear();
deba@162
   357
      }
deba@162
   358
    };
deba@162
   359
deba@162
   360
    template <typename Functor>
deba@162
   361
    class StreamSection : public Section {
deba@162
   362
    private:
deba@162
   363
deba@162
   364
      Functor _functor;
deba@162
   365
deba@162
   366
    public:
alpar@209
   367
deba@162
   368
      StreamSection(const Functor& functor) : _functor(functor) {}
alpar@209
   369
      virtual ~StreamSection() {}
deba@162
   370
deba@162
   371
      virtual void process(std::istream& is, int& line_num) {
alpar@209
   372
        _functor(is, line_num);
alpar@209
   373
        char c;
alpar@209
   374
        std::string line;
alpar@209
   375
        while (is.get(c) && c != '@') {
alpar@209
   376
          if (c == '\n') {
alpar@209
   377
            ++line_num;
alpar@209
   378
          } else if (!isWhiteSpace(c)) {
alpar@209
   379
            getline(is, line);
alpar@209
   380
            ++line_num;
alpar@209
   381
          }
alpar@209
   382
        }
alpar@209
   383
        if (is) is.putback(c);
alpar@209
   384
        else if (is.eof()) is.clear();
deba@162
   385
      }
deba@162
   386
    };
alpar@209
   387
deba@127
   388
  }
alpar@156
   389
deba@598
   390
  template <typename DGR>
deba@190
   391
  class DigraphReader;
deba@190
   392
deba@598
   393
  template <typename TDGR>
deba@598
   394
  DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is = std::cin);
deba@598
   395
  template <typename TDGR>
deba@598
   396
  DigraphReader<TDGR> digraphReader(TDGR& digraph, const std::string& fn);
deba@598
   397
  template <typename TDGR>
deba@598
   398
  DigraphReader<TDGR> digraphReader(TDGR& digraph, const char *fn);
deba@190
   399
alpar@156
   400
  /// \ingroup lemon_io
alpar@209
   401
  ///
kpeter@192
   402
  /// \brief \ref lgf-format "LGF" reader for directed graphs
alpar@156
   403
  ///
alpar@156
   404
  /// This utility reads an \ref lgf-format "LGF" file.
alpar@156
   405
  ///
alpar@156
   406
  /// The reading method does a batch processing. The user creates a
alpar@156
   407
  /// reader object, then various reading rules can be added to the
alpar@156
   408
  /// reader, and eventually the reading is executed with the \c run()
alpar@156
   409
  /// member function. A map reading rule can be added to the reader
alpar@156
   410
  /// with the \c nodeMap() or \c arcMap() members. An optional
deba@162
   411
  /// converter parameter can also be added as a standard functor
kpeter@192
   412
  /// converting from \c std::string to the value type of the map. If it
deba@162
   413
  /// is set, it will determine how the tokens in the file should be
kpeter@192
   414
  /// converted to the value type of the map. If the functor is not set,
deba@162
   415
  /// then a default conversion will be used. One map can be read into
deba@162
   416
  /// multiple map objects at the same time. The \c attribute(), \c
deba@162
   417
  /// node() and \c arc() functions are used to add attribute reading
deba@162
   418
  /// rules.
alpar@156
   419
  ///
alpar@156
   420
  ///\code
deba@598
   421
  /// DigraphReader<DGR>(digraph, std::cin).
kpeter@192
   422
  ///   nodeMap("coordinates", coord_map).
kpeter@192
   423
  ///   arcMap("capacity", cap_map).
kpeter@192
   424
  ///   node("source", src).
kpeter@192
   425
  ///   node("target", trg).
kpeter@192
   426
  ///   attribute("caption", caption).
kpeter@192
   427
  ///   run();
alpar@156
   428
  ///\endcode
alpar@156
   429
  ///
kpeter@786
   430
  /// By default, the reader uses the first section in the file of the
alpar@156
   431
  /// proper type. If a section has an optional name, then it can be
deba@162
   432
  /// selected for reading by giving an optional name parameter to the
deba@189
   433
  /// \c nodes(), \c arcs() or \c attributes() functions.
alpar@156
   434
  ///
alpar@156
   435
  /// The \c useNodes() and \c useArcs() functions are used to tell the reader
alpar@156
   436
  /// that the nodes or arcs should not be constructed (added to the
alpar@156
   437
  /// graph) during the reading, but instead the label map of the items
alpar@156
   438
  /// are given as a parameter of these functions. An
kpeter@192
   439
  /// application of these functions is multipass reading, which is
kpeter@192
   440
  /// important if two \c \@arcs sections must be read from the
kpeter@192
   441
  /// file. In this case the first phase would read the node set and one
alpar@156
   442
  /// of the arc sets, while the second phase would read the second arc
alpar@156
   443
  /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
alpar@156
   444
  /// The previously read label node map should be passed to the \c
alpar@156
   445
  /// useNodes() functions. Another application of multipass reading when
alpar@210
   446
  /// paths are given as a node map or an arc map.
alpar@210
   447
  /// It is impossible to read this in
alpar@156
   448
  /// a single pass, because the arcs are not constructed when the node
alpar@156
   449
  /// maps are read.
deba@598
   450
  template <typename DGR>
deba@127
   451
  class DigraphReader {
deba@127
   452
  public:
deba@127
   453
deba@598
   454
    typedef DGR Digraph;
kpeter@559
   455
kpeter@559
   456
  private:
kpeter@559
   457
deba@598
   458
    TEMPLATE_DIGRAPH_TYPEDEFS(DGR);
alpar@209
   459
deba@127
   460
    std::istream* _is;
deba@127
   461
    bool local_is;
deba@290
   462
    std::string _filename;
deba@127
   463
deba@598
   464
    DGR& _digraph;
deba@127
   465
deba@127
   466
    std::string _nodes_caption;
deba@127
   467
    std::string _arcs_caption;
deba@127
   468
    std::string _attributes_caption;
deba@127
   469
deba@127
   470
    typedef std::map<std::string, Node> NodeIndex;
deba@127
   471
    NodeIndex _node_index;
deba@127
   472
    typedef std::map<std::string, Arc> ArcIndex;
deba@127
   473
    ArcIndex _arc_index;
alpar@209
   474
alpar@209
   475
    typedef std::vector<std::pair<std::string,
alpar@209
   476
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
alpar@209
   477
    NodeMaps _node_maps;
deba@127
   478
deba@127
   479
    typedef std::vector<std::pair<std::string,
deba@127
   480
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
deba@127
   481
    ArcMaps _arc_maps;
deba@127
   482
alpar@209
   483
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
deba@127
   484
      Attributes;
deba@127
   485
    Attributes _attributes;
deba@127
   486
deba@127
   487
    bool _use_nodes;
deba@127
   488
    bool _use_arcs;
deba@127
   489
deba@188
   490
    bool _skip_nodes;
deba@188
   491
    bool _skip_arcs;
deba@188
   492
deba@127
   493
    int line_num;
deba@127
   494
    std::istringstream line;
deba@127
   495
deba@127
   496
  public:
deba@127
   497
alpar@156
   498
    /// \brief Constructor
alpar@156
   499
    ///
alpar@156
   500
    /// Construct a directed graph reader, which reads from the given
alpar@156
   501
    /// input stream.
deba@598
   502
    DigraphReader(DGR& digraph, std::istream& is = std::cin)
deba@127
   503
      : _is(&is), local_is(false), _digraph(digraph),
alpar@209
   504
        _use_nodes(false), _use_arcs(false),
alpar@209
   505
        _skip_nodes(false), _skip_arcs(false) {}
deba@127
   506
alpar@156
   507
    /// \brief Constructor
alpar@156
   508
    ///
alpar@156
   509
    /// Construct a directed graph reader, which reads from the given
alpar@156
   510
    /// file.
deba@598
   511
    DigraphReader(DGR& digraph, const std::string& fn)
deba@290
   512
      : _is(new std::ifstream(fn.c_str())), local_is(true),
deba@290
   513
        _filename(fn), _digraph(digraph),
kpeter@212
   514
        _use_nodes(false), _use_arcs(false),
deba@290
   515
        _skip_nodes(false), _skip_arcs(false) {
deba@295
   516
      if (!(*_is)) {
deba@295
   517
        delete _is;
deba@295
   518
        throw IoError("Cannot open file", fn);
deba@295
   519
      }
deba@290
   520
    }
alpar@209
   521
alpar@156
   522
    /// \brief Constructor
alpar@156
   523
    ///
alpar@156
   524
    /// Construct a directed graph reader, which reads from the given
alpar@156
   525
    /// file.
deba@598
   526
    DigraphReader(DGR& digraph, const char* fn)
deba@290
   527
      : _is(new std::ifstream(fn)), local_is(true),
deba@290
   528
        _filename(fn), _digraph(digraph),
kpeter@212
   529
        _use_nodes(false), _use_arcs(false),
deba@290
   530
        _skip_nodes(false), _skip_arcs(false) {
deba@295
   531
      if (!(*_is)) {
deba@295
   532
        delete _is;
deba@295
   533
        throw IoError("Cannot open file", fn);
deba@295
   534
      }
deba@290
   535
    }
deba@127
   536
alpar@156
   537
    /// \brief Destructor
deba@127
   538
    ~DigraphReader() {
alpar@209
   539
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   540
           it != _node_maps.end(); ++it) {
alpar@209
   541
        delete it->second;
deba@127
   542
      }
deba@127
   543
alpar@209
   544
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   545
           it != _arc_maps.end(); ++it) {
alpar@209
   546
        delete it->second;
deba@127
   547
      }
deba@127
   548
alpar@209
   549
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
   550
           it != _attributes.end(); ++it) {
alpar@209
   551
        delete it->second;
deba@127
   552
      }
deba@127
   553
deba@127
   554
      if (local_is) {
alpar@209
   555
        delete _is;
deba@127
   556
      }
deba@127
   557
deba@127
   558
    }
deba@127
   559
deba@127
   560
  private:
deba@190
   561
deba@598
   562
    template <typename TDGR>
deba@598
   563
    friend DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is);
deba@598
   564
    template <typename TDGR>
deba@598
   565
    friend DigraphReader<TDGR> digraphReader(TDGR& digraph, 
deba@598
   566
                                             const std::string& fn);
deba@598
   567
    template <typename TDGR>
deba@598
   568
    friend DigraphReader<TDGR> digraphReader(TDGR& digraph, const char *fn);
alpar@209
   569
alpar@209
   570
    DigraphReader(DigraphReader& other)
deba@190
   571
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
alpar@209
   572
        _use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
alpar@209
   573
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
deba@190
   574
deba@190
   575
      other._is = 0;
deba@190
   576
      other.local_is = false;
alpar@209
   577
deba@190
   578
      _node_index.swap(other._node_index);
deba@190
   579
      _arc_index.swap(other._arc_index);
deba@190
   580
deba@190
   581
      _node_maps.swap(other._node_maps);
deba@190
   582
      _arc_maps.swap(other._arc_maps);
deba@190
   583
      _attributes.swap(other._attributes);
deba@190
   584
deba@190
   585
      _nodes_caption = other._nodes_caption;
deba@190
   586
      _arcs_caption = other._arcs_caption;
deba@190
   587
      _attributes_caption = other._attributes_caption;
deba@190
   588
deba@190
   589
    }
deba@190
   590
deba@127
   591
    DigraphReader& operator=(const DigraphReader&);
deba@127
   592
deba@127
   593
  public:
deba@127
   594
kpeter@584
   595
    /// \name Reading Rules
alpar@156
   596
    /// @{
alpar@209
   597
alpar@156
   598
    /// \brief Node map reading rule
alpar@156
   599
    ///
alpar@156
   600
    /// Add a node map reading rule to the reader.
deba@127
   601
    template <typename Map>
deba@127
   602
    DigraphReader& nodeMap(const std::string& caption, Map& map) {
deba@127
   603
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
alpar@209
   604
      _reader_bits::MapStorageBase<Node>* storage =
alpar@209
   605
        new _reader_bits::MapStorage<Node, Map>(map);
deba@127
   606
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   607
      return *this;
deba@127
   608
    }
deba@127
   609
alpar@156
   610
    /// \brief Node map reading rule
alpar@156
   611
    ///
alpar@156
   612
    /// Add a node map reading rule with specialized converter to the
alpar@156
   613
    /// reader.
deba@127
   614
    template <typename Map, typename Converter>
alpar@209
   615
    DigraphReader& nodeMap(const std::string& caption, Map& map,
alpar@209
   616
                           const Converter& converter = Converter()) {
deba@127
   617
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
alpar@209
   618
      _reader_bits::MapStorageBase<Node>* storage =
alpar@209
   619
        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@127
   620
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   621
      return *this;
deba@127
   622
    }
deba@127
   623
alpar@156
   624
    /// \brief Arc map reading rule
alpar@156
   625
    ///
alpar@156
   626
    /// Add an arc map reading rule to the reader.
deba@127
   627
    template <typename Map>
deba@127
   628
    DigraphReader& arcMap(const std::string& caption, Map& map) {
deba@127
   629
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
alpar@209
   630
      _reader_bits::MapStorageBase<Arc>* storage =
alpar@209
   631
        new _reader_bits::MapStorage<Arc, Map>(map);
deba@127
   632
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   633
      return *this;
deba@127
   634
    }
deba@127
   635
alpar@156
   636
    /// \brief Arc map reading rule
alpar@156
   637
    ///
alpar@156
   638
    /// Add an arc map reading rule with specialized converter to the
alpar@156
   639
    /// reader.
deba@127
   640
    template <typename Map, typename Converter>
alpar@209
   641
    DigraphReader& arcMap(const std::string& caption, Map& map,
alpar@209
   642
                          const Converter& converter = Converter()) {
deba@127
   643
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
alpar@209
   644
      _reader_bits::MapStorageBase<Arc>* storage =
alpar@209
   645
        new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
deba@127
   646
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   647
      return *this;
deba@127
   648
    }
deba@127
   649
alpar@156
   650
    /// \brief Attribute reading rule
alpar@156
   651
    ///
alpar@156
   652
    /// Add an attribute reading rule to the reader.
deba@127
   653
    template <typename Value>
deba@127
   654
    DigraphReader& attribute(const std::string& caption, Value& value) {
alpar@209
   655
      _reader_bits::ValueStorageBase* storage =
alpar@209
   656
        new _reader_bits::ValueStorage<Value>(value);
deba@127
   657
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   658
      return *this;
deba@127
   659
    }
deba@127
   660
alpar@156
   661
    /// \brief Attribute reading rule
alpar@156
   662
    ///
alpar@156
   663
    /// Add an attribute reading rule with specialized converter to the
alpar@156
   664
    /// reader.
deba@127
   665
    template <typename Value, typename Converter>
alpar@209
   666
    DigraphReader& attribute(const std::string& caption, Value& value,
alpar@209
   667
                             const Converter& converter = Converter()) {
alpar@209
   668
      _reader_bits::ValueStorageBase* storage =
alpar@209
   669
        new _reader_bits::ValueStorage<Value, Converter>(value, converter);
deba@127
   670
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   671
      return *this;
deba@127
   672
    }
deba@127
   673
alpar@156
   674
    /// \brief Node reading rule
alpar@156
   675
    ///
alpar@156
   676
    /// Add a node reading rule to reader.
deba@127
   677
    DigraphReader& node(const std::string& caption, Node& node) {
deba@127
   678
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
deba@127
   679
      Converter converter(_node_index);
alpar@209
   680
      _reader_bits::ValueStorageBase* storage =
alpar@209
   681
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
deba@127
   682
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   683
      return *this;
deba@127
   684
    }
deba@127
   685
alpar@156
   686
    /// \brief Arc reading rule
alpar@156
   687
    ///
alpar@156
   688
    /// Add an arc reading rule to reader.
deba@127
   689
    DigraphReader& arc(const std::string& caption, Arc& arc) {
deba@127
   690
      typedef _reader_bits::MapLookUpConverter<Arc> Converter;
deba@127
   691
      Converter converter(_arc_index);
alpar@209
   692
      _reader_bits::ValueStorageBase* storage =
alpar@209
   693
        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@127
   694
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   695
      return *this;
deba@127
   696
    }
deba@127
   697
alpar@156
   698
    /// @}
alpar@156
   699
kpeter@584
   700
    /// \name Select Section by Name
alpar@156
   701
    /// @{
alpar@156
   702
alpar@156
   703
    /// \brief Set \c \@nodes section to be read
alpar@156
   704
    ///
alpar@156
   705
    /// Set \c \@nodes section to be read
deba@127
   706
    DigraphReader& nodes(const std::string& caption) {
deba@127
   707
      _nodes_caption = caption;
deba@127
   708
      return *this;
deba@127
   709
    }
deba@127
   710
alpar@156
   711
    /// \brief Set \c \@arcs section to be read
alpar@156
   712
    ///
alpar@156
   713
    /// Set \c \@arcs section to be read
deba@127
   714
    DigraphReader& arcs(const std::string& caption) {
deba@127
   715
      _arcs_caption = caption;
deba@127
   716
      return *this;
deba@127
   717
    }
deba@127
   718
alpar@156
   719
    /// \brief Set \c \@attributes section to be read
alpar@156
   720
    ///
alpar@156
   721
    /// Set \c \@attributes section to be read
deba@127
   722
    DigraphReader& attributes(const std::string& caption) {
deba@127
   723
      _attributes_caption = caption;
deba@127
   724
      return *this;
deba@127
   725
    }
deba@127
   726
alpar@156
   727
    /// @}
alpar@156
   728
kpeter@584
   729
    /// \name Using Previously Constructed Node or Arc Set
alpar@156
   730
    /// @{
alpar@156
   731
alpar@156
   732
    /// \brief Use previously constructed node set
alpar@156
   733
    ///
alpar@156
   734
    /// Use previously constructed node set, and specify the node
alpar@156
   735
    /// label map.
deba@127
   736
    template <typename Map>
deba@127
   737
    DigraphReader& useNodes(const Map& map) {
deba@127
   738
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
   739
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
deba@127
   740
      _use_nodes = true;
deba@127
   741
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@127
   742
      for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   743
        _node_index.insert(std::make_pair(converter(map[n]), n));
deba@127
   744
      }
deba@127
   745
      return *this;
deba@127
   746
    }
deba@127
   747
alpar@156
   748
    /// \brief Use previously constructed node set
alpar@156
   749
    ///
alpar@156
   750
    /// Use previously constructed node set, and specify the node
alpar@156
   751
    /// label map and a functor which converts the label map values to
kpeter@192
   752
    /// \c std::string.
deba@127
   753
    template <typename Map, typename Converter>
alpar@209
   754
    DigraphReader& useNodes(const Map& map,
alpar@209
   755
                            const Converter& converter = Converter()) {
deba@127
   756
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
   757
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
deba@127
   758
      _use_nodes = true;
deba@127
   759
      for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   760
        _node_index.insert(std::make_pair(converter(map[n]), n));
deba@127
   761
      }
deba@127
   762
      return *this;
deba@127
   763
    }
deba@127
   764
alpar@156
   765
    /// \brief Use previously constructed arc set
alpar@156
   766
    ///
alpar@156
   767
    /// Use previously constructed arc set, and specify the arc
alpar@156
   768
    /// label map.
deba@127
   769
    template <typename Map>
deba@127
   770
    DigraphReader& useArcs(const Map& map) {
deba@127
   771
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@127
   772
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
deba@127
   773
      _use_arcs = true;
deba@127
   774
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@127
   775
      for (ArcIt a(_digraph); a != INVALID; ++a) {
alpar@209
   776
        _arc_index.insert(std::make_pair(converter(map[a]), a));
deba@127
   777
      }
deba@127
   778
      return *this;
deba@127
   779
    }
deba@127
   780
alpar@156
   781
    /// \brief Use previously constructed arc set
alpar@156
   782
    ///
alpar@156
   783
    /// Use previously constructed arc set, and specify the arc
alpar@156
   784
    /// label map and a functor which converts the label map values to
kpeter@192
   785
    /// \c std::string.
deba@127
   786
    template <typename Map, typename Converter>
alpar@209
   787
    DigraphReader& useArcs(const Map& map,
alpar@209
   788
                           const Converter& converter = Converter()) {
deba@127
   789
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
   790
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
deba@127
   791
      _use_arcs = true;
deba@127
   792
      for (ArcIt a(_digraph); a != INVALID; ++a) {
alpar@209
   793
        _arc_index.insert(std::make_pair(converter(map[a]), a));
deba@127
   794
      }
deba@127
   795
      return *this;
deba@127
   796
    }
deba@127
   797
deba@188
   798
    /// \brief Skips the reading of node section
deba@188
   799
    ///
deba@188
   800
    /// Omit the reading of the node section. This implies that each node
kpeter@192
   801
    /// map reading rule will be abandoned, and the nodes of the graph
deba@188
   802
    /// will not be constructed, which usually cause that the arc set
kpeter@192
   803
    /// could not be read due to lack of node name resolving.
kpeter@192
   804
    /// Therefore \c skipArcs() function should also be used, or
kpeter@192
   805
    /// \c useNodes() should be used to specify the label of the nodes.
deba@188
   806
    DigraphReader& skipNodes() {
alpar@209
   807
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
deba@188
   808
      _skip_nodes = true;
deba@188
   809
      return *this;
deba@188
   810
    }
deba@188
   811
deba@188
   812
    /// \brief Skips the reading of arc section
deba@188
   813
    ///
deba@188
   814
    /// Omit the reading of the arc section. This implies that each arc
kpeter@192
   815
    /// map reading rule will be abandoned, and the arcs of the graph
deba@188
   816
    /// will not be constructed.
deba@188
   817
    DigraphReader& skipArcs() {
alpar@209
   818
      LEMON_ASSERT(!_skip_arcs, "Skip arcs already set");
deba@188
   819
      _skip_arcs = true;
deba@188
   820
      return *this;
deba@188
   821
    }
deba@188
   822
alpar@156
   823
    /// @}
alpar@156
   824
deba@127
   825
  private:
deba@127
   826
deba@127
   827
    bool readLine() {
deba@127
   828
      std::string str;
deba@127
   829
      while(++line_num, std::getline(*_is, str)) {
alpar@209
   830
        line.clear(); line.str(str);
alpar@209
   831
        char c;
alpar@209
   832
        if (line >> std::ws >> c && c != '#') {
alpar@209
   833
          line.putback(c);
alpar@209
   834
          return true;
alpar@209
   835
        }
deba@127
   836
      }
deba@127
   837
      return false;
deba@127
   838
    }
deba@127
   839
deba@127
   840
    bool readSuccess() {
deba@127
   841
      return static_cast<bool>(*_is);
deba@127
   842
    }
alpar@209
   843
deba@127
   844
    void skipSection() {
deba@127
   845
      char c;
deba@127
   846
      while (readSuccess() && line >> c && c != '@') {
alpar@209
   847
        readLine();
deba@127
   848
      }
deba@427
   849
      if (readSuccess()) {
deba@427
   850
        line.putback(c);
deba@427
   851
      }
deba@127
   852
    }
deba@127
   853
deba@127
   854
    void readNodes() {
deba@127
   855
deba@127
   856
      std::vector<int> map_index(_node_maps.size());
deba@127
   857
      int map_num, label_index;
deba@127
   858
deba@186
   859
      char c;
deba@186
   860
      if (!readLine() || !(line >> c) || c == '@') {
alpar@209
   861
        if (readSuccess() && line) line.putback(c);
alpar@209
   862
        if (!_node_maps.empty())
deba@290
   863
          throw FormatError("Cannot find map names");
alpar@209
   864
        return;
deba@186
   865
      }
deba@186
   866
      line.putback(c);
deba@186
   867
deba@127
   868
      {
alpar@209
   869
        std::map<std::string, int> maps;
alpar@209
   870
alpar@209
   871
        std::string map;
alpar@209
   872
        int index = 0;
alpar@209
   873
        while (_reader_bits::readToken(line, map)) {
alpar@209
   874
          if (maps.find(map) != maps.end()) {
alpar@209
   875
            std::ostringstream msg;
alpar@209
   876
            msg << "Multiple occurence of node map: " << map;
deba@290
   877
            throw FormatError(msg.str());
alpar@209
   878
          }
alpar@209
   879
          maps.insert(std::make_pair(map, index));
alpar@209
   880
          ++index;
alpar@209
   881
        }
alpar@209
   882
alpar@209
   883
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
alpar@209
   884
          std::map<std::string, int>::iterator jt =
alpar@209
   885
            maps.find(_node_maps[i].first);
alpar@209
   886
          if (jt == maps.end()) {
alpar@209
   887
            std::ostringstream msg;
kpeter@291
   888
            msg << "Map not found: " << _node_maps[i].first;
deba@290
   889
            throw FormatError(msg.str());
alpar@209
   890
          }
alpar@209
   891
          map_index[i] = jt->second;
alpar@209
   892
        }
alpar@209
   893
alpar@209
   894
        {
alpar@209
   895
          std::map<std::string, int>::iterator jt = maps.find("label");
alpar@209
   896
          if (jt != maps.end()) {
alpar@209
   897
            label_index = jt->second;
alpar@209
   898
          } else {
alpar@209
   899
            label_index = -1;
alpar@209
   900
          }
alpar@209
   901
        }
alpar@209
   902
        map_num = maps.size();
deba@127
   903
      }
deba@127
   904
deba@127
   905
      while (readLine() && line >> c && c != '@') {
alpar@209
   906
        line.putback(c);
alpar@209
   907
alpar@209
   908
        std::vector<std::string> tokens(map_num);
alpar@209
   909
        for (int i = 0; i < map_num; ++i) {
alpar@209
   910
          if (!_reader_bits::readToken(line, tokens[i])) {
alpar@209
   911
            std::ostringstream msg;
alpar@209
   912
            msg << "Column not found (" << i + 1 << ")";
deba@290
   913
            throw FormatError(msg.str());
alpar@209
   914
          }
alpar@209
   915
        }
alpar@209
   916
        if (line >> std::ws >> c)
kpeter@291
   917
          throw FormatError("Extra character at the end of line");
alpar@209
   918
alpar@209
   919
        Node n;
alpar@209
   920
        if (!_use_nodes) {
alpar@209
   921
          n = _digraph.addNode();
alpar@209
   922
          if (label_index != -1)
alpar@209
   923
            _node_index.insert(std::make_pair(tokens[label_index], n));
alpar@209
   924
        } else {
alpar@209
   925
          if (label_index == -1)
kpeter@291
   926
            throw FormatError("Label map not found");
alpar@209
   927
          typename std::map<std::string, Node>::iterator it =
alpar@209
   928
            _node_index.find(tokens[label_index]);
alpar@209
   929
          if (it == _node_index.end()) {
alpar@209
   930
            std::ostringstream msg;
alpar@209
   931
            msg << "Node with label not found: " << tokens[label_index];
deba@290
   932
            throw FormatError(msg.str());
alpar@209
   933
          }
alpar@209
   934
          n = it->second;
alpar@209
   935
        }
alpar@209
   936
alpar@209
   937
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
alpar@209
   938
          _node_maps[i].second->set(n, tokens[map_index[i]]);
alpar@209
   939
        }
deba@127
   940
deba@127
   941
      }
deba@127
   942
      if (readSuccess()) {
alpar@209
   943
        line.putback(c);
deba@127
   944
      }
deba@127
   945
    }
deba@127
   946
deba@127
   947
    void readArcs() {
deba@127
   948
deba@127
   949
      std::vector<int> map_index(_arc_maps.size());
deba@127
   950
      int map_num, label_index;
deba@127
   951
deba@186
   952
      char c;
deba@186
   953
      if (!readLine() || !(line >> c) || c == '@') {
alpar@209
   954
        if (readSuccess() && line) line.putback(c);
alpar@209
   955
        if (!_arc_maps.empty())
deba@290
   956
          throw FormatError("Cannot find map names");
alpar@209
   957
        return;
deba@186
   958
      }
deba@186
   959
      line.putback(c);
alpar@209
   960
deba@127
   961
      {
alpar@209
   962
        std::map<std::string, int> maps;
alpar@209
   963
alpar@209
   964
        std::string map;
alpar@209
   965
        int index = 0;
alpar@209
   966
        while (_reader_bits::readToken(line, map)) {
alpar@209
   967
          if (maps.find(map) != maps.end()) {
alpar@209
   968
            std::ostringstream msg;
alpar@209
   969
            msg << "Multiple occurence of arc map: " << map;
deba@290
   970
            throw FormatError(msg.str());
alpar@209
   971
          }
alpar@209
   972
          maps.insert(std::make_pair(map, index));
alpar@209
   973
          ++index;
alpar@209
   974
        }
alpar@209
   975
alpar@209
   976
        for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
alpar@209
   977
          std::map<std::string, int>::iterator jt =
alpar@209
   978
            maps.find(_arc_maps[i].first);
alpar@209
   979
          if (jt == maps.end()) {
alpar@209
   980
            std::ostringstream msg;
kpeter@291
   981
            msg << "Map not found: " << _arc_maps[i].first;
deba@290
   982
            throw FormatError(msg.str());
alpar@209
   983
          }
alpar@209
   984
          map_index[i] = jt->second;
alpar@209
   985
        }
alpar@209
   986
alpar@209
   987
        {
alpar@209
   988
          std::map<std::string, int>::iterator jt = maps.find("label");
alpar@209
   989
          if (jt != maps.end()) {
alpar@209
   990
            label_index = jt->second;
alpar@209
   991
          } else {
alpar@209
   992
            label_index = -1;
alpar@209
   993
          }
alpar@209
   994
        }
alpar@209
   995
        map_num = maps.size();
deba@127
   996
      }
deba@127
   997
deba@127
   998
      while (readLine() && line >> c && c != '@') {
alpar@209
   999
        line.putback(c);
alpar@209
  1000
alpar@209
  1001
        std::string source_token;
alpar@209
  1002
        std::string target_token;
alpar@209
  1003
alpar@209
  1004
        if (!_reader_bits::readToken(line, source_token))
deba@290
  1005
          throw FormatError("Source not found");
alpar@209
  1006
alpar@209
  1007
        if (!_reader_bits::readToken(line, target_token))
deba@290
  1008
          throw FormatError("Target not found");
alpar@209
  1009
alpar@209
  1010
        std::vector<std::string> tokens(map_num);
alpar@209
  1011
        for (int i = 0; i < map_num; ++i) {
alpar@209
  1012
          if (!_reader_bits::readToken(line, tokens[i])) {
alpar@209
  1013
            std::ostringstream msg;
alpar@209
  1014
            msg << "Column not found (" << i + 1 << ")";
deba@290
  1015
            throw FormatError(msg.str());
alpar@209
  1016
          }
alpar@209
  1017
        }
alpar@209
  1018
        if (line >> std::ws >> c)
kpeter@291
  1019
          throw FormatError("Extra character at the end of line");
alpar@209
  1020
alpar@209
  1021
        Arc a;
alpar@209
  1022
        if (!_use_arcs) {
deba@127
  1023
deba@127
  1024
          typename NodeIndex::iterator it;
alpar@209
  1025
deba@127
  1026
          it = _node_index.find(source_token);
deba@127
  1027
          if (it == _node_index.end()) {
deba@127
  1028
            std::ostringstream msg;
deba@127
  1029
            msg << "Item not found: " << source_token;
deba@290
  1030
            throw FormatError(msg.str());
deba@127
  1031
          }
deba@127
  1032
          Node source = it->second;
deba@127
  1033
deba@127
  1034
          it = _node_index.find(target_token);
alpar@209
  1035
          if (it == _node_index.end()) {
alpar@209
  1036
            std::ostringstream msg;
deba@127
  1037
            msg << "Item not found: " << target_token;
deba@290
  1038
            throw FormatError(msg.str());
alpar@209
  1039
          }
alpar@209
  1040
          Node target = it->second;
alpar@209
  1041
alpar@209
  1042
          a = _digraph.addArc(source, target);
alpar@209
  1043
          if (label_index != -1)
alpar@209
  1044
            _arc_index.insert(std::make_pair(tokens[label_index], a));
alpar@209
  1045
        } else {
alpar@209
  1046
          if (label_index == -1)
kpeter@291
  1047
            throw FormatError("Label map not found");
alpar@209
  1048
          typename std::map<std::string, Arc>::iterator it =
alpar@209
  1049
            _arc_index.find(tokens[label_index]);
alpar@209
  1050
          if (it == _arc_index.end()) {
alpar@209
  1051
            std::ostringstream msg;
alpar@209
  1052
            msg << "Arc with label not found: " << tokens[label_index];
deba@290
  1053
            throw FormatError(msg.str());
alpar@209
  1054
          }
alpar@209
  1055
          a = it->second;
alpar@209
  1056
        }
alpar@209
  1057
alpar@209
  1058
        for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
alpar@209
  1059
          _arc_maps[i].second->set(a, tokens[map_index[i]]);
alpar@209
  1060
        }
deba@127
  1061
deba@127
  1062
      }
deba@127
  1063
      if (readSuccess()) {
alpar@209
  1064
        line.putback(c);
deba@127
  1065
      }
deba@127
  1066
    }
deba@127
  1067
deba@127
  1068
    void readAttributes() {
deba@127
  1069
deba@127
  1070
      std::set<std::string> read_attr;
deba@127
  1071
deba@127
  1072
      char c;
deba@127
  1073
      while (readLine() && line >> c && c != '@') {
alpar@209
  1074
        line.putback(c);
alpar@209
  1075
alpar@209
  1076
        std::string attr, token;
alpar@209
  1077
        if (!_reader_bits::readToken(line, attr))
deba@290
  1078
          throw FormatError("Attribute name not found");
alpar@209
  1079
        if (!_reader_bits::readToken(line, token))
deba@290
  1080
          throw FormatError("Attribute value not found");
alpar@209
  1081
        if (line >> c)
kpeter@291
  1082
          throw FormatError("Extra character at the end of line");
alpar@209
  1083
alpar@209
  1084
        {
alpar@209
  1085
          std::set<std::string>::iterator it = read_attr.find(attr);
alpar@209
  1086
          if (it != read_attr.end()) {
alpar@209
  1087
            std::ostringstream msg;
kpeter@291
  1088
            msg << "Multiple occurence of attribute: " << attr;
deba@290
  1089
            throw FormatError(msg.str());
alpar@209
  1090
          }
alpar@209
  1091
          read_attr.insert(attr);
alpar@209
  1092
        }
alpar@209
  1093
alpar@209
  1094
        {
alpar@209
  1095
          typename Attributes::iterator it = _attributes.lower_bound(attr);
alpar@209
  1096
          while (it != _attributes.end() && it->first == attr) {
alpar@209
  1097
            it->second->set(token);
alpar@209
  1098
            ++it;
alpar@209
  1099
          }
alpar@209
  1100
        }
deba@127
  1101
deba@127
  1102
      }
deba@127
  1103
      if (readSuccess()) {
alpar@209
  1104
        line.putback(c);
deba@127
  1105
      }
deba@127
  1106
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1107
           it != _attributes.end(); ++it) {
alpar@209
  1108
        if (read_attr.find(it->first) == read_attr.end()) {
alpar@209
  1109
          std::ostringstream msg;
kpeter@291
  1110
          msg << "Attribute not found: " << it->first;
deba@290
  1111
          throw FormatError(msg.str());
alpar@209
  1112
        }
deba@127
  1113
      }
deba@127
  1114
    }
deba@127
  1115
deba@127
  1116
  public:
alpar@156
  1117
kpeter@584
  1118
    /// \name Execution of the Reader
alpar@156
  1119
    /// @{
alpar@156
  1120
alpar@156
  1121
    /// \brief Start the batch processing
alpar@156
  1122
    ///
alpar@156
  1123
    /// This function starts the batch processing
deba@127
  1124
    void run() {
deba@127
  1125
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
alpar@209
  1126
deba@188
  1127
      bool nodes_done = _skip_nodes;
deba@188
  1128
      bool arcs_done = _skip_arcs;
deba@127
  1129
      bool attributes_done = false;
deba@127
  1130
alpar@209
  1131
      line_num = 0;
deba@127
  1132
      readLine();
deba@172
  1133
      skipSection();
deba@127
  1134
deba@127
  1135
      while (readSuccess()) {
alpar@209
  1136
        try {
alpar@209
  1137
          char c;
alpar@209
  1138
          std::string section, caption;
alpar@209
  1139
          line >> c;
alpar@209
  1140
          _reader_bits::readToken(line, section);
alpar@209
  1141
          _reader_bits::readToken(line, caption);
alpar@209
  1142
alpar@209
  1143
          if (line >> c)
kpeter@291
  1144
            throw FormatError("Extra character at the end of line");
alpar@209
  1145
alpar@209
  1146
          if (section == "nodes" && !nodes_done) {
alpar@209
  1147
            if (_nodes_caption.empty() || _nodes_caption == caption) {
alpar@209
  1148
              readNodes();
alpar@209
  1149
              nodes_done = true;
alpar@209
  1150
            }
alpar@209
  1151
          } else if ((section == "arcs" || section == "edges") &&
alpar@209
  1152
                     !arcs_done) {
alpar@209
  1153
            if (_arcs_caption.empty() || _arcs_caption == caption) {
alpar@209
  1154
              readArcs();
alpar@209
  1155
              arcs_done = true;
alpar@209
  1156
            }
alpar@209
  1157
          } else if (section == "attributes" && !attributes_done) {
alpar@209
  1158
            if (_attributes_caption.empty() || _attributes_caption == caption) {
alpar@209
  1159
              readAttributes();
alpar@209
  1160
              attributes_done = true;
alpar@209
  1161
            }
alpar@209
  1162
          } else {
alpar@209
  1163
            readLine();
alpar@209
  1164
            skipSection();
alpar@209
  1165
          }
deba@290
  1166
        } catch (FormatError& error) {
alpar@209
  1167
          error.line(line_num);
deba@290
  1168
          error.file(_filename);
alpar@209
  1169
          throw;
alpar@209
  1170
        }
deba@127
  1171
      }
deba@127
  1172
deba@127
  1173
      if (!nodes_done) {
deba@290
  1174
        throw FormatError("Section @nodes not found");
deba@127
  1175
      }
deba@127
  1176
deba@127
  1177
      if (!arcs_done) {
deba@290
  1178
        throw FormatError("Section @arcs not found");
deba@127
  1179
      }
deba@127
  1180
deba@127
  1181
      if (!attributes_done && !_attributes.empty()) {
deba@290
  1182
        throw FormatError("Section @attributes not found");
deba@127
  1183
      }
deba@127
  1184
deba@127
  1185
    }
alpar@156
  1186
alpar@156
  1187
    /// @}
alpar@209
  1188
deba@127
  1189
  };
deba@598
  1190
  
deba@598
  1191
  /// \ingroup lemon_io
deba@598
  1192
  ///
deba@598
  1193
  /// \brief Return a \ref DigraphReader class
deba@598
  1194
  ///
deba@598
  1195
  /// This function just returns a \ref DigraphReader class.
deba@598
  1196
  ///
deba@598
  1197
  /// With this function a digraph can be read from an 
deba@598
  1198
  /// \ref lgf-format "LGF" file or input stream with several maps and
deba@598
  1199
  /// attributes. For example, there is network flow problem on a
deba@598
  1200
  /// digraph, i.e. a digraph with a \e capacity map on the arcs and
deba@598
  1201
  /// \e source and \e target nodes. This digraph can be read with the
deba@598
  1202
  /// following code:
deba@598
  1203
  ///
deba@598
  1204
  ///\code
deba@598
  1205
  ///ListDigraph digraph;
deba@598
  1206
  ///ListDigraph::ArcMap<int> cm(digraph);
deba@598
  1207
  ///ListDigraph::Node src, trg;
deba@598
  1208
  ///digraphReader(digraph, std::cin).
deba@598
  1209
  ///  arcMap("capacity", cap).
deba@598
  1210
  ///  node("source", src).
deba@598
  1211
  ///  node("target", trg).
deba@598
  1212
  ///  run();
deba@598
  1213
  ///\endcode
deba@598
  1214
  ///
deba@598
  1215
  /// For a complete documentation, please see the \ref DigraphReader
deba@598
  1216
  /// class documentation.
deba@598
  1217
  /// \warning Don't forget to put the \ref DigraphReader::run() "run()"
deba@598
  1218
  /// to the end of the parameter list.
deba@598
  1219
  /// \relates DigraphReader
deba@598
  1220
  /// \sa digraphReader(TDGR& digraph, const std::string& fn)
deba@598
  1221
  /// \sa digraphReader(TDGR& digraph, const char* fn)
deba@598
  1222
  template <typename TDGR>
deba@598
  1223
  DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is) {
deba@598
  1224
    DigraphReader<TDGR> tmp(digraph, is);
deba@598
  1225
    return tmp;
deba@598
  1226
  }
deba@127
  1227
kpeter@498
  1228
  /// \brief Return a \ref DigraphReader class
kpeter@498
  1229
  ///
kpeter@498
  1230
  /// This function just returns a \ref DigraphReader class.
kpeter@498
  1231
  /// \relates DigraphReader
deba@598
  1232
  /// \sa digraphReader(TDGR& digraph, std::istream& is)
deba@598
  1233
  template <typename TDGR>
deba@598
  1234
  DigraphReader<TDGR> digraphReader(TDGR& digraph, const std::string& fn) {
deba@598
  1235
    DigraphReader<TDGR> tmp(digraph, fn);
kpeter@498
  1236
    return tmp;
kpeter@498
  1237
  }
kpeter@498
  1238
kpeter@498
  1239
  /// \brief Return a \ref DigraphReader class
kpeter@498
  1240
  ///
kpeter@498
  1241
  /// This function just returns a \ref DigraphReader class.
kpeter@498
  1242
  /// \relates DigraphReader
deba@598
  1243
  /// \sa digraphReader(TDGR& digraph, std::istream& is)
deba@598
  1244
  template <typename TDGR>
deba@598
  1245
  DigraphReader<TDGR> digraphReader(TDGR& digraph, const char* fn) {
deba@598
  1246
    DigraphReader<TDGR> tmp(digraph, fn);
kpeter@498
  1247
    return tmp;
kpeter@498
  1248
  }
kpeter@498
  1249
deba@598
  1250
  template <typename GR>
ladanyi@303
  1251
  class GraphReader;
kpeter@498
  1252
 
deba@598
  1253
  template <typename TGR>
deba@598
  1254
  GraphReader<TGR> graphReader(TGR& graph, std::istream& is = std::cin);
deba@598
  1255
  template <typename TGR>
deba@598
  1256
  GraphReader<TGR> graphReader(TGR& graph, const std::string& fn);
deba@598
  1257
  template <typename TGR>
deba@598
  1258
  GraphReader<TGR> graphReader(TGR& graph, const char *fn);
deba@165
  1259
deba@165
  1260
  /// \ingroup lemon_io
alpar@209
  1261
  ///
kpeter@192
  1262
  /// \brief \ref lgf-format "LGF" reader for undirected graphs
deba@165
  1263
  ///
deba@165
  1264
  /// This utility reads an \ref lgf-format "LGF" file.
kpeter@192
  1265
  ///
kpeter@192
  1266
  /// It can be used almost the same way as \c DigraphReader.
kpeter@192
  1267
  /// The only difference is that this class can handle edges and
kpeter@192
  1268
  /// edge maps as well as arcs and arc maps.
deba@201
  1269
  ///
deba@201
  1270
  /// The columns in the \c \@edges (or \c \@arcs) section are the
deba@201
  1271
  /// edge maps. However, if there are two maps with the same name
deba@201
  1272
  /// prefixed with \c '+' and \c '-', then these can be read into an
deba@201
  1273
  /// arc map.  Similarly, an attribute can be read into an arc, if
deba@201
  1274
  /// it's value is an edge label prefixed with \c '+' or \c '-'.
kpeter@559
  1275
  template <typename GR>
deba@165
  1276
  class GraphReader {
deba@165
  1277
  public:
deba@165
  1278
kpeter@559
  1279
    typedef GR Graph;
kpeter@559
  1280
kpeter@559
  1281
  private:
kpeter@559
  1282
deba@598
  1283
    TEMPLATE_GRAPH_TYPEDEFS(GR);
alpar@209
  1284
deba@165
  1285
    std::istream* _is;
deba@165
  1286
    bool local_is;
deba@290
  1287
    std::string _filename;
deba@165
  1288
deba@598
  1289
    GR& _graph;
deba@165
  1290
deba@165
  1291
    std::string _nodes_caption;
deba@165
  1292
    std::string _edges_caption;
deba@165
  1293
    std::string _attributes_caption;
deba@165
  1294
deba@165
  1295
    typedef std::map<std::string, Node> NodeIndex;
deba@165
  1296
    NodeIndex _node_index;
deba@165
  1297
    typedef std::map<std::string, Edge> EdgeIndex;
deba@165
  1298
    EdgeIndex _edge_index;
alpar@209
  1299
alpar@209
  1300
    typedef std::vector<std::pair<std::string,
alpar@209
  1301
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
alpar@209
  1302
    NodeMaps _node_maps;
deba@165
  1303
deba@165
  1304
    typedef std::vector<std::pair<std::string,
deba@165
  1305
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
deba@165
  1306
    EdgeMaps _edge_maps;
deba@165
  1307
alpar@209
  1308
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
deba@165
  1309
      Attributes;
deba@165
  1310
    Attributes _attributes;
deba@165
  1311
deba@165
  1312
    bool _use_nodes;
deba@165
  1313
    bool _use_edges;
deba@165
  1314
deba@188
  1315
    bool _skip_nodes;
deba@188
  1316
    bool _skip_edges;
deba@188
  1317
deba@165
  1318
    int line_num;
deba@165
  1319
    std::istringstream line;
deba@165
  1320
deba@165
  1321
  public:
deba@165
  1322
deba@165
  1323
    /// \brief Constructor
deba@165
  1324
    ///
kpeter@192
  1325
    /// Construct an undirected graph reader, which reads from the given
deba@165
  1326
    /// input stream.
deba@598
  1327
    GraphReader(GR& graph, std::istream& is = std::cin)
deba@165
  1328
      : _is(&is), local_is(false), _graph(graph),
alpar@209
  1329
        _use_nodes(false), _use_edges(false),
alpar@209
  1330
        _skip_nodes(false), _skip_edges(false) {}
deba@165
  1331
deba@165
  1332
    /// \brief Constructor
deba@165
  1333
    ///
kpeter@192
  1334
    /// Construct an undirected graph reader, which reads from the given
deba@165
  1335
    /// file.
deba@598
  1336
    GraphReader(GR& graph, const std::string& fn)
deba@290
  1337
      : _is(new std::ifstream(fn.c_str())), local_is(true),
deba@290
  1338
        _filename(fn), _graph(graph),
kpeter@212
  1339
        _use_nodes(false), _use_edges(false),
deba@290
  1340
        _skip_nodes(false), _skip_edges(false) {
deba@295
  1341
      if (!(*_is)) {
deba@295
  1342
        delete _is;
deba@295
  1343
        throw IoError("Cannot open file", fn);
deba@295
  1344
      }
deba@290
  1345
    }
alpar@209
  1346
deba@165
  1347
    /// \brief Constructor
deba@165
  1348
    ///
kpeter@192
  1349
    /// Construct an undirected graph reader, which reads from the given
deba@165
  1350
    /// file.
deba@598
  1351
    GraphReader(GR& graph, const char* fn)
deba@290
  1352
      : _is(new std::ifstream(fn)), local_is(true),
deba@290
  1353
        _filename(fn), _graph(graph),
kpeter@212
  1354
        _use_nodes(false), _use_edges(false),
deba@290
  1355
        _skip_nodes(false), _skip_edges(false) {
deba@295
  1356
      if (!(*_is)) {
deba@295
  1357
        delete _is;
deba@295
  1358
        throw IoError("Cannot open file", fn);
deba@295
  1359
      }
deba@290
  1360
    }
deba@165
  1361
deba@165
  1362
    /// \brief Destructor
deba@165
  1363
    ~GraphReader() {
alpar@209
  1364
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1365
           it != _node_maps.end(); ++it) {
alpar@209
  1366
        delete it->second;
deba@165
  1367
      }
deba@165
  1368
alpar@209
  1369
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1370
           it != _edge_maps.end(); ++it) {
alpar@209
  1371
        delete it->second;
deba@165
  1372
      }
deba@165
  1373
alpar@209
  1374
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1375
           it != _attributes.end(); ++it) {
alpar@209
  1376
        delete it->second;
deba@165
  1377
      }
deba@165
  1378
deba@165
  1379
      if (local_is) {
alpar@209
  1380
        delete _is;
deba@165
  1381
      }
deba@165
  1382
deba@165
  1383
    }
deba@165
  1384
deba@165
  1385
  private:
deba@598
  1386
    template <typename TGR>
deba@598
  1387
    friend GraphReader<TGR> graphReader(TGR& graph, std::istream& is);
deba@598
  1388
    template <typename TGR>
deba@598
  1389
    friend GraphReader<TGR> graphReader(TGR& graph, const std::string& fn); 
deba@598
  1390
    template <typename TGR>
deba@598
  1391
    friend GraphReader<TGR> graphReader(TGR& graph, const char *fn);
alpar@209
  1392
alpar@209
  1393
    GraphReader(GraphReader& other)
deba@190
  1394
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
alpar@209
  1395
        _use_nodes(other._use_nodes), _use_edges(other._use_edges),
alpar@209
  1396
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
deba@190
  1397
deba@190
  1398
      other._is = 0;
deba@190
  1399
      other.local_is = false;
alpar@209
  1400
deba@190
  1401
      _node_index.swap(other._node_index);
deba@190
  1402
      _edge_index.swap(other._edge_index);
deba@190
  1403
deba@190
  1404
      _node_maps.swap(other._node_maps);
deba@190
  1405
      _edge_maps.swap(other._edge_maps);
deba@190
  1406
      _attributes.swap(other._attributes);
deba@190
  1407
deba@190
  1408
      _nodes_caption = other._nodes_caption;
deba@190
  1409
      _edges_caption = other._edges_caption;
deba@190
  1410
      _attributes_caption = other._attributes_caption;
deba@190
  1411
deba@190
  1412
    }
deba@190
  1413
deba@165
  1414
    GraphReader& operator=(const GraphReader&);
deba@165
  1415
deba@165
  1416
  public:
deba@165
  1417
kpeter@584
  1418
    /// \name Reading Rules
deba@165
  1419
    /// @{
alpar@209
  1420
deba@165
  1421
    /// \brief Node map reading rule
deba@165
  1422
    ///
deba@165
  1423
    /// Add a node map reading rule to the reader.
deba@165
  1424
    template <typename Map>
deba@165
  1425
    GraphReader& nodeMap(const std::string& caption, Map& map) {
deba@165
  1426
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
alpar@209
  1427
      _reader_bits::MapStorageBase<Node>* storage =
alpar@209
  1428
        new _reader_bits::MapStorage<Node, Map>(map);
deba@165
  1429
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1430
      return *this;
deba@165
  1431
    }
deba@165
  1432
deba@165
  1433
    /// \brief Node map reading rule
deba@165
  1434
    ///
deba@165
  1435
    /// Add a node map reading rule with specialized converter to the
deba@165
  1436
    /// reader.
deba@165
  1437
    template <typename Map, typename Converter>
alpar@209
  1438
    GraphReader& nodeMap(const std::string& caption, Map& map,
alpar@209
  1439
                           const Converter& converter = Converter()) {
deba@165
  1440
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
alpar@209
  1441
      _reader_bits::MapStorageBase<Node>* storage =
alpar@209
  1442
        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@165
  1443
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1444
      return *this;
deba@165
  1445
    }
deba@165
  1446
deba@165
  1447
    /// \brief Edge map reading rule
deba@165
  1448
    ///
deba@165
  1449
    /// Add an edge map reading rule to the reader.
deba@165
  1450
    template <typename Map>
deba@165
  1451
    GraphReader& edgeMap(const std::string& caption, Map& map) {
deba@165
  1452
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
alpar@209
  1453
      _reader_bits::MapStorageBase<Edge>* storage =
alpar@209
  1454
        new _reader_bits::MapStorage<Edge, Map>(map);
deba@165
  1455
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1456
      return *this;
deba@165
  1457
    }
deba@165
  1458
deba@165
  1459
    /// \brief Edge map reading rule
deba@165
  1460
    ///
deba@165
  1461
    /// Add an edge map reading rule with specialized converter to the
deba@165
  1462
    /// reader.
deba@165
  1463
    template <typename Map, typename Converter>
alpar@209
  1464
    GraphReader& edgeMap(const std::string& caption, Map& map,
alpar@209
  1465
                          const Converter& converter = Converter()) {
deba@165
  1466
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
alpar@209
  1467
      _reader_bits::MapStorageBase<Edge>* storage =
alpar@209
  1468
        new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
deba@165
  1469
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1470
      return *this;
deba@165
  1471
    }
deba@165
  1472
deba@165
  1473
    /// \brief Arc map reading rule
deba@165
  1474
    ///
deba@165
  1475
    /// Add an arc map reading rule to the reader.
deba@165
  1476
    template <typename Map>
deba@165
  1477
    GraphReader& arcMap(const std::string& caption, Map& map) {
deba@165
  1478
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
alpar@209
  1479
      _reader_bits::MapStorageBase<Edge>* forward_storage =
alpar@209
  1480
        new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
deba@165
  1481
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
alpar@209
  1482
      _reader_bits::MapStorageBase<Edge>* backward_storage =
deba@598
  1483
        new _reader_bits::GraphArcMapStorage<GR, false, Map>(_graph, map);
deba@165
  1484
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1485
      return *this;
deba@165
  1486
    }
deba@165
  1487
deba@165
  1488
    /// \brief Arc map reading rule
deba@165
  1489
    ///
deba@165
  1490
    /// Add an arc map reading rule with specialized converter to the
deba@165
  1491
    /// reader.
deba@165
  1492
    template <typename Map, typename Converter>
alpar@209
  1493
    GraphReader& arcMap(const std::string& caption, Map& map,
alpar@209
  1494
                          const Converter& converter = Converter()) {
deba@165
  1495
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
alpar@209
  1496
      _reader_bits::MapStorageBase<Edge>* forward_storage =
deba@598
  1497
        new _reader_bits::GraphArcMapStorage<GR, true, Map, Converter>
alpar@209
  1498
        (_graph, map, converter);
deba@165
  1499
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
alpar@209
  1500
      _reader_bits::MapStorageBase<Edge>* backward_storage =
deba@598
  1501
        new _reader_bits::GraphArcMapStorage<GR, false, Map, Converter>
alpar@209
  1502
        (_graph, map, converter);
deba@165
  1503
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1504
      return *this;
deba@165
  1505
    }
deba@165
  1506
deba@165
  1507
    /// \brief Attribute reading rule
deba@165
  1508
    ///
deba@165
  1509
    /// Add an attribute reading rule to the reader.
deba@165
  1510
    template <typename Value>
deba@165
  1511
    GraphReader& attribute(const std::string& caption, Value& value) {
alpar@209
  1512
      _reader_bits::ValueStorageBase* storage =
alpar@209
  1513
        new _reader_bits::ValueStorage<Value>(value);
deba@165
  1514
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1515
      return *this;
deba@165
  1516
    }
deba@165
  1517
deba@165
  1518
    /// \brief Attribute reading rule
deba@165
  1519
    ///
deba@165
  1520
    /// Add an attribute reading rule with specialized converter to the
deba@165
  1521
    /// reader.
deba@165
  1522
    template <typename Value, typename Converter>
alpar@209
  1523
    GraphReader& attribute(const std::string& caption, Value& value,
alpar@209
  1524
                             const Converter& converter = Converter()) {
alpar@209
  1525
      _reader_bits::ValueStorageBase* storage =
alpar@209
  1526
        new _reader_bits::ValueStorage<Value, Converter>(value, converter);
deba@165
  1527
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1528
      return *this;
deba@165
  1529
    }
deba@165
  1530
deba@165
  1531
    /// \brief Node reading rule
deba@165
  1532
    ///
deba@165
  1533
    /// Add a node reading rule to reader.
deba@165
  1534
    GraphReader& node(const std::string& caption, Node& node) {
deba@165
  1535
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
deba@165
  1536
      Converter converter(_node_index);
alpar@209
  1537
      _reader_bits::ValueStorageBase* storage =
alpar@209
  1538
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
deba@165
  1539
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1540
      return *this;
deba@165
  1541
    }
deba@165
  1542
deba@165
  1543
    /// \brief Edge reading rule
deba@165
  1544
    ///
deba@165
  1545
    /// Add an edge reading rule to reader.
deba@165
  1546
    GraphReader& edge(const std::string& caption, Edge& edge) {
deba@165
  1547
      typedef _reader_bits::MapLookUpConverter<Edge> Converter;
deba@165
  1548
      Converter converter(_edge_index);
alpar@209
  1549
      _reader_bits::ValueStorageBase* storage =
alpar@209
  1550
        new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
deba@165
  1551
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1552
      return *this;
deba@165
  1553
    }
deba@165
  1554
deba@165
  1555
    /// \brief Arc reading rule
deba@165
  1556
    ///
deba@165
  1557
    /// Add an arc reading rule to reader.
deba@165
  1558
    GraphReader& arc(const std::string& caption, Arc& arc) {
deba@598
  1559
      typedef _reader_bits::GraphArcLookUpConverter<GR> Converter;
deba@165
  1560
      Converter converter(_graph, _edge_index);
alpar@209
  1561
      _reader_bits::ValueStorageBase* storage =
alpar@209
  1562
        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@165
  1563
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1564
      return *this;
deba@165
  1565
    }
deba@165
  1566
deba@165
  1567
    /// @}
deba@165
  1568
kpeter@584
  1569
    /// \name Select Section by Name
deba@165
  1570
    /// @{
deba@165
  1571
deba@165
  1572
    /// \brief Set \c \@nodes section to be read
deba@165
  1573
    ///
kpeter@192
  1574
    /// Set \c \@nodes section to be read.
deba@165
  1575
    GraphReader& nodes(const std::string& caption) {
deba@165
  1576
      _nodes_caption = caption;
deba@165
  1577
      return *this;
deba@165
  1578
    }
deba@165
  1579
deba@165
  1580
    /// \brief Set \c \@edges section to be read
deba@165
  1581
    ///
kpeter@192
  1582
    /// Set \c \@edges section to be read.
deba@165
  1583
    GraphReader& edges(const std::string& caption) {
deba@165
  1584
      _edges_caption = caption;
deba@165
  1585
      return *this;
deba@165
  1586
    }
deba@165
  1587
deba@165
  1588
    /// \brief Set \c \@attributes section to be read
deba@165
  1589
    ///
kpeter@192
  1590
    /// Set \c \@attributes section to be read.
deba@165
  1591
    GraphReader& attributes(const std::string& caption) {
deba@165
  1592
      _attributes_caption = caption;
deba@165
  1593
      return *this;
deba@165
  1594
    }
deba@165
  1595
deba@165
  1596
    /// @}
deba@165
  1597
kpeter@584
  1598
    /// \name Using Previously Constructed Node or Edge Set
deba@165
  1599
    /// @{
deba@165
  1600
deba@165
  1601
    /// \brief Use previously constructed node set
deba@165
  1602
    ///
deba@165
  1603
    /// Use previously constructed node set, and specify the node
deba@165
  1604
    /// label map.
deba@165
  1605
    template <typename Map>
deba@165
  1606
    GraphReader& useNodes(const Map& map) {
deba@165
  1607
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
  1608
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
deba@165
  1609
      _use_nodes = true;
deba@165
  1610
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@165
  1611
      for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1612
        _node_index.insert(std::make_pair(converter(map[n]), n));
deba@165
  1613
      }
deba@165
  1614
      return *this;
deba@165
  1615
    }
deba@165
  1616
deba@165
  1617
    /// \brief Use previously constructed node set
deba@165
  1618
    ///
deba@165
  1619
    /// Use previously constructed node set, and specify the node
deba@165
  1620
    /// label map and a functor which converts the label map values to
kpeter@192
  1621
    /// \c std::string.
deba@165
  1622
    template <typename Map, typename Converter>
alpar@209
  1623
    GraphReader& useNodes(const Map& map,
alpar@209
  1624
                            const Converter& converter = Converter()) {
deba@165
  1625
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
  1626
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
deba@165
  1627
      _use_nodes = true;
deba@165
  1628
      for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1629
        _node_index.insert(std::make_pair(converter(map[n]), n));
deba@165
  1630
      }
deba@165
  1631
      return *this;
deba@165
  1632
    }
deba@165
  1633
deba@165
  1634
    /// \brief Use previously constructed edge set
deba@165
  1635
    ///
deba@165
  1636
    /// Use previously constructed edge set, and specify the edge
deba@165
  1637
    /// label map.
deba@165
  1638
    template <typename Map>
deba@165
  1639
    GraphReader& useEdges(const Map& map) {
deba@165
  1640
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@165
  1641
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
deba@165
  1642
      _use_edges = true;
deba@165
  1643
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@165
  1644
      for (EdgeIt a(_graph); a != INVALID; ++a) {
alpar@209
  1645
        _edge_index.insert(std::make_pair(converter(map[a]), a));
deba@165
  1646
      }
deba@165
  1647
      return *this;
deba@165
  1648
    }
deba@165
  1649
deba@165
  1650
    /// \brief Use previously constructed edge set
deba@165
  1651
    ///
deba@165
  1652
    /// Use previously constructed edge set, and specify the edge
deba@165
  1653
    /// label map and a functor which converts the label map values to
kpeter@192
  1654
    /// \c std::string.
deba@165
  1655
    template <typename Map, typename Converter>
alpar@209
  1656
    GraphReader& useEdges(const Map& map,
alpar@209
  1657
                            const Converter& converter = Converter()) {
deba@165
  1658
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
alpar@209
  1659
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
deba@165
  1660
      _use_edges = true;
deba@165
  1661
      for (EdgeIt a(_graph); a != INVALID; ++a) {
alpar@209
  1662
        _edge_index.insert(std::make_pair(converter(map[a]), a));
deba@165
  1663
      }
deba@165
  1664
      return *this;
deba@165
  1665
    }
deba@165
  1666
kpeter@192
  1667
    /// \brief Skip the reading of node section
deba@188
  1668
    ///
deba@188
  1669
    /// Omit the reading of the node section. This implies that each node
kpeter@192
  1670
    /// map reading rule will be abandoned, and the nodes of the graph
deba@188
  1671
    /// will not be constructed, which usually cause that the edge set
deba@188
  1672
    /// could not be read due to lack of node name
kpeter@192
  1673
    /// could not be read due to lack of node name resolving.
kpeter@192
  1674
    /// Therefore \c skipEdges() function should also be used, or
kpeter@192
  1675
    /// \c useNodes() should be used to specify the label of the nodes.
deba@188
  1676
    GraphReader& skipNodes() {
alpar@209
  1677
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
deba@188
  1678
      _skip_nodes = true;
deba@188
  1679
      return *this;
deba@188
  1680
    }
deba@188
  1681
kpeter@192
  1682
    /// \brief Skip the reading of edge section
deba@188
  1683
    ///
deba@188
  1684
    /// Omit the reading of the edge section. This implies that each edge
kpeter@192
  1685
    /// map reading rule will be abandoned, and the edges of the graph
deba@188
  1686
    /// will not be constructed.
deba@188
  1687
    GraphReader& skipEdges() {
alpar@209
  1688
      LEMON_ASSERT(!_skip_edges, "Skip edges already set");
deba@188
  1689
      _skip_edges = true;
deba@188
  1690
      return *this;
deba@188
  1691
    }
deba@188
  1692
deba@165
  1693
    /// @}
deba@165
  1694
deba@165
  1695
  private:
deba@165
  1696
deba@165
  1697
    bool readLine() {
deba@165
  1698
      std::string str;
deba@165
  1699
      while(++line_num, std::getline(*_is, str)) {
alpar@209
  1700
        line.clear(); line.str(str);
alpar@209
  1701
        char c;
alpar@209
  1702
        if (line >> std::ws >> c && c != '#') {
alpar@209
  1703
          line.putback(c);
alpar@209
  1704
          return true;
alpar@209
  1705
        }
deba@165
  1706
      }
deba@165
  1707
      return false;
deba@165
  1708
    }
deba@165
  1709
deba@165
  1710
    bool readSuccess() {
deba@165
  1711
      return static_cast<bool>(*_is);
deba@165
  1712
    }
alpar@209
  1713
deba@165
  1714
    void skipSection() {
deba@165
  1715
      char c;
deba@165
  1716
      while (readSuccess() && line >> c && c != '@') {
alpar@209
  1717
        readLine();
deba@165
  1718
      }
deba@427
  1719
      if (readSuccess()) {
deba@427
  1720
        line.putback(c);
deba@427
  1721
      }
deba@165
  1722
    }
deba@165
  1723
deba@165
  1724
    void readNodes() {
deba@165
  1725
deba@165
  1726
      std::vector<int> map_index(_node_maps.size());
deba@165
  1727
      int map_num, label_index;
deba@165
  1728
deba@186
  1729
      char c;
deba@186
  1730
      if (!readLine() || !(line >> c) || c == '@') {
alpar@209
  1731
        if (readSuccess() && line) line.putback(c);
alpar@209
  1732
        if (!_node_maps.empty())
deba@290
  1733
          throw FormatError("Cannot find map names");
alpar@209
  1734
        return;
deba@186
  1735
      }
deba@186
  1736
      line.putback(c);
alpar@209
  1737
deba@165
  1738
      {
alpar@209
  1739
        std::map<std::string, int> maps;
alpar@209
  1740
alpar@209
  1741
        std::string map;
alpar@209
  1742
        int index = 0;
alpar@209
  1743
        while (_reader_bits::readToken(line, map)) {
alpar@209
  1744
          if (maps.find(map) != maps.end()) {
alpar@209
  1745
            std::ostringstream msg;
alpar@209
  1746
            msg << "Multiple occurence of node map: " << map;
deba@290
  1747
            throw FormatError(msg.str());
alpar@209
  1748
          }
alpar@209
  1749
          maps.insert(std::make_pair(map, index));
alpar@209
  1750
          ++index;
alpar@209
  1751
        }
alpar@209
  1752
alpar@209
  1753
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
alpar@209
  1754
          std::map<std::string, int>::iterator jt =
alpar@209
  1755
            maps.find(_node_maps[i].first);
alpar@209
  1756
          if (jt == maps.end()) {
alpar@209
  1757
            std::ostringstream msg;
kpeter@291
  1758
            msg << "Map not found: " << _node_maps[i].first;
deba@290
  1759
            throw FormatError(msg.str());
alpar@209
  1760
          }
alpar@209
  1761
          map_index[i] = jt->second;
alpar@209
  1762
        }
alpar@209
  1763
alpar@209
  1764
        {
alpar@209
  1765
          std::map<std::string, int>::iterator jt = maps.find("label");
alpar@209
  1766
          if (jt != maps.end()) {
alpar@209
  1767
            label_index = jt->second;
alpar@209
  1768
          } else {
alpar@209
  1769
            label_index = -1;
alpar@209
  1770
          }
alpar@209
  1771
        }
alpar@209
  1772
        map_num = maps.size();
deba@165
  1773
      }
deba@165
  1774
deba@165
  1775
      while (readLine() && line >> c && c != '@') {
alpar@209
  1776
        line.putback(c);
alpar@209
  1777
alpar@209
  1778
        std::vector<std::string> tokens(map_num);
alpar@209
  1779
        for (int i = 0; i < map_num; ++i) {
alpar@209
  1780
          if (!_reader_bits::readToken(line, tokens[i])) {
alpar@209
  1781
            std::ostringstream msg;
alpar@209
  1782
            msg << "Column not found (" << i + 1 << ")";
deba@290
  1783
            throw FormatError(msg.str());
alpar@209
  1784
          }
alpar@209
  1785
        }
alpar@209
  1786
        if (line >> std::ws >> c)
kpeter@291
  1787
          throw FormatError("Extra character at the end of line");
alpar@209
  1788
alpar@209
  1789
        Node n;
alpar@209
  1790
        if (!_use_nodes) {
alpar@209
  1791
          n = _graph.addNode();
alpar@209
  1792
          if (label_index != -1)
alpar@209
  1793
            _node_index.insert(std::make_pair(tokens[label_index], n));
alpar@209
  1794
        } else {
alpar@209
  1795
          if (label_index == -1)
kpeter@291
  1796
            throw FormatError("Label map not found");
alpar@209
  1797
          typename std::map<std::string, Node>::iterator it =
alpar@209
  1798
            _node_index.find(tokens[label_index]);
alpar@209
  1799
          if (it == _node_index.end()) {
alpar@209
  1800
            std::ostringstream msg;
alpar@209
  1801
            msg << "Node with label not found: " << tokens[label_index];
deba@290
  1802
            throw FormatError(msg.str());
alpar@209
  1803
          }
alpar@209
  1804
          n = it->second;
alpar@209
  1805
        }
alpar@209
  1806
alpar@209
  1807
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
alpar@209
  1808
          _node_maps[i].second->set(n, tokens[map_index[i]]);
alpar@209
  1809
        }
deba@165
  1810
deba@165
  1811
      }
deba@165
  1812
      if (readSuccess()) {
alpar@209
  1813
        line.putback(c);
deba@165
  1814
      }
deba@165
  1815
    }
deba@165
  1816
deba@165
  1817
    void readEdges() {
deba@165
  1818
deba@165
  1819
      std::vector<int> map_index(_edge_maps.size());
deba@165
  1820
      int map_num, label_index;
deba@165
  1821
deba@186
  1822
      char c;
deba@186
  1823
      if (!readLine() || !(line >> c) || c == '@') {
alpar@209
  1824
        if (readSuccess() && line) line.putback(c);
alpar@209
  1825
        if (!_edge_maps.empty())
deba@290
  1826
          throw FormatError("Cannot find map names");
alpar@209
  1827
        return;
deba@186
  1828
      }
deba@186
  1829
      line.putback(c);
alpar@209
  1830
deba@165
  1831
      {
alpar@209
  1832
        std::map<std::string, int> maps;
alpar@209
  1833
alpar@209
  1834
        std::string map;
alpar@209
  1835
        int index = 0;
alpar@209
  1836
        while (_reader_bits::readToken(line, map)) {
alpar@209
  1837
          if (maps.find(map) != maps.end()) {
alpar@209
  1838
            std::ostringstream msg;
alpar@209
  1839
            msg << "Multiple occurence of edge map: " << map;
deba@290
  1840
            throw FormatError(msg.str());
alpar@209
  1841
          }
alpar@209
  1842
          maps.insert(std::make_pair(map, index));
alpar@209
  1843
          ++index;
alpar@209
  1844
        }
alpar@209
  1845
alpar@209
  1846
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
alpar@209
  1847
          std::map<std::string, int>::iterator jt =
alpar@209
  1848
            maps.find(_edge_maps[i].first);
alpar@209
  1849
          if (jt == maps.end()) {
alpar@209
  1850
            std::ostringstream msg;
kpeter@291
  1851
            msg << "Map not found: " << _edge_maps[i].first;
deba@290
  1852
            throw FormatError(msg.str());
alpar@209
  1853
          }
alpar@209
  1854
          map_index[i] = jt->second;
alpar@209
  1855
        }
alpar@209
  1856
alpar@209
  1857
        {
alpar@209
  1858
          std::map<std::string, int>::iterator jt = maps.find("label");
alpar@209
  1859
          if (jt != maps.end()) {
alpar@209
  1860
            label_index = jt->second;
alpar@209
  1861
          } else {
alpar@209
  1862
            label_index = -1;
alpar@209
  1863
          }
alpar@209
  1864
        }
alpar@209
  1865
        map_num = maps.size();
deba@165
  1866
      }
deba@165
  1867
deba@165
  1868
      while (readLine() && line >> c && c != '@') {
alpar@209
  1869
        line.putback(c);
alpar@209
  1870
alpar@209
  1871
        std::string source_token;
alpar@209
  1872
        std::string target_token;
alpar@209
  1873
alpar@209
  1874
        if (!_reader_bits::readToken(line, source_token))
deba@290
  1875
          throw FormatError("Node u not found");
alpar@209
  1876
alpar@209
  1877
        if (!_reader_bits::readToken(line, target_token))
deba@290
  1878
          throw FormatError("Node v not found");
alpar@209
  1879
alpar@209
  1880
        std::vector<std::string> tokens(map_num);
alpar@209
  1881
        for (int i = 0; i < map_num; ++i) {
alpar@209
  1882
          if (!_reader_bits::readToken(line, tokens[i])) {
alpar@209
  1883
            std::ostringstream msg;
alpar@209
  1884
            msg << "Column not found (" << i + 1 << ")";
deba@290
  1885
            throw FormatError(msg.str());
alpar@209
  1886
          }
alpar@209
  1887
        }
alpar@209
  1888
        if (line >> std::ws >> c)
kpeter@291
  1889
          throw FormatError("Extra character at the end of line");
alpar@209
  1890
alpar@209
  1891
        Edge e;
alpar@209
  1892
        if (!_use_edges) {
deba@165
  1893
deba@165
  1894
          typename NodeIndex::iterator it;
alpar@209
  1895
deba@165
  1896
          it = _node_index.find(source_token);
deba@165
  1897
          if (it == _node_index.end()) {
deba@165
  1898
            std::ostringstream msg;
deba@165
  1899
            msg << "Item not found: " << source_token;
deba@290
  1900
            throw FormatError(msg.str());
deba@165
  1901
          }
deba@165
  1902
          Node source = it->second;
deba@165
  1903
deba@165
  1904
          it = _node_index.find(target_token);
alpar@209
  1905
          if (it == _node_index.end()) {
alpar@209
  1906
            std::ostringstream msg;
deba@165
  1907
            msg << "Item not found: " << target_token;
deba@290
  1908
            throw FormatError(msg.str());
alpar@209
  1909
          }
alpar@209
  1910
          Node target = it->second;
alpar@209
  1911
alpar@209
  1912
          e = _graph.addEdge(source, target);
alpar@209
  1913
          if (label_index != -1)
alpar@209
  1914
            _edge_index.insert(std::make_pair(tokens[label_index], e));
alpar@209
  1915
        } else {
alpar@209
  1916
          if (label_index == -1)
kpeter@291
  1917
            throw FormatError("Label map not found");
alpar@209
  1918
          typename std::map<std::string, Edge>::iterator it =
alpar@209
  1919
            _edge_index.find(tokens[label_index]);
alpar@209
  1920
          if (it == _edge_index.end()) {
alpar@209
  1921
            std::ostringstream msg;
alpar@209
  1922
            msg << "Edge with label not found: " << tokens[label_index];
deba@290
  1923
            throw FormatError(msg.str());
alpar@209
  1924
          }
alpar@209
  1925
          e = it->second;
alpar@209
  1926
        }
alpar@209
  1927
alpar@209
  1928
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
alpar@209
  1929
          _edge_maps[i].second->set(e, tokens[map_index[i]]);
alpar@209
  1930
        }
deba@165
  1931
deba@165
  1932
      }
deba@165
  1933
      if (readSuccess()) {
alpar@209
  1934
        line.putback(c);
deba@165
  1935
      }
deba@165
  1936
    }
deba@165
  1937
deba@165
  1938
    void readAttributes() {
deba@165
  1939
deba@165
  1940
      std::set<std::string> read_attr;
deba@165
  1941
deba@165
  1942
      char c;
deba@165
  1943
      while (readLine() && line >> c && c != '@') {
alpar@209
  1944
        line.putback(c);
alpar@209
  1945
alpar@209
  1946
        std::string attr, token;
alpar@209
  1947
        if (!_reader_bits::readToken(line, attr))
deba@290
  1948
          throw FormatError("Attribute name not found");
alpar@209
  1949
        if (!_reader_bits::readToken(line, token))
deba@290
  1950
          throw FormatError("Attribute value not found");
alpar@209
  1951
        if (line >> c)
kpeter@291
  1952
          throw FormatError("Extra character at the end of line");
alpar@209
  1953
alpar@209
  1954
        {
alpar@209
  1955
          std::set<std::string>::iterator it = read_attr.find(attr);
alpar@209
  1956
          if (it != read_attr.end()) {
alpar@209
  1957
            std::ostringstream msg;
kpeter@291
  1958
            msg << "Multiple occurence of attribute: " << attr;
deba@290
  1959
            throw FormatError(msg.str());
alpar@209
  1960
          }
alpar@209
  1961
          read_attr.insert(attr);
alpar@209
  1962
        }
alpar@209
  1963
alpar@209
  1964
        {
alpar@209
  1965
          typename Attributes::iterator it = _attributes.lower_bound(attr);
alpar@209
  1966
          while (it != _attributes.end() && it->first == attr) {
alpar@209
  1967
            it->second->set(token);
alpar@209
  1968
            ++it;
alpar@209
  1969
          }
alpar@209
  1970
        }
deba@165
  1971
deba@165
  1972
      }
deba@165
  1973
      if (readSuccess()) {
alpar@209
  1974
        line.putback(c);
deba@165
  1975
      }
deba@165
  1976
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1977
           it != _attributes.end(); ++it) {
alpar@209
  1978
        if (read_attr.find(it->first) == read_attr.end()) {
alpar@209
  1979
          std::ostringstream msg;
kpeter@291
  1980
          msg << "Attribute not found: " << it->first;
deba@290
  1981
          throw FormatError(msg.str());
alpar@209
  1982
        }
deba@165
  1983
      }
deba@165
  1984
    }
deba@165
  1985
deba@165
  1986
  public:
deba@165
  1987
kpeter@584
  1988
    /// \name Execution of the Reader
deba@165
  1989
    /// @{
deba@165
  1990
deba@165
  1991
    /// \brief Start the batch processing
deba@165
  1992
    ///
deba@165
  1993
    /// This function starts the batch processing
deba@165
  1994
    void run() {
alpar@209
  1995
deba@165
  1996
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
alpar@209
  1997
deba@188
  1998
      bool nodes_done = _skip_nodes;
deba@188
  1999
      bool edges_done = _skip_edges;
deba@165
  2000
      bool attributes_done = false;
deba@165
  2001
alpar@209
  2002
      line_num = 0;
deba@165
  2003
      readLine();
deba@172
  2004
      skipSection();
deba@165
  2005
deba@165
  2006
      while (readSuccess()) {
alpar@209
  2007
        try {
alpar@209
  2008
          char c;
alpar@209
  2009
          std::string section, caption;
alpar@209
  2010
          line >> c;
alpar@209
  2011
          _reader_bits::readToken(line, section);
alpar@209
  2012
          _reader_bits::readToken(line, caption);
alpar@209
  2013
alpar@209
  2014
          if (line >> c)
kpeter@291
  2015
            throw FormatError("Extra character at the end of line");
alpar@209
  2016
alpar@209
  2017
          if (section == "nodes" && !nodes_done) {
alpar@209
  2018
            if (_nodes_caption.empty() || _nodes_caption == caption) {
alpar@209
  2019
              readNodes();
alpar@209
  2020
              nodes_done = true;
alpar@209
  2021
            }
alpar@209
  2022
          } else if ((section == "edges" || section == "arcs") &&
alpar@209
  2023
                     !edges_done) {
alpar@209
  2024
            if (_edges_caption.empty() || _edges_caption == caption) {
alpar@209
  2025
              readEdges();
alpar@209
  2026
              edges_done = true;
alpar@209
  2027
            }
alpar@209
  2028
          } else if (section == "attributes" && !attributes_done) {
alpar@209
  2029
            if (_attributes_caption.empty() || _attributes_caption == caption) {
alpar@209
  2030
              readAttributes();
alpar@209
  2031
              attributes_done = true;
alpar@209
  2032
            }
alpar@209
  2033
          } else {
alpar@209
  2034
            readLine();
alpar@209
  2035
            skipSection();
alpar@209
  2036
          }
deba@290
  2037
        } catch (FormatError& error) {
alpar@209
  2038
          error.line(line_num);
deba@290
  2039
          error.file(_filename);
alpar@209
  2040
          throw;
alpar@209
  2041
        }
deba@165
  2042
      }
deba@165
  2043
deba@165
  2044
      if (!nodes_done) {
deba@290
  2045
        throw FormatError("Section @nodes not found");
deba@165
  2046
      }
deba@165
  2047
deba@165
  2048
      if (!edges_done) {
deba@290
  2049
        throw FormatError("Section @edges not found");
deba@165
  2050
      }
deba@165
  2051
deba@165
  2052
      if (!attributes_done && !_attributes.empty()) {
deba@290
  2053
        throw FormatError("Section @attributes not found");
deba@165
  2054
      }
deba@165
  2055
deba@165
  2056
    }
deba@165
  2057
deba@165
  2058
    /// @}
alpar@209
  2059
deba@165
  2060
  };
deba@165
  2061
deba@598
  2062
  /// \ingroup lemon_io
deba@598
  2063
  ///
deba@598
  2064
  /// \brief Return a \ref GraphReader class
deba@598
  2065
  ///
deba@598
  2066
  /// This function just returns a \ref GraphReader class. 
deba@598
  2067
  ///
deba@598
  2068
  /// With this function a graph can be read from an 
deba@598
  2069
  /// \ref lgf-format "LGF" file or input stream with several maps and
deba@598
  2070
  /// attributes. For example, there is weighted matching problem on a
deba@598
  2071
  /// graph, i.e. a graph with a \e weight map on the edges. This
deba@598
  2072
  /// graph can be read with the following code:
deba@598
  2073
  ///
deba@598
  2074
  ///\code
deba@598
  2075
  ///ListGraph graph;
deba@598
  2076
  ///ListGraph::EdgeMap<int> weight(graph);
deba@598
  2077
  ///graphReader(graph, std::cin).
deba@598
  2078
  ///  edgeMap("weight", weight).
deba@598
  2079
  ///  run();
deba@598
  2080
  ///\endcode
deba@598
  2081
  ///
deba@598
  2082
  /// For a complete documentation, please see the \ref GraphReader
deba@598
  2083
  /// class documentation.
deba@598
  2084
  /// \warning Don't forget to put the \ref GraphReader::run() "run()"
deba@598
  2085
  /// to the end of the parameter list.
deba@598
  2086
  /// \relates GraphReader
deba@598
  2087
  /// \sa graphReader(TGR& graph, const std::string& fn)
deba@598
  2088
  /// \sa graphReader(TGR& graph, const char* fn)
deba@598
  2089
  template <typename TGR>
deba@598
  2090
  GraphReader<TGR> graphReader(TGR& graph, std::istream& is) {
deba@598
  2091
    GraphReader<TGR> tmp(graph, is);
deba@598
  2092
    return tmp;
deba@598
  2093
  }
deba@598
  2094
kpeter@498
  2095
  /// \brief Return a \ref GraphReader class
kpeter@498
  2096
  ///
kpeter@498
  2097
  /// This function just returns a \ref GraphReader class.
kpeter@498
  2098
  /// \relates GraphReader
deba@598
  2099
  /// \sa graphReader(TGR& graph, std::istream& is)
deba@598
  2100
  template <typename TGR>
deba@598
  2101
  GraphReader<TGR> graphReader(TGR& graph, const std::string& fn) {
deba@598
  2102
    GraphReader<TGR> tmp(graph, fn);
kpeter@498
  2103
    return tmp;
kpeter@498
  2104
  }
kpeter@498
  2105
kpeter@498
  2106
  /// \brief Return a \ref GraphReader class
kpeter@498
  2107
  ///
kpeter@498
  2108
  /// This function just returns a \ref GraphReader class.
kpeter@498
  2109
  /// \relates GraphReader
deba@598
  2110
  /// \sa graphReader(TGR& graph, std::istream& is)
deba@598
  2111
  template <typename TGR>
deba@598
  2112
  GraphReader<TGR> graphReader(TGR& graph, const char* fn) {
deba@598
  2113
    GraphReader<TGR> tmp(graph, fn);
kpeter@498
  2114
    return tmp;
kpeter@498
  2115
  }
kpeter@498
  2116
deba@190
  2117
  class SectionReader;
deba@190
  2118
deba@190
  2119
  SectionReader sectionReader(std::istream& is);
deba@190
  2120
  SectionReader sectionReader(const std::string& fn);
deba@190
  2121
  SectionReader sectionReader(const char* fn);
alpar@209
  2122
kpeter@192
  2123
  /// \ingroup lemon_io
kpeter@192
  2124
  ///
deba@189
  2125
  /// \brief Section reader class
deba@189
  2126
  ///
alpar@209
  2127
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
kpeter@192
  2128
  /// which contain any data in arbitrary format. Such sections can be
alpar@209
  2129
  /// read with this class. A reading rule can be added to the class
kpeter@192
  2130
  /// with two different functions. With the \c sectionLines() function a
kpeter@192
  2131
  /// functor can process the section line-by-line, while with the \c
deba@189
  2132
  /// sectionStream() member the section can be read from an input
deba@189
  2133
  /// stream.
deba@189
  2134
  class SectionReader {
deba@189
  2135
  private:
alpar@209
  2136
deba@189
  2137
    std::istream* _is;
deba@189
  2138
    bool local_is;
deba@290
  2139
    std::string _filename;
deba@189
  2140
deba@189
  2141
    typedef std::map<std::string, _reader_bits::Section*> Sections;
deba@189
  2142
    Sections _sections;
deba@189
  2143
deba@189
  2144
    int line_num;
deba@189
  2145
    std::istringstream line;
deba@189
  2146
deba@189
  2147
  public:
deba@189
  2148
deba@189
  2149
    /// \brief Constructor
deba@189
  2150
    ///
deba@189
  2151
    /// Construct a section reader, which reads from the given input
deba@189
  2152
    /// stream.
alpar@209
  2153
    SectionReader(std::istream& is)
deba@189
  2154
      : _is(&is), local_is(false) {}
deba@189
  2155
deba@189
  2156
    /// \brief Constructor
deba@189
  2157
    ///
deba@189
  2158
    /// Construct a section reader, which reads from the given file.
alpar@209
  2159
    SectionReader(const std::string& fn)
deba@290
  2160
      : _is(new std::ifstream(fn.c_str())), local_is(true),
deba@290
  2161
        _filename(fn) {
deba@295
  2162
      if (!(*_is)) {
deba@295
  2163
        delete _is;
deba@295
  2164
        throw IoError("Cannot open file", fn);
deba@295
  2165
      }
deba@290
  2166
    }
alpar@209
  2167
deba@189
  2168
    /// \brief Constructor
deba@189
  2169
    ///
deba@189
  2170
    /// Construct a section reader, which reads from the given file.
alpar@209
  2171
    SectionReader(const char* fn)
deba@290
  2172
      : _is(new std::ifstream(fn)), local_is(true),
deba@290
  2173
        _filename(fn) {
deba@295
  2174
      if (!(*_is)) {
deba@295
  2175
        delete _is;
deba@295
  2176
        throw IoError("Cannot open file", fn);
deba@295
  2177
      }
deba@290
  2178
    }
deba@189
  2179
deba@189
  2180
    /// \brief Destructor
deba@189
  2181
    ~SectionReader() {
alpar@209
  2182
      for (Sections::iterator it = _sections.begin();
alpar@209
  2183
           it != _sections.end(); ++it) {
alpar@209
  2184
        delete it->second;
deba@189
  2185
      }
deba@189
  2186
deba@189
  2187
      if (local_is) {
alpar@209
  2188
        delete _is;
deba@189
  2189
      }
deba@189
  2190
deba@189
  2191
    }
deba@189
  2192
deba@189
  2193
  private:
deba@190
  2194
deba@190
  2195
    friend SectionReader sectionReader(std::istream& is);
deba@190
  2196
    friend SectionReader sectionReader(const std::string& fn);
deba@190
  2197
    friend SectionReader sectionReader(const char* fn);
deba@190
  2198
alpar@209
  2199
    SectionReader(SectionReader& other)
deba@190
  2200
      : _is(other._is), local_is(other.local_is) {
deba@190
  2201
deba@190
  2202
      other._is = 0;
deba@190
  2203
      other.local_is = false;
alpar@209
  2204
deba@190
  2205
      _sections.swap(other._sections);
deba@190
  2206
    }
alpar@209
  2207
deba@189
  2208
    SectionReader& operator=(const SectionReader&);
deba@189
  2209
deba@189
  2210
  public:
deba@189
  2211
kpeter@584
  2212
    /// \name Section Readers
deba@189
  2213
    /// @{
deba@189
  2214
deba@189
  2215
    /// \brief Add a section processor with line oriented reading
deba@189
  2216
    ///
deba@189
  2217
    /// The first parameter is the type descriptor of the section, the
deba@189
  2218
    /// second is a functor, which takes just one \c std::string
deba@189
  2219
    /// parameter. At the reading process, each line of the section
deba@189
  2220
    /// will be given to the functor object. However, the empty lines
deba@189
  2221
    /// and the comment lines are filtered out, and the leading
deba@189
  2222
    /// whitespaces are trimmed from each processed string.
deba@189
  2223
    ///
kpeter@786
  2224
    /// For example, let's see a section, which contain several
deba@189
  2225
    /// integers, which should be inserted into a vector.
deba@189
  2226
    ///\code
deba@189
  2227
    ///  @numbers
deba@189
  2228
    ///  12 45 23
deba@189
  2229
    ///  4
deba@189
  2230
    ///  23 6
deba@189
  2231
    ///\endcode
deba@189
  2232
    ///
kpeter@192
  2233
    /// The functor is implemented as a struct:
deba@189
  2234
    ///\code
deba@189
  2235
    ///  struct NumberSection {
deba@189
  2236
    ///    std::vector<int>& _data;
deba@189
  2237
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
deba@189
  2238
    ///    void operator()(const std::string& line) {
deba@189
  2239
    ///      std::istringstream ls(line);
deba@189
  2240
    ///      int value;
deba@189
  2241
    ///      while (ls >> value) _data.push_back(value);
deba@189
  2242
    ///    }
deba@189
  2243
    ///  };
deba@189
  2244
    ///
deba@189
  2245
    ///  // ...
deba@189
  2246
    ///
alpar@209
  2247
    ///  reader.sectionLines("numbers", NumberSection(vec));
deba@189
  2248
    ///\endcode
deba@189
  2249
    template <typename Functor>
deba@189
  2250
    SectionReader& sectionLines(const std::string& type, Functor functor) {
kpeter@192
  2251
      LEMON_ASSERT(!type.empty(), "Type is empty.");
alpar@209
  2252
      LEMON_ASSERT(_sections.find(type) == _sections.end(),
alpar@209
  2253
                   "Multiple reading of section.");
alpar@209
  2254
      _sections.insert(std::make_pair(type,
deba@189
  2255
        new _reader_bits::LineSection<Functor>(functor)));
deba@189
  2256
      return *this;
deba@189
  2257
    }
deba@189
  2258
deba@189
  2259
deba@189
  2260
    /// \brief Add a section processor with stream oriented reading
deba@189
  2261
    ///
deba@189
  2262
    /// The first parameter is the type of the section, the second is
kpeter@192
  2263
    /// a functor, which takes an \c std::istream& and an \c int&
deba@189
  2264
    /// parameter, the latter regard to the line number of stream. The
deba@189
  2265
    /// functor can read the input while the section go on, and the
deba@189
  2266
    /// line number should be modified accordingly.
deba@189
  2267
    template <typename Functor>
deba@189
  2268
    SectionReader& sectionStream(const std::string& type, Functor functor) {
kpeter@192
  2269
      LEMON_ASSERT(!type.empty(), "Type is empty.");
alpar@209
  2270
      LEMON_ASSERT(_sections.find(type) == _sections.end(),
alpar@209
  2271
                   "Multiple reading of section.");
alpar@209
  2272
      _sections.insert(std::make_pair(type,
alpar@209
  2273
         new _reader_bits::StreamSection<Functor>(functor)));
deba@189
  2274
      return *this;
alpar@209
  2275
    }
alpar@209
  2276
deba@189
  2277
    /// @}
deba@189
  2278
deba@189
  2279
  private:
deba@189
  2280
deba@189
  2281
    bool readLine() {
deba@189
  2282
      std::string str;
deba@189
  2283
      while(++line_num, std::getline(*_is, str)) {
alpar@209
  2284
        line.clear(); line.str(str);
alpar@209
  2285
        char c;
alpar@209
  2286
        if (line >> std::ws >> c && c != '#') {
alpar@209
  2287
          line.putback(c);
alpar@209
  2288
          return true;
alpar@209
  2289
        }
deba@189
  2290
      }
deba@189
  2291
      return false;
deba@189
  2292
    }
deba@189
  2293
deba@189
  2294
    bool readSuccess() {
deba@189
  2295
      return static_cast<bool>(*_is);
deba@189
  2296
    }
alpar@209
  2297
deba@189
  2298
    void skipSection() {
deba@189
  2299
      char c;
deba@189
  2300
      while (readSuccess() && line >> c && c != '@') {
alpar@209
  2301
        readLine();
deba@189
  2302
      }
deba@427
  2303
      if (readSuccess()) {
deba@427
  2304
        line.putback(c);
deba@427
  2305
      }
deba@189
  2306
    }
deba@189
  2307
deba@189
  2308
  public:
deba@189
  2309
deba@189
  2310
kpeter@584
  2311
    /// \name Execution of the Reader
deba@189
  2312
    /// @{
deba@189
  2313
deba@189
  2314
    /// \brief Start the batch processing
deba@189
  2315
    ///
kpeter@192
  2316
    /// This function starts the batch processing.
deba@189
  2317
    void run() {
alpar@209
  2318
deba@189
  2319
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
alpar@209
  2320
deba@189
  2321
      std::set<std::string> extra_sections;
deba@189
  2322
alpar@209
  2323
      line_num = 0;
deba@189
  2324
      readLine();
deba@189
  2325
      skipSection();
deba@189
  2326
deba@189
  2327
      while (readSuccess()) {
alpar@209
  2328
        try {
alpar@209
  2329
          char c;
alpar@209
  2330
          std::string section, caption;
alpar@209
  2331
          line >> c;
alpar@209
  2332
          _reader_bits::readToken(line, section);
alpar@209
  2333
          _reader_bits::readToken(line, caption);
alpar@209
  2334
alpar@209
  2335
          if (line >> c)
kpeter@291
  2336
            throw FormatError("Extra character at the end of line");
alpar@209
  2337
alpar@209
  2338
          if (extra_sections.find(section) != extra_sections.end()) {
alpar@209
  2339
            std::ostringstream msg;
kpeter@291
  2340
            msg << "Multiple occurence of section: " << section;
deba@290
  2341
            throw FormatError(msg.str());
alpar@209
  2342
          }
alpar@209
  2343
          Sections::iterator it = _sections.find(section);
alpar@209
  2344
          if (it != _sections.end()) {
alpar@209
  2345
            extra_sections.insert(section);
alpar@209
  2346
            it->second->process(*_is, line_num);
alpar@209
  2347
          }
alpar@209
  2348
          readLine();
alpar@209
  2349
          skipSection();
deba@290
  2350
        } catch (FormatError& error) {
alpar@209
  2351
          error.line(line_num);
deba@290
  2352
          error.file(_filename);
alpar@209
  2353
          throw;
alpar@209
  2354
        }
deba@189
  2355
      }
deba@189
  2356
      for (Sections::iterator it = _sections.begin();
alpar@209
  2357
           it != _sections.end(); ++it) {
alpar@209
  2358
        if (extra_sections.find(it->first) == extra_sections.end()) {
alpar@209
  2359
          std::ostringstream os;
alpar@209
  2360
          os << "Cannot find section: " << it->first;
deba@290
  2361
          throw FormatError(os.str());
alpar@209
  2362
        }
deba@189
  2363
      }
deba@189
  2364
    }
deba@189
  2365
deba@189
  2366
    /// @}
alpar@209
  2367
deba@189
  2368
  };
deba@189
  2369
deba@598
  2370
  /// \ingroup lemon_io
deba@598
  2371
  ///
deba@598
  2372
  /// \brief Return a \ref SectionReader class
deba@598
  2373
  ///
deba@598
  2374
  /// This function just returns a \ref SectionReader class.
deba@598
  2375
  ///
deba@598
  2376
  /// Please see SectionReader documentation about the custom section
deba@598
  2377
  /// input.
deba@598
  2378
  ///
deba@598
  2379
  /// \relates SectionReader
deba@598
  2380
  /// \sa sectionReader(const std::string& fn)
deba@598
  2381
  /// \sa sectionReader(const char *fn)
deba@598
  2382
  inline SectionReader sectionReader(std::istream& is) {
deba@598
  2383
    SectionReader tmp(is);
deba@598
  2384
    return tmp;
deba@598
  2385
  }
deba@598
  2386
kpeter@192
  2387
  /// \brief Return a \ref SectionReader class
alpar@209
  2388
  ///
kpeter@192
  2389
  /// This function just returns a \ref SectionReader class.
deba@189
  2390
  /// \relates SectionReader
deba@598
  2391
  /// \sa sectionReader(std::istream& is)
deba@598
  2392
  inline SectionReader sectionReader(const std::string& fn) {
deba@598
  2393
    SectionReader tmp(fn);
deba@189
  2394
    return tmp;
deba@189
  2395
  }
deba@189
  2396
kpeter@192
  2397
  /// \brief Return a \ref SectionReader class
alpar@209
  2398
  ///
kpeter@192
  2399
  /// This function just returns a \ref SectionReader class.
deba@189
  2400
  /// \relates SectionReader
deba@598
  2401
  /// \sa sectionReader(std::istream& is)
deba@189
  2402
  inline SectionReader sectionReader(const char* fn) {
deba@189
  2403
    SectionReader tmp(fn);
deba@189
  2404
    return tmp;
deba@189
  2405
  }
deba@189
  2406
deba@173
  2407
  /// \ingroup lemon_io
deba@173
  2408
  ///
alpar@209
  2409
  /// \brief Reader for the contents of the \ref lgf-format "LGF" file
deba@173
  2410
  ///
deba@173
  2411
  /// This class can be used to read the sections, the map names and
ladanyi@236
  2412
  /// the attributes from a file. Usually, the LEMON programs know
deba@173
  2413
  /// that, which type of graph, which maps and which attributes
deba@173
  2414
  /// should be read from a file, but in general tools (like glemon)
alpar@179
  2415
  /// the contents of an LGF file should be guessed somehow. This class
deba@173
  2416
  /// reads the graph and stores the appropriate information for
deba@173
  2417
  /// reading the graph.
deba@173
  2418
  ///
alpar@209
  2419
  ///\code
alpar@209
  2420
  /// LgfContents contents("graph.lgf");
alpar@179
  2421
  /// contents.run();
deba@173
  2422
  ///
kpeter@192
  2423
  /// // Does it contain any node section and arc section?
alpar@179
  2424
  /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
kpeter@192
  2425
  ///   std::cerr << "Failure, cannot find graph." << std::endl;
deba@173
  2426
  ///   return -1;
deba@173
  2427
  /// }
alpar@209
  2428
  /// std::cout << "The name of the default node section: "
alpar@179
  2429
  ///           << contents.nodeSection(0) << std::endl;
alpar@209
  2430
  /// std::cout << "The number of the arc maps: "
alpar@179
  2431
  ///           << contents.arcMaps(0).size() << std::endl;
alpar@209
  2432
  /// std::cout << "The name of second arc map: "
alpar@179
  2433
  ///           << contents.arcMaps(0)[1] << std::endl;
deba@173
  2434
  ///\endcode
alpar@209
  2435
  class LgfContents {
deba@173
  2436
  private:
deba@173
  2437
deba@173
  2438
    std::istream* _is;
deba@173
  2439
    bool local_is;
deba@173
  2440
deba@173
  2441
    std::vector<std::string> _node_sections;
deba@173
  2442
    std::vector<std::string> _edge_sections;
deba@173
  2443
    std::vector<std::string> _attribute_sections;
deba@173
  2444
    std::vector<std::string> _extra_sections;
deba@173
  2445
deba@173
  2446
    std::vector<bool> _arc_sections;
deba@173
  2447
deba@173
  2448
    std::vector<std::vector<std::string> > _node_maps;
deba@173
  2449
    std::vector<std::vector<std::string> > _edge_maps;
deba@173
  2450
deba@173
  2451
    std::vector<std::vector<std::string> > _attributes;
deba@173
  2452
deba@173
  2453
deba@173
  2454
    int line_num;
deba@173
  2455
    std::istringstream line;
alpar@209
  2456
deba@173
  2457
  public:
deba@173
  2458
deba@173
  2459
    /// \brief Constructor
deba@173
  2460
    ///
alpar@179
  2461
    /// Construct an \e LGF contents reader, which reads from the given
deba@173
  2462
    /// input stream.
alpar@209
  2463
    LgfContents(std::istream& is)
deba@173
  2464
      : _is(&is), local_is(false) {}
deba@173
  2465
deba@173
  2466
    /// \brief Constructor
deba@173
  2467
    ///
alpar@179
  2468
    /// Construct an \e LGF contents reader, which reads from the given
deba@173
  2469
    /// file.
alpar@209
  2470
    LgfContents(const std::string& fn)
deba@290
  2471
      : _is(new std::ifstream(fn.c_str())), local_is(true) {
deba@295
  2472
      if (!(*_is)) {
deba@295
  2473
        delete _is;
deba@295
  2474
        throw IoError("Cannot open file", fn);
deba@295
  2475
      }
deba@290
  2476
    }
deba@173
  2477
deba@173
  2478
    /// \brief Constructor
deba@173
  2479
    ///
alpar@179
  2480
    /// Construct an \e LGF contents reader, which reads from the given
deba@173
  2481
    /// file.
alpar@179
  2482
    LgfContents(const char* fn)
deba@290
  2483
      : _is(new std::ifstream(fn)), local_is(true) {
deba@295
  2484
      if (!(*_is)) {
deba@295
  2485
        delete _is;
deba@295
  2486
        throw IoError("Cannot open file", fn);
deba@295
  2487
      }
deba@290
  2488
    }
alpar@209
  2489
deba@173
  2490
    /// \brief Destructor
alpar@179
  2491
    ~LgfContents() {
deba@173
  2492
      if (local_is) delete _is;
deba@173
  2493
    }
deba@173
  2494
deba@190
  2495
  private:
alpar@209
  2496
deba@190
  2497
    LgfContents(const LgfContents&);
deba@190
  2498
    LgfContents& operator=(const LgfContents&);
deba@190
  2499
deba@190
  2500
  public:
deba@190
  2501
deba@173
  2502
kpeter@584
  2503
    /// \name Node Sections
deba@173
  2504
    /// @{
deba@173
  2505
deba@173
  2506
    /// \brief Gives back the number of node sections in the file.
deba@173
  2507
    ///
deba@173
  2508
    /// Gives back the number of node sections in the file.
deba@173
  2509
    int nodeSectionNum() const {
deba@173
  2510
      return _node_sections.size();
deba@173
  2511
    }
deba@173
  2512
alpar@209
  2513
    /// \brief Returns the node section name at the given position.
deba@173
  2514
    ///
alpar@209
  2515
    /// Returns the node section name at the given position.
deba@173
  2516
    const std::string& nodeSection(int i) const {
deba@173
  2517
      return _node_sections[i];
deba@173
  2518
    }
deba@173
  2519
deba@173
  2520
    /// \brief Gives back the node maps for the given section.
deba@173
  2521
    ///
deba@173
  2522
    /// Gives back the node maps for the given section.
alpar@182
  2523
    const std::vector<std::string>& nodeMapNames(int i) const {
deba@173
  2524
      return _node_maps[i];
deba@173
  2525
    }
deba@173
  2526
deba@173
  2527
    /// @}
deba@173
  2528
kpeter@584
  2529
    /// \name Arc/Edge Sections
deba@173
  2530
    /// @{
deba@173
  2531
alpar@181
  2532
    /// \brief Gives back the number of arc/edge sections in the file.
deba@173
  2533
    ///
alpar@181
  2534
    /// Gives back the number of arc/edge sections in the file.
alpar@181
  2535
    /// \note It is synonym of \c edgeSectionNum().
deba@173
  2536
    int arcSectionNum() const {
deba@173
  2537
      return _edge_sections.size();
deba@173
  2538
    }
deba@173
  2539
alpar@209
  2540
    /// \brief Returns the arc/edge section name at the given position.
deba@173
  2541
    ///
alpar@209
  2542
    /// Returns the arc/edge section name at the given position.
alpar@181
  2543
    /// \note It is synonym of \c edgeSection().
deba@173
  2544
    const std::string& arcSection(int i) const {
deba@173
  2545
      return _edge_sections[i];
deba@173
  2546
    }
deba@173
  2547
alpar@181
  2548
    /// \brief Gives back the arc/edge maps for the given section.
deba@173
  2549
    ///
alpar@181
  2550
    /// Gives back the arc/edge maps for the given section.
alpar@182
  2551
    /// \note It is synonym of \c edgeMapNames().
alpar@182
  2552
    const std::vector<std::string>& arcMapNames(int i) const {
deba@173
  2553
      return _edge_maps[i];
deba@173
  2554
    }
deba@173
  2555
deba@173
  2556
    /// @}
deba@173
  2557
alpar@181
  2558
    /// \name Synonyms
deba@173
  2559
    /// @{
deba@173
  2560
alpar@181
  2561
    /// \brief Gives back the number of arc/edge sections in the file.
deba@173
  2562
    ///
alpar@181
  2563
    /// Gives back the number of arc/edge sections in the file.
alpar@181
  2564
    /// \note It is synonym of \c arcSectionNum().
deba@173
  2565
    int edgeSectionNum() const {
deba@173
  2566
      return _edge_sections.size();
deba@173
  2567
    }
deba@173
  2568
alpar@209
  2569
    /// \brief Returns the section name at the given position.
deba@173
  2570
    ///
alpar@209
  2571
    /// Returns the section name at the given position.
alpar@181
  2572
    /// \note It is synonym of \c arcSection().
deba@173
  2573
    const std::string& edgeSection(int i) const {
deba@173
  2574
      return _edge_sections[i];
deba@173
  2575
    }
deba@173
  2576
deba@173
  2577
    /// \brief Gives back the edge maps for the given section.
deba@173
  2578
    ///
deba@173
  2579
    /// Gives back the edge maps for the given section.
alpar@182
  2580
    /// \note It is synonym of \c arcMapNames().
alpar@182
  2581
    const std::vector<std::string>& edgeMapNames(int i) const {
deba@173
  2582
      return _edge_maps[i];
deba@173
  2583
    }
deba@173
  2584
deba@173
  2585
    /// @}
deba@173
  2586
kpeter@584
  2587
    /// \name Attribute Sections
deba@173
  2588
    /// @{
deba@173
  2589
deba@173
  2590
    /// \brief Gives back the number of attribute sections in the file.
deba@173
  2591
    ///
deba@173
  2592
    /// Gives back the number of attribute sections in the file.
deba@173
  2593
    int attributeSectionNum() const {
deba@173
  2594
      return _attribute_sections.size();
deba@173
  2595
    }
deba@173
  2596
alpar@209
  2597
    /// \brief Returns the attribute section name at the given position.
deba@173
  2598
    ///
alpar@209
  2599
    /// Returns the attribute section name at the given position.
alpar@182
  2600
    const std::string& attributeSectionNames(int i) const {
deba@173
  2601
      return _attribute_sections[i];
deba@173
  2602
    }
deba@173
  2603
deba@173
  2604
    /// \brief Gives back the attributes for the given section.
deba@173
  2605
    ///
deba@173
  2606
    /// Gives back the attributes for the given section.
deba@173
  2607
    const std::vector<std::string>& attributes(int i) const {
deba@173
  2608
      return _attributes[i];
deba@173
  2609
    }
deba@173
  2610
deba@173
  2611
    /// @}
deba@173
  2612
kpeter@584
  2613
    /// \name Extra Sections
deba@173
  2614
    /// @{
deba@173
  2615
deba@173
  2616
    /// \brief Gives back the number of extra sections in the file.
deba@173
  2617
    ///
deba@173
  2618
    /// Gives back the number of extra sections in the file.
deba@173
  2619
    int extraSectionNum() const {
deba@173
  2620
      return _extra_sections.size();
deba@173
  2621
    }
deba@173
  2622
alpar@209
  2623
    /// \brief Returns the extra section type at the given position.
deba@173
  2624
    ///
alpar@209
  2625
    /// Returns the section type at the given position.
deba@173
  2626
    const std::string& extraSection(int i) const {
deba@173
  2627
      return _extra_sections[i];
deba@173
  2628
    }
deba@173
  2629
deba@173
  2630
    /// @}
deba@173
  2631
deba@173
  2632
  private:
deba@173
  2633
deba@173
  2634
    bool readLine() {
deba@173
  2635
      std::string str;
deba@173
  2636
      while(++line_num, std::getline(*_is, str)) {
alpar@209
  2637
        line.clear(); line.str(str);
alpar@209
  2638
        char c;
alpar@209
  2639
        if (line >> std::ws >> c && c != '#') {
alpar@209
  2640
          line.putback(c);
alpar@209
  2641
          return true;
alpar@209
  2642
        }
deba@173
  2643
      }
deba@173
  2644
      return false;
deba@173
  2645
    }
deba@173
  2646
deba@173
  2647
    bool readSuccess() {
deba@173
  2648
      return static_cast<bool>(*_is);
deba@173
  2649
    }
deba@173
  2650
deba@173
  2651
    void skipSection() {
deba@173
  2652
      char c;
deba@173
  2653
      while (readSuccess() && line >> c && c != '@') {
alpar@209
  2654
        readLine();
deba@173
  2655
      }
deba@427
  2656
      if (readSuccess()) {
deba@427
  2657
        line.putback(c);
deba@427
  2658
      }
deba@173
  2659
    }
deba@173
  2660
deba@173
  2661
    void readMaps(std::vector<std::string>& maps) {
deba@186
  2662
      char c;
deba@186
  2663
      if (!readLine() || !(line >> c) || c == '@') {
alpar@209
  2664
        if (readSuccess() && line) line.putback(c);
alpar@209
  2665
        return;
deba@186
  2666
      }
deba@186
  2667
      line.putback(c);
deba@173
  2668
      std::string map;
deba@173
  2669
      while (_reader_bits::readToken(line, map)) {
alpar@209
  2670
        maps.push_back(map);
deba@173
  2671
      }
deba@173
  2672
    }
deba@173
  2673
deba@173
  2674
    void readAttributes(std::vector<std::string>& attrs) {
deba@173
  2675
      readLine();
deba@173
  2676
      char c;
deba@173
  2677
      while (readSuccess() && line >> c && c != '@') {
alpar@209
  2678
        line.putback(c);
alpar@209
  2679
        std::string attr;
alpar@209
  2680
        _reader_bits::readToken(line, attr);
alpar@209
  2681
        attrs.push_back(attr);
alpar@209
  2682
        readLine();
deba@173
  2683
      }
deba@173
  2684
      line.putback(c);
deba@173
  2685
    }
deba@173
  2686
deba@173
  2687
  public:
deba@173
  2688
kpeter@584
  2689
    /// \name Execution of the Contents Reader
deba@173
  2690
    /// @{
deba@173
  2691
kpeter@192
  2692
    /// \brief Starts the reading
deba@173
  2693
    ///
kpeter@192
  2694
    /// This function starts the reading.
deba@173
  2695
    void run() {
deba@173
  2696
deba@173
  2697
      readLine();
deba@173
  2698
      skipSection();
deba@173
  2699
deba@173
  2700
      while (readSuccess()) {
deba@173
  2701
alpar@209
  2702
        char c;
alpar@209
  2703
        line >> c;
alpar@209
  2704
alpar@209
  2705
        std::string section, caption;
alpar@209
  2706
        _reader_bits::readToken(line, section);
alpar@209
  2707
        _reader_bits::readToken(line, caption);
alpar@209
  2708
alpar@209
  2709
        if (section == "nodes") {
alpar@209
  2710
          _node_sections.push_back(caption);
alpar@209
  2711
          _node_maps.push_back(std::vector<std::string>());
alpar@209
  2712
          readMaps(_node_maps.back());
alpar@209
  2713
          readLine(); skipSection();
alpar@209
  2714
        } else if (section == "arcs" || section == "edges") {
alpar@209
  2715
          _edge_sections.push_back(caption);
alpar@209
  2716
          _arc_sections.push_back(section == "arcs");
alpar@209
  2717
          _edge_maps.push_back(std::vector<std::string>());
alpar@209
  2718
          readMaps(_edge_maps.back());
alpar@209
  2719
          readLine(); skipSection();
alpar@209
  2720
        } else if (section == "attributes") {
alpar@209
  2721
          _attribute_sections.push_back(caption);
alpar@209
  2722
          _attributes.push_back(std::vector<std::string>());
alpar@209
  2723
          readAttributes(_attributes.back());
alpar@209
  2724
        } else {
alpar@209
  2725
          _extra_sections.push_back(section);
alpar@209
  2726
          readLine(); skipSection();
alpar@209
  2727
        }
deba@173
  2728
      }
deba@173
  2729
    }
deba@173
  2730
deba@173
  2731
    /// @}
alpar@209
  2732
deba@173
  2733
  };
deba@127
  2734
}
deba@127
  2735
deba@127
  2736
#endif