lemon/lgf_reader.h
author Alpar Juttner <alpar@cs.elte.hu>
Mon, 15 Oct 2018 23:39:22 +0200
changeset 1172 d7e25df22e88
parent 1076 97d978243703
permissions -rw-r--r--
Fix warnings emitted by g++ 7.3.1 (#614)
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@1092
     5
 * Copyright (C) 2003-2013
deba@127
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@127
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@127
     8
 *
deba@127
     9
 * Permission to use, modify and distribute this software is granted
deba@127
    10
 * provided that this copyright notice appears in all copies. For
deba@127
    11
 * precise terms see the accompanying LICENSE file.
deba@127
    12
 *
deba@127
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@127
    14
 * express or implied, and with no claim as to its suitability for any
deba@127
    15
 * purpose.
deba@127
    16
 *
deba@127
    17
 */
deba@127
    18
deba@127
    19
///\ingroup lemon_io
deba@127
    20
///\file
ladanyi@236
    21
///\brief \ref lgf-format "LEMON Graph Format" reader.
deba@127
    22
deba@127
    23
deba@127
    24
#ifndef LEMON_LGF_READER_H
deba@127
    25
#define LEMON_LGF_READER_H
deba@127
    26
deba@127
    27
#include <iostream>
deba@127
    28
#include <fstream>
deba@127
    29
#include <sstream>
deba@127
    30
deba@127
    31
#include <set>
deba@127
    32
#include <map>
deba@127
    33
deba@220
    34
#include <lemon/core.h>
deba@127
    35
deba@127
    36
#include <lemon/lgf_writer.h>
deba@127
    37
deba@127
    38
#include <lemon/concept_check.h>
deba@127
    39
#include <lemon/concepts/maps.h>
deba@127
    40
deba@127
    41
namespace lemon {
deba@127
    42
deba@127
    43
  namespace _reader_bits {
deba@127
    44
deba@127
    45
    template <typename Value>
deba@127
    46
    struct DefaultConverter {
deba@127
    47
      Value operator()(const std::string& str) {
alpar@209
    48
        std::istringstream is(str);
alpar@209
    49
        Value value;
deba@290
    50
        if (!(is >> value)) {
deba@290
    51
          throw FormatError("Cannot read token");
deba@290
    52
        }
alpar@209
    53
alpar@209
    54
        char c;
alpar@209
    55
        if (is >> std::ws >> c) {
deba@290
    56
          throw FormatError("Remaining characters in token");
alpar@209
    57
        }
alpar@209
    58
        return value;
deba@127
    59
      }
deba@127
    60
    };
deba@127
    61
deba@127
    62
    template <>
deba@127
    63
    struct DefaultConverter<std::string> {
deba@127
    64
      std::string operator()(const std::string& str) {
alpar@209
    65
        return str;
deba@127
    66
      }
deba@127
    67
    };
deba@127
    68
alpar@209
    69
    template <typename _Item>
deba@127
    70
    class MapStorageBase {
deba@127
    71
    public:
deba@127
    72
      typedef _Item Item;
deba@127
    73
deba@127
    74
    public:
deba@127
    75
      MapStorageBase() {}
deba@127
    76
      virtual ~MapStorageBase() {}
deba@127
    77
deba@127
    78
      virtual void set(const Item& item, const std::string& value) = 0;
deba@127
    79
deba@127
    80
    };
deba@127
    81
alpar@209
    82
    template <typename _Item, typename _Map,
alpar@209
    83
              typename _Converter = DefaultConverter<typename _Map::Value> >
deba@127
    84
    class MapStorage : public MapStorageBase<_Item> {
deba@127
    85
    public:
deba@127
    86
      typedef _Map Map;
deba@127
    87
      typedef _Converter Converter;
deba@127
    88
      typedef _Item Item;
alpar@209
    89
deba@127
    90
    private:
deba@127
    91
      Map& _map;
deba@127
    92
      Converter _converter;
deba@127
    93
deba@127
    94
    public:
alpar@209
    95
      MapStorage(Map& map, const Converter& converter = Converter())
alpar@209
    96
        : _map(map), _converter(converter) {}
deba@127
    97
      virtual ~MapStorage() {}
deba@127
    98
deba@127
    99
      virtual void set(const Item& item ,const std::string& value) {
alpar@209
   100
        _map.set(item, _converter(value));
deba@127
   101
      }
deba@127
   102
    };
deba@127
   103
deba@598
   104
    template <typename _GR, bool _dir, typename _Map,
alpar@209
   105
              typename _Converter = DefaultConverter<typename _Map::Value> >
deba@598
   106
    class GraphArcMapStorage : public MapStorageBase<typename _GR::Edge> {
deba@165
   107
    public:
deba@165
   108
      typedef _Map Map;
deba@165
   109
      typedef _Converter Converter;
deba@598
   110
      typedef _GR GR;
deba@598
   111
      typedef typename GR::Edge Item;
deba@165
   112
      static const bool dir = _dir;
alpar@209
   113
deba@165
   114
    private:
deba@598
   115
      const GR& _graph;
deba@165
   116
      Map& _map;
deba@165
   117
      Converter _converter;
deba@165
   118
deba@165
   119
    public:
deba@598
   120
      GraphArcMapStorage(const GR& graph, Map& map,
alpar@209
   121
                         const Converter& converter = Converter())
alpar@209
   122
        : _graph(graph), _map(map), _converter(converter) {}
deba@165
   123
      virtual ~GraphArcMapStorage() {}
deba@165
   124
deba@165
   125
      virtual void set(const Item& item ,const std::string& value) {
alpar@209
   126
        _map.set(_graph.direct(item, dir), _converter(value));
deba@165
   127
      }
deba@165
   128
    };
deba@165
   129
deba@127
   130
    class ValueStorageBase {
deba@127
   131
    public:
deba@127
   132
      ValueStorageBase() {}
deba@127
   133
      virtual ~ValueStorageBase() {}
deba@127
   134
deba@127
   135
      virtual void set(const std::string&) = 0;
deba@127
   136
    };
deba@127
   137
deba@127
   138
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
deba@127
   139
    class ValueStorage : public ValueStorageBase {
deba@127
   140
    public:
deba@127
   141
      typedef _Value Value;
deba@127
   142
      typedef _Converter Converter;
deba@127
   143
deba@127
   144
    private:
deba@127
   145
      Value& _value;
deba@127
   146
      Converter _converter;
deba@127
   147
deba@127
   148
    public:
deba@127
   149
      ValueStorage(Value& value, const Converter& converter = Converter())
kpeter@212
   150
        : _value(value), _converter(converter) {}
deba@127
   151
deba@127
   152
      virtual void set(const std::string& value) {
alpar@209
   153
        _value = _converter(value);
deba@127
   154
      }
deba@127
   155
    };
deba@127
   156
deba@1030
   157
    template <typename Value,
deba@1030
   158
              typename Map = std::map<std::string, Value> >
deba@127
   159
    struct MapLookUpConverter {
deba@1030
   160
      const Map& _map;
deba@1030
   161
deba@1030
   162
      MapLookUpConverter(const Map& map)
deba@127
   163
        : _map(map) {}
deba@127
   164
deba@127
   165
      Value operator()(const std::string& str) {
deba@1030
   166
        typename Map::const_iterator it = _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@1030
   176
    template <typename Value,
deba@1030
   177
              typename Map1 = std::map<std::string, Value>,
deba@1030
   178
              typename Map2 = std::map<std::string, Value> >
deba@1030
   179
    struct DoubleMapLookUpConverter {
deba@1030
   180
      const Map1& _map1;
deba@1030
   181
      const Map2& _map2;
deba@1030
   182
deba@1030
   183
      DoubleMapLookUpConverter(const Map1& map1, const Map2& map2)
deba@1030
   184
        : _map1(map1), _map2(map2) {}
deba@1030
   185
deba@1030
   186
      Value operator()(const std::string& str) {
deba@1030
   187
        typename Map1::const_iterator it1 = _map1.find(str);
deba@1030
   188
        typename Map2::const_iterator it2 = _map2.find(str);
deba@1030
   189
        if (it1 == _map1.end()) {
deba@1030
   190
          if (it2 == _map2.end()) {
deba@1030
   191
            std::ostringstream msg;
deba@1030
   192
            msg << "Item not found: " << str;
deba@1030
   193
            throw FormatError(msg.str());
deba@1030
   194
          } else {
deba@1030
   195
            return it2->second;
deba@1030
   196
          }
deba@1030
   197
        } else {
deba@1030
   198
          if (it2 == _map2.end()) {
deba@1030
   199
            return it1->second;
deba@1030
   200
          } else {
deba@1030
   201
            std::ostringstream msg;
deba@1030
   202
            msg << "Item is ambigous: " << str;
deba@1030
   203
            throw FormatError(msg.str());
deba@1030
   204
          }
deba@1030
   205
        }
deba@1030
   206
      }
deba@1030
   207
    };
deba@1030
   208
deba@598
   209
    template <typename GR>
deba@165
   210
    struct GraphArcLookUpConverter {
deba@598
   211
      const GR& _graph;
deba@598
   212
      const std::map<std::string, typename GR::Edge>& _map;
deba@598
   213
deba@598
   214
      GraphArcLookUpConverter(const GR& graph,
alpar@209
   215
                              const std::map<std::string,
deba@598
   216
                                             typename GR::Edge>& map)
alpar@209
   217
        : _graph(graph), _map(map) {}
alpar@209
   218
deba@598
   219
      typename GR::Arc operator()(const std::string& str) {
alpar@209
   220
        if (str.empty() || (str[0] != '+' && str[0] != '-')) {
deba@290
   221
          throw FormatError("Item must start with '+' or '-'");
alpar@209
   222
        }
deba@598
   223
        typename std::map<std::string, typename GR::Edge>
alpar@209
   224
          ::const_iterator it = _map.find(str.substr(1));
alpar@209
   225
        if (it == _map.end()) {
deba@290
   226
          throw FormatError("Item not found");
alpar@209
   227
        }
alpar@209
   228
        return _graph.direct(it->second, str[0] == '+');
deba@165
   229
      }
deba@165
   230
    };
deba@165
   231
deba@197
   232
    inline bool isWhiteSpace(char c) {
alpar@209
   233
      return c == ' ' || c == '\t' || c == '\v' ||
alpar@209
   234
        c == '\n' || c == '\r' || c == '\f';
deba@127
   235
    }
alpar@209
   236
deba@197
   237
    inline bool isOct(char c) {
alpar@209
   238
      return '0' <= c && c <='7';
deba@127
   239
    }
alpar@209
   240
deba@197
   241
    inline int valueOct(char c) {
deba@127
   242
      LEMON_ASSERT(isOct(c), "The character is not octal.");
deba@127
   243
      return c - '0';
deba@127
   244
    }
deba@127
   245
deba@197
   246
    inline bool isHex(char c) {
alpar@209
   247
      return ('0' <= c && c <= '9') ||
alpar@209
   248
        ('a' <= c && c <= 'z') ||
alpar@209
   249
        ('A' <= c && c <= 'Z');
deba@127
   250
    }
alpar@209
   251
deba@197
   252
    inline int valueHex(char c) {
deba@127
   253
      LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
deba@127
   254
      if ('0' <= c && c <= '9') return c - '0';
deba@127
   255
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
deba@127
   256
      return c - 'A' + 10;
deba@127
   257
    }
deba@127
   258
deba@197
   259
    inline bool isIdentifierFirstChar(char c) {
deba@127
   260
      return ('a' <= c && c <= 'z') ||
alpar@209
   261
        ('A' <= c && c <= 'Z') || c == '_';
deba@127
   262
    }
deba@127
   263
deba@197
   264
    inline bool isIdentifierChar(char c) {
deba@127
   265
      return isIdentifierFirstChar(c) ||
alpar@209
   266
        ('0' <= c && c <= '9');
deba@127
   267
    }
deba@127
   268
deba@197
   269
    inline char readEscape(std::istream& is) {
deba@127
   270
      char c;
deba@127
   271
      if (!is.get(c))
deba@290
   272
        throw FormatError("Escape format error");
deba@127
   273
deba@127
   274
      switch (c) {
deba@127
   275
      case '\\':
alpar@209
   276
        return '\\';
deba@127
   277
      case '\"':
alpar@209
   278
        return '\"';
deba@127
   279
      case '\'':
alpar@209
   280
        return '\'';
deba@127
   281
      case '\?':
alpar@209
   282
        return '\?';
deba@127
   283
      case 'a':
alpar@209
   284
        return '\a';
deba@127
   285
      case 'b':
alpar@209
   286
        return '\b';
deba@127
   287
      case 'f':
alpar@209
   288
        return '\f';
deba@127
   289
      case 'n':
alpar@209
   290
        return '\n';
deba@127
   291
      case 'r':
alpar@209
   292
        return '\r';
deba@127
   293
      case 't':
alpar@209
   294
        return '\t';
deba@127
   295
      case 'v':
alpar@209
   296
        return '\v';
deba@127
   297
      case 'x':
alpar@209
   298
        {
alpar@209
   299
          int code;
alpar@209
   300
          if (!is.get(c) || !isHex(c))
deba@290
   301
            throw FormatError("Escape format error");
alpar@209
   302
          else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
alpar@209
   303
          else code = code * 16 + valueHex(c);
alpar@209
   304
          return code;
alpar@209
   305
        }
deba@127
   306
      default:
alpar@209
   307
        {
alpar@209
   308
          int code;
alpar@209
   309
          if (!isOct(c))
deba@290
   310
            throw FormatError("Escape format error");
alpar@209
   311
          else if (code = valueOct(c), !is.get(c) || !isOct(c))
alpar@209
   312
            is.putback(c);
alpar@209
   313
          else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
alpar@209
   314
            is.putback(c);
alpar@209
   315
          else code = code * 8 + valueOct(c);
alpar@209
   316
          return code;
alpar@209
   317
        }
alpar@209
   318
      }
deba@127
   319
    }
alpar@209
   320
deba@197
   321
    inline std::istream& readToken(std::istream& is, std::string& str) {
deba@127
   322
      std::ostringstream os;
deba@127
   323
deba@127
   324
      char c;
deba@127
   325
      is >> std::ws;
alpar@209
   326
alpar@209
   327
      if (!is.get(c))
alpar@209
   328
        return is;
deba@127
   329
deba@127
   330
      if (c == '\"') {
alpar@209
   331
        while (is.get(c) && c != '\"') {
alpar@209
   332
          if (c == '\\')
alpar@209
   333
            c = readEscape(is);
alpar@209
   334
          os << c;
alpar@209
   335
        }
alpar@209
   336
        if (!is)
deba@290
   337
          throw FormatError("Quoted format error");
deba@127
   338
      } else {
alpar@209
   339
        is.putback(c);
alpar@209
   340
        while (is.get(c) && !isWhiteSpace(c)) {
alpar@209
   341
          if (c == '\\')
alpar@209
   342
            c = readEscape(is);
alpar@209
   343
          os << c;
alpar@209
   344
        }
alpar@209
   345
        if (!is) {
alpar@209
   346
          is.clear();
alpar@209
   347
        } else {
alpar@209
   348
          is.putback(c);
alpar@209
   349
        }
deba@127
   350
      }
deba@127
   351
      str = os.str();
deba@127
   352
      return is;
deba@127
   353
    }
deba@162
   354
deba@162
   355
    class Section {
deba@162
   356
    public:
deba@162
   357
      virtual ~Section() {}
deba@162
   358
      virtual void process(std::istream& is, int& line_num) = 0;
deba@162
   359
    };
deba@162
   360
deba@162
   361
    template <typename Functor>
deba@162
   362
    class LineSection : public Section {
deba@162
   363
    private:
deba@162
   364
deba@162
   365
      Functor _functor;
deba@162
   366
deba@162
   367
    public:
alpar@209
   368
deba@162
   369
      LineSection(const Functor& functor) : _functor(functor) {}
deba@162
   370
      virtual ~LineSection() {}
deba@162
   371
deba@162
   372
      virtual void process(std::istream& is, int& 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 (c == '#') {
alpar@209
   379
            getline(is, line);
alpar@209
   380
            ++line_num;
alpar@209
   381
          } else if (!isWhiteSpace(c)) {
alpar@209
   382
            is.putback(c);
alpar@209
   383
            getline(is, line);
alpar@209
   384
            _functor(line);
alpar@209
   385
            ++line_num;
alpar@209
   386
          }
alpar@209
   387
        }
alpar@209
   388
        if (is) is.putback(c);
alpar@209
   389
        else if (is.eof()) is.clear();
deba@162
   390
      }
deba@162
   391
    };
deba@162
   392
deba@162
   393
    template <typename Functor>
deba@162
   394
    class StreamSection : public Section {
deba@162
   395
    private:
deba@162
   396
deba@162
   397
      Functor _functor;
deba@162
   398
deba@162
   399
    public:
alpar@209
   400
deba@162
   401
      StreamSection(const Functor& functor) : _functor(functor) {}
alpar@209
   402
      virtual ~StreamSection() {}
deba@162
   403
deba@162
   404
      virtual void process(std::istream& is, int& line_num) {
alpar@209
   405
        _functor(is, line_num);
alpar@209
   406
        char c;
alpar@209
   407
        std::string line;
alpar@209
   408
        while (is.get(c) && c != '@') {
alpar@209
   409
          if (c == '\n') {
alpar@209
   410
            ++line_num;
alpar@209
   411
          } else if (!isWhiteSpace(c)) {
alpar@209
   412
            getline(is, line);
alpar@209
   413
            ++line_num;
alpar@209
   414
          }
alpar@209
   415
        }
alpar@209
   416
        if (is) is.putback(c);
alpar@209
   417
        else if (is.eof()) is.clear();
deba@162
   418
      }
deba@162
   419
    };
alpar@209
   420
deba@127
   421
  }
alpar@156
   422
deba@598
   423
  template <typename DGR>
deba@190
   424
  class DigraphReader;
deba@190
   425
deba@598
   426
  template <typename TDGR>
deba@598
   427
  DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is = std::cin);
deba@598
   428
  template <typename TDGR>
deba@598
   429
  DigraphReader<TDGR> digraphReader(TDGR& digraph, const std::string& fn);
deba@598
   430
  template <typename TDGR>
deba@598
   431
  DigraphReader<TDGR> digraphReader(TDGR& digraph, const char *fn);
deba@190
   432
alpar@156
   433
  /// \ingroup lemon_io
alpar@209
   434
  ///
kpeter@192
   435
  /// \brief \ref lgf-format "LGF" reader for directed graphs
alpar@156
   436
  ///
alpar@156
   437
  /// This utility reads an \ref lgf-format "LGF" file.
alpar@156
   438
  ///
alpar@156
   439
  /// The reading method does a batch processing. The user creates a
alpar@156
   440
  /// reader object, then various reading rules can be added to the
alpar@156
   441
  /// reader, and eventually the reading is executed with the \c run()
alpar@156
   442
  /// member function. A map reading rule can be added to the reader
alpar@156
   443
  /// with the \c nodeMap() or \c arcMap() members. An optional
deba@162
   444
  /// converter parameter can also be added as a standard functor
kpeter@192
   445
  /// converting from \c std::string to the value type of the map. If it
deba@162
   446
  /// is set, it will determine how the tokens in the file should be
kpeter@192
   447
  /// converted to the value type of the map. If the functor is not set,
deba@162
   448
  /// then a default conversion will be used. One map can be read into
deba@162
   449
  /// multiple map objects at the same time. The \c attribute(), \c
deba@162
   450
  /// node() and \c arc() functions are used to add attribute reading
deba@162
   451
  /// rules.
alpar@156
   452
  ///
alpar@156
   453
  ///\code
deba@598
   454
  /// DigraphReader<DGR>(digraph, std::cin).
kpeter@192
   455
  ///   nodeMap("coordinates", coord_map).
kpeter@192
   456
  ///   arcMap("capacity", cap_map).
kpeter@192
   457
  ///   node("source", src).
kpeter@192
   458
  ///   node("target", trg).
kpeter@192
   459
  ///   attribute("caption", caption).
kpeter@192
   460
  ///   run();
alpar@156
   461
  ///\endcode
alpar@156
   462
  ///
kpeter@786
   463
  /// By default, the reader uses the first section in the file of the
alpar@156
   464
  /// proper type. If a section has an optional name, then it can be
deba@162
   465
  /// selected for reading by giving an optional name parameter to the
deba@189
   466
  /// \c nodes(), \c arcs() or \c attributes() functions.
alpar@156
   467
  ///
alpar@156
   468
  /// The \c useNodes() and \c useArcs() functions are used to tell the reader
alpar@156
   469
  /// that the nodes or arcs should not be constructed (added to the
alpar@156
   470
  /// graph) during the reading, but instead the label map of the items
alpar@156
   471
  /// are given as a parameter of these functions. An
kpeter@192
   472
  /// application of these functions is multipass reading, which is
kpeter@192
   473
  /// important if two \c \@arcs sections must be read from the
kpeter@192
   474
  /// file. In this case the first phase would read the node set and one
alpar@156
   475
  /// of the arc sets, while the second phase would read the second arc
alpar@156
   476
  /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
alpar@156
   477
  /// The previously read label node map should be passed to the \c
alpar@156
   478
  /// useNodes() functions. Another application of multipass reading when
alpar@210
   479
  /// paths are given as a node map or an arc map.
alpar@210
   480
  /// It is impossible to read this in
alpar@156
   481
  /// a single pass, because the arcs are not constructed when the node
alpar@156
   482
  /// maps are read.
deba@598
   483
  template <typename DGR>
deba@127
   484
  class DigraphReader {
deba@127
   485
  public:
deba@127
   486
deba@598
   487
    typedef DGR Digraph;
kpeter@559
   488
kpeter@559
   489
  private:
kpeter@559
   490
deba@598
   491
    TEMPLATE_DIGRAPH_TYPEDEFS(DGR);
alpar@209
   492
deba@127
   493
    std::istream* _is;
deba@127
   494
    bool local_is;
deba@290
   495
    std::string _filename;
deba@127
   496
deba@598
   497
    DGR& _digraph;
deba@127
   498
deba@127
   499
    std::string _nodes_caption;
deba@127
   500
    std::string _arcs_caption;
deba@127
   501
    std::string _attributes_caption;
deba@127
   502
deba@127
   503
    typedef std::map<std::string, Node> NodeIndex;
deba@127
   504
    NodeIndex _node_index;
deba@127
   505
    typedef std::map<std::string, Arc> ArcIndex;
deba@127
   506
    ArcIndex _arc_index;
alpar@209
   507
alpar@209
   508
    typedef std::vector<std::pair<std::string,
alpar@209
   509
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
alpar@209
   510
    NodeMaps _node_maps;
deba@127
   511
deba@127
   512
    typedef std::vector<std::pair<std::string,
deba@127
   513
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
deba@127
   514
    ArcMaps _arc_maps;
deba@127
   515
alpar@209
   516
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
deba@127
   517
      Attributes;
deba@127
   518
    Attributes _attributes;
deba@127
   519
deba@127
   520
    bool _use_nodes;
deba@127
   521
    bool _use_arcs;
deba@127
   522
deba@188
   523
    bool _skip_nodes;
deba@188
   524
    bool _skip_arcs;
deba@188
   525
deba@127
   526
    int line_num;
deba@127
   527
    std::istringstream line;
deba@127
   528
deba@127
   529
  public:
deba@127
   530
alpar@156
   531
    /// \brief Constructor
alpar@156
   532
    ///
alpar@156
   533
    /// Construct a directed graph reader, which reads from the given
alpar@156
   534
    /// input stream.
deba@598
   535
    DigraphReader(DGR& digraph, std::istream& is = std::cin)
deba@127
   536
      : _is(&is), local_is(false), _digraph(digraph),
alpar@209
   537
        _use_nodes(false), _use_arcs(false),
alpar@209
   538
        _skip_nodes(false), _skip_arcs(false) {}
deba@127
   539
alpar@156
   540
    /// \brief Constructor
alpar@156
   541
    ///
alpar@156
   542
    /// Construct a directed graph reader, which reads from the given
alpar@156
   543
    /// file.
deba@598
   544
    DigraphReader(DGR& digraph, const std::string& fn)
deba@290
   545
      : _is(new std::ifstream(fn.c_str())), local_is(true),
deba@290
   546
        _filename(fn), _digraph(digraph),
kpeter@212
   547
        _use_nodes(false), _use_arcs(false),
deba@290
   548
        _skip_nodes(false), _skip_arcs(false) {
deba@295
   549
      if (!(*_is)) {
deba@295
   550
        delete _is;
deba@295
   551
        throw IoError("Cannot open file", fn);
deba@295
   552
      }
deba@290
   553
    }
alpar@209
   554
alpar@156
   555
    /// \brief Constructor
alpar@156
   556
    ///
alpar@156
   557
    /// Construct a directed graph reader, which reads from the given
alpar@156
   558
    /// file.
deba@598
   559
    DigraphReader(DGR& digraph, const char* fn)
deba@290
   560
      : _is(new std::ifstream(fn)), local_is(true),
deba@290
   561
        _filename(fn), _digraph(digraph),
kpeter@212
   562
        _use_nodes(false), _use_arcs(false),
deba@290
   563
        _skip_nodes(false), _skip_arcs(false) {
deba@295
   564
      if (!(*_is)) {
deba@295
   565
        delete _is;
deba@295
   566
        throw IoError("Cannot open file", fn);
deba@295
   567
      }
deba@290
   568
    }
deba@127
   569
alpar@156
   570
    /// \brief Destructor
deba@127
   571
    ~DigraphReader() {
alpar@209
   572
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   573
           it != _node_maps.end(); ++it) {
alpar@209
   574
        delete it->second;
deba@127
   575
      }
deba@127
   576
alpar@209
   577
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   578
           it != _arc_maps.end(); ++it) {
alpar@209
   579
        delete it->second;
deba@127
   580
      }
deba@127
   581
alpar@209
   582
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
   583
           it != _attributes.end(); ++it) {
alpar@209
   584
        delete it->second;
deba@127
   585
      }
deba@127
   586
deba@127
   587
      if (local_is) {
alpar@209
   588
        delete _is;
deba@127
   589
      }
deba@127
   590
deba@127
   591
    }
