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