lemon/lgf_reader.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 24 Mar 2009 00:18:25 +0100
changeset 596 8c3112a66878
parent 440 88ed40ad0d4f
parent 498 afd134142111
child 550 c5fd2d996909
permissions -rw-r--r--
Use XTI implementation instead of ATI in NetworkSimplex (#234)

XTI (eXtended Threaded Index) is an imporved version of the widely
known ATI (Augmented Threaded Index) method for storing and updating
the spanning tree structure in Network Simplex algorithms.

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