deba@127
   592
deba@127
   593
  private:
deba@190
   594
deba@598
   595
    template <typename TDGR>
deba@598
   596
    friend DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is);
deba@598
   597
    template <typename TDGR>
alpar@877
   598
    friend DigraphReader<TDGR> digraphReader(TDGR& digraph,
deba@598
   599
                                             const std::string& fn);
deba@598
   600
    template <typename TDGR>
deba@598
   601
    friend DigraphReader<TDGR> digraphReader(TDGR& digraph, const char *fn);
alpar@209
   602
alpar@209
   603
    DigraphReader(DigraphReader& other)
deba@190
   604
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
alpar@209
   605
        _use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
alpar@209
   606
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
deba@190
   607
deba@190
   608
      other._is = 0;
deba@190
   609
      other.local_is = false;
alpar@209
   610
deba@190
   611
      _node_index.swap(other._node_index);
deba@190
   612
      _arc_index.swap(other._arc_index);
deba@190
   613
deba@190
   614
      _node_maps.swap(other._node_maps);
deba@190
   615
      _arc_maps.swap(other._arc_maps);
deba@190
   616
      _attributes.swap(other._attributes);
deba@190
   617
deba@190
   618
      _nodes_caption = other._nodes_caption;
deba@190
   619
      _arcs_caption = other._arcs_caption;
deba@190
   620
      _attributes_caption = other._attributes_caption;
deba@190
   621
deba@190
   622
    }
deba@190
   623
deba@127
   624
    DigraphReader& operator=(const DigraphReader&);
deba@127
   625
deba@127
   626
  public:
deba@127
   627
kpeter@584
   628
    /// \name Reading Rules
alpar@156
   629
    /// @{
alpar@209
   630
alpar@156
   631
    /// \brief Node map reading rule
alpar@156
   632
    ///
alpar@156
   633
    /// Add a node map reading rule to the reader.
deba@127
   634
    template <typename Map>
deba@127
   635
    DigraphReader& nodeMap(const std::string& caption, Map& map) {
deba@127
   636
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
alpar@209
   637
      _reader_bits::MapStorageBase<Node>* storage =
alpar@209
   638
        new _reader_bits::MapStorage<Node, Map>(map);
deba@127
   639
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   640
      return *this;
deba@127
   641
    }
deba@127
   642
alpar@156
   643
    /// \brief Node map reading rule
alpar@156
   644
    ///
alpar@156
   645
    /// Add a node map reading rule with specialized converter to the
alpar@156
   646
    /// reader.
deba@127
   647
    template <typename Map, typename Converter>
alpar@209
   648
    DigraphReader& nodeMap(const std::string& caption, Map& map,
alpar@209
   649
                           const Converter& converter = Converter()) {
deba@127
   650
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
alpar@209
   651
      _reader_bits::MapStorageBase<Node>* storage =
alpar@209
   652
        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@127
   653
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   654
      return *this;
deba@127
   655
    }
deba@127
   656
alpar@156
   657
    /// \brief Arc map reading rule
alpar@156
   658
    ///
alpar@156
   659
    /// Add an arc map reading rule to the reader.
deba@127
   660
    template <typename Map>
deba@127
   661
    DigraphReader& arcMap(const std::string& caption, Map& map) {
deba@127
   662
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
alpar@209
   663
      _reader_bits::MapStorageBase<Arc>* storage =
alpar@209
   664
        new _reader_bits::MapStorage<Arc, Map>(map);
deba@127
   665
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   666
      return *this;
deba@127
   667
    }
deba@127
   668
alpar@156
   669
    /// \brief Arc map reading rule
alpar@156
   670
    ///
alpar@156
   671
    /// Add an arc map reading rule with specialized converter to the
alpar@156
   672
    /// reader.
deba@127
   673
    template <typename Map, typename Converter>
alpar@209
   674
    DigraphReader& arcMap(const std::string& caption, Map& map,
alpar@209
   675
                          const Converter& converter = Converter()) {
deba@127
   676
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
alpar@209
   677
      _reader_bits::MapStorageBase<Arc>* storage =
alpar@209
   678
        new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
deba@127
   679
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   680
      return *this;
deba@127
   681
    }
deba@127
   682
alpar@156
   683
    /// \brief Attribute reading rule
alpar@156
   684
    ///
alpar@156
   685
    /// Add an attribute reading rule to the reader.
deba@127
   686
    template <typename Value>
deba@127
   687
    DigraphReader& attribute(const std::string& caption, Value& value) {
alpar@209
   688
      _reader_bits::ValueStorageBase* storage =
alpar@209
   689
        new _reader_bits::ValueStorage<Value>(value);
deba@127
   690
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   691
      return *this;
deba@127
   692
    }
deba@127
   693
alpar@156
   694
    /// \brief Attribute reading rule
alpar@156
   695
    ///
alpar@156
   696
    /// Add an attribute reading rule with specialized converter to the
alpar@156
   697
    /// reader.
deba@127
   698
    template <typename Value, typename Converter>
alpar@209
   699
    DigraphReader& attribute(const std::string& caption, Value& value,
alpar@209
   700
                             const Converter& converter = Converter()) {
alpar@209
   701
      _reader_bits::ValueStorageBase* storage =
alpar@209
   702
        new _reader_bits::ValueStorage<Value, Converter>(value, converter);
deba@127
   703
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   704
      return *this;
deba@127
   705
    }
deba@127
   706
alpar@156
   707
    /// \brief Node reading rule
alpar@156
   708
    ///
alpar@156
   709
    /// Add a node reading rule to reader.
deba@127
   710
    DigraphReader& node(const std::string& caption, Node& node) {
deba@127
   711
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
deba@127
   712
      Converter converter(_node_index);
alpar@209
   713
      _reader_bits::ValueStorageBase* storage =
alpar@209
   714
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
deba@127
   715
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   716
      return *this;
deba@127
   717
    }
deba@127
   718
alpar@156
   719
    /// \brief Arc reading rule
alpar@156
   720
    ///
alpar@156
   721
    /// Add an arc reading rule to reader.
deba@127
   722
    DigraphReader& arc(const std::string& caption, Arc& arc) {
deba@127
   723
      typedef _reader_bits::MapLookUpConverter<Arc> Converter;
deba@127
   724
      Converter converter(_arc_index);
alpar@209
   725
      _reader_bits::ValueStorageBase* storage =
alpar@209
   726
        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@127
   727
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   728
      return *this;
deba@127
   729
    }
deba@127
   730
alpar@156
   731
    /// @}
alpar@156
   732
kpeter@584
   733
    /// \name Select Section by Name
alpar@156
   734
    /// @{
alpar@156
   735
alpar@156
   736
    /// \brief Set \c \@nodes section to be read
alpar@156
   737
    ///
alpar@156
   738
    /// Set \c \@nodes section to be read
deba@127
   739
    DigraphReader& nodes(const std::string& caption) {
deba@127
   740
      _nodes_caption = caption;
deba@127
   741
      return *this;
deba@127
   742
    }
deba@127
   743
alpar@156
   744
    /// \brief Set \c \@arcs section to be read
alpar@156
   745
    ///
alpar@156
   746
    /// Set \c \@arcs section to be read
deba@127
   747
    DigraphReader& arcs(const std::string& caption) {
deba@127
   748
      _arcs_caption = caption;
deba@127
   749
      return *this;
deba@127
   750
    }
deba@127
   751
alpar@156
   752
    /// \brief Set \c \@attributes section to be read
alpar@156
   753
    ///
alpar@156
   754
    /// Set \c \@attributes section to be read
deba@127
   755
    DigraphReader& attributes(const std::string& caption) {
deba@127
   756
      _attributes_caption = caption;
deba@127
   757
      return *this;
deba@127
   758
    }
deba@127
   759
alpar@156
   760
    /// @}
alpar@156
   761
kpeter@584
   762
    /// \name Using Previously Constructed Node or Arc Set
alpar@156
   763
    /// @{
alpar@156
   764
alpar@156
   765
    /// \brief Use previously constructed node set
alpar@156
   766
    ///
alpar@156
   767
    /// Use previously constructed node set, and specify the node
alpar@156
   768
    /// label map.
deba@127
   769
    template <typename Map>
deba@127
   770
    DigraphReader& useNodes(const Map& map) {
deba@127
   771
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
   772
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
deba@127
   773
      _use_nodes = true;
deba@127
   774
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@127
   775
      for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   776
        _node_index.insert(std::make_pair(converter(map[n]), n));
deba@127
   777
      }
deba@127
   778
      return *this;
deba@127
   779
    }
deba@127
   780
alpar@156
   781
    /// \brief Use previously constructed node set
alpar@156
   782
    ///
alpar@156
   783
    /// Use previously constructed node set, and specify the node
alpar@156
   784
    /// label map and a functor which converts the label map values to
kpeter@192
   785
    /// \c std::string.
deba@127
   786
    template <typename Map, typename Converter>
alpar@209
   787
    DigraphReader& useNodes(const Map& map,
alpar@209
   788
                            const Converter& converter = Converter()) {
deba@127
   789
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
   790
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
deba@127
   791
      _use_nodes = true;
deba@127
   792
      for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   793
        _node_index.insert(std::make_pair(converter(map[n]), n));
deba@127
   794
      }
deba@127
   795
      return *this;
deba@127
   796
    }
deba@127
   797
alpar@156
   798
    /// \brief Use previously constructed arc set
alpar@156
   799
    ///
alpar@156
   800
    /// Use previously constructed arc set, and specify the arc
alpar@156
   801
    /// label map.
deba@127
   802
    template <typename Map>
deba@127
   803
    DigraphReader& useArcs(const Map& map) {
deba@127
   804
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@127
   805
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
deba@127
   806
      _use_arcs = true;
deba@127
   807
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@127
   808
      for (ArcIt a(_digraph); a != INVALID; ++a) {
alpar@209
   809
        _arc_index.insert(std::make_pair(converter(map[a]), a));
deba@127
   810
      }
deba@127
   811
      return *this;
deba@127
   812
    }
deba@127
   813
alpar@156
   814
    /// \brief Use previously constructed arc set
alpar@156
   815
    ///
alpar@156
   816
    /// Use previously constructed arc set, and specify the arc
alpar@156
   817
    /// label map and a functor which converts the label map values to
kpeter@192
   818
    /// \c std::string.
deba@127
   819
    template <typename Map, typename Converter>
alpar@209
   820
    DigraphReader& useArcs(const Map& map,
alpar@209
   821
                           const Converter& converter = Converter()) {
deba@127
   822
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
   823
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
deba@127
   824
      _use_arcs = true;
deba@127
   825
      for (ArcIt a(_digraph); a != INVALID; ++a) {
alpar@209
   826
        _arc_index.insert(std::make_pair(converter(map[a]), a));
deba@127
   827
      }
deba@127
   828
      return *this;
deba@127
   829
    }
deba@127
   830
deba@188
   831
    /// \brief Skips the reading of node section
deba@188
   832
    ///
deba@188
   833
    /// Omit the reading of the node section. This implies that each node
kpeter@192
   834
    /// map reading rule will be abandoned, and the nodes of the graph
deba@188
   835
    /// will not be constructed, which usually cause that the arc set
kpeter@192
   836
    /// could not be read due to lack of node name resolving.
kpeter@192
   837
    /// Therefore \c skipArcs() function should also be used, or
kpeter@192
   838
    /// \c useNodes() should be used to specify the label of the nodes.
deba@188
   839
    DigraphReader& skipNodes() {
alpar@209
   840
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
deba@188
   841
      _skip_nodes = true;
deba@188
   842
      return *this;
deba@188
   843
    }
deba@188
   844
deba@188
   845
    /// \brief Skips the reading of arc section
deba@188
   846
    ///
deba@188
   847
    /// Omit the reading of the arc section. This implies that each arc
kpeter@192
   848
    /// map reading rule will be abandoned, and the arcs of the graph
deba@188
   849
    /// will not be constructed.
deba@188
   850
    DigraphReader& skipArcs() {
alpar@209
   851
      LEMON_ASSERT(!_skip_arcs, "Skip arcs already set");
deba@188
   852
      _skip_arcs = true;
deba@188
   853
      return *this;
deba@188
   854
    }
deba@188
   855
alpar@156
   856
    /// @}
alpar@156
   857
deba@127
   858
  private:
deba@127
   859
deba@127
   860
    bool readLine() {
deba@127
   861
      std::string str;
deba@127
   862
      while(++line_num, std::getline(*_is, str)) {
alpar@209
   863
        line.clear(); line.str(str);
alpar@209
   864
        char c;
alpar@209
   865
        if (line >> std::ws >> c && c != '#') {
alpar@209
   866
          line.putback(c);
alpar@209
   867
          return true;
alpar@209
   868
        }
deba@127
   869
      }
deba@127
   870
      return false;
deba@127
   871
    }
deba@127
   872
deba@127
   873
    bool readSuccess() {
deba@127
   874
      return static_cast<bool>(*_is);
deba@127
   875
    }
alpar@209
   876
deba@127
   877
    void skipSection() {
deba@127
   878
      char c;
deba@127
   879
      while (readSuccess() && line >> c && c != '@') {
alpar@209
   880
        readLine();
deba@127
   881
      }
deba@427
   882
      if (readSuccess()) {
deba@427
   883
        line.putback(c);
deba@427
   884
      }
deba@127
   885
    }
deba@127
   886
deba@127
   887
    void readNodes() {
deba@127
   888
deba@127
   889
      std::vector<int> map_index(_node_maps.size());
deba@127
   890
      int map_num, label_index;
deba@127
   891
deba@186
   892
      char c;
deba@186
   893
      if (!readLine() || !(line >> c) || c == '@') {
alpar@209
   894
        if (readSuccess() && line) line.putback(c);
alpar@209
   895
        if (!_node_maps.empty())
deba@290
   896
          throw FormatError("Cannot find map names");
alpar@209
   897
        return;
deba@186
   898
      }
deba@186
   899
      line.putback(c);
deba@186
   900
deba@127
   901
      {
alpar@209
   902
        std::map<std::string, int> maps;
alpar@209
   903
alpar@209
   904
        std::string map;
alpar@209
   905
        int index = 0;
alpar@209
   906
        while (_reader_bits::readToken(line, map)) {
alpar@209
   907
          if (maps.find(map) != maps.end()) {
alpar@209
   908
            std::ostringstream msg;
alpar@209
   909
            msg << "Multiple occurence of node map: " << map;
deba@290
   910
            throw FormatError(msg.str());
alpar@209
   911
          }
alpar@209
   912
          maps.insert(std::make_pair(map, index));
alpar@209
   913
          ++index;
alpar@209
   914
        }
alpar@209
   915
alpar@209
   916
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
alpar@209
   917
          std::map<std::string, int>::iterator jt =
alpar@209
   918
            maps.find(_node_maps[i].first);
alpar@209
   919
          if (jt == maps.end()) {
alpar@209
   920
            std::ostringstream msg;
kpeter@291
   921
            msg << "Map not found: " << _node_maps[i].first;
deba@290
   922
            throw FormatError(msg.str());
alpar@209
   923
          }
alpar@209
   924
          map_index[i] = jt->second;
alpar@209
   925
        }
alpar@209
   926
alpar@209
   927
        {
alpar@209
   928
          std::map<std::string, int>::iterator jt = maps.find("label");
alpar@209
   929
          if (jt != maps.end()) {
alpar@209
   930
            label_index = jt->second;
alpar@209
   931
          } else {
alpar@209
   932
            label_index = -1;
alpar@209
   933
          }
alpar@209
   934
        }
alpar@209
   935
        map_num = maps.size();
deba@127
   936
      }
deba@127
   937
deba@127
   938
      while (readLine() && line >> c && c != '@') {
alpar@209
   939
        line.putback(c);
alpar@209
   940
alpar@209
   941
        std::vector<std::string> tokens(map_num);
alpar@209
   942
        for (int i = 0; i < map_num; ++i) {
alpar@209
   943
          if (!_reader_bits::readToken(line, tokens[i])) {
alpar@209
   944
            std::ostringstream msg;
alpar@209
   945
            msg << "Column not found (" << i + 1 << ")";
deba@290
   946
            throw FormatError(msg.str());
alpar@209
   947
          }
alpar@209
   948
        }
alpar@209
   949
        if (line >> std::ws >> c)
kpeter@291
   950
          throw FormatError("Extra character at the end of line");
alpar@209
   951
alpar@209
   952
        Node n;
alpar@209
   953
        if (!_use_nodes) {
alpar@209
   954
          n = _digraph.addNode();
alpar@209
   955
          if (label_index != -1)
alpar@209
   956
            _node_index.insert(std::make_pair(tokens[label_index], n));
alpar@209
   957
        } else {
alpar@209
   958
          if (label_index == -1)
kpeter@291
   959
            throw FormatError("Label map not found");
alpar@209
   960
          typename std::map<std::string, Node>::iterator it =
alpar@209
   961
            _node_index.find(tokens[label_index]);
alpar@209
   962
          if (it == _node_index.end()) {
alpar@209
   963
            std::ostringstream msg;
alpar@209
   964
            msg << "Node with label not found: " << tokens[label_index];
deba@290
   965
            throw FormatError(msg.str());
alpar@209
   966
          }
alpar@209
   967
          n = it->second;
alpar@209
   968
        }
alpar@209
   969
alpar@209
   970
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
alpar@209
   971
          _node_maps[i].second->set(n, tokens[map_index[i]]);
alpar@209
   972
        }
deba@127
   973
deba@127
   974
      }
deba@127
   975
      if (readSuccess()) {
alpar@209
   976
        line.putback(c);
deba@127
   977
      }
deba@127
   978
    }
deba@127
   979
deba@127
   980
    void readArcs() {
deba@127
   981
deba@127
   982
      std::vector<int> map_index(_arc_maps.size());
deba@127
   983
      int map_num, label_index;
deba@127
   984
deba@186
   985
      char c;
deba@186
   986
      if (!readLine() || !(line >> c) || c == '@') {
alpar@209
   987
        if (readSuccess() && line) line.putback(c);
alpar@209
   988
        if (!_arc_maps.empty())
deba@290
   989
          throw FormatError("Cannot find map names");
alpar@209
   990
        return;
deba@186
   991
      }
deba@186
   992
      line.putback(c);
alpar@209
   993
deba@127
   994
      {
alpar@209
   995
        std::map<std::string, int> maps;
alpar@209
   996
alpar@209
   997
        std::string map;
alpar@209
   998
        int index = 0;
alpar@209
   999
        while (_reader_bits::readToken(line, map)) {
alpar@949
  1000
          if(map == "-") {
alpar@949
  1001
              if(index!=0)
alpar@949
  1002
                throw FormatError("'-' is not allowed as a map name");
alpar@949
  1003
              else if (line >> std::ws >> c)
alpar@949
  1004
                throw FormatError("Extra character at the end of line");
alpar@949
  1005
              else break;
alpar@949
  1006
            }
alpar@209
  1007
          if (maps.find(map) != maps.end()) {
alpar@209
  1008
            std::ostringstream msg;
alpar@209
  1009
            msg << "Multiple occurence of arc map: " << map;
deba@290
  1010
            throw FormatError(msg.str());
alpar@209
  1011
          }
alpar@209
  1012
          maps.insert(std::make_pair(map, index));
alpar@209
  1013
          ++index;
alpar@209
  1014
        }
alpar@209
  1015
alpar@209
  1016
        for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
alpar@209
  1017
          std::map<std::string, int>::iterator jt =
alpar@209
  1018
            maps.find(_arc_maps[i].first);
alpar@209
  1019
          if (jt == maps.end()) {
alpar@209
  1020
            std::ostringstream msg;
kpeter@291
  1021
            msg << "Map not found: " << _arc_maps[i].first;
deba@290
  1022
            throw FormatError(msg.str());
alpar@209
  1023
          }
alpar@209
  1024
          map_index[i] = jt->second;
alpar@209
  1025
        }
alpar@209
  1026
alpar@209
  1027
        {
alpar@209
  1028
          std::map<std::string, int>::iterator jt = maps.find("label");
alpar@209
  1029
          if (jt != maps.end()) {
alpar@209
  1030
            label_index = jt->second;
alpar@209
  1031
          } else {
alpar@209
  1032
            label_index = -1;
alpar@209
  1033
          }
alpar@209
  1034
        }
alpar@209
  1035
        map_num = maps.size();
deba@127
  1036
      }
deba@127
  1037
