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