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