deba@127
  1038
      while (readLine() && line >> c && c != '@') {
alpar@209
  1039
        line.putback(c);
alpar@209
  1040
alpar@209
  1041
        std::string source_token;
alpar@209
  1042
        std::string target_token;
alpar@209
  1043
alpar@209
  1044
        if (!_reader_bits::readToken(line, source_token))
deba@290
  1045
          throw FormatError("Source not found");
alpar@209
  1046
alpar@209
  1047
        if (!_reader_bits::readToken(line, target_token))
deba@290
  1048
          throw FormatError("Target not found");
alpar@209
  1049
alpar@209
  1050
        std::vector<std::string> tokens(map_num);
alpar@209
  1051
        for (int i = 0; i < map_num; ++i) {
alpar@209
  1052
          if (!_reader_bits::readToken(line, tokens[i])) {
alpar@209
  1053
            std::ostringstream msg;
alpar@209
  1054
            msg << "Column not found (" << i + 1 << ")";
deba@290
  1055
            throw FormatError(msg.str());
alpar@209
  1056
          }
alpar@209
  1057
        }
alpar@209
  1058
        if (line >> std::ws >> c)
kpeter@291
  1059
          throw FormatError("Extra character at the end of line");
alpar@209
  1060
alpar@209
  1061
        Arc a;
alpar@209
  1062
        if (!_use_arcs) {
deba@127
  1063
deba@127
  1064
          typename NodeIndex::iterator it;
alpar@209
  1065
deba@127
  1066
          it = _node_index.find(source_token);
deba@127
  1067
          if (it == _node_index.end()) {
deba@127
  1068
            std::ostringstream msg;
deba@127
  1069
            msg << "Item not found: " << source_token;
deba@290
  1070
            throw FormatError(msg.str());
deba@127
  1071
          }
deba@127
  1072
          Node source = it->second;
deba@127
  1073
deba@127
  1074
          it = _node_index.find(target_token);
alpar@209
  1075
          if (it == _node_index.end()) {
alpar@209
  1076
            std::ostringstream msg;
deba@127
  1077
            msg << "Item not found: " << target_token;
deba@290
  1078
            throw FormatError(msg.str());
alpar@209
  1079
          }
alpar@209
  1080
          Node target = it->second;
alpar@209
  1081
alpar@209
  1082
          a = _digraph.addArc(source, target);
alpar@209
  1083
          if (label_index != -1)
alpar@209
  1084
            _arc_index.insert(std::make_pair(tokens[label_index], a));
alpar@209
  1085
        } else {
alpar@209
  1086
          if (label_index == -1)
kpeter@291
  1087
            throw FormatError("Label map not found");
alpar@209
  1088
          typename std::map<std::string, Arc>::iterator it =
alpar@209
  1089
            _arc_index.find(tokens[label_index]);
alpar@209
  1090
          if (it == _arc_index.end()) {
alpar@209
  1091
            std::ostringstream msg;
alpar@209
  1092
            msg << "Arc with label not found: " << tokens[label_index];
deba@290
  1093
            throw FormatError(msg.str());
alpar@209
  1094
          }
alpar@209
  1095
          a = it->second;
alpar@209
  1096
        }
alpar@209
  1097
alpar@209
  1098
        for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
alpar@209
  1099
          _arc_maps[i].second->set(a, tokens[map_index[i]]);
alpar@209
  1100
        }
deba@127
  1101
deba@127
  1102
      }
deba@127
  1103
      if (readSuccess()) {
alpar@209
  1104
        line.putback(c);
deba@127
  1105
      }
deba@127
  1106
    }
deba@127
  1107
deba@127
  1108
    void readAttributes() {
deba@127
  1109
deba@127
  1110
      std::set<std::string> read_attr;
deba@127
  1111
deba@127
  1112
      char c;
deba@127
  1113
      while (readLine() && line >> c && c != '@') {
alpar@209
  1114
        line.putback(c);
alpar@209
  1115
alpar@209
  1116
        std::string attr, token;
alpar@209
  1117
        if (!_reader_bits::readToken(line, attr))
deba@290
  1118
          throw FormatError("Attribute name not found");
alpar@209
  1119
        if (!_reader_bits::readToken(line, token))
deba@290
  1120
          throw FormatError("Attribute value not found");
alpar@209
  1121
        if (line >> c)
kpeter@291
  1122
          throw FormatError("Extra character at the end of line");
alpar@209
  1123
alpar@209
  1124
        {
alpar@209
  1125
          std::set<std::string>::iterator it = read_attr.find(attr);
alpar@209
  1126
          if (it != read_attr.end()) {
alpar@209
  1127
            std::ostringstream msg;
kpeter@291
  1128
            msg << "Multiple occurence of attribute: " << attr;
deba@290
  1129
            throw FormatError(msg.str());
alpar@209
  1130
          }
alpar@209
  1131
          read_attr.insert(attr);
alpar@209
  1132
        }
alpar@209
  1133
alpar@209
  1134
        {
alpar@209
  1135
          typename Attributes::iterator it = _attributes.lower_bound(attr);
alpar@209
  1136
          while (it != _attributes.end() && it->first == attr) {
alpar@209
  1137
            it->second->set(token);
alpar@209
  1138
            ++it;
alpar@209
  1139
          }
alpar@209
  1140
        }
deba@127
  1141
deba@127
  1142
      }
deba@127
  1143
      if (readSuccess()) {
alpar@209
  1144
        line.putback(c);
deba@127
  1145
      }
deba@127
  1146
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1147
           it != _attributes.end(); ++it) {
alpar@209
  1148
        if (read_attr.find(it->first) == read_attr.end()) {
alpar@209
  1149
          std::ostringstream msg;
kpeter@291
  1150
          msg << "Attribute not found: " << it->first;
deba@290
  1151
          throw FormatError(msg.str());
alpar@209
  1152
        }
deba@127
  1153
      }
deba@127
  1154
    }
deba@127
  1155
deba@127
  1156
  public:
alpar@156
  1157
kpeter@584
  1158
    /// \name Execution of the Reader
alpar@156
  1159
    /// @{
alpar@156
  1160
alpar@156
  1161
    /// \brief Start the batch processing
alpar@156
  1162
    ///
alpar@156
  1163
    /// This function starts the batch processing
deba@127
  1164
    void run() {
deba@127
  1165
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
alpar@209
  1166
deba@188
  1167
      bool nodes_done = _skip_nodes;
deba@188
  1168
      bool arcs_done = _skip_arcs;
deba@127
  1169
      bool attributes_done = false;
deba@127
  1170
alpar@209
  1171
      line_num = 0;
deba@127
  1172
      readLine();
deba@172
  1173
      skipSection();
deba@127
  1174
deba@127
  1175
      while (readSuccess()) {
alpar@209
  1176
        try {
alpar@209
  1177
          char c;
alpar@209
  1178
          std::string section, caption;
alpar@209
  1179
          line >> c;
alpar@209
  1180
          _reader_bits::readToken(line, section);
alpar@209
  1181
          _reader_bits::readToken(line, caption);
alpar@209
  1182
alpar@209
  1183
          if (line >> c)
kpeter@291
  1184
            throw FormatError("Extra character at the end of line");
alpar@209
  1185
alpar@209
  1186
          if (section == "nodes" && !nodes_done) {
alpar@209
  1187
            if (_nodes_caption.empty() || _nodes_caption == caption) {
alpar@209
  1188
              readNodes();
alpar@209
  1189
              nodes_done = true;
alpar@209
  1190
            }
alpar@209
  1191
          } else if ((section == "arcs" || section == "edges") &&
alpar@209
  1192
                     !arcs_done) {
alpar@209
  1193
            if (_arcs_caption.empty() || _arcs_caption == caption) {
alpar@209
  1194
              readArcs();
alpar@209
  1195
              arcs_done = true;
alpar@209
  1196
            }
alpar@209
  1197
          } else if (section == "attributes" && !attributes_done) {
alpar@209
  1198
            if (_attributes_caption.empty() || _attributes_caption == caption) {
alpar@209
  1199
              readAttributes();
alpar@209
  1200
              attributes_done = true;
alpar@209
  1201
            }
alpar@209
  1202
          } else {
alpar@209
  1203
            readLine();
alpar@209
  1204
            skipSection();
alpar@209
  1205
          }
deba@290
  1206
        } catch (FormatError& error) {
alpar@209
  1207
          error.line(line_num);
deba@290
  1208
          error.file(_filename);
alpar@209
  1209
          throw;
alpar@209
  1210
        }
deba@127
  1211
      }
deba@127
  1212
deba@127
  1213
      if (!nodes_done) {
deba@290
  1214
        throw FormatError("Section @nodes not found");
deba@127
  1215
      }
deba@127
  1216
deba@127
  1217
      if (!arcs_done) {
deba@290
  1218
        throw FormatError("Section @arcs not found");
deba@127
  1219
      }
deba@127
  1220
deba@127
  1221
      if (!attributes_done && !_attributes.empty()) {
deba@290
  1222
        throw FormatError("Section @attributes not found");
deba@127
  1223
      }
deba@127
  1224
deba@127
  1225
    }
alpar@156
  1226
alpar@156
  1227
    /// @}
alpar@209
  1228
deba@127
  1229
  };
alpar@877
  1230
deba@598
  1231
  /// \ingroup lemon_io
deba@598
  1232
  ///
alpar@1076
  1233
  /// \brief Return a \ref lemon::DigraphReader "DigraphReader" class
deba@598
  1234
  ///
alpar@1076
  1235
  /// This function just returns a \ref lemon::DigraphReader
alpar@1076
  1236
  /// "DigraphReader" class.
deba@598
  1237
  ///
alpar@877
  1238
  /// With this function a digraph can be read from an
deba@598
  1239
  /// \ref lgf-format "LGF" file or input stream with several maps and
deba@598
  1240
  /// attributes. For example, there is network flow problem on a
deba@598
  1241
  /// digraph, i.e. a digraph with a \e capacity map on the arcs and
deba@598
  1242
  /// \e source and \e target nodes. This digraph can be read with the
deba@598
  1243
  /// following code:
deba@598
  1244
  ///
deba@598
  1245
  ///\code
deba@598
  1246
  ///ListDigraph digraph;
deba@598
  1247
  ///ListDigraph::ArcMap<int> cm(digraph);
deba@598
  1248
  ///ListDigraph::Node src, trg;
deba@598
  1249
  ///digraphReader(digraph, std::cin).
deba@598
  1250
  ///  arcMap("capacity", cap).
deba@598
  1251
  ///  node("source", src).
deba@598
  1252
  ///  node("target", trg).
deba@598
  1253
  ///  run();
deba@598
  1254
  ///\endcode
deba@598
  1255
  ///
alpar@1076
  1256
  /// For a complete documentation, please see the
alpar@1076
  1257
  /// \ref lemon::DigraphReader "DigraphReader"
deba@598
  1258
  /// class documentation.
alpar@1076
  1259
  /// \warning Don't forget to put the \ref lemon::DigraphReader::run() "run()"
deba@598
  1260
  /// to the end of the parameter list.
deba@598
  1261
  /// \relates DigraphReader
deba@598
  1262
  /// \sa digraphReader(TDGR& digraph, const std::string& fn)
deba@598
  1263
  /// \sa digraphReader(TDGR& digraph, const char* fn)
deba@598
  1264
  template <typename TDGR>
deba@598
  1265
  DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is) {
deba@598
  1266
    DigraphReader<TDGR> tmp(digraph, is);
deba@598
  1267
    return tmp;
deba@598
  1268
  }
deba@127
  1269
kpeter@487
  1270
  /// \brief Return a \ref DigraphReader class
kpeter@487
  1271
  ///
kpeter@487
  1272
  /// This function just returns a \ref DigraphReader class.
kpeter@487
  1273
  /// \relates DigraphReader
deba@598
  1274
  /// \sa digraphReader(TDGR& digraph, std::istream& is)
deba@598
  1275
  template <typename TDGR>
deba@598
  1276
  DigraphReader<TDGR> digraphReader(TDGR& digraph, const std::string& fn) {
deba@598
  1277
    DigraphReader<TDGR> tmp(digraph, fn);
kpeter@487
  1278
    return tmp;
kpeter@487
  1279
  }
kpeter@487
  1280
kpeter@487
  1281
  /// \brief Return a \ref DigraphReader class
kpeter@487
  1282
  ///
kpeter@487
  1283
  /// This function just returns a \ref DigraphReader class.
kpeter@487
  1284
  /// \relates DigraphReader
deba@598
  1285
  /// \sa digraphReader(TDGR& digraph, std::istream& is)
deba@598
  1286
  template <typename TDGR>
deba@598
  1287
  DigraphReader<TDGR> digraphReader(TDGR& digraph, const char* fn) {
deba@598
  1288
    DigraphReader<TDGR> tmp(digraph, fn);
kpeter@487
  1289
    return tmp;
kpeter@487
  1290
  }
kpeter@487
  1291
deba@598
  1292
  template <typename GR>
ladanyi@303
  1293
  class GraphReader;
alpar@877
  1294
deba@598
  1295
  template <typename TGR>
deba@598
  1296
  GraphReader<TGR> graphReader(TGR& graph, std::istream& is = std::cin);
deba@598
  1297
  template <typename TGR>
deba@598
  1298
  GraphReader<TGR> graphReader(TGR& graph, const std::string& fn);
deba@598
  1299
  template <typename TGR>
deba@598
  1300
  GraphReader<TGR> graphReader(TGR& graph, const char *fn);
deba@165
  1301
deba@165
  1302
  /// \ingroup lemon_io
alpar@209
  1303
  ///
kpeter@192
  1304
  /// \brief \ref lgf-format "LGF" reader for undirected graphs
deba@165
  1305
  ///
deba@165
  1306
  /// This utility reads an \ref lgf-format "LGF" file.
kpeter@192
  1307
  ///
kpeter@192
  1308
  /// It can be used almost the same way as \c DigraphReader.
kpeter@192
  1309
  /// The only difference is that this class can handle edges and
kpeter@192
  1310
  /// edge maps as well as arcs and arc maps.
deba@201
  1311
  ///
deba@201
  1312
  /// The columns in the \c \@edges (or \c \@arcs) section are the
deba@201
  1313
  /// edge maps. However, if there are two maps with the same name
deba@201
  1314
  /// prefixed with \c '+' and \c '-', then these can be read into an
deba@201
  1315
  /// arc map.  Similarly, an attribute can be read into an arc, if
deba@201
  1316
  /// it's value is an edge label prefixed with \c '+' or \c '-'.
kpeter@559
  1317
  template <typename GR>
deba@165
  1318
  class GraphReader {
deba@165
  1319
  public:
deba@165
  1320
kpeter@559
  1321
    typedef GR Graph;
kpeter@559
  1322
kpeter@559
  1323
  private:
kpeter@559
  1324
deba@598
  1325
    TEMPLATE_GRAPH_TYPEDEFS(GR);
alpar@209
  1326
deba@165
  1327
    std::istream* _is;
deba@165
  1328
    bool local_is;
deba@290
  1329
    std::string _filename;
deba@165
  1330
deba@598
  1331
    GR& _graph;
deba@165
  1332
deba@165
  1333
    std::string _nodes_caption;
deba@165
  1334
    std::string _edges_caption;
deba@165
  1335
    std::string _attributes_caption;
deba@165
  1336
deba@165
  1337
    typedef std::map<std::string, Node> NodeIndex;
deba@165
  1338
    NodeIndex _node_index;
deba@165
  1339
    typedef std::map<std::string, Edge> EdgeIndex;
deba@165
  1340
    EdgeIndex _edge_index;
alpar@209
  1341
alpar@209
  1342
    typedef std::vector<std::pair<std::string,
alpar@209
  1343
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
alpar@209
  1344
    NodeMaps _node_maps;
deba@165
  1345
deba@165
  1346
    typedef std::vector<std::pair<std::string,
deba@165
  1347
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
deba@165
  1348
    EdgeMaps _edge_maps;
deba@165
  1349
alpar@209
  1350
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
deba@165
  1351
      Attributes;
deba@165
  1352
    Attributes _attributes;
deba@165
  1353
deba@165
  1354
    bool _use_nodes;
deba@165
  1355
    bool _use_edges;
deba@165
  1356
deba@188
  1357
    bool _skip_nodes;
deba@188
  1358
    bool _skip_edges;
deba@188
  1359
deba@165
  1360
    int line_num;
deba@165
  1361
    std::istringstream line;
deba@165
  1362
deba@165
  1363
  public:
deba@165
  1364
deba@165
  1365
    /// \brief Constructor
deba@165
  1366
    ///
kpeter@192
  1367
    /// Construct an undirected graph reader, which reads from the given
deba@165
  1368
    /// input stream.
deba@598
  1369
    GraphReader(GR& graph, std::istream& is = std::cin)
deba@165
  1370
      : _is(&is), local_is(false), _graph(graph),
alpar@209
  1371
        _use_nodes(false), _use_edges(false),
alpar@209
  1372
        _skip_nodes(false), _skip_edges(false) {}
deba@165
  1373
deba@165
  1374
    /// \brief Constructor
deba@165
  1375
    ///
kpeter@192
  1376
    /// Construct an undirected graph reader, which reads from the given
deba@165
  1377
    /// file.
deba@598
  1378
    GraphReader(GR& graph, const std::string& fn)
deba@290
  1379
      : _is(new std::ifstream(fn.c_str())), local_is(true),
deba@290
  1380
        _filename(fn), _graph(graph),
kpeter@212
  1381
        _use_nodes(false), _use_edges(false),
deba@290
  1382
        _skip_nodes(false), _skip_edges(false) {
deba@295
  1383
      if (!(*_is)) {
deba@295
  1384
        delete _is;
deba@295
  1385
        throw IoError("Cannot open file", fn);
deba@295
  1386
      }
deba@290
  1387
    }
alpar@209
  1388
deba@165
  1389
    /// \brief Constructor
deba@165
  1390
    ///
kpeter@192
  1391
    /// Construct an undirected graph reader, which reads from the given
deba@165
  1392
    /// file.
deba@598
  1393
    GraphReader(GR& graph, const char* fn)
deba@290
  1394
      : _is(new std::ifstream(fn)), local_is(true),
deba@290
  1395
        _filename(fn), _graph(graph),
kpeter@212
  1396
        _use_nodes(false), _use_edges(false),
deba@290
  1397
        _skip_nodes(false), _skip_edges(false) {
deba@295
  1398
      if (!(*_is)) {
deba@295
  1399
        delete _is;
deba@295
  1400
        throw IoError("Cannot open file", fn);
deba@295
  1401
      }
deba@290
  1402
    }
deba@165
  1403
deba@165
  1404
    /// \brief Destructor
deba@165
  1405
    ~GraphReader() {
alpar@209
  1406
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1407
           it != _node_maps.end(); ++it) {
alpar@209
  1408
        delete it->second;
deba@165
  1409
      }
deba@165
  1410
alpar@209
  1411
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1412
           it != _edge_maps.end(); ++it) {
alpar@209
  1413
        delete it->second;
deba@165
  1414
      }
deba@165
  1415
alpar@209
  1416
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1417
           it != _attributes.end(); ++it) {
alpar@209
  1418
        delete it->second;
deba@165
  1419
      }
deba@165
  1420
deba@165
  1421
      if (local_is) {
alpar@209
  1422
        delete _is;
deba@165
  1423
      }
deba@165
  1424
deba@165
  1425
    }
deba@165
  1426
deba@165
  1427
  private:
deba@598
  1428
    template <typename TGR>
deba@598
  1429
    friend GraphReader<TGR> graphReader(TGR& graph, std::istream& is);
deba@598
  1430
    template <typename TGR>
alpar@877
  1431
    friend GraphReader<TGR> graphReader(TGR& graph, const std::string& fn);
deba@598
  1432
    template <typename TGR>
deba@598
  1433
    friend GraphReader<TGR> graphReader(TGR& graph, const char *fn);
alpar@209
  1434
alpar@209
  1435
    GraphReader(GraphReader& other)
deba@190
  1436
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
alpar@209
  1437
        _use_nodes(other._use_nodes), _use_edges(other._use_edges),
alpar@209
  1438
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
deba@190
  1439
deba@190
  1440
      other._is = 0;
deba@190
  1441
      other.local_is = false;
alpar@209
  1442
deba@190
  1443
      _node_index.swap(other._node_index);
deba@190
  1444
      _edge_index.swap(other._edge_index);
deba@190
  1445
deba@190
  1446
      _node_maps.swap(other._node_maps);
deba@190
  1447
      _edge_maps.swap(other._edge_maps);
deba@190
  1448
      _attributes.swap(other._attributes);
deba@190
  1449
deba@190
  1450
      _nodes_caption = other._nodes_caption;
deba@190
  1451
      _edges_caption = other._edges_caption;
deba@190
  1452
      _attributes_caption = other._attributes_caption;
deba@190
  1453
deba@190
  1454
    }
deba@190
  1455
deba@165
  1456
    GraphReader& operator=(const GraphReader&);
deba@165
  1457
deba@165
  1458
  public:
deba@165
  1459
kpeter@584
  1460
    /// \name Reading Rules
deba@165
  1461
    /// @{
alpar@209
  1462
deba@165
  1463
    /// \brief Node map reading rule
deba@165
  1464
    ///
deba@165
  1465
    /// Add a node map reading rule to the reader.
deba@165
  1466
    template <typename Map>
deba@165
  1467
    GraphReader& nodeMap(const std::string& caption, Map& map) {
deba@165
  1468
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
alpar@209
  1469
      _reader_bits::MapStorageBase<Node>* storage =
alpar@209
  1470
        new _reader_bits::MapStorage<Node, Map>(map);
deba@165
  1471
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1472
      return *this;
deba@165
  1473
    }
deba@165
  1474
deba@165
  1475
    /// \brief Node map reading rule
deba@165
  1476
    ///
deba@165
  1477
    /// Add a node map reading rule with specialized converter to the
deba@165
  1478
    /// reader.
deba@165
  1479
    template <typename Map, typename Converter>
alpar@209
  1480
    GraphReader& nodeMap(const std::string& caption, Map& map,
alpar@209
  1481
                           const Converter& converter = Converter()) {
deba@165
  1482
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
alpar@209
  1483
      _reader_bits::MapStorageBase<Node>* storage =
alpar@209
  1484
        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@165
  1485
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1486
      return *this;
deba@165
  1487
    }
deba@165
  1488
deba@165
  1489
    /// \brief Edge map reading rule
deba@165
  1490
    ///
deba@165
  1491
    /// Add an edge map reading rule to the reader.
deba@165
  1492
    template <typename Map>
deba@165
  1493
    GraphReader& edgeMap(const std::string& caption, Map& map) {
deba@165
  1494
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
alpar@209
  1495
      _reader_bits::MapStorageBase<Edge>* storage =
alpar@209
  1496
        new _reader_bits::MapStorage<Edge, Map>(map);
deba@165
  1497
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1498
      return *this;
deba@165
  1499
    }
deba@165
  1500
deba@165
  1501
    /// \brief Edge map reading rule
deba@165
  1502
    ///
deba@165
  1503
    /// Add an edge map reading rule with specialized converter to the
deba@165
  1504
    /// reader.
deba@165
  1505
    template <typename Map, typename Converter>
alpar@209
  1506
    GraphReader& edgeMap(const std::string& caption, Map& map,
alpar@209
  1507
                          const Converter& converter = Converter()) {
deba@165
  1508
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
alpar@209
  1509
      _reader_bits::MapStorageBase<Edge>* storage =
alpar@209
  1510
        new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
deba@165
  1511
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1512
      return *this;
deba@165
  1513
    }
deba@165
  1514
deba@165
  1515
    /// \brief Arc map reading rule
deba@165
  1516
    ///
deba@165
  1517
    /// Add an arc map reading rule to the reader.
deba@165
  1518
    template <typename Map>
deba@165
  1519
    GraphReader& arcMap(const std::string& caption, Map& map) {
deba@165
  1520
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
alpar@209
  1521
      _reader_bits::MapStorageBase<Edge>* forward_storage =
alpar@209
  1522
        new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
deba@165
  1523
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
alpar@209
  1524
      _reader_bits::MapStorageBase<Edge>* backward_storage =
deba@598
  1525
        new _reader_bits::GraphArcMapStorage<GR, false, Map>(_graph, map);
deba@165
  1526
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1527
      return *this;
deba@165
  1528
    }
deba@165
  1529
deba@165
  1530
    /// \brief Arc map reading rule
deba@165
  1531
    ///
deba@165
  1532
    /// Add an arc map reading rule with specialized converter to the
deba@165
  1533
    /// reader.
deba@165
  1534
    template <typename Map, typename Converter>
alpar@209
  1535
    GraphReader& arcMap(const std::string& caption, Map& map,
alpar@209
  1536
                          const Converter& converter = Converter()) {
deba@165
  1537
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
alpar@209
  1538
      _reader_bits::MapStorageBase<Edge>* forward_storage =
deba@598
  1539
        new _reader_bits::GraphArcMapStorage<GR, true, Map, Converter>
alpar@209
  1540
        (_graph, map, converter);
deba@165
  1541
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
alpar@209
  1542
      _reader_bits::MapStorageBase<Edge>* backward_storage =
deba@598
  1543
        new _reader_bits::GraphArcMapStorage<GR, false, Map, Converter>
alpar@209
  1544
        (_graph, map, converter);
deba@165
  1545
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1546
      return *this;
deba@165
  1547
    }
deba@165
  1548
deba@165
  1549
    /// \brief Attribute reading rule
deba@165
  1550
    ///
deba@165
  1551
    /// Add an attribute reading rule to the reader.
deba@165
  1552
    template <typename Value>
deba@165
  1553
    GraphReader& attribute(const std::string& caption, Value& value) {
alpar@209
  1554
      _reader_bits::ValueStorageBase* storage =
alpar@209
  1555
        new _reader_bits::ValueStorage<Value>(value);
deba@165
  1556
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1557
      return *this;
deba@165
  1558
    }
deba@165
  1559
deba@165
  1560
    /// \brief Attribute reading rule
deba@165
  1561
    ///
deba@165
  1562
    /// Add an attribute reading rule with specialized converter to the
deba@165
  1563
    /// reader.
deba@165
  1564
    template <typename Value, typename Converter>
alpar@209
  1565
    GraphReader& attribute(const std::string& caption, Value& value,
alpar@209
  1566
                             const Converter& converter = Converter()) {
alpar@209
  1567
      _reader_bits::ValueStorageBase* storage =
alpar@209
  1568
        new _reader_bits::ValueStorage<Value, Converter>(value, converter);
deba@165
  1569
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1570
      return *this;
deba@165
  1571
    }
deba@165
  1572
deba@165
  1573
    /// \brief Node reading rule
deba@165
  1574
    ///
deba@165
  1575
    /// Add a node reading rule to reader.
deba@165
  1576
    GraphReader& node(const std::string& caption, Node& node) {
deba@165
  1577
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
deba@165
  1578
      Converter converter(_node_index);
alpar@209
  1579
      _reader_bits::ValueStorageBase* storage =
alpar@209
  1580
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
deba@165
  1581
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1582
      return *this;
deba@165
  1583
    }
deba@165
  1584
deba@165
  1585
    /// \brief Edge reading rule
deba@165
  1586
    ///
deba@165
  1587
    /// Add an edge reading rule to reader.
deba@165
  1588
    GraphReader& edge(const std::string& caption, Edge& edge) {
deba@165
  1589
      typedef _reader_bits::MapLookUpConverter<Edge> Converter;
deba@165
  1590
      Converter converter(_edge_index);
alpar@209
  1591
      _reader_bits::ValueStorageBase* storage =
alpar@209
  1592
        new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
deba@165
  1593
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1594
      return *this;
deba@165
  1595
    }
deba@165
  1596
deba@165
  1597
    /// \brief Arc reading rule
deba@165
  1598
    ///
deba@165
  1599
    /// Add an arc reading rule to reader.
deba@165
  1600
    GraphReader& arc(const std::string& caption, Arc& arc) {
deba@598
  1601
      typedef _reader_bits::GraphArcLookUpConverter<GR> Converter;
deba@165
  1602
      Converter converter(_graph, _edge_index);
alpar@209
  1603
      _reader_bits::ValueStorageBase* storage =
alpar@209
  1604
        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@165
  1605
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1606
      return *this;
deba@165
  1607
    }
deba@165
  1608
deba@165
  1609
    /// @}
deba@165
  1610
kpeter@584
  1611
    /// \name Select Section by Name
deba@165
  1612
    /// @{
deba@165
  1613
deba@165
  1614
    /// \brief Set \c \@nodes section to be read
deba@165
  1615
    ///
kpeter@192
  1616
    /// Set \c \@nodes section to be read.
deba@165
  1617
    GraphReader& nodes(const std::string& caption) {
deba@165
  1618
      _nodes_caption = caption;
deba@165
  1619
      return *this;
deba@165
  1620
    }
deba@165
  1621
deba@165
  1622
    /// \brief Set \c \@edges section to be read
deba@165
  1623
    ///
kpeter@192
  1624
    /// Set \c \@edges section to be read.
deba@165
  1625
    GraphReader& edges(const std::string& caption) {
deba@165
  1626
      _edges_caption = caption;
deba@165
  1627
      return *this;
deba@165
  1628
    }
deba@165
  1629
deba@165
  1630
    /// \brief Set \c \@attributes section to be read
deba@165
  1631
    ///
kpeter@192
  1632
    /// Set \c \@attributes section to be read.
deba@165
  1633
    GraphReader& attributes(const std::string& caption) {
deba@165
  1634
      _attributes_caption = caption;
deba@165
  1635
      return *this;
deba@165
  1636
    }
deba@165
  1637
deba@165
  1638
    /// @}
deba@165
  1639
kpeter@584
  1640
    /// \name Using Previously Constructed Node or Edge Set
deba@165
  1641
    /// @{
deba@165
  1642
deba@165
  1643
    /// \brief Use previously constructed node set
deba@165
  1644
    ///
deba@165
  1645
    /// Use previously constructed node set, and specify the node
deba@165
  1646
    /// label map.
deba@165
  1647
    template <typename Map>
deba@165
  1648
    GraphReader& useNodes(const Map& map) {
deba@165
  1649
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
  1650
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
deba@165
  1651
      _use_nodes = true;
deba@165
  1652
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@165
  1653
      for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1654
        _node_index.insert(std::make_pair(converter(map[n]), n));
deba@165
  1655
      }
deba@165
  1656
      return *this;
deba@165
  1657
    }
deba@165
  1658
deba@165
  1659
    /// \brief Use previously constructed node set
deba@165
  1660
    ///
deba@165
  1661
    /// Use previously constructed node set, and specify the node
deba@165
  1662
    /// label map and a functor which converts the label map values to
kpeter@192
  1663
    /// \c std::string.
deba@165
  1664
    template <typename Map, typename Converter>
alpar@209
  1665
    GraphReader& useNodes(const Map& map,
alpar@209
  1666
                            const Converter& converter = Converter()) {
deba@165
  1667
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
  1668
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
deba@165
  1669
      _use_nodes = true;
deba@165
  1670
      for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1671
        _node_index.insert(std::make_pair(converter(map[n]), n));
deba@165
  1672
      }
deba@165
  1673
      return *this;
deba@165
  1674
    }
deba@165
  1675
deba@165
  1676
    /// \brief Use previously constructed edge set
deba@165
  1677
    ///
deba@165
  1678
    /// Use previously constructed edge set, and specify the edge
deba@165
  1679
    /// label map.
deba@165
  1680
    template <typename Map>
deba@165
  1681
    GraphReader& useEdges(const Map& map) {
deba@165
  1682
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@165
  1683
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
deba@165
  1684
      _use_edges = true;
deba@165
  1685
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@165
  1686
      for (EdgeIt a(_graph); a != INVALID; ++a) {
alpar@209
  1687
        _edge_index.insert(std::make_pair(converter(map[a]), a));
deba@165
  1688
      }
deba@165
  1689
      return *this;
deba@165
  1690
    }
deba@165
  1691
deba@165
  1692
    /// \brief Use previously constructed edge set
deba@165
  1693
    ///
deba@165
  1694
    /// Use previously constructed edge set, and specify the edge
deba@165
  1695
    /// label map and a functor which converts the label map values to
kpeter@192
  1696
    /// \c std::string.
deba@165
  1697
    template <typename Map, typename Converter>
alpar@209
  1698
    GraphReader& useEdges(const Map& map,
alpar@209
  1699
                            const Converter& converter = Converter()) {
deba@165
  1700
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
alpar@209
  1701
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
deba@165
  1702
      _use_edges = true;
deba@165
  1703
      for (EdgeIt a(_graph); a != INVALID; ++a) {
alpar@209
  1704
        _edge_index.insert(std::make_pair(converter(map[a]), a));
deba@165
  1705
      }
deba@165
  1706
      return *this;
deba@165
  1707
    }
deba@165
  1708
kpeter@192
  1709
    /// \brief Skip the reading of node section
deba@188
  1710
    ///
deba@188
  1711
    /// Omit the reading of the node section. This implies that each node
kpeter@192
  1712
    /// map reading rule will be abandoned, and the nodes of the graph
deba@188
  1713
    /// will not be constructed, which usually cause that the edge set
deba@188
  1714
    /// could not be read due to lack of node name
kpeter@192
  1715
    /// could not be read due to lack of node name resolving.
kpeter@192
  1716
    /// Therefore \c skipEdges() function should also be used, or
kpeter@192
  1717
    /// \c useNodes() should be used to specify the label of the nodes.
deba@188
  1718
    GraphReader& skipNodes() {
alpar@209
  1719
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
deba@188
  1720
      _skip_nodes = true;
deba@188
  1721
      return *this;
deba@188
  1722
    }
deba@188
  1723
kpeter@192
  1724
    /// \brief Skip the reading of edge section
deba@188
  1725
    ///
deba@188
  1726
    /// Omit the reading of the edge section. This implies that each edge
kpeter@192
  1727
    /// map reading rule will be abandoned, and the edges of the graph
deba@188
  1728
    /// will not be constructed.
deba@188
  1729
    GraphReader& skipEdges() {
alpar@209
  1730
      LEMON_ASSERT(!_skip_edges, "Skip edges already set");
deba@188
  1731
      _skip_edges = true;
deba@188
  1732
      return *this;
deba@188
  1733
    }
deba@188
  1734
deba@165
  1735
    /// @}
deba@165
  1736
deba@165
  1737
  private:
deba@165
  1738
deba@165
  1739
    bool readLine() {
deba@165
  1740
      std::string str;
deba@165
  1741
      while(++line_num, std::getline(*_is, str)) {
alpar@209
  1742
        line.clear(); line.str(str);
alpar@209
  1743
        char c;
alpar@209
  1744
        if (line >> std::ws >> c && c != '#') {
alpar@209
  1745
          line.putback(c);
alpar@209
  1746
          return true;
alpar@209
  1747
        }
deba@165
  1748
      }
deba@165
  1749
      return false;
deba@165
  1750
    }
deba@165
  1751
deba@165
  1752
    bool readSuccess() {
deba@165
  1753
      return static_cast<bool>(*_is);
deba@165
  1754
    }
alpar@209
  1755
deba@165
  1756
    void skipSection() {
deba@165
  1757
      char c;
deba@165
  1758
      while (readSuccess() && line >> c && c != '@') {
alpar@209
  1759
        readLine();
deba@165
  1760
      }
deba@427
  1761
      if (readSuccess()) {
deba@427
  1762
        line.putback(c);
deba@427
  1763
      }
deba@165
  1764
    }
deba@165
  1765
deba@165
  1766
    void readNodes() {
deba@165
  1767
deba@165
  1768
      std::vector<int> map_index(_node_maps.size());
deba@165
  1769
      int map_num, label_index;
deba@165
  1770
deba@186
  1771
      char c;
deba@186
  1772
      if (!readLine() || !(line >> c) || c == '@') {
alpar@209
  1773
        if (readSuccess() && line) line.putback(c);
alpar@209
  1774
        if (!_node_maps.empty())
deba@290
  1775
          throw FormatError("Cannot find map names");
alpar@209
  1776
        return;
deba@186
  1777
      }
deba@186
  1778
      line.putback(c);
alpar@209
  1779
deba@165
  1780
      {
alpar@209
  1781
        std::map<std::string, int> maps;
alpar@209
  1782
alpar@209
  1783
        std::string map;
alpar@209
  1784
        int index = 0;
alpar@209
  1785
        while (_reader_bits::readToken(line, map)) {
alpar@209
  1786
          if (maps.find(map) != maps.end()) {
alpar@209
  1787
            std::ostringstream msg;
alpar@209
  1788
            msg << "Multiple occurence of node map: " << map;
deba@290
  1789
            throw FormatError(msg.str());
alpar@209
  1790
          }
alpar@209
  1791
          maps.insert(std::make_pair(map, index));
alpar@209
  1792
          ++index;
alpar@209
  1793
        }
alpar@209
  1794
alpar@209
  1795
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
alpar@209
  1796
          std::map<std::string, int>::iterator jt =
alpar@209
  1797
            maps.find(_node_maps[i].first);
alpar@209
  1798
          if (jt == maps.end()) {
alpar@209
  1799
            std::ostringstream msg;
kpeter@291
  1800
            msg << "Map not found: " << _node_maps[i].first;
deba@290
  1801
            throw FormatError(msg.str());
alpar@209
  1802
          }
alpar@209
  1803
          map_index[i] = jt->second;
alpar@209
  1804
        }
alpar@209
  1805
alpar@209
  1806
        {
alpar@209
  1807
          std::map<std::string, int>::iterator jt = maps.find("label");
alpar@209
  1808
          if (jt != maps.end()) {
alpar@209
  1809
            label_index = jt->second;
alpar@209
  1810
          } else {
alpar@209
  1811
            label_index = -1;
alpar@209
  1812
          }
alpar@209
  1813
        }
alpar@209
  1814
        map_num = maps.size();
deba@165
  1815
      }
deba@165
  1816
deba@165
  1817
      while (readLine() && line >> c && c != '@') {
alpar@209
  1818
        line.putback(c);
alpar@209
  1819
alpar@209
  1820
        std::vector<std::string> tokens(map_num);
alpar@209
  1821
        for (int i = 0; i < map_num; ++i) {
alpar@209
  1822
          if (!_reader_bits::readToken(line, tokens[i])) {
alpar@209
  1823
            std::ostringstream msg;
alpar@209
  1824
            msg << "Column not found (" << i + 1 << ")";
deba@290
  1825
            throw FormatError(msg.str());
alpar@209
  1826
          }
alpar@209
  1827
        }
alpar@209
  1828
        if (line >> std::ws >> c)
kpeter@291
  1829
          throw FormatError("Extra character at the end of line");
alpar@209
  1830
alpar@209
  1831
        Node n;
alpar@209
  1832
        if (!_use_nodes) {
alpar@209
  1833
          n = _graph.addNode();
alpar@209
  1834
          if (label_index != -1)
alpar@209
  1835
            _node_index.insert(std::make_pair(tokens[label_index], n));
alpar@209
  1836
        } else {
alpar@209
  1837
          if (label_index == -1)
kpeter@291
  1838
            throw FormatError("Label map not found");
alpar@209
  1839
          typename std::map<std::string, Node>::iterator it =
alpar@209
  1840
            _node_index.find(tokens[label_index]);
alpar@209
  1841
          if (it == _node_index.end()) {
alpar@209
  1842
            std::ostringstream msg;
alpar@209
  1843
            msg << "Node with label not found: " << tokens[label_index];
deba@290
  1844
            throw FormatError(msg.str());
alpar@209
  1845
          }
alpar@209
  1846
          n = it->second;
alpar@209
  1847
        }
alpar@209
  1848
alpar@209
  1849
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
alpar@209
  1850
          _node_maps[i].second->set(n, tokens[map_index[i]]);
alpar@209
  1851
        }
deba@165
  1852
deba@165
  1853
      }
deba@165
  1854
      if (readSuccess()) {
alpar@209
  1855
        line.putback(c);
deba@165
  1856
      }
deba@165
  1857
    }
deba@165
  1858
deba@165
  1859
    void readEdges() {
deba@165
  1860
deba@165
  1861
      std::vector<int> map_index(_edge_maps.size());
deba@165
  1862
      int map_num, label_index;
deba@165
  1863
deba@186
  1864
      char c;
deba@186
  1865
      if (!readLine() || !(line >> c) || c == '@') {
alpar@209
  1866
        if (readSuccess() && line) line.putback(c);
alpar@209
  1867
        if (!_edge_maps.empty())
deba@290
  1868
          throw FormatError("Cannot find map names");
alpar@209
  1869
        return;
deba@186
  1870
      }
deba@186
  1871
      line.putback(c);
alpar@209
  1872
deba@165
  1873
      {
alpar@209
  1874
        std::map<std::string, int> maps;
alpar@209
  1875
alpar@209
  1876
        std::string map;
alpar@209
  1877
        int index = 0;
alpar@209
  1878
        while (_reader_bits::readToken(line, map)) {
alpar@949
  1879
          if(map == "-") {
alpar@949
  1880
              if(index!=0)
alpar@949
  1881
                throw FormatError("'-' is not allowed as a map name");
alpar@949
  1882
              else if (line >> std::ws >> c)
alpar@949
  1883
                throw FormatError("Extra character at the end of line");
alpar@949
  1884
              else break;
alpar@949
  1885
            }
alpar@209
  1886
          if (maps.find(map) != maps.end()) {
alpar@209
  1887
            std::ostringstream msg;
alpar@209
  1888
            msg << "Multiple occurence of edge map: " << map;
deba@290
  1889
            throw FormatError(msg.str());
alpar@209
  1890
          }
alpar@209
  1891
          maps.insert(std::make_pair(map, index));
alpar@209
  1892
          ++index;
alpar@209
  1893
        }
alpar@209
  1894
alpar@209
  1895
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
alpar@209
  1896
          std::map<std::string, int>::iterator jt =
alpar@209
  1897
            maps.find(_edge_maps[i].first);
alpar@209
  1898
          if (jt == maps.end()) {
alpar@209
  1899
            std::ostringstream msg;
kpeter@291
  1900
            msg << "Map not found: " << _edge_maps[i].first;
deba@290
  1901
            throw FormatError(msg.str());
alpar@209
  1902
          }
alpar@209
  1903
          map_index[i] = jt->second;
alpar@209
  1904
        }
alpar@209
  1905
alpar@209
  1906
        {
alpar@209
  1907
          std::map<std::string, int>::iterator jt = maps.find("label");
alpar@209
  1908
          if (jt != maps.end()) {
alpar@209
  1909
            label_index = jt->second;
alpar@209
  1910
          } else {
alpar@209
  1911
            label_index = -1;
alpar@209
  1912
          }
alpar@209
  1913
        }
alpar@209
  1914
        map_num = maps.size();
deba@165
  1915
      }
deba@165
  1916
deba@165
  1917
      while (readLine() && line >> c && c != '@') {
alpar@209
  1918
        line.putback(c);
alpar@209
  1919
alpar@209
  1920
        std::string source_token;
alpar@209
  1921
        std::string target_token;
alpar@209
  1922
alpar@209
  1923
        if (!_reader_bits::readToken(line, source_token))
deba@290
  1924
          throw FormatError("Node u not found");
alpar@209
  1925
alpar@209
  1926
        if (!_reader_bits::readToken(line, target_token))
deba@290
  1927
          throw FormatError("Node v not found");
alpar@209
  1928
alpar@209
  1929
        std::vector<std::string> tokens(map_num);
alpar@209
  1930
        for (int i = 0; i < map_num; ++i) {
alpar@209
  1931
          if (!_reader_bits::readToken(line, tokens[i])) {
alpar@209
  1932
            std::ostringstream msg;
alpar@209
  1933
            msg << "Column not found (" << i + 1 << ")";
deba@290
  1934
            throw FormatError(msg.str());
alpar@209
  1935
          }
alpar@209
  1936
        }
alpar@209
  1937
        if (line >> std::ws >> c)
kpeter@291
  1938
          throw FormatError("Extra character at the end of line");
alpar@209
  1939
alpar@209
  1940
        Edge e;
alpar@209
  1941
        if (!_use_edges) {
deba@165
  1942
deba@165
  1943
          typename NodeIndex::iterator it;
alpar@209
  1944
deba@165
  1945
          it = _node_index.find(source_token);
deba@165
  1946
          if (it == _node_index.end()) {
deba@165
  1947
            std::ostringstream msg;
deba@165
  1948
            msg << "Item not found: " << source_token;
deba@290
  1949
            throw FormatError(msg.str());
deba@165
  1950
          }
deba@165
  1951
          Node source = it->second;
deba@165
  1952
deba@165
  1953
          it = _node_index.find(target_token);
alpar@209
  1954
          if (it == _node_index.end()) {
alpar@209
  1955
            std::ostringstream msg;
deba@165
  1956
            msg << "Item not found: " << target_token;
deba@290
  1957
            throw FormatError(msg.str());
alpar@209
  1958
          }
alpar@209
  1959
          Node target = it->second;
alpar@209
  1960
alpar@209
  1961
          e = _graph.addEdge(source, target);
alpar@209
  1962
          if (label_index != -1)
alpar@209
  1963
            _edge_index.insert(std::make_pair(tokens[label_index], e));
alpar@209
  1964
        } else {
alpar@209
  1965
          if (label_index == -1)
kpeter@291
  1966
            throw FormatError("Label map not found");
alpar@209
  1967
          typename std::map<std::string, Edge>::iterator it =
alpar@209
  1968
            _edge_index.find(tokens[label_index]);
alpar@209
  1969
          if (it == _edge_index.end()) {
alpar@209
  1970
            std::ostringstream msg;
alpar@209
  1971
            msg << "Edge with label not found: " << tokens[label_index];
deba@290
  1972
            throw FormatError(msg.str());
alpar@209
  1973
          }
alpar@209
  1974
          e = it->second;
alpar@209
  1975
        }
alpar@209
  1976
alpar@209
  1977
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
alpar@209
  1978
          _edge_maps[i].second->set(e, tokens[map_index[i]]);
alpar@209
  1979
        }
deba@165
  1980
deba@165
  1981
      }
deba@165
  1982
      if (readSuccess()) {
alpar@209
  1983
        line.putback(c);
deba@165
  1984
      }
deba@165
  1985
    }
deba@165
  1986
deba@165
  1987
    void readAttributes() {
deba@165
  1988
deba@165
  1989
      std::set<std::string> read_attr;
deba@165
  1990
deba@165
  1991
      char c;
deba@165
  1992
      while (readLine() && line >> c && c != '@') {
alpar@209
  1993
        line.putback(c);
alpar@209
  1994
alpar@209
  1995
        std::string attr, token;
alpar@209
  1996
        if (!_reader_bits::readToken(line, attr))
deba@290
  1997
          throw FormatError("Attribute name not found");
alpar@209
  1998
        if (!_reader_bits::readToken(line, token))
deba@290
  1999
          throw FormatError("Attribute value not found");
alpar@209
  2000
        if (line >> c)
kpeter@291
  2001
          throw FormatError("Extra character at the end of line");
alpar@209
  2002
alpar@209
  2003
        {
alpar@209
  2004
          std::set<std::string>::iterator it = read_attr.find(attr);
alpar@209
  2005
          if (it != read_attr.end()) {
alpar@209
  2006
            std::ostringstream msg;
kpeter@291
  2007
            msg << "Multiple occurence of attribute: " << attr;
deba@290
  2008
            throw FormatError(msg.str());
alpar@209
  2009
          }
alpar@209
  2010
          read_attr.insert(attr);
alpar@209
  2011
        }
alpar@209
  2012
alpar@209
  2013
        {
alpar@209
  2014
          typename Attributes::iterator it = _attributes.lower_bound(attr);
alpar@209
  2015
          while (it != _attributes.end() && it->first == attr) {
alpar@209
  2016
            it->second->set(token);
alpar@209
  2017
            ++it;
alpar@209
  2018
          }
alpar@209
  2019
        }
deba@165
  2020
deba@165
  2021
      }
deba@165
  2022
      if (readSuccess()) {
alpar@209
  2023
        line.putback(c);
deba@165
  2024
      }
deba@165
  2025
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  2026
           it != _attributes.end(); ++it) {
alpar@209
  2027
        if (read_attr.find(it->first) == read_attr.end()) {
alpar@209
  2028
          std::ostringstream msg;
kpeter@291
  2029
          msg << "Attribute not found: " << it->first;
deba@290
  2030
          throw FormatError(msg.str());
alpar@209
  2031
        }
deba@165
  2032
      }
deba@165
  2033
    }
deba@165
  2034
deba@165
  2035
  public:
deba@165
  2036
kpeter@584
  2037
    /// \name Execution of the Reader
deba@165
  2038
    /// @{
deba@165
  2039
deba@165
  2040
    /// \brief Start the batch processing
deba@165
  2041
    ///
deba@165
  2042
    /// This function starts the batch processing
deba@165
  2043
    void run() {
alpar@209
  2044
deba@165
  2045
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
alpar@209
  2046
deba@188
  2047
      bool nodes_done = _skip_nodes;
deba@188
  2048
      bool edges_done = _skip_edges;
deba@165
  2049
      bool attributes_done = false;
deba@165
  2050
alpar@209
  2051
      line_num = 0;
deba@165
  2052
      readLine();
deba@172
  2053
      skipSection();
deba@165
  2054
deba@165
  2055
      while (readSuccess()) {
alpar@209
  2056
        try {
alpar@209
  2057
          char c;
alpar@209
  2058
          std::string section, caption;
alpar@209
  2059
          line >> c;
alpar@209
  2060
          _reader_bits::readToken(line, section);
alpar@209
  2061
          _reader_bits::readToken(line, caption);
alpar@209
  2062
alpar@209
  2063
          if (line >> c)
kpeter@291
  2064
            throw FormatError("Extra character at the end of line");
alpar@209
  2065
alpar@209
  2066
          if (section == "nodes" && !nodes_done) {
alpar@209
  2067
            if (_nodes_caption.empty() || _nodes_caption == caption) {
alpar@209
  2068
              readNodes();
alpar@209
  2069
              nodes_done = true;
alpar@209
  2070
            }
alpar@209
  2071
          } else if ((section == "edges" || section == "arcs") &&
alpar@209
  2072
                     !edges_done) {
alpar@209
  2073
            if (_edges_caption.empty() || _edges_caption == caption) {
alpar@209
  2074
              readEdges();
alpar@209
  2075
              edges_done = true;
alpar@209
  2076
            }
alpar@209
  2077
          } else if (section == "attributes" && !attributes_done) {
alpar@209
  2078
            if (_attributes_caption.empty() || _attributes_caption == caption) {
alpar@209
  2079
              readAttributes();
alpar@209
  2080
              attributes_done = true;
alpar@209
  2081
            }
alpar@209
  2082
          } else {
alpar@209
  2083
            readLine();
alpar@209
  2084
            skipSection();
alpar@209
  2085
          }
deba@290
  2086
        } catch (FormatError& error) {
alpar@209
  2087
          error.line(line_num);
deba@290
  2088
          error.file(_filename);
alpar@209
  2089
          throw;
alpar@209
  2090
        }
deba@165
  2091
      }
deba@165
  2092
deba@165
  2093
      if (!nodes_done) {
deba@290
  2094
        throw FormatError("Section @nodes not found");
deba@165
  2095
      }
deba@165
  2096
deba@165
  2097
      if (!edges_done) {
deba@290
  2098
        throw FormatError("Section @edges not found");
deba@165
  2099
      }
deba@165
  2100
deba@165
  2101
      if (!attributes_done && !_attributes.empty()) {
deba@290
  2102
        throw FormatError("Section @attributes not found");
deba@165
  2103
      }
deba@165
  2104
deba@165
  2105
    }
deba@165
  2106
deba@165
  2107
    /// @}
alpar@209
  2108
deba@165
  2109
  };
deba@165
  2110
deba@598
  2111
  /// \ingroup lemon_io
deba@598
  2112
  ///
alpar@1076
  2113
  /// \brief Return a \ref lemon::GraphReader "GraphReader" class
deba@598
  2114
  ///
alpar@1076
  2115
  /// This function just returns a \ref lemon::GraphReader "GraphReader" class.
deba@598
  2116
  ///
alpar@877
  2117
  /// With this function a graph can be read from an
deba@598
  2118
  /// \ref lgf-format "LGF" file or input stream with several maps and
deba@598
  2119
  /// attributes. For example, there is weighted matching problem on a
deba@598
  2120
  /// graph, i.e. a graph with a \e weight map on the edges. This
deba@598
  2121
  /// graph can be read with the following code:
deba@598
  2122
  ///
deba@598
  2123
  ///\code
deba@598
  2124
  ///ListGraph graph;
deba@598
  2125
  ///ListGraph::EdgeMap<int> weight(graph);
deba@598
  2126
  ///graphReader(graph, std::cin).
deba@598
  2127
  ///  edgeMap("weight", weight).
deba@598
  2128
  ///  run();
deba@598
  2129
  ///\endcode
deba@598
  2130
  ///
alpar@1076
  2131
  /// For a complete documentation, please see the
alpar@1076
  2132
  /// \ref lemon::GraphReader "GraphReader"
deba@598
  2133
  /// class documentation.
alpar@1076
  2134
  /// \warning Don't forget to put the \ref lemon::GraphReader::run() "run()"
deba@598
  2135
  /// to the end of the parameter list.
deba@598
  2136
  /// \relates GraphReader
deba@598
  2137
  /// \sa graphReader(TGR& graph, const std::string& fn)
deba@598
  2138
  /// \sa graphReader(TGR& graph, const char* fn)
deba@598
  2139
  template <typename TGR>
deba@598
  2140
  GraphReader<TGR> graphReader(TGR& graph, std::istream& is) {
deba@598
  2141
    GraphReader<TGR> tmp(graph, is);
deba@598
  2142
    return tmp;
deba@598
  2143
  }
deba@598
  2144
kpeter@487
  2145
  /// \brief Return a \ref GraphReader class
kpeter@487
  2146
  ///
kpeter@487
  2147
  /// This function just returns a \ref GraphReader class.
kpeter@487
  2148
  /// \relates GraphReader
deba@598
  2149
  /// \sa graphReader(TGR& graph, std::istream& is)
deba@598
  2150
  template <typename TGR>
deba@598
  2151
  GraphReader<TGR> graphReader(TGR& graph, const std::string& fn) {
deba@598
  2152
    GraphReader<TGR> tmp(graph, fn);
kpeter@487
  2153
    return tmp;
kpeter@487
  2154
  }
kpeter@487
  2155
kpeter@487
  2156
  /// \brief Return a \ref GraphReader class
kpeter@487
  2157
  ///
kpeter@487
  2158
  /// This function just returns a \ref GraphReader class.
kpeter@487
  2159
  /// \relates GraphReader
deba@598
  2160
  /// \sa graphReader(TGR& graph, std::istream& is)
deba@598
  2161
  template <typename TGR>
deba@598
  2162
  GraphReader<TGR> graphReader(TGR& graph, const char* fn) {
deba@598
  2163
    GraphReader<TGR> tmp(graph, fn);
kpeter@487
  2164
    return tmp;
kpeter@487
  2165
  }
kpeter@487
  2166
deba@1024
  2167
  template <typename BGR>
deba@1024
  2168
  class BpGraphReader;
deba@1024
  2169
deba@1024
  2170
  template <typename TBGR>
deba@1024
  2171
  BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is = std::cin);
deba@1024
  2172
  template <typename TBGR>
deba@1024
  2173
  BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn);
deba@1024
  2174
  template <typename TBGR>
deba@1024
  2175
  BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
deba@1024
  2176
deba@1024
  2177
  /// \ingroup lemon_io
deba@1024
  2178
  ///
deba@1024
  2179
  /// \brief \ref lgf-format "LGF" reader for bipartite graphs
deba@1024
  2180
  ///
deba@1024
  2181
  /// This utility reads an \ref lgf-format "LGF" file.
deba@1024
  2182
  ///
deba@1024
  2183
  /// It can be used almost the same way as \c GraphReader, but it
deba@1024
  2184
  /// reads the red and blue nodes from separate sections, and these
deba@1024
  2185
  /// sections can contain different set of maps.
deba@1024
  2186
  ///
deba@1026
  2187
  /// The red and blue node maps are read from the corresponding
deba@1024
  2188
  /// sections. If a map is defined with the same name in both of
deba@1024
  2189
  /// these sections, then it can be read as a node map.
deba@1024
  2190
  template <typename BGR>
deba@1024
  2191
  class BpGraphReader {
deba@1024
  2192
  public:
deba@1024
  2193
deba@1024
  2194
    typedef BGR Graph;
deba@1024
  2195
deba@1024
  2196
  private:
deba@1024
  2197
deba@1024
  2198
    TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
deba@1024
  2199
deba@1024
  2200
    std::istream* _is;
deba@1024
  2201
    bool local_is;
deba@1024
  2202
    std::string _filename;
deba@1024
  2203
deba@1024
  2204
    BGR& _graph;
deba@1024
  2205
deba@1024
  2206
    std::string _nodes_caption;
deba@1024
  2207
    std::string _edges_caption;
deba@1024
  2208
    std::string _attributes_caption;
deba@1024
  2209
deba@1030
  2210
    typedef std::map<std::string, RedNode> RedNodeIndex;
deba@1030
  2211
    RedNodeIndex _red_node_index;
deba@1030
  2212
    typedef std::map<std::string, BlueNode> BlueNodeIndex;
deba@1030
  2213
    BlueNodeIndex _blue_node_index;
deba@1024
  2214
    typedef std::map<std::string, Edge> EdgeIndex;
deba@1024
  2215
    EdgeIndex _edge_index;
deba@1024
  2216
deba@1024
  2217
    typedef std::vector<std::pair<std::string,
deba@1030
  2218
      _reader_bits::MapStorageBase<RedNode>*> > RedNodeMaps;
deba@1030
  2219
    RedNodeMaps _red_node_maps;
deba@1030
  2220
    typedef std::vector<std::pair<std::string,
deba@1030
  2221
      _reader_bits::MapStorageBase<BlueNode>*> > BlueNodeMaps;
deba@1030
  2222
    BlueNodeMaps _blue_node_maps;
deba@1024
  2223
deba@1024
  2224
    typedef std::vector<std::pair<std::string,
deba@1024
  2225
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
deba@1024
  2226
    EdgeMaps _edge_maps;
deba@1024
  2227
deba@1024
  2228
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
deba@1024
  2229
      Attributes;
deba@1024
  2230
    Attributes _attributes;
deba@1024
  2231
deba@1024
  2232
    bool _use_nodes;
deba@1024
  2233
    bool _use_edges;
deba@1024
  2234
deba@1024
  2235
    bool _skip_nodes;
deba@1024
  2236
    bool _skip_edges;
deba@1024
  2237
deba@1024
  2238
    int line_num;
deba@1024
  2239
    std::istringstream line;
deba@1024
  2240
deba@1024
  2241
  public:
deba@1024
  2242
deba@1024
  2243
    /// \brief Constructor
deba@1024
  2244
    ///
deba@1024
  2245
    /// Construct an undirected graph reader, which reads from the given
deba@1024
  2246
    /// input stream.
deba@1024
  2247
    BpGraphReader(BGR& graph, std::istream& is = std::cin)
deba@1024
  2248
      : _is(&is), local_is(false), _graph(graph),
deba@1024
  2249
        _use_nodes(false), _use_edges(false),
deba@1024
  2250
        _skip_nodes(false), _skip_edges(false) {}
deba@1024
  2251
deba@1024
  2252
    /// \brief Constructor
deba@1024
  2253
    ///
deba@1024
  2254
    /// Construct an undirected graph reader, which reads from the given
deba@1024
  2255
    /// file.
deba@1024
  2256
    BpGraphReader(BGR& graph, const std::string& fn)
deba@1024
  2257
      : _is(new std::ifstream(fn.c_str())), local_is(true),
deba@1024
  2258
        _filename(fn), _graph(graph),
deba@1024
  2259
        _use_nodes(false), _use_edges(false),
deba@1024
  2260
        _skip_nodes(false), _skip_edges(false) {
deba@1024
  2261
      if (!(*_is)) {
deba@1024
  2262
        delete _is;
deba@1024
  2263
        throw IoError("Cannot open file", fn);
deba@1024
  2264
      }
deba@1024
  2265
    }
deba@1024
  2266
deba@1024
  2267
    /// \brief Constructor
deba@1024
  2268
    ///
deba@1024
  2269
    /// Construct an undirected graph reader, which reads from the given
deba@1024
  2270
    /// file.
deba@1024
  2271
    BpGraphReader(BGR& graph, const char* fn)
deba@1024
  2272
      : _is(new std::ifstream(fn)), local_is(true),
deba@1024
  2273
        _filename(fn), _graph(graph),
deba@1024
  2274
        _use_nodes(false), _use_edges(false),
deba@1024
  2275
        _skip_nodes(false), _skip_edges(false) {
deba@1024
  2276
      if (!(*_is)) {
deba@1024
  2277
        delete _is;
deba@1024
  2278
        throw IoError("Cannot open file", fn);
deba@1024
  2279
      }
deba@1024
  2280
    }
deba@1024
  2281
deba@1024
  2282
    /// \brief Destructor
deba@1024
  2283
    ~BpGraphReader() {
deba@1030
  2284
      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
deba@1030
  2285
           it != _red_node_maps.end(); ++it) {
deba@1024
  2286
        delete it->second;
deba@1024
  2287
      }
deba@1024
  2288
deba@1030
  2289
      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
deba@1030
  2290
           it != _blue_node_maps.end(); ++it) {
deba@1024
  2291
        delete it->second;
deba@1024
  2292
      }
deba@1024
  2293
deba@1024
  2294
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  2295
           it != _edge_maps.end(); ++it) {
deba@1024
  2296
        delete it->second;
deba@1024
  2297
      }
deba@1024
  2298
deba@1024
  2299
      for (typename Attributes::iterator it = _attributes.begin();
deba@1024
  2300
           it != _attributes.end(); ++it) {
deba@1024
  2301
        delete it->second;
deba@1024
  2302
      }
deba@1024
  2303
deba@1024
  2304
      if (local_is) {
deba@1024
  2305
        delete _is;
deba@1024
  2306
      }
deba@1024
  2307
deba@1024
  2308
    }
deba@1024
  2309
deba@1024
  2310
  private:
deba@1024
  2311
    template <typename TBGR>
deba@1024
  2312
    friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is);
deba@1024
  2313
    template <typename TBGR>
deba@1024
  2314
    friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph,
deba@1024
  2315
                                             const std::string& fn);
deba@1024
  2316
    template <typename TBGR>
deba@1024
  2317
    friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
deba@1024
  2318
deba@1024
  2319
    BpGraphReader(BpGraphReader& other)
deba@1024
  2320
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
deba@1024
  2321
        _use_nodes(other._use_nodes), _use_edges(other._use_edges),
deba@1024
  2322
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
deba@1024
  2323
deba@1024
  2324
      other._is = 0;
deba@1024
  2325
      other.local_is = false;
deba@1024
  2326
deba@1030
  2327
      _red_node_index.swap(other._red_node_index);
deba@1030
  2328
      _blue_node_index.swap(other._blue_node_index);
deba@1024
  2329
      _edge_index.swap(other._edge_index);
deba@1024
  2330
deba@1030
  2331
      _red_node_maps.swap(other._red_node_maps);
deba@1030
  2332
      _blue_node_maps.swap(other._blue_node_maps);
deba@1024
  2333
      _edge_maps.swap(other._edge_maps);
deba@1024
  2334
      _attributes.swap(other._attributes);
deba@1024
  2335
deba@1024
  2336
      _nodes_caption = other._nodes_caption;
deba@1024
  2337
      _edges_caption = other._edges_caption;
deba@1024
  2338
      _attributes_caption = other._attributes_caption;
deba@1024
  2339
deba@1024
  2340
    }
deba@1024
  2341
deba@1024
  2342
    BpGraphReader& operator=(const BpGraphReader&);
deba@1024
  2343
deba@1024
  2344
  public:
deba@1024
  2345
deba@1024
  2346
    /// \name Reading Rules
deba@1024
  2347
    /// @{
deba@1024
  2348
deba@1024
  2349
    /// \brief Node map reading rule
deba@1024
  2350
    ///
deba@1024
  2351
    /// Add a node map reading rule to the reader.
deba@1024
  2352
    template <typename Map>
deba@1024
  2353
    BpGraphReader& nodeMap(const std::string& caption, Map& map) {
deba@1024
  2354
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@1030
  2355
      _reader_bits::MapStorageBase<RedNode>* red_storage =
deba@1030
  2356
        new _reader_bits::MapStorage<RedNode, Map>(map);
deba@1030
  2357
      _red_node_maps.push_back(std::make_pair(caption, red_storage));
deba@1030
  2358
      _reader_bits::MapStorageBase<BlueNode>* blue_storage =
deba@1030
  2359
        new _reader_bits::MapStorage<BlueNode, Map>(map);
deba@1030
  2360
      _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
deba@1024
  2361
      return *this;
deba@1024
  2362
    }
deba@1024
  2363
deba@1024
  2364
    /// \brief Node map reading rule
deba@1024
  2365
    ///
deba@1024
  2366
    /// Add a node map reading rule with specialized converter to the
deba@1024
  2367
    /// reader.
deba@1024
  2368
    template <typename Map, typename Converter>
deba@1024
  2369
    BpGraphReader& nodeMap(const std::string& caption, Map& map,
deba@1024
  2370
                           const Converter& converter = Converter()) {
deba@1024
  2371
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@1030
  2372
      _reader_bits::MapStorageBase<RedNode>* red_storage =
deba@1030
  2373
        new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
deba@1030
  2374
      _red_node_maps.push_back(std::make_pair(caption, red_storage));
deba@1030
  2375
      _reader_bits::MapStorageBase<BlueNode>* blue_storage =
deba@1030
  2376
        new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
deba@1030
  2377
      _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
deba@1024
  2378
      return *this;
deba@1024
  2379
    }
deba@1024
  2380
deba@1026
  2381
    /// Add a red node map reading rule to the reader.
deba@1024
  2382
    template <typename Map>
deba@1026
  2383
    BpGraphReader& redNodeMap(const std::string& caption, Map& map) {
deba@1030
  2384
      checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
deba@1030
  2385
      _reader_bits::MapStorageBase<RedNode>* storage =
deba@1030
  2386
        new _reader_bits::MapStorage<RedNode, Map>(map);
deba@1030
  2387
      _red_node_maps.push_back(std::make_pair(caption, storage));
deba@1024
  2388
      return *this;
deba@1024
  2389
    }
deba@1024
  2390
deba@1026
  2391
    /// \brief Red node map reading rule
deba@1024
  2392
    ///
deba@1026
  2393
    /// Add a red node map node reading rule with specialized converter to
deba@1026
  2394
    /// the reader.
deba@1024
  2395
    template <typename Map, typename Converter>
deba@1026
  2396
    BpGraphReader& redNodeMap(const std::string& caption, Map& map,
deba@1026
  2397
                              const Converter& converter = Converter()) {
deba@1030
  2398
      checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
deba@1030
  2399
      _reader_bits::MapStorageBase<RedNode>* storage =
deba@1030
  2400
        new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
deba@1030
  2401
      _red_node_maps.push_back(std::make_pair(caption, storage));
deba@1024
  2402
      return *this;
deba@1024
  2403
    }
deba@1024
  2404
deba@1026
  2405
    /// Add a blue node map reading rule to the reader.
deba@1024
  2406
    template <typename Map>
deba@1026
  2407
    BpGraphReader& blueNodeMap(const std::string& caption, Map& map) {
deba@1030
  2408
      checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
deba@1030
  2409
      _reader_bits::MapStorageBase<BlueNode>* storage =
deba@1030
  2410
        new _reader_bits::MapStorage<BlueNode, Map>(map);
deba@1030
  2411
      _blue_node_maps.push_back(std::make_pair(caption, storage));
deba@1024
  2412
      return *this;
deba@1024
  2413
    }
deba@1024
  2414
deba@1026
  2415
    /// \brief Blue node map reading rule
deba@1024
  2416
    ///
deba@1026
  2417
    /// Add a blue node map reading rule with specialized converter to
deba@1026
  2418
    /// the reader.
deba@1024
  2419
    template <typename Map, typename Converter>
deba@1026
  2420
    BpGraphReader& blueNodeMap(const std::string& caption, Map& map,
deba@1026
  2421
                               const Converter& converter = Converter()) {
deba@1030
  2422
      checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
deba@1030
  2423
      _reader_bits::MapStorageBase<BlueNode>* storage =
deba@1030
  2424
        new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
deba@1030
  2425
      _blue_node_maps.push_back(std::make_pair(caption, storage));
deba@1024
  2426
      return *this;
deba@1024
  2427
    }
deba@1024
  2428
deba@1024
  2429
    /// \brief Edge map reading rule
deba@1024
  2430
    ///
deba@1024
  2431
    /// Add an edge map reading rule to the reader.
deba@1024
  2432
    template <typename Map>
deba@1024
  2433
    BpGraphReader& edgeMap(const std::string& caption, Map& map) {
deba@1024
  2434
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
deba@1024
  2435
      _reader_bits::MapStorageBase<Edge>* storage =
deba@1024
  2436
        new _reader_bits::MapStorage<Edge, Map>(map);
deba@1024
  2437
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@1024
  2438
      return *this;
deba@1024
  2439
    }
deba@1024
  2440
deba@1024
  2441
    /// \brief Edge map reading rule
deba@1024
  2442
    ///
deba@1024
  2443
    /// Add an edge map reading rule with specialized converter to the
deba@1024
  2444
    /// reader.
deba@1024
  2445
    template <typename Map, typename Converter>
deba@1024
  2446
    BpGraphReader& edgeMap(const std::string& caption, Map& map,
deba@1024
  2447
                          const Converter& converter = Converter()) {
deba@1024
  2448
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
deba@1024
  2449
      _reader_bits::MapStorageBase<Edge>* storage =
deba@1024
  2450
        new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
deba@1024
  2451
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@1024
  2452
      return *this;
deba@1024
  2453
    }
deba@1024
  2454
deba@1024
  2455
    /// \brief Arc map reading rule
deba@1024
  2456
    ///
deba@1024
  2457
    /// Add an arc map reading rule to the reader.
deba@1024
  2458
    template <typename Map>
deba@1024
  2459
    BpGraphReader& arcMap(const std::string& caption, Map& map) {
deba@1024
  2460
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
deba@1024
  2461
      _reader_bits::MapStorageBase<Edge>* forward_storage =
deba@1024
  2462
        new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
deba@1024
  2463
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
deba@1024
  2464
      _reader_bits::MapStorageBase<Edge>* backward_storage =
deba@1024
  2465
        new _reader_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
deba@1024
  2466
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@1024
  2467
      return *this;
deba@1024
  2468
    }
deba@1024
  2469
deba@1024
  2470
    /// \brief Arc map reading rule
deba@1024
  2471
    ///
deba@1024
  2472
    /// Add an arc map reading rule with specialized converter to the
deba@1024
  2473
    /// reader.
deba@1024
  2474
    template <typename Map, typename Converter>
deba@1024
  2475
    BpGraphReader& arcMap(const std::string& caption, Map& map,
deba@1024
  2476
                          const Converter& converter = Converter()) {
deba@1024
  2477
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
deba@1024
  2478
      _reader_bits::MapStorageBase<Edge>* forward_storage =
deba@1024
  2479
        new _reader_bits::GraphArcMapStorage<BGR, true, Map, Converter>
deba@1024
  2480
        (_graph, map, converter);
deba@1024
  2481
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
deba@1024
  2482
      _reader_bits::MapStorageBase<Edge>* backward_storage =
deba@1024
  2483
        new _reader_bits::GraphArcMapStorage<BGR, false, Map, Converter>
deba@1024
  2484
        (_graph, map, converter);
deba@1024
  2485
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@1024
  2486
      return *this;
deba@1024
  2487
    }
deba@1024
  2488
deba@1024
  2489
    /// \brief Attribute reading rule
deba@1024
  2490
    ///
deba@1024
  2491
    /// Add an attribute reading rule to the reader.
deba@1024
  2492
    template <typename Value>
deba@1024
  2493
    BpGraphReader& attribute(const std::string& caption, Value& value) {
deba@1024
  2494
      _reader_bits::ValueStorageBase* storage =
deba@1024
  2495
        new _reader_bits::ValueStorage<Value>(value);
deba@1024
  2496
      _attributes.insert(std::make_pair(caption, storage));
deba@1024
  2497
      return *this;
deba@1024
  2498
    }
deba@1024
  2499
deba@1024
  2500
    /// \brief Attribute reading rule
deba@1024
  2501
    ///
deba@1024
  2502
    /// Add an attribute reading rule with specialized converter to the
deba@1024
  2503
    /// reader.
deba@1024
  2504
    template <typename Value, typename Converter>
deba@1024
  2505
    BpGraphReader& attribute(const std::string& caption, Value& value,
deba@1024
  2506
                             const Converter& converter = Converter()) {
deba@1024
  2507
      _reader_bits::ValueStorageBase* storage =
deba@1024
  2508
        new _reader_bits::ValueStorage<Value, Converter>(value, converter);
deba@1024
  2509
      _attributes.insert(std::make_pair(caption, storage));
deba@1024
  2510
      return *this;
deba@1024
  2511
    }
deba@1024
  2512
deba@1024
  2513
    /// \brief Node reading rule
deba@1024
  2514
    ///
deba@1024
  2515
    /// Add a node reading rule to reader.
deba@1024
  2516
    BpGraphReader& node(const std::string& caption, Node& node) {
deba@1030
  2517
      typedef _reader_bits::DoubleMapLookUpConverter<
deba@1030
  2518
        Node, RedNodeIndex, BlueNodeIndex> Converter;
deba@1030
  2519
      Converter converter(_red_node_index, _blue_node_index);
deba@1024
  2520
      _reader_bits::ValueStorageBase* storage =
deba@1024
  2521
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
deba@1024
  2522
      _attributes.insert(std::make_pair(caption, storage));
deba@1024
  2523
      return *this;
deba@1024
  2524
    }
deba@1024
  2525
deba@1030
  2526
    /// \brief Red node reading rule
deba@1030
  2527
    ///
deba@1030
  2528
    /// Add a red node reading rule to reader.
deba@1030
  2529
    BpGraphReader& redNode(const std::string& caption, RedNode& node) {
deba@1030
  2530
      typedef _reader_bits::MapLookUpConverter<RedNode> Converter;
deba@1030
  2531
      Converter converter(_red_node_index);
deba@1030
  2532
      _reader_bits::ValueStorageBase* storage =
deba@1030
  2533
        new _reader_bits::ValueStorage<RedNode, Converter>(node, converter);
deba@1030
  2534
      _attributes.insert(std::make_pair(caption, storage));
deba@1030
  2535
      return *this;
deba@1030
  2536
    }
deba@1030
  2537
deba@1030
  2538
    /// \brief Blue node reading rule
deba@1030
  2539
    ///
deba@1030
  2540
    /// Add a blue node reading rule to reader.
deba@1030
  2541
    BpGraphReader& blueNode(const std::string& caption, BlueNode& node) {
deba@1030
  2542
      typedef _reader_bits::MapLookUpConverter<BlueNode> Converter;
deba@1030
  2543
      Converter converter(_blue_node_index);
deba@1030
  2544
      _reader_bits::ValueStorageBase* storage =
deba@1030
  2545
        new _reader_bits::ValueStorage<BlueNode, Converter>(node, converter);
deba@1030
  2546
      _attributes.insert(std::make_pair(caption, storage));
deba@1030
  2547
      return *this;
deba@1030
  2548
    }
deba@1030
  2549
deba@1024
  2550
    /// \brief Edge reading rule
deba@1024
  2551
    ///
deba@1024
  2552
    /// Add an edge reading rule to reader.
deba@1024
  2553
    BpGraphReader& edge(const std::string& caption, Edge& edge) {
deba@1024
  2554
      typedef _reader_bits::MapLookUpConverter<Edge> Converter;
deba@1024
  2555
      Converter converter(_edge_index);
deba@1024
  2556
      _reader_bits::ValueStorageBase* storage =
deba@1024
  2557
        new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
deba@1024
  2558
      _attributes.insert(std::make_pair(caption, storage));
deba@1024
  2559
      return *this;
deba@1024
  2560
    }
deba@1024
  2561
deba@1024
  2562
    /// \brief Arc reading rule
deba@1024
  2563
    ///
deba@1024
  2564
    /// Add an arc reading rule to reader.
deba@1024
  2565
    BpGraphReader& arc(const std::string& caption, Arc& arc) {
deba@1024
  2566
      typedef _reader_bits::GraphArcLookUpConverter<BGR> Converter;
deba@1024
  2567
      Converter converter(_graph, _edge_index);
deba@1024
  2568
      _reader_bits::ValueStorageBase* storage =
deba@1024
  2569
        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@1024
  2570
      _attributes.insert(std::make_pair(caption, storage));
deba@1024
  2571
      return *this;
deba@1024
  2572
    }
deba@1024
  2573
deba@1024
  2574
    /// @}
deba@1024
  2575
deba@1024
  2576
    /// \name Select Section by Name
deba@1024
  2577
    /// @{
deba@1024
  2578
deba@1024
  2579
    /// \brief Set \c \@nodes section to be read
deba@1024
  2580
    ///
deba@1024
  2581
    /// Set \c \@nodes section to be read.
deba@1024
  2582
    BpGraphReader& nodes(const std::string& caption) {
deba@1024
  2583
      _nodes_caption = caption;
deba@1024
  2584
      return *this;
deba@1024
  2585
    }
deba@1024
  2586
deba@1024
  2587
    /// \brief Set \c \@edges section to be read
deba@1024
  2588
    ///
deba@1024
  2589
    /// Set \c \@edges section to be read.
deba@1024
  2590
    BpGraphReader& edges(const std::string& caption) {
deba@1024
  2591
      _edges_caption = caption;
deba@1024
  2592
      return *this;
deba@1024
  2593
    }
deba@1024
  2594
deba@1024
  2595
    /// \brief Set \c \@attributes section to be read
deba@1024
  2596
    ///
deba@1024
  2597
    /// Set \c \@attributes section to be read.
deba@1024
  2598
    BpGraphReader& attributes(const std::string& caption) {
deba@1024
  2599
      _attributes_caption = caption;
deba@1024
  2600
      return *this;
deba@1024
  2601
    }
deba@1024
  2602
deba@1024
  2603
    /// @}
deba@1024
  2604
deba@1024
  2605
    /// \name Using Previously Constructed Node or Edge Set
deba@1024
  2606
    /// @{
deba@1024
  2607
deba@1024
  2608
    /// \brief Use previously constructed node set
deba@1024
  2609
    ///
deba@1024
  2610
    /// Use previously constructed node set, and specify the node
deba@1024
  2611
    /// label map.
deba@1024
  2612
    template <typename Map>
deba@1024
  2613
    BpGraphReader& useNodes(const Map& map) {
deba@1024
  2614
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@1024
  2615
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
deba@1024
  2616
      _use_nodes = true;
deba@1024
  2617
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@1030
  2618
      for (RedNodeIt n(_graph); n != INVALID; ++n) {
deba@1030
  2619
        _red_node_index.insert(std::make_pair(converter(map[n]), n));
deba@1030
  2620
      }
deba@1030
  2621
      for (BlueNodeIt n(_graph); n != INVALID; ++n) {
deba@1030
  2622
        _blue_node_index.insert(std::make_pair(converter(map[n]), n));
deba@1024
  2623
      }
deba@1024
  2624
      return *this;
deba@1024
  2625
    }
deba@1024
  2626
deba@1024
  2627
    /// \brief Use previously constructed node set
deba@1024
  2628
    ///
deba@1024
  2629
    /// Use previously constructed node set, and specify the node
deba@1024
  2630
    /// label map and a functor which converts the label map values to
deba@1024
  2631
    /// \c std::string.
deba@1024
  2632
    template <typename Map, typename Converter>
deba@1024
  2633
    BpGraphReader& useNodes(const Map& map,
deba@1024
  2634
                            const Converter& converter = Converter()) {
deba@1024
  2635
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@1024
  2636
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
deba@1024
  2637
      _use_nodes = true;
deba@1030
  2638
      for (RedNodeIt n(_graph); n != INVALID; ++n) {
deba@1030
  2639
        _red_node_index.insert(std::make_pair(converter(map[n]), n));
deba@1030
  2640
      }
alpar@1092
  2641
      for (BlueNodeIt n(_graph); n != INVALID; ++n) {
deba@1030
  2642
        _blue_node_index.insert(std::make_pair(converter(map[n]), n));
deba@1024
  2643
      }
deba@1024
  2644
      return *this;
deba@1024
  2645
    }
deba@1024
  2646
deba@1024
  2647
    /// \brief Use previously constructed edge set
deba@1024
  2648
    ///
deba@1024
  2649
    /// Use previously constructed edge set, and specify the edge
deba@1024
  2650
    /// label map.
deba@1024
  2651
    template <typename Map>
deba@1024
  2652
    BpGraphReader& useEdges(const Map& map) {
deba@1024
  2653
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@1024
  2654
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
deba@1024
  2655
      _use_edges = true;
deba@1024
  2656
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@1024
  2657
      for (EdgeIt a(_graph); a != INVALID; ++a) {
deba@1024
  2658
        _edge_index.insert(std::make_pair(converter(map[a]), a));
deba@1024
  2659
      }
deba@1024
  2660
      return *this;
deba@1024
  2661
    }
deba@1024
  2662
deba@1024
  2663
    /// \brief Use previously constructed edge set
deba@1024
  2664
    ///
deba@1024
  2665
    /// Use previously constructed edge set, and specify the edge
deba@1024
  2666
    /// label map and a functor which converts the label map values to
deba@1024
  2667
    /// \c std::string.
deba@1024
  2668
    template <typename Map, typename Converter>
deba@1024
  2669
    BpGraphReader& useEdges(const Map& map,
deba@1024
  2670
                            const Converter& converter = Converter()) {
deba@1024
  2671
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@1024
  2672
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
deba@1024
  2673
      _use_edges = true;
deba@1024
  2674
      for (EdgeIt a(_graph); a != INVALID; ++a) {
deba@1024
  2675
        _edge_index.insert(std::make_pair(converter(map[a]), a));
deba@1024
  2676
      }
deba@1024
  2677
      return *this;
deba@1024
  2678
    }
deba@1024
  2679
deba@1024
  2680
    /// \brief Skip the reading of node section
deba@1024
  2681
    ///
deba@1024
  2682
    /// Omit the reading of the node section. This implies that each node
deba@1024
  2683
    /// map reading rule will be abandoned, and the nodes of the graph
deba@1024
  2684
    /// will not be constructed, which usually cause that the edge set
deba@1024
  2685
    /// could not be read due to lack of node name
deba@1024
  2686
    /// could not be read due to lack of node name resolving.
deba@1024
  2687
    /// Therefore \c skipEdges() function should also be used, or
deba@1024
  2688
    /// \c useNodes() should be used to specify the label of the nodes.
deba@1024
  2689
    BpGraphReader& skipNodes() {
deba@1024
  2690
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
deba@1024
  2691
      _skip_nodes = true;
deba@1024
  2692
      return *this;
deba@1024
  2693
    }
deba@1024
  2694
deba@1024
  2695
    /// \brief Skip the reading of edge section
deba@1024
  2696
    ///
deba@1024
  2697
    /// Omit the reading of the edge section. This implies that each edge
deba@1024
  2698
    /// map reading rule will be abandoned, and the edges of the graph
deba@1024
  2699
    /// will not be constructed.
deba@1024
  2700
    BpGraphReader& skipEdges() {
deba@1024
  2701
      LEMON_ASSERT(!_skip_edges, "Skip edges already set");
deba@1024
  2702
      _skip_edges = true;
deba@1024
  2703
      return *this;
deba@1024
  2704
    }
deba@1024
  2705
deba@1024
  2706
    /// @}
deba@1024
  2707
deba@1024
  2708
  private:
deba@1024
  2709
deba@1024
  2710
    bool readLine() {
deba@1024
  2711
      std::string str;
deba@1024
  2712
      while(++line_num, std::getline(*_is, str)) {
deba@1024
  2713
        line.clear(); line.str(str);
deba@1024
  2714
        char c;
deba@1024
  2715
        if (line >> std::ws >> c && c != '#') {
deba@1024
  2716
          line.putback(c);
deba@1024
  2717
          return true;
deba@1024
  2718
        }
deba@1024
  2719
      }
deba@1024
  2720
      return false;
deba@1024
  2721
    }
deba@1024
  2722
deba@1024
  2723
    bool readSuccess() {
deba@1024
  2724
      return static_cast<bool>(*_is);
deba@1024
  2725
    }
deba@1024
  2726
deba@1024
  2727
    void skipSection() {
deba@1024
  2728
      char c;
deba@1024
  2729
      while (readSuccess() && line >> c && c != '@') {
deba@1024
  2730
        readLine();
deba@1024
  2731
      }
deba@1024
  2732
      if (readSuccess()) {
deba@1024
  2733
        line.putback(c);
deba@1024
  2734
      }
deba@1024
  2735
    }
deba@1024
  2736
deba@1024
  2737
    void readRedNodes() {
deba@1024
  2738
deba@1030
  2739
      std::vector<int> map_index(_red_node_maps.size());
deba@1024
  2740
      int map_num, label_index;
deba@1024
  2741
deba@1024
  2742
      char c;
deba@1024
  2743
      if (!readLine() || !(line >> c) || c == '@') {
deba@1024
  2744
        if (readSuccess() && line) line.putback(c);
deba@1030
  2745
        if (!_red_node_maps.empty())
deba@1024
  2746
          throw FormatError("Cannot find map names");
deba@1024
  2747
        return;
deba@1024
  2748
      }
deba@1024
  2749
      line.putback(c);
deba@1024
  2750
deba@1024
  2751
      {
deba@1024
  2752
        std::map<std::string, int> maps;
deba@1024
  2753
deba@1024
  2754
        std::string map;
deba@1024
  2755
        int index = 0;
deba@1024
  2756
        while (_reader_bits::readToken(line, map)) {
deba@1024
  2757
          if (maps.find(map) != maps.end()) {
deba@1024
  2758
            std::ostringstream msg;
deba@1026
  2759
            msg << "Multiple occurence of red node map: " << map;
deba@1024
  2760
            throw FormatError(msg.str());
deba@1024
  2761
          }
deba@1024
  2762
          maps.insert(std::make_pair(map, index));
deba@1024
  2763
          ++index;
deba@1024
  2764
        }
deba@1024
  2765
deba@1030
  2766
        for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
deba@1024
  2767
          std::map<std::string, int>::iterator jt =
deba@1030
  2768
            maps.find(_red_node_maps[i].first);
deba@1024
  2769
          if (jt == maps.end()) {
deba@1024
  2770
            std::ostringstream msg;
deba@1030
  2771
            msg << "Map not found: " << _red_node_maps[i].first;
deba@1024
  2772
            throw FormatError(msg.str());
deba@1024
  2773
          }
deba@1024
  2774
          map_index[i] = jt->second;
deba@1024
  2775
        }
deba@1024
  2776
deba@1024
  2777
        {
deba@1024
  2778
          std::map<std::string, int>::iterator jt = maps.find("label");
deba@1024
  2779
          if (jt != maps.end()) {
deba@1024
  2780
            label_index = jt->second;
deba@1024
  2781
          } else {
deba@1024
  2782
            label_index = -1;
deba@1024
  2783
          }
deba@1024
  2784
        }
deba@1024
  2785
        map_num = maps.size();
deba@1024
  2786
      }
deba@1024
  2787
deba@1024
  2788
      while (readLine() && line >> c && c != '@') {
deba@1024
  2789
        line.putback(c);
deba@1024
  2790
deba@1024
  2791
        std::vector<std::string> tokens(map_num);
deba@1024
  2792
        for (int i = 0; i < map_num; ++i) {
deba@1024
  2793
          if (!_reader_bits::readToken(line, tokens[i])) {
deba@1024
  2794
            std::ostringstream msg;
deba@1024
  2795
            msg << "Column not found (" << i + 1 << ")";
deba@1024
  2796
            throw FormatError(msg.str());
deba@1024
  2797
          }
deba@1024
  2798
        }
deba@1024
  2799
        if (line >> std::ws >> c)
deba@1024
  2800
          throw FormatError("Extra character at the end of line");
deba@1024
  2801
deba@1030
  2802
        RedNode n;
deba@1024
  2803
        if (!_use_nodes) {
deba@1024
  2804
          n = _graph.addRedNode();
deba@1024
  2805
          if (label_index != -1)
deba@1030
  2806
            _red_node_index.insert(std::make_pair(tokens[label_index], n));
deba@1024
  2807
        } else {
deba@1024
  2808
          if (label_index == -1)
deba@1024
  2809
            throw FormatError("Label map not found");
deba@1030
  2810
          typename std::map<std::string, RedNode>::iterator it =
deba@1030
  2811
            _red_node_index.find(tokens[label_index]);
deba@1030
  2812
          if (it == _red_node_index.end()) {
deba@1024
  2813
            std::ostringstream msg;
deba@1024
  2814
            msg << "Node with label not found: " << tokens[label_index];
deba@1024
  2815
            throw FormatError(msg.str());
deba@1024
  2816
          }
deba@1024
  2817
          n = it->second;
deba@1024
  2818
        }
deba@1024
  2819
deba@1030
  2820
        for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
deba@1030
  2821
          _red_node_maps[i].second->set(n, tokens[map_index[i]]);
deba@1024
  2822
        }
deba@1024
  2823
deba@1024
  2824
      }
deba@1024
  2825
      if (readSuccess()) {
deba@1024
  2826
        line.putback(c);
deba@1024
  2827
      }
deba@1024
  2828
    }
deba@1024
  2829
deba@1024
  2830
    void readBlueNodes() {
deba@1024
  2831
deba@1030
  2832
      std::vector<int> map_index(_blue_node_maps.size());
deba@1024
  2833
      int map_num, label_index;
deba@1024
  2834
deba@1024
  2835
      char c;
deba@1024
  2836
      if (!readLine() || !(line >> c) || c == '@') {
deba@1024
  2837
        if (readSuccess() && line) line.putback(c);
deba@1030
  2838
        if (!_blue_node_maps.empty())
deba@1024
  2839
          throw FormatError("Cannot find map names");
deba@1024
  2840
        return;
deba@1024
  2841
      }
deba@1024
  2842
      line.putback(c);
deba@1024
  2843
deba@1024
  2844
      {
deba@1024
  2845
        std::map<std::string, int> maps;
deba@1024
  2846
deba@1024
  2847
        std::string map;
deba@1024
  2848
        int index = 0;
deba@1024
  2849
        while (_reader_bits::readToken(line, map)) {
deba@1024
  2850
          if (maps.find(map) != maps.end()) {
deba@1024
  2851
            std::ostringstream msg;
deba@1026
  2852
            msg << "Multiple occurence of blue node map: " << map;
deba@1024
  2853
            throw FormatError(msg.str());
deba@1024
  2854
          }
deba@1024
  2855
          maps.insert(std::make_pair(map, index));
deba@1024
  2856
          ++index;
deba@1024
  2857
        }
deba@1024
  2858
deba@1030
  2859
        for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
deba@1024
  2860
          std::map<std::string, int>::iterator jt =
deba@1030
  2861
            maps.find(_blue_node_maps[i].first);
deba@1024
  2862
          if (jt == maps.end()) {
deba@1024
  2863
            std::ostringstream msg;
deba@1030
  2864
            msg << "Map not found: " << _blue_node_maps[i].first;
deba@1024
  2865
            throw FormatError(msg.str());
deba@1024
  2866
          }
deba@1024
  2867
          map_index[i] = jt->second;
deba@1024
  2868
        }
deba@1024
  2869
deba@1024
  2870
        {
deba@1024
  2871
          std::map<std::string, int>::iterator jt = maps.find("label");
deba@1024
  2872
          if (jt != maps.end()) {
deba@1024
  2873
            label_index = jt->second;
deba@1024
  2874
          } else {
deba@1024
  2875
            label_index = -1;
deba@1024
  2876
          }
deba@1024
  2877
        }
deba@1024
  2878
        map_num = maps.size();
deba@1024
  2879
      }
deba@1024
  2880
deba@1024
  2881
      while (readLine() && line >> c && c != '@') {
deba@1024
  2882
        line.putback(c);
deba@1024
  2883
deba@1024
  2884
        std::vector<std::string> tokens(map_num);
deba@1024
  2885
        for (int i = 0; i < map_num; ++i) {
deba@1024
  2886
          if (!_reader_bits::readToken(line, tokens[i])) {
deba@1024
  2887
            std::ostringstream msg;
deba@1024
  2888
            msg << "Column not found (" << i + 1 << ")";
deba@1024
  2889
            throw FormatError(msg.str());
deba@1024
  2890
          }
deba@1024
  2891
        }
deba@1024
  2892
        if (line >> std::ws >> c)
deba@1024
  2893
          throw FormatError("Extra character at the end of line");
deba@1024
  2894
deba@1030
  2895
        BlueNode n;
deba@1024
  2896
        if (!_use_nodes) {
deba@1024
  2897
          n = _graph.addBlueNode();
deba@1024
  2898
          if (label_index != -1)
deba@1030
  2899
            _blue_node_index.insert(std::make_pair(tokens[label_index], n));
deba@1024
  2900
        } else {
deba@1024
  2901
          if (label_index == -1)
deba@1024
  2902
            throw FormatError("Label map not found");
deba@1030
  2903
          typename std::map<std::string, BlueNode>::iterator it =
deba@1030
  2904
            _blue_node_index.find(tokens[label_index]);
deba@1030
  2905
          if (it == _blue_node_index.end()) {
deba@1024
  2906
            std::ostringstream msg;
deba@1024
  2907
            msg << "Node with label not found: " << tokens[label_index];
deba@1024
  2908
            throw FormatError(msg.str());
deba@1024
  2909
          }
deba@1024
  2910
          n = it->second;
deba@1024
  2911
        }
deba@1024
  2912
deba@1030
  2913
        for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
deba@1030
  2914
          _blue_node_maps[i].second->set(n, tokens[map_index[i]]);
deba@1024
  2915
        }
deba@1024
  2916
deba@1024
  2917
      }
deba@1024
  2918
      if (readSuccess()) {
deba@1024
  2919
        line.putback(c);
deba@1024
  2920
      }
deba@1024
  2921
    }
deba@1024
  2922
deba@1024
  2923
    void readEdges() {
deba@1024
  2924
deba@1024
  2925
      std::vector<int> map_index(_edge_maps.size());
deba@1024
  2926
      int map_num, label_index;
deba@1024
  2927
deba@1024
  2928
      char c;
deba@1024
  2929
      if (!readLine() || !(line >> c) || c == '@') {
deba@1024
  2930
        if (readSuccess() && line) line.putback(c);
deba@1024
  2931
        if (!_edge_maps.empty())
deba@1024
  2932
          throw FormatError("Cannot find map names");
deba@1024
  2933
        return;
deba@1024
  2934
      }
deba@1024
  2935
      line.putback(c);
deba@1024
  2936
deba@1024
  2937
      {
deba@1024
  2938
        std::map<std::string, int> maps;
deba@1024
  2939
deba@1024
  2940
        std::string map;
deba@1024
  2941
        int index = 0;
deba@1024
  2942
        while (_reader_bits::readToken(line, map)) {
deba@1024
  2943
          if (maps.find(map) != maps.end()) {
deba@1024
  2944
            std::ostringstream msg;
deba@1024
  2945
            msg << "Multiple occurence of edge map: " << map;
deba@1024
  2946
            throw FormatError(msg.str());
deba@1024
  2947
          }
deba@1024
  2948
          maps.insert(std::make_pair(map, index));
deba@1024
  2949
          ++index;
deba@1024
  2950
        }
deba@1024
  2951
deba@1024
  2952
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
deba@1024
  2953
          std::map<std::string, int>::iterator jt =
deba@1024
  2954
            maps.find(_edge_maps[i].first);
deba@1024
  2955
          if (jt == maps.end()) {
deba@1024
  2956
            std::ostringstream msg;
deba@1024
  2957
            msg << "Map not found: " << _edge_maps[i].first;
deba@1024
  2958
            throw FormatError(msg.str());
deba@1024
  2959
          }
deba@1024
  2960
          map_index[i] = jt->second;
deba@1024
  2961
        }
deba@1024
  2962
deba@1024
  2963
        {
deba@1024
  2964
          std::map<std::string, int>::iterator jt = maps.find("label");
deba@1024
  2965
          if (jt != maps.end()) {
deba@1024
  2966
            label_index = jt->second;
deba@1024
  2967
          } else {
deba@1024
  2968
            label_index = -1;
deba@1024
  2969
          }
deba@1024
  2970
        }
deba@1024
  2971
        map_num = maps.size();
deba@1024
  2972
      }
deba@1024
  2973
deba@1024
  2974
      while (readLine() && line >> c && c != '@') {
deba@1024
  2975
        line.putback(c);
deba@1024
  2976
deba@1024
  2977
        std::string source_token;
deba@1024
  2978
        std::string target_token;
deba@1024
  2979
deba@1024
  2980
        if (!_reader_bits::readToken(line, source_token))
deba@1024
  2981
          throw FormatError("Red node not found");
deba@1024
  2982
deba@1024
  2983
        if (!_reader_bits::readToken(line, target_token))
deba@1024
  2984
          throw FormatError("Blue node not found");
deba@1024
  2985
deba@1024
  2986
        std::vector<std::string> tokens(map_num);
deba@1024
  2987
        for (int i = 0; i < map_num; ++i) {
deba@1024
  2988
          if (!_reader_bits::readToken(line, tokens[i])) {
deba@1024
  2989
            std::ostringstream msg;
deba@1024
  2990
            msg << "Column not found (" << i + 1 << ")";
deba@1024
  2991
            throw FormatError(msg.str());
deba@1024
  2992
          }
deba@1024
  2993
        }
deba@1024
  2994
        if (line >> std::ws >> c)
deba@1024
  2995
          throw FormatError("Extra character at the end of line");
deba@1024
  2996
deba@1024
  2997
        Edge e;
deba@1024
  2998
        if (!_use_edges) {
deba@1030
  2999
          typename RedNodeIndex::iterator rit =
deba@1030
  3000
            _red_node_index.find(source_token);
deba@1030
  3001
          if (rit == _red_node_index.end()) {
deba@1024
  3002
            std::ostringstream msg;
deba@1024
  3003
            msg << "Item not found: " << source_token;
deba@1024
  3004
            throw FormatError(msg.str());
deba@1024
  3005
          }
deba@1030
  3006
          RedNode source = rit->second;
deba@1030
  3007
          typename BlueNodeIndex::iterator it =
deba@1030
  3008
            _blue_node_index.find(target_token);
deba@1030
  3009
          if (it == _blue_node_index.end()) {
deba@1024
  3010
            std::ostringstream msg;
deba@1024
  3011
            msg << "Item not found: " << target_token;
deba@1024
  3012
            throw FormatError(msg.str());
deba@1024
  3013
          }
deba@1030
  3014
          BlueNode target = it->second;
deba@1024
  3015
poroszd@1029
  3016
          // It is checked that source is red and
poroszd@1029
  3017
          // target is blue, so this should be safe:
deba@1030
  3018
          e = _graph.addEdge(source, target);
deba@1024
  3019
          if (label_index != -1)
deba@1024
  3020
            _edge_index.insert(std::make_pair(tokens[label_index], e));
deba@1024
  3021
        } else {
deba@1024
  3022
          if (label_index == -1)
deba@1024
  3023
            throw FormatError("Label map not found");
deba@1024
  3024
          typename std::map<std::string, Edge>::iterator it =
deba@1024
  3025
            _edge_index.find(tokens[label_index]);
deba@1024
  3026
          if (it == _edge_index.end()) {
deba@1024
  3027
            std::ostringstream msg;
deba@1024
  3028
            msg << "Edge with label not found: " << tokens[label_index];
deba@1024
  3029
            throw FormatError(msg.str());
deba@1024
  3030
          }
deba@1024
  3031
          e = it->second;
deba@1024
  3032
        }
deba@1024
  3033
deba@1024
  3034
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
deba@1024
  3035
          _edge_maps[i].second->set(e, tokens[map_index[i]]);
deba@1024
  3036
        }
deba@1024
  3037
deba@1024
  3038
      }
deba@1024
  3039
      if (readSuccess()) {
deba@1024
  3040
        line.putback(c);
deba@1024
  3041
      }
deba@1024
  3042
    }
deba@1024
  3043
deba@1024
  3044
    void readAttributes() {
deba@1024
  3045
deba@1024
  3046
      std::set<std::string> read_attr;
deba@1024
  3047
deba@1024
  3048
      char c;
deba@1024
  3049
      while (readLine() && line >> c && c != '@') {
deba@1024
  3050
        line.putback(c);
deba@1024
  3051
deba@1024
  3052
        std::string attr, token;
deba@1024
  3053
        if (!_reader_bits::readToken(line, attr))
deba@1024
  3054
          throw FormatError("Attribute name not found");
deba@1024
  3055
        if (!_reader_bits::readToken(line, token))
deba@1024
  3056
          throw FormatError("Attribute value not found");
deba@1024
  3057
        if (line >> c)
deba@1024
  3058
          throw FormatError("Extra character at the end of line");
deba@1024
  3059
deba@1024
  3060
        {
deba@1024
  3061
          std::set<std::string>::iterator it = read_attr.find(attr);
deba@1024
  3062
          if (it != read_attr.end()) {
deba@1024
  3063
            std::ostringstream msg;
deba@1024
  3064
            msg << "Multiple occurence of attribute: " << attr;
deba@1024
  3065
            throw FormatError(msg.str());
deba@1024
  3066
          }
deba@1024
  3067
          read_attr.insert(attr);
deba@1024
  3068
        }
deba@1024
  3069
deba@1024
  3070
        {
deba@1024
  3071
          typename Attributes::iterator it = _attributes.lower_bound(attr);
deba@1024
  3072
          while (it != _attributes.end() && it->first == attr) {
deba@1024
  3073
            it->second->set(token);
deba@1024
  3074
            ++it;
deba@1024
  3075
          }
deba@1024
  3076
        }
deba@1024
  3077
deba@1024
  3078
      }
deba@1024
  3079
      if (readSuccess()) {
deba@1024
  3080
        line.putback(c);
deba@1024
  3081
      }
deba@1024
  3082
      for (typename Attributes::iterator it = _attributes.begin();
deba@1024
  3083
           it != _attributes.end(); ++it) {
deba@1024
  3084
        if (read_attr.find(it->first) == read_attr.end()) {
deba@1024
  3085
          std::ostringstream msg;
deba@1024
  3086
          msg << "Attribute not found: " << it->first;
deba@1024
  3087
          throw FormatError(msg.str());
deba@1024
  3088
        }
deba@1024
  3089
      }
deba@1024
  3090
    }
deba@1024
  3091
deba@1024
  3092
  public:
deba@1024
  3093
deba@1024
  3094
    /// \name Execution of the Reader
deba@1024
  3095
    /// @{
deba@1024
  3096
deba@1024
  3097
    /// \brief Start the batch processing
deba@1024
  3098
    ///
deba@1024
  3099
    /// This function starts the batch processing
deba@1024
  3100
    void run() {
deba@1024
  3101
deba@1024
  3102
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
deba@1024
  3103
deba@1024
  3104
      bool red_nodes_done = _skip_nodes;
deba@1024
  3105
      bool blue_nodes_done = _skip_nodes;
deba@1024
  3106
      bool edges_done = _skip_edges;
deba@1024
  3107
      bool attributes_done = false;
deba@1024
  3108
deba@1024
  3109
      line_num = 0;
deba@1024
  3110
      readLine();
deba@1024
  3111
      skipSection();
deba@1024
  3112
deba@1024
  3113
      while (readSuccess()) {
deba@1024
  3114
        try {
deba@1024
  3115
          char c;
deba@1024
  3116
          std::string section, caption;
deba@1024
  3117
          line >> c;
deba@1024
  3118
          _reader_bits::readToken(line, section);
deba@1024
  3119
          _reader_bits::readToken(line, caption);
deba@1024
  3120
deba@1024
  3121
          if (line >> c)
deba@1024
  3122
            throw FormatError("Extra character at the end of line");
deba@1024
  3123
deba@1024
  3124
          if (section == "red_nodes" && !red_nodes_done) {
deba@1024
  3125
            if (_nodes_caption.empty() || _nodes_caption == caption) {
deba@1024
  3126
              readRedNodes();
deba@1024
  3127
              red_nodes_done = true;
deba@1024
  3128
            }
deba@1024
  3129
          } else if (section == "blue_nodes" && !blue_nodes_done) {
deba@1024
  3130
            if (_nodes_caption.empty() || _nodes_caption == caption) {
deba@1024
  3131
              readBlueNodes();
deba@1024
  3132
              blue_nodes_done = true;
deba@1024
  3133
            }
deba@1024
  3134
          } else if ((section == "edges" || section == "arcs") &&
deba@1024
  3135
                     !edges_done) {
deba@1024
  3136
            if (_edges_caption.empty() || _edges_caption == caption) {
deba@1024
  3137
              readEdges();
deba@1024
  3138
              edges_done = true;
deba@1024
  3139
            }
deba@1024
  3140
          } else if (section == "attributes" && !attributes_done) {
deba@1024
  3141
            if (_attributes_caption.empty() || _attributes_caption == caption) {
deba@1024
  3142
              readAttributes();
deba@1024
  3143
              attributes_done = true;
deba@1024
  3144
            }
deba@1024
  3145
          } else {
deba@1024
  3146
            readLine();
deba@1024
  3147
            skipSection();
deba@1024
  3148
          }
deba@1024
  3149
        } catch (FormatError& error) {
deba@1024
  3150
          error.line(line_num);
deba@1024
  3151
          error.file(_filename);
deba@1024
  3152
          throw;
deba@1024
  3153
        }
deba@1024
  3154
      }
deba@1024
  3155
deba@1024
  3156
      if (!red_nodes_done) {
deba@1024
  3157
        throw FormatError("Section @red_nodes not found");
deba@1024
  3158
      }
deba@1024
  3159
deba@1024
  3160
      if (!blue_nodes_done) {
deba@1024
  3161
        throw FormatError("Section @blue_nodes not found");
deba@1024
  3162
      }
deba@1024
  3163
deba@1024
  3164
      if (!edges_done) {
deba@1024
  3165
        throw FormatError("Section @edges not found");
deba@1024
  3166
      }
deba@1024
  3167
deba@1024
  3168
      if (!attributes_done && !_attributes.empty()) {
deba@1024
  3169
        throw FormatError("Section @attributes not found");
deba@1024
  3170
      }
deba@1024
  3171
deba@1024
  3172
    }
deba@1024
  3173
deba@1024
  3174
    /// @}
deba@1024
  3175
deba@1024
  3176
  };
deba@1024
  3177
deba@1024
  3178
  /// \ingroup lemon_io
deba@1024
  3179
  ///
alpar@1076
  3180
  /// \brief Return a \ref lemon::BpGraphReader "BpGraphReader" class
deba@1024
  3181
  ///
alpar@1076
  3182
  /// This function just returns a \ref lemon::BpGraphReader
alpar@1076
  3183
  /// "BpGraphReader" class.
deba@1024
  3184
  ///
deba@1024
  3185
  /// With this function a graph can be read from an
deba@1024
  3186
  /// \ref lgf-format "LGF" file or input stream with several maps and
deba@1024
  3187
  /// attributes. For example, there is bipartite weighted matching problem
deba@1024
  3188
  /// on a graph, i.e. a graph with a \e weight map on the edges. This
deba@1024
  3189
  /// graph can be read with the following code:
deba@1024
  3190
  ///
deba@1024
  3191
  ///\code
deba@1024
  3192
  ///ListBpGraph graph;
deba@1024
  3193
  ///ListBpGraph::EdgeMap<int> weight(graph);
deba@1024
  3194
  ///bpGraphReader(graph, std::cin).
deba@1024
  3195
  ///  edgeMap("weight", weight).
deba@1024
  3196
  ///  run();
deba@1024
  3197
  ///\endcode
deba@1024
  3198
  ///
alpar@1076
  3199
  /// For a complete documentation, please see the
alpar@1076
  3200
  /// \ref lemon::BpGraphReader "BpGraphReader"
deba@1024
  3201
  /// class documentation.
alpar@1076
  3202
  /// \warning Don't forget to put the \ref lemon::BpGraphReader::run() "run()"
deba@1024
  3203
  /// to the end of the parameter list.
deba@1024
  3204
  /// \relates BpGraphReader
deba@1024
  3205
  /// \sa bpGraphReader(TBGR& graph, const std::string& fn)
deba@1024
  3206
  /// \sa bpGraphReader(TBGR& graph, const char* fn)
deba@1024
  3207
  template <typename TBGR>
deba@1024
  3208
  BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is) {
deba@1024
  3209
    BpGraphReader<TBGR> tmp(graph, is);
deba@1024
  3210
    return tmp;
deba@1024
  3211
  }
deba@1024
  3212
deba@1024
  3213
  /// \brief Return a \ref BpGraphReader class
deba@1024
  3214
  ///
deba@1024
  3215
  /// This function just returns a \ref BpGraphReader class.
deba@1024
  3216
  /// \relates BpGraphReader
deba@1024
  3217
  /// \sa bpGraphReader(TBGR& graph, std::istream& is)
deba@1024
  3218
  template <typename TBGR>
deba@1024
  3219
  BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn) {
deba@1024
  3220
    BpGraphReader<TBGR> tmp(graph, fn);
deba@1024
  3221
    return tmp;
deba@1024
  3222
  }
deba@1024
  3223
deba@1024
  3224
  /// \brief Return a \ref BpGraphReader class
deba@1024
  3225
  ///
deba@1024
  3226
  /// This function just returns a \ref BpGraphReader class.
deba@1024
  3227
  /// \relates BpGraphReader
deba@1024
  3228
  /// \sa bpGraphReader(TBGR& graph, std::istream& is)
deba@1024
  3229
  template <typename TBGR>
deba@1024
  3230
  BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char* fn) {
deba@1024
  3231
    BpGraphReader<TBGR> tmp(graph, fn);
deba@1024
  3232
    return tmp;
deba@1024
  3233
  }
deba@1024
  3234
deba@190
  3235
  class SectionReader;
deba@190
  3236
deba@190
  3237
  SectionReader sectionReader(std::istream& is);
deba@190
  3238
  SectionReader sectionReader(const std::string& fn);
deba@190
  3239
  SectionReader sectionReader(const char* fn);
alpar@209
  3240
kpeter@192
  3241
  /// \ingroup lemon_io
kpeter@192
  3242
  ///
deba@189
  3243
  /// \brief Section reader class
deba@189
  3244
  ///
alpar@209
  3245
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
kpeter@192
  3246
  /// which contain any data in arbitrary format. Such sections can be
alpar@209
  3247
  /// read with this class. A reading rule can be added to the class
kpeter@192
  3248
  /// with two different functions. With the \c sectionLines() function a
kpeter@192
  3249
  /// functor can process the section line-by-line, while with the \c
deba@189
  3250
  /// sectionStream() member the section can be read from an input
deba@189
  3251
  /// stream.
deba@189
  3252
  class SectionReader {
deba@189
  3253
  private:
alpar@209
  3254
deba@189
  3255
    std::istream* _is;
deba@189
  3256
    bool local_is;
deba@290
  3257
    std::string _filename;
deba@189
  3258
deba@189
  3259
    typedef std::map<std::string, _reader_bits::Section*> Sections;
deba@189
  3260
    Sections _sections;
deba@189
  3261
deba@189
  3262
    int line_num;
deba@189
  3263
    std::istringstream line;
deba@189
  3264
deba@189
  3265
  public:
deba@189
  3266
deba@189
  3267
    /// \brief Constructor
deba@189
  3268
    ///
deba@189
  3269
    /// Construct a section reader, which reads from the given input
deba@189
  3270
    /// stream.
alpar@209
  3271
    SectionReader(std::istream& is)
deba@189
  3272
      : _is(&is), local_is(false) {}
deba@189
  3273
deba@189
  3274
    /// \brief Constructor
deba@189
  3275
    ///
deba@189
  3276
    /// Construct a section reader, which reads from the given file.
alpar@209
  3277
    SectionReader(const std::string& fn)
deba@290
  3278
      : _is(new std::ifstream(fn.c_str())), local_is(true),
deba@290
  3279
        _filename(fn) {
deba@295
  3280
      if (!(*_is)) {
deba@295
  3281
        delete _is;
deba@295
  3282
        throw IoError("Cannot open file", fn);
deba@295
  3283
      }
deba@290
  3284
    }
alpar@209
  3285
deba@189
  3286
    /// \brief Constructor
deba@189
  3287
    ///
deba@189
  3288
    /// Construct a section reader, which reads from the given file.
alpar@209
  3289
    SectionReader(const char* fn)
deba@290
  3290
      : _is(new std::ifstream(fn)), local_is(true),
deba@290
  3291
        _filename(fn) {
deba@295
  3292
      if (!(*_is)) {
deba@295
  3293
        delete _is;
deba@295
  3294
        throw IoError("Cannot open file", fn);
deba@295
  3295
      }
deba@290
  3296
    }
deba@189
  3297
deba@189
  3298
    /// \brief Destructor
deba@189
  3299
    ~SectionReader() {
alpar@209
  3300
      for (Sections::iterator it = _sections.begin();
alpar@209
  3301
           it != _sections.end(); ++it) {
alpar@209
  3302
        delete it->second;
deba@189
  3303
      }
deba@189
  3304
deba@189
  3305
      if (local_is) {
alpar@209
  3306
        delete _is;
deba@189
  3307
      }
deba@189
  3308
deba@189
  3309
    }
deba@189
  3310
deba@189
  3311
  private:
deba@190
  3312
deba@190
  3313
    friend SectionReader sectionReader(std::istream& is);
deba@190
  3314
    friend SectionReader sectionReader(const std::string& fn);
deba@190
  3315
    friend SectionReader sectionReader(const char* fn);
deba@190
  3316
alpar@209
  3317
    SectionReader(SectionReader& other)
deba@190
  3318
      : _is(other._is), local_is(other.local_is) {
deba@190
  3319
deba@190
  3320
      other._is = 0;
deba@190
  3321
      other.local_is = false;
alpar@209
  3322
deba@190
  3323
      _sections.swap(other._sections);
deba@190
  3324
    }
alpar@209
  3325
deba@189
  3326
    SectionReader& operator=(const SectionReader&);
deba@189
  3327
deba@189
  3328
  public:
deba@189
  3329
kpeter@584
  3330
    /// \name Section Readers
deba@189
  3331
    /// @{
deba@189
  3332
deba@189
  3333
    /// \brief Add a section processor with line oriented reading
deba@189
  3334
    ///
deba@189
  3335
    /// The first parameter is the type descriptor of the section, the
deba@189
  3336
    /// second is a functor, which takes just one \c std::string
deba@189
  3337
    /// parameter. At the reading process, each line of the section
deba@189
  3338
    /// will be given to the functor object. However, the empty lines
deba@189
  3339
    /// and the comment lines are filtered out, and the leading
deba@189
  3340
    /// whitespaces are trimmed from each processed string.
deba@189
  3341
    ///
kpeter@786
  3342
    /// For example, let's see a section, which contain several
deba@189
  3343
    /// integers, which should be inserted into a vector.
deba@189
  3344
    ///\code
deba@189
  3345
    ///  @numbers
deba@189
  3346
    ///  12 45 23
deba@189
  3347
    ///  4
deba@189
  3348
    ///  23 6
deba@189
  3349
    ///\endcode
deba@189
  3350
    ///
kpeter@192
  3351
    /// The functor is implemented as a struct:
deba@189
  3352
    ///\code
deba@189
  3353
    ///  struct NumberSection {
deba@189
  3354
    ///    std::vector<int>& _data;
deba@189
  3355
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
deba@189
  3356
    ///    void operator()(const std::string& line) {
deba@189
  3357
    ///      std::istringstream ls(line);
deba@189
  3358
    ///      int value;
deba@189
  3359
    ///      while (ls >> value) _data.push_back(value);
deba@189
  3360
    ///    }
deba@189
  3361
    ///  };
deba@189
  3362
    ///
deba@189
  3363
    ///  // ...
deba@189
  3364
    ///
alpar@209
  3365
    ///  reader.sectionLines("numbers", NumberSection(vec));
deba@189
  3366
    ///\endcode
deba@189
  3367
    template <typename Functor>
deba@189
  3368
    SectionReader& sectionLines(const std::string& type, Functor functor) {
kpeter@192
  3369
      LEMON_ASSERT(!type.empty(), "Type is empty.");
alpar@209
  3370
      LEMON_ASSERT(_sections.find(type) == _sections.end(),
alpar@209
  3371
                   "Multiple reading of section.");
alpar@209
  3372
      _sections.insert(std::make_pair(type,
deba@189
  3373
        new _reader_bits::LineSection<Functor>(functor)));
deba@189
  3374
      return *this;
deba@189
  3375
    }
deba@189
  3376
deba@189
  3377
deba@189
  3378
    /// \brief Add a section processor with stream oriented reading
deba@189
  3379
    ///
deba@189
  3380
    /// The first parameter is the type of the section, the second is
kpeter@192
  3381
    /// a functor, which takes an \c std::istream& and an \c int&
deba@189
  3382
    /// parameter, the latter regard to the line number of stream. The
deba@189
  3383
    /// functor can read the input while the section go on, and the
deba@189
  3384
    /// line number should be modified accordingly.
deba@189
  3385
    template <typename Functor>
deba@189
  3386
    SectionReader& sectionStream(const std::string& type, Functor functor) {
kpeter@192
  3387
      LEMON_ASSERT(!type.empty(), "Type is empty.");
alpar@209
  3388
      LEMON_ASSERT(_sections.find(type) == _sections.end(),
alpar@209
  3389
                   "Multiple reading of section.");
alpar@209
  3390
      _sections.insert(std::make_pair(type,
alpar@209
  3391
         new _reader_bits::StreamSection<Functor>(functor)));
deba@189
  3392
      return *this;
alpar@209
  3393
    }
alpar@209
  3394
deba@189
  3395
    /// @}
deba@189
  3396
deba@189
  3397
  private:
deba@189
  3398
deba@189
  3399
    bool readLine() {
deba@189
  3400
      std::string str;
deba@189
  3401
      while(++line_num, std::getline(*_is, str)) {
alpar@209
  3402
        line.clear(); line.str(str);
alpar@209
  3403
        char c;
alpar@209
  3404
        if (line >> std::ws >> c && c != '#') {
alpar@209
  3405
          line.putback(c);
alpar@209
  3406
          return true;
alpar@209
  3407
        }
deba@189
  3408
      }
deba@189
  3409
      return false;
deba@189
  3410
    }
deba@189
  3411
deba@189
  3412
    bool readSuccess() {
deba@189
  3413
      return static_cast<bool>(*_is);
deba@189
  3414
    }
alpar@209
  3415
deba@189
  3416
    void skipSection() {
deba@189
  3417
      char c;
deba@189
  3418
      while (readSuccess() && line >> c && c != '@') {
alpar@209
  3419
        readLine();
deba@189
  3420
      }
deba@427
  3421
      if (readSuccess()) {
deba@427
  3422
        line.putback(c);
deba@427
  3423
      }
deba@189
  3424
    }
deba@189
  3425
deba@189
  3426
  public:
deba@189
  3427
deba@189
  3428
kpeter@584
  3429
    /// \name Execution of the Reader
deba@189
  3430
    /// @{
deba@189
  3431
deba@189
  3432
    /// \brief Start the batch processing
deba@189
  3433
    ///
kpeter@192
  3434
    /// This function starts the batch processing.
deba@189
  3435
    void run() {
alpar@209
  3436
deba@189
  3437
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
alpar@209
  3438
deba@189
  3439
      std::set<std::string> extra_sections;
deba@189
  3440
alpar@209
  3441
      line_num = 0;
deba@189
  3442
      readLine();
deba@189
  3443
      skipSection();
deba@189
  3444
deba@189
  3445
      while (readSuccess()) {
alpar@209
  3446
        try {
alpar@209
  3447
          char c;
alpar@209
  3448
          std::string section, caption;
alpar@209
  3449
          line >> c;
alpar@209
  3450
          _reader_bits::readToken(line, section);
alpar@209
  3451
          _reader_bits::readToken(line, caption);
alpar@209
  3452
alpar@209
  3453
          if (line >> c)
kpeter@291
  3454
            throw FormatError("Extra character at the end of line");
alpar@209
  3455
alpar@209
  3456
          if (extra_sections.find(section) != extra_sections.end()) {
alpar@209
  3457
            std::ostringstream msg;
kpeter@291
  3458
            msg << "Multiple occurence of section: " << section;
deba@290
  3459
            throw FormatError(msg.str());
alpar@209
  3460
          }
alpar@209
  3461
          Sections::iterator it = _sections.find(section);
alpar@209
  3462
          if (it != _sections.end()) {
alpar@209
  3463
            extra_sections.insert(section);
alpar@209
  3464
            it->second->process(*_is, line_num);
alpar@209
  3465
          }
alpar@209
  3466
          readLine();
alpar@209
  3467
          skipSection();
deba@290
  3468
        } catch (FormatError& error) {
alpar@209
  3469
          error.line(line_num);
deba@290
  3470
          error.file(_filename);
alpar@209
  3471
          throw;
alpar@209
  3472
        }
deba@189
  3473
      }
deba@189
  3474
      for (Sections::iterator it = _sections.begin();
alpar@209
  3475
           it != _sections.end(); ++it) {
alpar@209
  3476
        if (extra_sections.find(it->first) == extra_sections.end()) {
alpar@209
  3477
          std::ostringstream os;
alpar@209
  3478
          os << "Cannot find section: " << it->first;
deba@290
  3479
          throw FormatError(os.str());
alpar@209
  3480
        }
deba@189
  3481
      }
deba@189
  3482
    }
deba@189
  3483
deba@189
  3484
    /// @}
alpar@209
  3485
deba@189
  3486
  };
deba@189
  3487
deba@598
  3488
  /// \ingroup lemon_io
deba@598
  3489
  ///
deba@598
  3490
  /// \brief Return a \ref SectionReader class
deba@598
  3491
  ///
deba@598
  3492
  /// This function just returns a \ref SectionReader class.
deba@598
  3493
  ///
deba@598
  3494
  /// Please see SectionReader documentation about the custom section
deba@598
  3495
  /// input.
deba@598
  3496
  ///
deba@598
  3497
  /// \relates SectionReader
deba@598
  3498
  /// \sa sectionReader(const std::string& fn)
deba@598
  3499
  /// \sa sectionReader(const char *fn)
deba@598
  3500
  inline SectionReader sectionReader(std::istream& is) {
deba@598
  3501
    SectionReader tmp(is);
deba@598
  3502
    return tmp;
deba@598
  3503
  }
deba@598
  3504
kpeter@192
  3505
  /// \brief Return a \ref SectionReader class
alpar@209
  3506
  ///
kpeter@192
  3507
  /// This function just returns a \ref SectionReader class.
deba@189
  3508
  /// \relates SectionReader
deba@598
  3509
  /// \sa sectionReader(std::istream& is)
deba@598
  3510
  inline SectionReader sectionReader(const std::string& fn) {
deba@598
  3511
    SectionReader tmp(fn);
deba@189
  3512
    return tmp;
deba@189
  3513
  }
deba@189
  3514
kpeter@192
  3515
  /// \brief Return a \ref SectionReader class
alpar@209
  3516
  ///
kpeter@192
  3517
  /// This function just returns a \ref SectionReader class.
deba@189
  3518
  /// \relates SectionReader
deba@598
  3519
  /// \sa sectionReader(std::istream& is)
deba@189
  3520
  inline SectionReader sectionReader(const char* fn) {
deba@189
  3521
    SectionReader tmp(fn);
deba@189
  3522
    return tmp;
deba@189
  3523
  }
deba@189
  3524
deba@173
  3525
  /// \ingroup lemon_io
deba@173
  3526
  ///
alpar@209
  3527
  /// \brief Reader for the contents of the \ref lgf-format "LGF" file
deba@173
  3528
  ///
deba@173
  3529
  /// This class can be used to read the sections, the map names and
ladanyi@236
  3530
  /// the attributes from a file. Usually, the LEMON programs know
deba@173
  3531
  /// that, which type of graph, which maps and which attributes
deba@173
  3532
  /// should be read from a file, but in general tools (like glemon)
alpar@179
  3533
  /// the contents of an LGF file should be guessed somehow. This class
deba@173
  3534
  /// reads the graph and stores the appropriate information for
deba@173
  3535
  /// reading the graph.
deba@173
  3536
  ///
alpar@209
  3537
  ///\code
alpar@209
  3538
  /// LgfContents contents("graph.lgf");
alpar@179
  3539
  /// contents.run();
deba@173
  3540
  ///
kpeter@192
  3541
  /// // Does it contain any node section and arc section?
alpar@179
  3542
  /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
kpeter@192
  3543
  ///   std::cerr << "Failure, cannot find graph." << std::endl;
deba@173
  3544
  ///   return -1;
deba@173
  3545
  /// }
alpar@209
  3546
  /// std::cout << "The name of the default node section: "
alpar@179
  3547
  ///           << contents.nodeSection(0) << std::endl;
alpar@209
  3548
  /// std::cout << "The number of the arc maps: "
alpar@179
  3549
  ///           << contents.arcMaps(0).size() << std::endl;
alpar@209
  3550
  /// std::cout << "The name of second arc map: "
alpar@179
  3551
  ///           << contents.arcMaps(0)[1] << std::endl;
deba@173
  3552
  ///\endcode
alpar@209
  3553
  class LgfContents {
deba@173
  3554
  private:
deba@173
  3555
deba@173
  3556
    std::istream* _is;
deba@173
  3557
    bool local_is;
deba@173
  3558
deba@173
  3559
    std::vector<std::string> _node_sections;
deba@173
  3560
    std::vector<std::string> _edge_sections;
deba@173
  3561
    std::vector<std::string> _attribute_sections;
deba@173
  3562
    std::vector<std::string> _extra_sections;
deba@173
  3563
deba@173
  3564
    std::vector<bool> _arc_sections;
deba@173
  3565
deba@173
  3566
    std::vector<std::vector<std::string> > _node_maps;
deba@173
  3567
    std::vector<std::vector<std::string> > _edge_maps;
deba@173
  3568
deba@173
  3569
    std::vector<std::vector<std::string> > _attributes;
deba@173
  3570
deba@173
  3571
deba@173
  3572
    int line_num;
deba@173
  3573
    std::istringstream line;
alpar@209
  3574
deba@173
  3575
  public:
deba@173
  3576
deba@173
  3577
    /// \brief Constructor
deba@173
  3578
    ///
alpar@179
  3579
    /// Construct an \e LGF contents reader, which reads from the given
deba@173
  3580
    /// input stream.
alpar@209
  3581
    LgfContents(std::istream& is)
deba@173
  3582
      : _is(&is), local_is(false) {}
deba@173
  3583
deba@173
  3584
    /// \brief Constructor
deba@173
  3585
    ///
alpar@179
  3586
    /// Construct an \e LGF contents reader, which reads from the given
deba@173
  3587
    /// file.
alpar@209
  3588
    LgfContents(const std::string& fn)
deba@290
  3589
      : _is(new std::ifstream(fn.c_str())), local_is(true) {
deba@295
  3590
      if (!(*_is)) {
deba@295
  3591
        delete _is;
deba@295
  3592
        throw IoError("Cannot open file", fn);
deba@295
  3593
      }
deba@290
  3594
    }
deba@173
  3595
deba@173
  3596
    /// \brief Constructor
deba@173
  3597
    ///
alpar@179
  3598
    /// Construct an \e LGF contents reader, which reads from the given
deba@173
  3599
    /// file.
alpar@179
  3600
    LgfContents(const char* fn)
deba@290
  3601
      : _is(new std::ifstream(fn)), local_is(true) {
deba@295
  3602
      if (!(*_is)) {
deba@295
  3603
        delete _is;
deba@295
  3604
        throw IoError("Cannot open file", fn);
deba@295
  3605
      }
deba@290
  3606
    }
alpar@209
  3607
deba@173
  3608
    /// \brief Destructor
alpar@179
  3609
    ~LgfContents() {
deba@173
  3610
      if (local_is) delete _is;
deba@173
  3611
    }
deba@173
  3612
deba@190
  3613
  private:
alpar@209
  3614
deba@190
  3615
    LgfContents(const LgfContents&);
deba@190
  3616
    LgfContents& operator=(const LgfContents&);
deba@190
  3617
deba@190
  3618
  public:
deba@190
  3619
deba@173
  3620
kpeter@584
  3621
    /// \name Node Sections
deba@173
  3622
    /// @{
deba@173
  3623
deba@173
  3624
    /// \brief Gives back the number of node sections in the file.
deba@173
  3625
    ///
deba@173
  3626
    /// Gives back the number of node sections in the file.
deba@173
  3627
    int nodeSectionNum() const {
deba@173
  3628
      return _node_sections.size();
deba@173
  3629
    }
deba@173
  3630
alpar@209
  3631
    /// \brief Returns the node section name at the given position.
deba@173
  3632
    ///
alpar@209
  3633
    /// Returns the node section name at the given position.
deba@173
  3634
    const std::string& nodeSection(int i) const {
deba@173
  3635
      return _node_sections[i];
deba@173
  3636
    }
deba@173
  3637
deba@173
  3638
    /// \brief Gives back the node maps for the given section.
deba@173
  3639
    ///
deba@173
  3640
    /// Gives back the node maps for the given section.
alpar@182
  3641
    const std::vector<std::string>& nodeMapNames(int i) const {
deba@173
  3642
      return _node_maps[i];
deba@173
  3643
    }
deba@173
  3644
deba@173
  3645
    /// @}
deba@173
  3646
kpeter@584
  3647
    /// \name Arc/Edge Sections
deba@173
  3648
    /// @{
deba@173
  3649
alpar@181
  3650
    /// \brief Gives back the number of arc/edge sections in the file.
deba@173
  3651
    ///
alpar@181
  3652
    /// Gives back the number of arc/edge sections in the file.
alpar@181
  3653
    /// \note It is synonym of \c edgeSectionNum().
deba@173
  3654
    int arcSectionNum() const {
deba@173
  3655
      return _edge_sections.size();
deba@173
  3656
    }
deba@173
  3657
alpar@209
  3658
    /// \brief Returns the arc/edge section name at the given position.
deba@173
  3659
    ///
alpar@209
  3660
    /// Returns the arc/edge section name at the given position.
alpar@181
  3661
    /// \note It is synonym of \c edgeSection().
deba@173
  3662
    const std::string& arcSection(int i) const {
deba@173
  3663
      return _edge_sections[i];
deba@173
  3664
    }
deba@173
  3665
alpar@181
  3666
    /// \brief Gives back the arc/edge maps for the given section.
deba@173
  3667
    ///
alpar@181
  3668
    /// Gives back the arc/edge maps for the given section.
alpar@182
  3669
    /// \note It is synonym of \c edgeMapNames().
alpar@182
  3670
    const std::vector<std::string>& arcMapNames(int i) const {
deba@173
  3671
      return _edge_maps[i];
deba@173
  3672
    }
deba@173
  3673
deba@173
  3674
    /// @}
deba@173
  3675
alpar@181
  3676
    /// \name Synonyms
deba@173
  3677
    /// @{
deba@173
  3678
alpar@181
  3679
    /// \brief Gives back the number of arc/edge sections in the file.
deba@173
  3680
    ///
alpar@181
  3681
    /// Gives back the number of arc/edge sections in the file.
alpar@181
  3682
    /// \note It is synonym of \c arcSectionNum().
deba@173
  3683
    int edgeSectionNum() const {
deba@173
  3684
      return _edge_sections.size();
deba@173
  3685
    }
deba@173
  3686
alpar@209
  3687
    /// \brief Returns the section name at the given position.
deba@173
  3688
    ///
alpar@209
  3689
    /// Returns the section name at the given position.
alpar@181
  3690
    /// \note It is synonym of \c arcSection().
deba@173
  3691
    const std::string& edgeSection(int i) const {
deba@173
  3692
      return _edge_sections[i];
deba@173
  3693
    }
deba@173
  3694
deba@173
  3695
    /// \brief Gives back the edge maps for the given section.
deba@173
  3696
    ///
deba@173
  3697
    /// Gives back the edge maps for the given section.
alpar@182
  3698
    /// \note It is synonym of \c arcMapNames().
alpar@182
  3699
    const std::vector<std::string>& edgeMapNames(int i) const {
deba@173
  3700
      return _edge_maps[i];
deba@173
  3701
    }
deba@173
  3702
deba@173
  3703
    /// @}
deba@173
  3704
kpeter@584
  3705
    /// \name Attribute Sections
deba@173
  3706
    /// @{
deba@173
  3707
deba@173
  3708
    /// \brief Gives back the number of attribute sections in the file.
deba@173
  3709
    ///
deba@173
  3710
    /// Gives back the number of attribute sections in the file.
deba@173
  3711
    int attributeSectionNum() const {
deba@173
  3712
      return _attribute_sections.size();
deba@173
  3713
    }
deba@173
  3714
alpar@209
  3715
    /// \brief Returns the attribute section name at the given position.
deba@173
  3716
    ///
alpar@209
  3717
    /// Returns the attribute section name at the given position.
alpar@182
  3718
    const std::string& attributeSectionNames(int i) const {
deba@173
  3719
      return _attribute_sections[i];
deba@173
  3720
    }
deba@173
  3721
deba@173
  3722
    /// \brief Gives back the attributes for the given section.
deba@173
  3723
    ///
deba@173
  3724
    /// Gives back the attributes for the given section.
deba@173
  3725
    const std::vector<std::string>& attributes(int i) const {
deba@173
  3726
      return _attributes[i];
deba@173
  3727
    }
deba@173
  3728
deba@173
  3729
    /// @}
deba@173
  3730
kpeter@584
  3731
    /// \name Extra Sections
deba@173
  3732
    /// @{
deba@173
  3733
deba@173
  3734
    /// \brief Gives back the number of extra sections in the file.
deba@173
  3735
    ///
deba@173
  3736
    /// Gives back the number of extra sections in the file.
deba@173
  3737
    int extraSectionNum() const {
deba@173
  3738
      return _extra_sections.size();
deba@173
  3739
    }
deba@173
  3740
alpar@209
  3741
    /// \brief Returns the extra section type at the given position.
deba@173
  3742
    ///
alpar@209
  3743
    /// Returns the section type at the given position.
deba@173
  3744
    const std::string& extraSection(int i) const {
deba@173
  3745
      return _extra_sections[i];
deba@173
  3746
    }
deba@173
  3747
deba@173
  3748
    /// @}
deba@173
  3749
deba@173
  3750
  private:
deba@173
  3751
deba@173
  3752
    bool readLine() {
deba@173
  3753
      std::string str;
deba@173
  3754
      while(++line_num, std::getline(*_is, str)) {
alpar@209
  3755
        line.clear(); line.str(str);
alpar@209
  3756
        char c;
alpar@209
  3757
        if (line >> std::ws >> c && c != '#') {
alpar@209
  3758
          line.putback(c);
alpar@209
  3759
          return true;
alpar@209
  3760
        }
deba@173
  3761
      }
deba@173
  3762
      return false;
deba@173
  3763
    }
deba@173
  3764
deba@173
  3765
    bool readSuccess() {
deba@173
  3766
      return static_cast<bool>(*_is);
deba@173
  3767
    }
deba@173
  3768
deba@173
  3769
    void skipSection() {
deba@173
  3770
      char c;
deba@173
  3771
      while (readSuccess() && line >> c && c != '@') {
alpar@209
  3772
        readLine();
deba@173
  3773
      }
deba@427
  3774
      if (readSuccess()) {
deba@427
  3775
        line.putback(c);
deba@427
  3776
      }
deba@173
  3777
    }
deba@173
  3778
deba@173
  3779
    void readMaps(std::vector<std::string>& maps) {
deba@186
  3780
      char c;
deba@186
  3781
      if (!readLine() || !(line >> c) || c == '@') {
alpar@209
  3782
        if (readSuccess() && line) line.putback(c);
alpar@209
  3783
        return;
deba@186
  3784
      }
deba@186
  3785
      line.putback(c);
deba@173
  3786
      std::string map;
deba@173
  3787
      while (_reader_bits::readToken(line, map)) {
alpar@209
  3788
        maps.push_back(map);
deba@173
  3789
      }
deba@173
  3790
    }
deba@173
  3791
deba@173
  3792
    void readAttributes(std::vector<std::string>& attrs) {
deba@173
  3793
      readLine();
deba@173
  3794
      char c;
deba@173
  3795
      while (readSuccess() && line >> c && c != '@') {
alpar@209
  3796
        line.putback(c);
alpar@209
  3797
        std::string attr;
alpar@209
  3798
        _reader_bits::readToken(line, attr);
alpar@209
  3799
        attrs.push_back(attr);
alpar@209
  3800
        readLine();
deba@173
  3801
      }
deba@173
  3802
      line.putback(c);
deba@173
  3803
    }
deba@173
  3804
deba@173
  3805
  public:
deba@173
  3806
kpeter@584
  3807
    /// \name Execution of the Contents Reader
deba@173
  3808
    /// @{
deba@173
  3809
kpeter@192
  3810
    /// \brief Starts the reading
deba@173
  3811
    ///
kpeter@192
  3812
    /// This function starts the reading.
deba@173
  3813
    void run() {
deba@173
  3814
deba@173
  3815
      readLine();
deba@173
  3816
      skipSection();
deba@173
  3817
deba@173
  3818
      while (readSuccess()) {
deba@173
  3819
alpar@209
  3820
        char c;
alpar@209
  3821
        line >> c;
alpar@209
  3822
alpar@209
  3823
        std::string section, caption;
alpar@209
  3824
        _reader_bits::readToken(line, section);
alpar@209
  3825
        _reader_bits::readToken(line, caption);
alpar@209
  3826
alpar@209
  3827
        if (section == "nodes") {
alpar@209
  3828
          _node_sections.push_back(caption);
alpar@209
  3829
          _node_maps.push_back(std::vector<std::string>());
alpar@209
  3830
          readMaps(_node_maps.back());
alpar@209
  3831
          readLine(); skipSection();
alpar@209
  3832
        } else if (section == "arcs" || section == "edges") {
alpar@209
  3833
          _edge_sections.push_back(caption);
alpar@209
  3834
          _arc_sections.push_back(section == "arcs");
alpar@209
  3835
          _edge_maps.push_back(std::vector<std::string>());
alpar@209
  3836
          readMaps(_edge_maps.back());
alpar@209
  3837
          readLine(); skipSection();
alpar@209
  3838
        } else if (section == "attributes") {
alpar@209
  3839
          _attribute_sections.push_back(caption);
alpar@209
  3840
          _attributes.push_back(std::vector<std::string>());
alpar@209
  3841
          readAttributes(_attributes.back());
alpar@209
  3842
        } else {
alpar@209
  3843
          _extra_sections.push_back(section);
alpar@209
  3844
          readLine(); skipSection();
alpar@209
  3845
        }
deba@173
  3846
      }
deba@173
  3847
    }
deba@173
  3848
deba@173
  3849
    /// @}
alpar@209
  3850
deba@173
  3851
  };
deba@127
  3852
}
deba@127
  3853
deba@127
  3854
#endif