lemon/lgf_writer.h
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 03 Apr 2009 18:59:15 +0200
changeset 600 6ac5d9ae1d3d
parent 440 88ed40ad0d4f
parent 498 afd134142111
child 550 c5fd2d996909
permissions -rw-r--r--
Support real types + numerical stability fix in NS (#254)

- Real types are supported by appropriate inicialization.
- A feature of the XTI spanning tree structure is removed to ensure
numerical stability (could cause problems using integer types).
The node potentials are updated always on the lower subtree,
in order to prevent overflow problems.
The former method isn't notably faster during to our tests.
alpar@209
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
deba@127
     2
 *
alpar@209
     3
 * This file is a part of LEMON, a generic C++ optimization library.
deba@127
     4
 *
alpar@440
     5
 * Copyright (C) 2003-2009
deba@127
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@127
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@127
     8
 *
deba@127
     9
 * Permission to use, modify and distribute this software is granted
deba@127
    10
 * provided that this copyright notice appears in all copies. For
deba@127
    11
 * precise terms see the accompanying LICENSE file.
deba@127
    12
 *
deba@127
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@127
    14
 * express or implied, and with no claim as to its suitability for any
deba@127
    15
 * purpose.
deba@127
    16
 *
deba@127
    17
 */
deba@127
    18
deba@127
    19
///\ingroup lemon_io
deba@127
    20
///\file
ladanyi@236
    21
///\brief \ref lgf-format "LEMON Graph Format" writer.
deba@127
    22
deba@127
    23
deba@127
    24
#ifndef LEMON_LGF_WRITER_H
deba@127
    25
#define LEMON_LGF_WRITER_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 <algorithm>
deba@127
    32
deba@127
    33
#include <vector>
deba@127
    34
#include <functional>
deba@127
    35
deba@220
    36
#include <lemon/core.h>
deba@220
    37
#include <lemon/maps.h>
deba@127
    38
deba@248
    39
#include <lemon/concept_check.h>
deba@248
    40
#include <lemon/concepts/maps.h>
deba@248
    41
deba@127
    42
namespace lemon {
deba@127
    43
deba@127
    44
  namespace _writer_bits {
deba@127
    45
deba@127
    46
    template <typename Value>
deba@127
    47
    struct DefaultConverter {
deba@127
    48
      std::string operator()(const Value& value) {
alpar@209
    49
        std::ostringstream os;
alpar@209
    50
        os << value;
alpar@209
    51
        return os.str();
deba@127
    52
      }
deba@127
    53
    };
deba@127
    54
deba@127
    55
    template <typename T>
deba@127
    56
    bool operator<(const T&, const T&) {
deba@290
    57
      throw FormatError("Label map is not comparable");
deba@127
    58
    }
deba@127
    59
deba@127
    60
    template <typename _Map>
deba@127
    61
    class MapLess {
deba@127
    62
    public:
deba@127
    63
      typedef _Map Map;
deba@127
    64
      typedef typename Map::Key Item;
deba@127
    65
deba@127
    66
    private:
deba@127
    67
      const Map& _map;
alpar@209
    68
deba@127
    69
    public:
deba@127
    70
      MapLess(const Map& map) : _map(map) {}
deba@127
    71
deba@127
    72
      bool operator()(const Item& left, const Item& right) {
alpar@209
    73
        return _map[left] < _map[right];
deba@127
    74
      }
deba@127
    75
    };
deba@127
    76
deba@165
    77
    template <typename _Graph, bool _dir, typename _Map>
deba@165
    78
    class GraphArcMapLess {
deba@165
    79
    public:
deba@165
    80
      typedef _Map Map;
deba@165
    81
      typedef _Graph Graph;
deba@165
    82
      typedef typename Graph::Edge Item;
deba@165
    83
deba@165
    84
    private:
deba@165
    85
      const Graph& _graph;
deba@165
    86
      const Map& _map;
alpar@209
    87
deba@165
    88
    public:
alpar@209
    89
      GraphArcMapLess(const Graph& graph, const Map& map)
alpar@209
    90
        : _graph(graph), _map(map) {}
deba@165
    91
deba@165
    92
      bool operator()(const Item& left, const Item& right) {
alpar@209
    93
        return _map[_graph.direct(left, _dir)] <
alpar@209
    94
          _map[_graph.direct(right, _dir)];
deba@165
    95
      }
deba@165
    96
    };
deba@165
    97
alpar@209
    98
    template <typename _Item>
deba@127
    99
    class MapStorageBase {
deba@127
   100
    public:
deba@127
   101
      typedef _Item Item;
deba@127
   102
deba@127
   103
    public:
deba@127
   104
      MapStorageBase() {}
deba@127
   105
      virtual ~MapStorageBase() {}
deba@127
   106
deba@127
   107
      virtual std::string get(const Item& item) = 0;
deba@127
   108
      virtual void sort(std::vector<Item>&) = 0;
deba@127
   109
    };
deba@127
   110
alpar@209
   111
    template <typename _Item, typename _Map,
alpar@209
   112
              typename _Converter = DefaultConverter<typename _Map::Value> >
deba@127
   113
    class MapStorage : public MapStorageBase<_Item> {
deba@127
   114
    public:
deba@127
   115
      typedef _Map Map;
deba@127
   116
      typedef _Converter Converter;
deba@127
   117
      typedef _Item Item;
alpar@209
   118
deba@127
   119
    private:
deba@127
   120
      const Map& _map;
deba@127
   121
      Converter _converter;
deba@127
   122
deba@127
   123
    public:
alpar@209
   124
      MapStorage(const Map& map, const Converter& converter = Converter())
alpar@209
   125
        : _map(map), _converter(converter) {}
deba@127
   126
      virtual ~MapStorage() {}
deba@127
   127
deba@127
   128
      virtual std::string get(const Item& item) {
alpar@209
   129
        return _converter(_map[item]);
deba@127
   130
      }
deba@127
   131
      virtual void sort(std::vector<Item>& items) {
alpar@209
   132
        MapLess<Map> less(_map);
alpar@209
   133
        std::sort(items.begin(), items.end(), less);
deba@127
   134
      }
deba@127
   135
    };
deba@127
   136
alpar@209
   137
    template <typename _Graph, bool _dir, typename _Map,
alpar@209
   138
              typename _Converter = DefaultConverter<typename _Map::Value> >
deba@165
   139
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
deba@165
   140
    public:
deba@165
   141
      typedef _Map Map;
deba@165
   142
      typedef _Converter Converter;
deba@165
   143
      typedef _Graph Graph;
deba@165
   144
      typedef typename Graph::Edge Item;
deba@165
   145
      static const bool dir = _dir;
alpar@209
   146
deba@165
   147
    private:
deba@165
   148
      const Graph& _graph;
deba@165
   149
      const Map& _map;
deba@165
   150
      Converter _converter;
deba@165
   151
deba@165
   152
    public:
alpar@209
   153
      GraphArcMapStorage(const Graph& graph, const Map& map,
alpar@209
   154
                         const Converter& converter = Converter())
alpar@209
   155
        : _graph(graph), _map(map), _converter(converter) {}
deba@165
   156
      virtual ~GraphArcMapStorage() {}
deba@165
   157
deba@165
   158
      virtual std::string get(const Item& item) {
alpar@209
   159
        return _converter(_map[_graph.direct(item, dir)]);
deba@165
   160
      }
deba@165
   161
      virtual void sort(std::vector<Item>& items) {
alpar@209
   162
        GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
alpar@209
   163
        std::sort(items.begin(), items.end(), less);
deba@165
   164
      }
deba@165
   165
    };
deba@165
   166
deba@127
   167
    class ValueStorageBase {
deba@127
   168
    public:
deba@127
   169
      ValueStorageBase() {}
deba@127
   170
      virtual ~ValueStorageBase() {}
deba@127
   171
alpar@209
   172
      virtual std::string get() = 0;
deba@127
   173
    };
deba@127
   174
deba@127
   175
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
deba@127
   176
    class ValueStorage : public ValueStorageBase {
deba@127
   177
    public:
deba@127
   178
      typedef _Value Value;
deba@127
   179
      typedef _Converter Converter;
deba@127
   180
deba@127
   181
    private:
deba@127
   182
      const Value& _value;
deba@127
   183
      Converter _converter;
deba@127
   184
deba@127
   185
    public:
deba@127
   186
      ValueStorage(const Value& value, const Converter& converter = Converter())
kpeter@212
   187
        : _value(value), _converter(converter) {}
deba@127
   188
deba@127
   189
      virtual std::string get() {
alpar@209
   190
        return _converter(_value);
deba@127
   191
      }
deba@127
   192
    };
deba@127
   193
deba@127
   194
    template <typename Value>
deba@127
   195
    struct MapLookUpConverter {
deba@127
   196
      const std::map<Value, std::string>& _map;
alpar@209
   197
alpar@209
   198
      MapLookUpConverter(const std::map<Value, std::string>& map)
alpar@209
   199
        : _map(map) {}
alpar@209
   200
deba@127
   201
      std::string operator()(const Value& str) {
alpar@209
   202
        typename std::map<Value, std::string>::const_iterator it =
alpar@209
   203
          _map.find(str);
alpar@209
   204
        if (it == _map.end()) {
deba@290
   205
          throw FormatError("Item not found");
alpar@209
   206
        }
alpar@209
   207
        return it->second;
deba@127
   208
      }
deba@127
   209
    };
deba@127
   210
deba@165
   211
    template <typename Graph>
deba@165
   212
    struct GraphArcLookUpConverter {
deba@165
   213
      const Graph& _graph;
deba@165
   214
      const std::map<typename Graph::Edge, std::string>& _map;
alpar@209
   215
alpar@209
   216
      GraphArcLookUpConverter(const Graph& graph,
alpar@209
   217
                              const std::map<typename Graph::Edge,
alpar@209
   218
                                             std::string>& map)
alpar@209
   219
        : _graph(graph), _map(map) {}
alpar@209
   220
deba@165
   221
      std::string operator()(const typename Graph::Arc& val) {
alpar@209
   222
        typename std::map<typename Graph::Edge, std::string>
alpar@209
   223
          ::const_iterator it = _map.find(val);
alpar@209
   224
        if (it == _map.end()) {
deba@290
   225
          throw FormatError("Item not found");
alpar@209
   226
        }
alpar@209
   227
        return (_graph.direction(val) ? '+' : '-') + it->second;
deba@165
   228
      }
deba@165
   229
    };
deba@165
   230
deba@197
   231
    inline bool isWhiteSpace(char c) {
alpar@209
   232
      return c == ' ' || c == '\t' || c == '\v' ||
alpar@209
   233
        c == '\n' || c == '\r' || c == '\f';
deba@127
   234
    }
deba@127
   235
deba@197
   236
    inline bool isEscaped(char c) {
alpar@209
   237
      return c == '\\' || c == '\"' || c == '\'' ||
alpar@209
   238
        c == '\a' || c == '\b';
deba@127
   239
    }
deba@127
   240
deba@197
   241
    inline static void writeEscape(std::ostream& os, char c) {
deba@127
   242
      switch (c) {
deba@127
   243
      case '\\':
alpar@209
   244
        os << "\\\\";
alpar@209
   245
        return;
deba@127
   246
      case '\"':
alpar@209
   247
        os << "\\\"";
alpar@209
   248
        return;
deba@127
   249
      case '\a':
alpar@209
   250
        os << "\\a";
alpar@209
   251
        return;
deba@127
   252
      case '\b':
alpar@209
   253
        os << "\\b";
alpar@209
   254
        return;
deba@127
   255
      case '\f':
alpar@209
   256
        os << "\\f";
alpar@209
   257
        return;
deba@127
   258
      case '\r':
alpar@209
   259
        os << "\\r";
alpar@209
   260
        return;
deba@127
   261
      case '\n':
alpar@209
   262
        os << "\\n";
alpar@209
   263
        return;
deba@127
   264
      case '\t':
alpar@209
   265
        os << "\\t";
alpar@209
   266
        return;
deba@127
   267
      case '\v':
alpar@209
   268
        os << "\\v";
alpar@209
   269
        return;
deba@127
   270
      default:
alpar@209
   271
        if (c < 0x20) {
alpar@209
   272
          std::ios::fmtflags flags = os.flags();
alpar@209
   273
          os << '\\' << std::oct << static_cast<int>(c);
alpar@209
   274
          os.flags(flags);
alpar@209
   275
        } else {
alpar@209
   276
          os << c;
alpar@209
   277
        }
alpar@209
   278
        return;
alpar@209
   279
      }
deba@127
   280
    }
deba@127
   281
deba@197
   282
    inline bool requireEscape(const std::string& str) {
alpar@156
   283
      if (str.empty() || str[0] == '@') return true;
deba@127
   284
      std::istringstream is(str);
deba@127
   285
      char c;
deba@127
   286
      while (is.get(c)) {
alpar@209
   287
        if (isWhiteSpace(c) || isEscaped(c)) {
alpar@209
   288
          return true;
alpar@209
   289
        }
deba@127
   290
      }
deba@127
   291
      return false;
deba@127
   292
    }
alpar@209
   293
deba@197
   294
    inline std::ostream& writeToken(std::ostream& os, const std::string& str) {
deba@127
   295
deba@127
   296
      if (requireEscape(str)) {
alpar@209
   297
        os << '\"';
alpar@209
   298
        for (std::string::const_iterator it = str.begin();
alpar@209
   299
             it != str.end(); ++it) {
alpar@209
   300
          writeEscape(os, *it);
alpar@209
   301
        }
alpar@209
   302
        os << '\"';
deba@127
   303
      } else {
alpar@209
   304
        os << str;
deba@127
   305
      }
deba@127
   306
      return os;
deba@127
   307
    }
deba@127
   308
deba@248
   309
    class Section {
deba@248
   310
    public:
deba@248
   311
      virtual ~Section() {}
deba@248
   312
      virtual void process(std::ostream& os) = 0;
deba@248
   313
    };
deba@248
   314
deba@248
   315
    template <typename Functor>
deba@248
   316
    class LineSection : public Section {
deba@248
   317
    private:
deba@248
   318
deba@248
   319
      Functor _functor;
deba@248
   320
deba@248
   321
    public:
deba@248
   322
deba@248
   323
      LineSection(const Functor& functor) : _functor(functor) {}
deba@248
   324
      virtual ~LineSection() {}
deba@248
   325
deba@248
   326
      virtual void process(std::ostream& os) {
deba@248
   327
        std::string line;
deba@248
   328
        while (!(line = _functor()).empty()) os << line << std::endl;
deba@248
   329
      }
deba@248
   330
    };
deba@248
   331
deba@248
   332
    template <typename Functor>
deba@248
   333
    class StreamSection : public Section {
deba@248
   334
    private:
deba@248
   335
deba@248
   336
      Functor _functor;
deba@248
   337
deba@248
   338
    public:
deba@248
   339
deba@248
   340
      StreamSection(const Functor& functor) : _functor(functor) {}
deba@248
   341
      virtual ~StreamSection() {}
deba@248
   342
deba@248
   343
      virtual void process(std::ostream& os) {
deba@248
   344
        _functor(os);
deba@248
   345
      }
deba@248
   346
    };
deba@248
   347
deba@127
   348
  }
deba@190
   349
deba@190
   350
  template <typename Digraph>
deba@190
   351
  class DigraphWriter;
deba@190
   352
deba@190
   353
  template <typename Digraph>
kpeter@293
   354
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
kpeter@498
   355
                                       std::ostream& os = std::cout);
deba@190
   356
  template <typename Digraph>
kpeter@293
   357
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
kpeter@498
   358
                                       const std::string& fn);
deba@190
   359
deba@190
   360
  template <typename Digraph>
kpeter@293
   361
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
kpeter@498
   362
                                       const char* fn);
kpeter@498
   363
alpar@209
   364
alpar@156
   365
  /// \ingroup lemon_io
alpar@209
   366
  ///
kpeter@192
   367
  /// \brief \ref lgf-format "LGF" writer for directed graphs
alpar@156
   368
  ///
alpar@156
   369
  /// This utility writes an \ref lgf-format "LGF" file.
alpar@156
   370
  ///
alpar@156
   371
  /// The writing method does a batch processing. The user creates a
alpar@156
   372
  /// writer object, then various writing rules can be added to the
alpar@156
   373
  /// writer, and eventually the writing is executed with the \c run()
alpar@156
   374
  /// member function. A map writing rule can be added to the writer
alpar@156
   375
  /// with the \c nodeMap() or \c arcMap() members. An optional
deba@163
   376
  /// converter parameter can also be added as a standard functor
kpeter@192
   377
  /// converting from the value type of the map to \c std::string. If it
kpeter@192
   378
  /// is set, it will determine how the value type of the map is written to
deba@163
   379
  /// the output stream. If the functor is not set, then a default
deba@163
   380
  /// conversion will be used. The \c attribute(), \c node() and \c
deba@163
   381
  /// arc() functions are used to add attribute writing rules.
alpar@156
   382
  ///
alpar@156
   383
  ///\code
kpeter@293
   384
  /// DigraphWriter<Digraph>(digraph, std::cout).
kpeter@192
   385
  ///   nodeMap("coordinates", coord_map).
kpeter@192
   386
  ///   nodeMap("size", size).
kpeter@192
   387
  ///   nodeMap("title", title).
kpeter@192
   388
  ///   arcMap("capacity", cap_map).
kpeter@192
   389
  ///   node("source", src).
kpeter@192
   390
  ///   node("target", trg).
kpeter@192
   391
  ///   attribute("caption", caption).
kpeter@192
   392
  ///   run();
alpar@156
   393
  ///\endcode
alpar@156
   394
  ///
alpar@156
   395
  ///
alpar@156
   396
  /// By default, the writer does not write additional captions to the
alpar@156
   397
  /// sections, but they can be give as an optional parameter of
alpar@156
   398
  /// the \c nodes(), \c arcs() or \c
alpar@156
   399
  /// attributes() functions.
alpar@156
   400
  ///
alpar@156
   401
  /// The \c skipNodes() and \c skipArcs() functions forbid the
deba@163
   402
  /// writing of the sections. If two arc sections should be written
deba@163
   403
  /// to the output, it can be done in two passes, the first pass
deba@163
   404
  /// writes the node section and the first arc section, then the
deba@163
   405
  /// second pass skips the node section and writes just the arc
deba@163
   406
  /// section to the stream. The output stream can be retrieved with
deba@163
   407
  /// the \c ostream() function, hence the second pass can append its
deba@163
   408
  /// output to the output of the first pass.
deba@127
   409
  template <typename _Digraph>
deba@127
   410
  class DigraphWriter {
deba@127
   411
  public:
deba@127
   412
deba@127
   413
    typedef _Digraph Digraph;
deba@148
   414
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
alpar@209
   415
deba@127
   416
  private:
deba@127
   417
deba@127
   418
deba@127
   419
    std::ostream* _os;
deba@127
   420
    bool local_os;
deba@127
   421
deba@190
   422
    const Digraph& _digraph;
deba@127
   423
deba@127
   424
    std::string _nodes_caption;
deba@127
   425
    std::string _arcs_caption;
deba@127
   426
    std::string _attributes_caption;
alpar@209
   427
deba@127
   428
    typedef std::map<Node, std::string> NodeIndex;
deba@127
   429
    NodeIndex _node_index;
deba@127
   430
    typedef std::map<Arc, std::string> ArcIndex;
deba@127
   431
    ArcIndex _arc_index;
deba@127
   432
alpar@209
   433
    typedef std::vector<std::pair<std::string,
alpar@209
   434
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
alpar@209
   435
    NodeMaps _node_maps;
deba@127
   436
alpar@209
   437
    typedef std::vector<std::pair<std::string,
deba@127
   438
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
deba@127
   439
    ArcMaps _arc_maps;
deba@127
   440
alpar@209
   441
    typedef std::vector<std::pair<std::string,
deba@127
   442
      _writer_bits::ValueStorageBase*> > Attributes;
deba@127
   443
    Attributes _attributes;
deba@127
   444
deba@127
   445
    bool _skip_nodes;
deba@127
   446
    bool _skip_arcs;
deba@127
   447
deba@127
   448
  public:
deba@127
   449
alpar@156
   450
    /// \brief Constructor
alpar@156
   451
    ///
alpar@156
   452
    /// Construct a directed graph writer, which writes to the given
alpar@156
   453
    /// output stream.
kpeter@293
   454
    DigraphWriter(const Digraph& digraph, std::ostream& os = std::cout)
kpeter@293
   455
      : _os(&os), local_os(false), _digraph(digraph),
alpar@209
   456
        _skip_nodes(false), _skip_arcs(false) {}
deba@127
   457
alpar@156
   458
    /// \brief Constructor
alpar@156
   459
    ///
alpar@156
   460
    /// Construct a directed graph writer, which writes to the given
alpar@156
   461
    /// output file.
kpeter@293
   462
    DigraphWriter(const Digraph& digraph, const std::string& fn)
deba@127
   463
      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
deba@290
   464
        _skip_nodes(false), _skip_arcs(false) {
deba@295
   465
      if (!(*_os)) {
deba@295
   466
        delete _os;
deba@295
   467
        throw IoError("Cannot write file", fn);
deba@295
   468
      }
deba@290
   469
    }
deba@127
   470
alpar@156
   471
    /// \brief Constructor
alpar@156
   472
    ///
alpar@156
   473
    /// Construct a directed graph writer, which writes to the given
alpar@156
   474
    /// output file.
kpeter@293
   475
    DigraphWriter(const Digraph& digraph, const char* fn)
deba@127
   476
      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
deba@290
   477
        _skip_nodes(false), _skip_arcs(false) {
deba@295
   478
      if (!(*_os)) {
deba@295
   479
        delete _os;
deba@295
   480
        throw IoError("Cannot write file", fn);
deba@295
   481
      }
deba@290
   482
    }
deba@127
   483
alpar@156
   484
    /// \brief Destructor
deba@127
   485
    ~DigraphWriter() {
alpar@209
   486
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   487
           it != _node_maps.end(); ++it) {
alpar@209
   488
        delete it->second;
deba@127
   489
      }
deba@127
   490
alpar@209
   491
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   492
           it != _arc_maps.end(); ++it) {
alpar@209
   493
        delete it->second;
deba@127
   494
      }
deba@127
   495
alpar@209
   496
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
   497
           it != _attributes.end(); ++it) {
alpar@209
   498
        delete it->second;
deba@127
   499
      }
deba@127
   500
deba@127
   501
      if (local_os) {
alpar@209
   502
        delete _os;
deba@127
   503
      }
deba@127
   504
    }
deba@127
   505
deba@127
   506
  private:
deba@190
   507
kpeter@498
   508
    template <typename DGR>
kpeter@498
   509
    friend DigraphWriter<DGR> digraphWriter(const DGR& digraph, 
kpeter@498
   510
                                            std::ostream& os);
kpeter@498
   511
    template <typename DGR>
kpeter@498
   512
    friend DigraphWriter<DGR> digraphWriter(const DGR& digraph,
kpeter@498
   513
                                            const std::string& fn);
kpeter@498
   514
    template <typename DGR>
kpeter@498
   515
    friend DigraphWriter<DGR> digraphWriter(const DGR& digraph,
kpeter@498
   516
                                            const char *fn);
deba@190
   517
alpar@209
   518
    DigraphWriter(DigraphWriter& other)
deba@190
   519
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
alpar@209
   520
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
deba@190
   521
deba@190
   522
      other._os = 0;
deba@190
   523
      other.local_os = false;
deba@190
   524
deba@190
   525
      _node_index.swap(other._node_index);
deba@190
   526
      _arc_index.swap(other._arc_index);
deba@190
   527
deba@190
   528
      _node_maps.swap(other._node_maps);
deba@190
   529
      _arc_maps.swap(other._arc_maps);
deba@190
   530
      _attributes.swap(other._attributes);
deba@190
   531
deba@190
   532
      _nodes_caption = other._nodes_caption;
deba@190
   533
      _arcs_caption = other._arcs_caption;
deba@190
   534
      _attributes_caption = other._attributes_caption;
deba@190
   535
    }
alpar@209
   536
deba@127
   537
    DigraphWriter& operator=(const DigraphWriter&);
deba@127
   538
deba@127
   539
  public:
deba@127
   540
alpar@156
   541
    /// \name Writing rules
alpar@156
   542
    /// @{
alpar@209
   543
kpeter@192
   544
    /// \brief Node map writing rule
alpar@156
   545
    ///
kpeter@192
   546
    /// Add a node map writing rule to the writer.
deba@127
   547
    template <typename Map>
deba@127
   548
    DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@127
   549
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
   550
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
   551
        new _writer_bits::MapStorage<Node, Map>(map);
deba@127
   552
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   553
      return *this;
deba@127
   554
    }
deba@127
   555
alpar@156
   556
    /// \brief Node map writing rule
alpar@156
   557
    ///
alpar@156
   558
    /// Add a node map writing rule with specialized converter to the
alpar@156
   559
    /// writer.
deba@127
   560
    template <typename Map, typename Converter>
alpar@209
   561
    DigraphWriter& nodeMap(const std::string& caption, const Map& map,
alpar@209
   562
                           const Converter& converter = Converter()) {
deba@127
   563
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
   564
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
   565
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@127
   566
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   567
      return *this;
deba@127
   568
    }
deba@127
   569
alpar@156
   570
    /// \brief Arc map writing rule
alpar@156
   571
    ///
alpar@156
   572
    /// Add an arc map writing rule to the writer.
deba@127
   573
    template <typename Map>
deba@127
   574
    DigraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@127
   575
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
   576
      _writer_bits::MapStorageBase<Arc>* storage =
alpar@209
   577
        new _writer_bits::MapStorage<Arc, Map>(map);
deba@127
   578
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   579
      return *this;
deba@127
   580
    }
deba@127
   581
alpar@156
   582
    /// \brief Arc map writing rule
alpar@156
   583
    ///
alpar@156
   584
    /// Add an arc map writing rule with specialized converter to the
alpar@156
   585
    /// writer.
deba@127
   586
    template <typename Map, typename Converter>
alpar@209
   587
    DigraphWriter& arcMap(const std::string& caption, const Map& map,
alpar@209
   588
                          const Converter& converter = Converter()) {
deba@127
   589
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
   590
      _writer_bits::MapStorageBase<Arc>* storage =
alpar@209
   591
        new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
deba@127
   592
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   593
      return *this;
deba@127
   594
    }
deba@127
   595
alpar@156
   596
    /// \brief Attribute writing rule
alpar@156
   597
    ///
alpar@156
   598
    /// Add an attribute writing rule to the writer.
deba@127
   599
    template <typename Value>
deba@127
   600
    DigraphWriter& attribute(const std::string& caption, const Value& value) {
alpar@209
   601
      _writer_bits::ValueStorageBase* storage =
alpar@209
   602
        new _writer_bits::ValueStorage<Value>(value);
deba@127
   603
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   604
      return *this;
deba@127
   605
    }
deba@127
   606
alpar@156
   607
    /// \brief Attribute writing rule
alpar@156
   608
    ///
alpar@156
   609
    /// Add an attribute writing rule with specialized converter to the
alpar@156
   610
    /// writer.
deba@127
   611
    template <typename Value, typename Converter>
alpar@209
   612
    DigraphWriter& attribute(const std::string& caption, const Value& value,
alpar@209
   613
                             const Converter& converter = Converter()) {
alpar@209
   614
      _writer_bits::ValueStorageBase* storage =
alpar@209
   615
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@127
   616
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   617
      return *this;
deba@127
   618
    }
deba@127
   619
alpar@156
   620
    /// \brief Node writing rule
alpar@156
   621
    ///
alpar@156
   622
    /// Add a node writing rule to the writer.
deba@127
   623
    DigraphWriter& node(const std::string& caption, const Node& node) {
deba@127
   624
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@127
   625
      Converter converter(_node_index);
alpar@209
   626
      _writer_bits::ValueStorageBase* storage =
alpar@209
   627
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@127
   628
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   629
      return *this;
deba@127
   630
    }
deba@127
   631
alpar@156
   632
    /// \brief Arc writing rule
alpar@156
   633
    ///
alpar@156
   634
    /// Add an arc writing rule to writer.
deba@127
   635
    DigraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@127
   636
      typedef _writer_bits::MapLookUpConverter<Arc> Converter;
deba@127
   637
      Converter converter(_arc_index);
alpar@209
   638
      _writer_bits::ValueStorageBase* storage =
alpar@209
   639
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@127
   640
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   641
      return *this;
deba@127
   642
    }
deba@127
   643
kpeter@192
   644
    /// \name Section captions
alpar@156
   645
    /// @{
alpar@156
   646
kpeter@192
   647
    /// \brief Add an additional caption to the \c \@nodes section
alpar@156
   648
    ///
kpeter@192
   649
    /// Add an additional caption to the \c \@nodes section.
deba@127
   650
    DigraphWriter& nodes(const std::string& caption) {
deba@127
   651
      _nodes_caption = caption;
deba@127
   652
      return *this;
deba@127
   653
    }
deba@127
   654
kpeter@192
   655
    /// \brief Add an additional caption to the \c \@arcs section
alpar@156
   656
    ///
kpeter@192
   657
    /// Add an additional caption to the \c \@arcs section.
deba@127
   658
    DigraphWriter& arcs(const std::string& caption) {
deba@127
   659
      _arcs_caption = caption;
deba@127
   660
      return *this;
deba@127
   661
    }
deba@127
   662
kpeter@192
   663
    /// \brief Add an additional caption to the \c \@attributes section
alpar@156
   664
    ///
kpeter@192
   665
    /// Add an additional caption to the \c \@attributes section.
deba@127
   666
    DigraphWriter& attributes(const std::string& caption) {
deba@127
   667
      _attributes_caption = caption;
deba@127
   668
      return *this;
deba@127
   669
    }
deba@127
   670
alpar@156
   671
    /// \name Skipping section
alpar@156
   672
    /// @{
alpar@156
   673
alpar@156
   674
    /// \brief Skip writing the node set
alpar@156
   675
    ///
kpeter@192
   676
    /// The \c \@nodes section will not be written to the stream.
deba@127
   677
    DigraphWriter& skipNodes() {
deba@127
   678
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@185
   679
      _skip_nodes = true;
deba@127
   680
      return *this;
deba@127
   681
    }
deba@127
   682
alpar@156
   683
    /// \brief Skip writing arc set
alpar@156
   684
    ///
kpeter@192
   685
    /// The \c \@arcs section will not be written to the stream.
deba@127
   686
    DigraphWriter& skipArcs() {
deba@127
   687
      LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
deba@185
   688
      _skip_arcs = true;
deba@127
   689
      return *this;
deba@127
   690
    }
deba@127
   691
alpar@156
   692
    /// @}
alpar@156
   693
deba@127
   694
  private:
deba@127
   695
deba@127
   696
    void writeNodes() {
deba@127
   697
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@127
   698
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   699
           it != _node_maps.end(); ++it) {
deba@127
   700
        if (it->first == "label") {
alpar@209
   701
          label = it->second;
alpar@209
   702
          break;
alpar@209
   703
        }
deba@127
   704
      }
deba@127
   705
deba@127
   706
      *_os << "@nodes";
deba@127
   707
      if (!_nodes_caption.empty()) {
alpar@209
   708
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@127
   709
      }
deba@127
   710
      *_os << std::endl;
deba@127
   711
deba@127
   712
      if (label == 0) {
alpar@209
   713
        *_os << "label" << '\t';
deba@127
   714
      }
deba@127
   715
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   716
           it != _node_maps.end(); ++it) {
alpar@209
   717
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@127
   718
      }
deba@127
   719
      *_os << std::endl;
deba@127
   720
deba@127
   721
      std::vector<Node> nodes;
deba@127
   722
      for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   723
        nodes.push_back(n);
deba@127
   724
      }
alpar@209
   725
deba@127
   726
      if (label == 0) {
alpar@209
   727
        IdMap<Digraph, Node> id_map(_digraph);
alpar@209
   728
        _writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
alpar@209
   729
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@127
   730
      } else {
alpar@209
   731
        label->sort(nodes);
deba@127
   732
      }
deba@127
   733
deba@127
   734
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
alpar@209
   735
        Node n = nodes[i];
alpar@209
   736
        if (label == 0) {
alpar@209
   737
          std::ostringstream os;
alpar@209
   738
          os << _digraph.id(n);
alpar@209
   739
          _writer_bits::writeToken(*_os, os.str());
alpar@209
   740
          *_os << '\t';
alpar@209
   741
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
   742
        }
alpar@209
   743
        for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   744
             it != _node_maps.end(); ++it) {
alpar@209
   745
          std::string value = it->second->get(n);
alpar@209
   746
          _writer_bits::writeToken(*_os, value);
alpar@209
   747
          if (it->first == "label") {
alpar@209
   748
            _node_index.insert(std::make_pair(n, value));
alpar@209
   749
          }
alpar@209
   750
          *_os << '\t';
alpar@209
   751
        }
alpar@209
   752
        *_os << std::endl;
deba@127
   753
      }
deba@127
   754
    }
deba@127
   755
deba@185
   756
    void createNodeIndex() {
deba@185
   757
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@185
   758
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   759
           it != _node_maps.end(); ++it) {
deba@185
   760
        if (it->first == "label") {
alpar@209
   761
          label = it->second;
alpar@209
   762
          break;
alpar@209
   763
        }
deba@185
   764
      }
deba@185
   765
deba@185
   766
      if (label == 0) {
alpar@209
   767
        for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   768
          std::ostringstream os;
alpar@209
   769
          os << _digraph.id(n);
alpar@209
   770
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
   771
        }
deba@185
   772
      } else {
alpar@209
   773
        for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   774
          std::string value = label->get(n);
alpar@209
   775
          _node_index.insert(std::make_pair(n, value));
alpar@209
   776
        }
deba@185
   777
      }
deba@185
   778
    }
deba@185
   779
deba@127
   780
    void writeArcs() {
deba@127
   781
      _writer_bits::MapStorageBase<Arc>* label = 0;
deba@127
   782
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   783
           it != _arc_maps.end(); ++it) {
deba@127
   784
        if (it->first == "label") {
alpar@209
   785
          label = it->second;
alpar@209
   786
          break;
alpar@209
   787
        }
deba@127
   788
      }
deba@127
   789
deba@127
   790
      *_os << "@arcs";
deba@127
   791
      if (!_arcs_caption.empty()) {
alpar@209
   792
        _writer_bits::writeToken(*_os << ' ', _arcs_caption);
deba@127
   793
      }
deba@127
   794
      *_os << std::endl;
deba@127
   795
deba@127
   796
      *_os << '\t' << '\t';
deba@127
   797
      if (label == 0) {
alpar@209
   798
        *_os << "label" << '\t';
deba@127
   799
      }
deba@127
   800
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   801
           it != _arc_maps.end(); ++it) {
alpar@209
   802
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@127
   803
      }
deba@127
   804
      *_os << std::endl;
deba@127
   805
deba@127
   806
      std::vector<Arc> arcs;
deba@127
   807
      for (ArcIt n(_digraph); n != INVALID; ++n) {
alpar@209
   808
        arcs.push_back(n);
deba@127
   809
      }
alpar@209
   810
deba@127
   811
      if (label == 0) {
alpar@209
   812
        IdMap<Digraph, Arc> id_map(_digraph);
alpar@209
   813
        _writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
alpar@209
   814
        std::sort(arcs.begin(), arcs.end(), id_less);
deba@127
   815
      } else {
alpar@209
   816
        label->sort(arcs);
deba@127
   817
      }
deba@127
   818
deba@127
   819
      for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
alpar@209
   820
        Arc a = arcs[i];
alpar@209
   821
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
   822
                                 find(_digraph.source(a))->second);
alpar@209
   823
        *_os << '\t';
alpar@209
   824
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
   825
                                 find(_digraph.target(a))->second);
alpar@209
   826
        *_os << '\t';
alpar@209
   827
        if (label == 0) {
alpar@209
   828
          std::ostringstream os;
alpar@209
   829
          os << _digraph.id(a);
alpar@209
   830
          _writer_bits::writeToken(*_os, os.str());
alpar@209
   831
          *_os << '\t';
alpar@209
   832
          _arc_index.insert(std::make_pair(a, os.str()));
alpar@209
   833
        }
alpar@209
   834
        for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   835
             it != _arc_maps.end(); ++it) {
alpar@209
   836
          std::string value = it->second->get(a);
alpar@209
   837
          _writer_bits::writeToken(*_os, value);
alpar@209
   838
          if (it->first == "label") {
alpar@209
   839
            _arc_index.insert(std::make_pair(a, value));
alpar@209
   840
          }
alpar@209
   841
          *_os << '\t';
alpar@209
   842
        }
alpar@209
   843
        *_os << std::endl;
deba@127
   844
      }
deba@127
   845
    }
deba@127
   846
deba@185
   847
    void createArcIndex() {
deba@185
   848
      _writer_bits::MapStorageBase<Arc>* label = 0;
deba@185
   849
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   850
           it != _arc_maps.end(); ++it) {
deba@185
   851
        if (it->first == "label") {
alpar@209
   852
          label = it->second;
alpar@209
   853
          break;
alpar@209
   854
        }
deba@185
   855
      }
deba@185
   856
deba@185
   857
      if (label == 0) {
alpar@209
   858
        for (ArcIt a(_digraph); a != INVALID; ++a) {
alpar@209
   859
          std::ostringstream os;
alpar@209
   860
          os << _digraph.id(a);
alpar@209
   861
          _arc_index.insert(std::make_pair(a, os.str()));
alpar@209
   862
        }
deba@185
   863
      } else {
alpar@209
   864
        for (ArcIt a(_digraph); a != INVALID; ++a) {
alpar@209
   865
          std::string value = label->get(a);
alpar@209
   866
          _arc_index.insert(std::make_pair(a, value));
alpar@209
   867
        }
deba@185
   868
      }
deba@185
   869
    }
deba@185
   870
deba@127
   871
    void writeAttributes() {
deba@127
   872
      if (_attributes.empty()) return;
deba@127
   873
      *_os << "@attributes";
deba@127
   874
      if (!_attributes_caption.empty()) {
alpar@209
   875
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@127
   876
      }
deba@127
   877
      *_os << std::endl;
deba@127
   878
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
   879
           it != _attributes.end(); ++it) {
alpar@209
   880
        _writer_bits::writeToken(*_os, it->first) << ' ';
alpar@209
   881
        _writer_bits::writeToken(*_os, it->second->get());
alpar@209
   882
        *_os << std::endl;
deba@127
   883
      }
deba@127
   884
    }
alpar@209
   885
deba@127
   886
  public:
alpar@209
   887
alpar@209
   888
    /// \name Execution of the writer
alpar@156
   889
    /// @{
alpar@156
   890
alpar@156
   891
    /// \brief Start the batch processing
alpar@156
   892
    ///
kpeter@192
   893
    /// This function starts the batch processing.
deba@127
   894
    void run() {
deba@127
   895
      if (!_skip_nodes) {
alpar@209
   896
        writeNodes();
deba@185
   897
      } else {
alpar@209
   898
        createNodeIndex();
deba@127
   899
      }
alpar@209
   900
      if (!_skip_arcs) {
alpar@209
   901
        writeArcs();
deba@185
   902
      } else {
alpar@209
   903
        createArcIndex();
deba@127
   904
      }
deba@127
   905
      writeAttributes();
deba@127
   906
    }
deba@127
   907
kpeter@192
   908
    /// \brief Give back the stream of the writer
alpar@156
   909
    ///
kpeter@192
   910
    /// Give back the stream of the writer.
alpar@156
   911
    std::ostream& ostream() {
deba@127
   912
      return *_os;
deba@127
   913
    }
alpar@156
   914
alpar@156
   915
    /// @}
deba@127
   916
  };
deba@127
   917
kpeter@498
   918
  /// \brief Return a \ref DigraphWriter class
kpeter@498
   919
  ///
kpeter@498
   920
  /// This function just returns a \ref DigraphWriter class.
kpeter@498
   921
  /// \relates DigraphWriter
kpeter@498
   922
  template <typename Digraph>
kpeter@498
   923
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
kpeter@498
   924
                                       std::ostream& os) {
kpeter@498
   925
    DigraphWriter<Digraph> tmp(digraph, os);
kpeter@498
   926
    return tmp;
kpeter@498
   927
  }
kpeter@498
   928
kpeter@498
   929
  /// \brief Return a \ref DigraphWriter class
kpeter@498
   930
  ///
kpeter@498
   931
  /// This function just returns a \ref DigraphWriter class.
kpeter@498
   932
  /// \relates DigraphWriter
kpeter@498
   933
  template <typename Digraph>
kpeter@498
   934
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
kpeter@498
   935
                                       const std::string& fn) {
kpeter@498
   936
    DigraphWriter<Digraph> tmp(digraph, fn);
kpeter@498
   937
    return tmp;
kpeter@498
   938
  }
kpeter@498
   939
kpeter@498
   940
  /// \brief Return a \ref DigraphWriter class
kpeter@498
   941
  ///
kpeter@498
   942
  /// This function just returns a \ref DigraphWriter class.
kpeter@498
   943
  /// \relates DigraphWriter
kpeter@498
   944
  template <typename Digraph>
kpeter@498
   945
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
kpeter@498
   946
                                       const char* fn) {
kpeter@498
   947
    DigraphWriter<Digraph> tmp(digraph, fn);
kpeter@498
   948
    return tmp;
kpeter@498
   949
  }
kpeter@498
   950
ladanyi@303
   951
  template <typename Graph>
ladanyi@303
   952
  class GraphWriter;
ladanyi@303
   953
ladanyi@303
   954
  template <typename Graph>
ladanyi@303
   955
  GraphWriter<Graph> graphWriter(const Graph& graph,
kpeter@498
   956
                                 std::ostream& os = std::cout);
ladanyi@303
   957
  template <typename Graph>
kpeter@498
   958
  GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn);
ladanyi@303
   959
  template <typename Graph>
kpeter@498
   960
  GraphWriter<Graph> graphWriter(const Graph& graph, const char* fn);
deba@165
   961
deba@165
   962
  /// \ingroup lemon_io
alpar@209
   963
  ///
kpeter@192
   964
  /// \brief \ref lgf-format "LGF" writer for directed graphs
deba@165
   965
  ///
deba@165
   966
  /// This utility writes an \ref lgf-format "LGF" file.
kpeter@192
   967
  ///
kpeter@192
   968
  /// It can be used almost the same way as \c DigraphWriter.
kpeter@192
   969
  /// The only difference is that this class can handle edges and
kpeter@192
   970
  /// edge maps as well as arcs and arc maps.
deba@201
   971
  ///
deba@201
   972
  /// The arc maps are written into the file as two columns, the
deba@201
   973
  /// caption of the columns are the name of the map prefixed with \c
deba@201
   974
  /// '+' and \c '-'. The arcs are written into the \c \@attributes
deba@201
   975
  /// section as a \c '+' or a \c '-' prefix (depends on the direction
deba@201
   976
  /// of the arc) and the label of corresponding edge.
deba@165
   977
  template <typename _Graph>
deba@165
   978
  class GraphWriter {
deba@165
   979
  public:
deba@165
   980
deba@165
   981
    typedef _Graph Graph;
deba@165
   982
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
alpar@209
   983
deba@165
   984
  private:
deba@165
   985
deba@165
   986
deba@165
   987
    std::ostream* _os;
deba@165
   988
    bool local_os;
deba@165
   989
deba@237
   990
    const Graph& _graph;
deba@165
   991
deba@165
   992
    std::string _nodes_caption;
deba@165
   993
    std::string _edges_caption;
deba@165
   994
    std::string _attributes_caption;
alpar@209
   995
deba@165
   996
    typedef std::map<Node, std::string> NodeIndex;
deba@165
   997
    NodeIndex _node_index;
deba@165
   998
    typedef std::map<Edge, std::string> EdgeIndex;
deba@165
   999
    EdgeIndex _edge_index;
deba@165
  1000
alpar@209
  1001
    typedef std::vector<std::pair<std::string,
alpar@209
  1002
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
alpar@209
  1003
    NodeMaps _node_maps;
deba@165
  1004
alpar@209
  1005
    typedef std::vector<std::pair<std::string,
deba@165
  1006
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
deba@165
  1007
    EdgeMaps _edge_maps;
deba@165
  1008
alpar@209
  1009
    typedef std::vector<std::pair<std::string,
deba@165
  1010
      _writer_bits::ValueStorageBase*> > Attributes;
deba@165
  1011
    Attributes _attributes;
deba@165
  1012
deba@165
  1013
    bool _skip_nodes;
deba@165
  1014
    bool _skip_edges;
deba@165
  1015
deba@165
  1016
  public:
deba@165
  1017
deba@165
  1018
    /// \brief Constructor
deba@165
  1019
    ///
deba@165
  1020
    /// Construct a directed graph writer, which writes to the given
deba@165
  1021
    /// output stream.
kpeter@293
  1022
    GraphWriter(const Graph& graph, std::ostream& os = std::cout)
kpeter@293
  1023
      : _os(&os), local_os(false), _graph(graph),
alpar@209
  1024
        _skip_nodes(false), _skip_edges(false) {}
deba@165
  1025
deba@165
  1026
    /// \brief Constructor
deba@165
  1027
    ///
deba@165
  1028
    /// Construct a directed graph writer, which writes to the given
deba@165
  1029
    /// output file.
kpeter@293
  1030
    GraphWriter(const Graph& graph, const std::string& fn)
deba@165
  1031
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
deba@290
  1032
        _skip_nodes(false), _skip_edges(false) {
deba@295
  1033
      if (!(*_os)) {
deba@295
  1034
        delete _os;
deba@295
  1035
        throw IoError("Cannot write file", fn);
deba@295
  1036
      }
deba@290
  1037
    }
deba@165
  1038
deba@165
  1039
    /// \brief Constructor
deba@165
  1040
    ///
deba@165
  1041
    /// Construct a directed graph writer, which writes to the given
deba@165
  1042
    /// output file.
kpeter@293
  1043
    GraphWriter(const Graph& graph, const char* fn)
deba@165
  1044
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
deba@290
  1045
        _skip_nodes(false), _skip_edges(false) {
deba@295
  1046
      if (!(*_os)) {
deba@295
  1047
        delete _os;
deba@295
  1048
        throw IoError("Cannot write file", fn);
deba@295
  1049
      }
deba@290
  1050
    }
deba@165
  1051
deba@165
  1052
    /// \brief Destructor
deba@165
  1053
    ~GraphWriter() {
alpar@209
  1054
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1055
           it != _node_maps.end(); ++it) {
alpar@209
  1056
        delete it->second;
deba@165
  1057
      }
deba@165
  1058
alpar@209
  1059
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1060
           it != _edge_maps.end(); ++it) {
alpar@209
  1061
        delete it->second;
deba@165
  1062
      }
deba@165
  1063
alpar@209
  1064
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1065
           it != _attributes.end(); ++it) {
alpar@209
  1066
        delete it->second;
deba@165
  1067
      }
deba@165
  1068
deba@165
  1069
      if (local_os) {
alpar@209
  1070
        delete _os;
deba@165
  1071
      }
deba@165
  1072
    }
alpar@209
  1073
deba@190
  1074
  private:
deba@165
  1075
kpeter@498
  1076
    template <typename GR>
kpeter@498
  1077
    friend GraphWriter<GR> graphWriter(const GR& graph,
kpeter@498
  1078
                                       std::ostream& os);
kpeter@498
  1079
    template <typename GR>
kpeter@498
  1080
    friend GraphWriter<GR> graphWriter(const GR& graph,
kpeter@498
  1081
                                       const std::string& fn);
kpeter@498
  1082
    template <typename GR>
kpeter@498
  1083
    friend GraphWriter<GR> graphWriter(const GR& graph,
kpeter@498
  1084
                                       const char *fn);
kpeter@498
  1085
    
alpar@209
  1086
    GraphWriter(GraphWriter& other)
deba@190
  1087
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
alpar@209
  1088
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
deba@190
  1089
deba@190
  1090
      other._os = 0;
deba@190
  1091
      other.local_os = false;
deba@190
  1092
deba@190
  1093
      _node_index.swap(other._node_index);
deba@190
  1094
      _edge_index.swap(other._edge_index);
deba@190
  1095
deba@190
  1096
      _node_maps.swap(other._node_maps);
deba@190
  1097
      _edge_maps.swap(other._edge_maps);
deba@190
  1098
      _attributes.swap(other._attributes);
deba@190
  1099
deba@190
  1100
      _nodes_caption = other._nodes_caption;
deba@190
  1101
      _edges_caption = other._edges_caption;
deba@190
  1102
      _attributes_caption = other._attributes_caption;
deba@190
  1103
    }
deba@190
  1104
deba@165
  1105
    GraphWriter& operator=(const GraphWriter&);
deba@165
  1106
deba@165
  1107
  public:
deba@165
  1108
deba@165
  1109
    /// \name Writing rules
deba@165
  1110
    /// @{
alpar@209
  1111
kpeter@192
  1112
    /// \brief Node map writing rule
deba@165
  1113
    ///
kpeter@192
  1114
    /// Add a node map writing rule to the writer.
deba@165
  1115
    template <typename Map>
deba@165
  1116
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@165
  1117
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
  1118
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
  1119
        new _writer_bits::MapStorage<Node, Map>(map);
deba@165
  1120
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1121
      return *this;
deba@165
  1122
    }
deba@165
  1123
deba@165
  1124
    /// \brief Node map writing rule
deba@165
  1125
    ///
deba@165
  1126
    /// Add a node map writing rule with specialized converter to the
deba@165
  1127
    /// writer.
deba@165
  1128
    template <typename Map, typename Converter>
alpar@209
  1129
    GraphWriter& nodeMap(const std::string& caption, const Map& map,
alpar@209
  1130
                           const Converter& converter = Converter()) {
deba@165
  1131
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
  1132
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
  1133
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@165
  1134
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1135
      return *this;
deba@165
  1136
    }
deba@165
  1137
deba@165
  1138
    /// \brief Edge map writing rule
deba@165
  1139
    ///
deba@165
  1140
    /// Add an edge map writing rule to the writer.
deba@165
  1141
    template <typename Map>
deba@165
  1142
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
deba@165
  1143
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
alpar@209
  1144
      _writer_bits::MapStorageBase<Edge>* storage =
alpar@209
  1145
        new _writer_bits::MapStorage<Edge, Map>(map);
deba@165
  1146
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1147
      return *this;
deba@165
  1148
    }
deba@165
  1149
deba@165
  1150
    /// \brief Edge map writing rule
deba@165
  1151
    ///
deba@165
  1152
    /// Add an edge map writing rule with specialized converter to the
deba@165
  1153
    /// writer.
deba@165
  1154
    template <typename Map, typename Converter>
alpar@209
  1155
    GraphWriter& edgeMap(const std::string& caption, const Map& map,
alpar@209
  1156
                          const Converter& converter = Converter()) {
deba@165
  1157
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
alpar@209
  1158
      _writer_bits::MapStorageBase<Edge>* storage =
alpar@209
  1159
        new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
deba@165
  1160
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1161
      return *this;
deba@165
  1162
    }
deba@165
  1163
deba@165
  1164
    /// \brief Arc map writing rule
deba@165
  1165
    ///
deba@165
  1166
    /// Add an arc map writing rule to the writer.
deba@165
  1167
    template <typename Map>
deba@165
  1168
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@165
  1169
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
  1170
      _writer_bits::MapStorageBase<Edge>* forward_storage =
alpar@209
  1171
        new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
deba@165
  1172
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
alpar@209
  1173
      _writer_bits::MapStorageBase<Edge>* backward_storage =
alpar@209
  1174
        new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
deba@165
  1175
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1176
      return *this;
deba@165
  1177
    }
deba@165
  1178
deba@165
  1179
    /// \brief Arc map writing rule
deba@165
  1180
    ///
deba@165
  1181
    /// Add an arc map writing rule with specialized converter to the
deba@165
  1182
    /// writer.
deba@165
  1183
    template <typename Map, typename Converter>
alpar@209
  1184
    GraphWriter& arcMap(const std::string& caption, const Map& map,
alpar@209
  1185
                          const Converter& converter = Converter()) {
deba@165
  1186
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
  1187
      _writer_bits::MapStorageBase<Edge>* forward_storage =
alpar@209
  1188
        new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
alpar@209
  1189
        (_graph, map, converter);
deba@165
  1190
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
alpar@209
  1191
      _writer_bits::MapStorageBase<Edge>* backward_storage =
alpar@209
  1192
        new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
alpar@209
  1193
        (_graph, map, converter);
deba@165
  1194
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1195
      return *this;
deba@165
  1196
    }
deba@165
  1197
deba@165
  1198
    /// \brief Attribute writing rule
deba@165
  1199
    ///
deba@165
  1200
    /// Add an attribute writing rule to the writer.
deba@165
  1201
    template <typename Value>
deba@165
  1202
    GraphWriter& attribute(const std::string& caption, const Value& value) {
alpar@209
  1203
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1204
        new _writer_bits::ValueStorage<Value>(value);
deba@165
  1205
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1206
      return *this;
deba@165
  1207
    }
deba@165
  1208
deba@165
  1209
    /// \brief Attribute writing rule
deba@165
  1210
    ///
deba@165
  1211
    /// Add an attribute writing rule with specialized converter to the
deba@165
  1212
    /// writer.
deba@165
  1213
    template <typename Value, typename Converter>
alpar@209
  1214
    GraphWriter& attribute(const std::string& caption, const Value& value,
alpar@209
  1215
                             const Converter& converter = Converter()) {
alpar@209
  1216
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1217
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@165
  1218
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1219
      return *this;
deba@165
  1220
    }
deba@165
  1221
deba@165
  1222
    /// \brief Node writing rule
deba@165
  1223
    ///
deba@165
  1224
    /// Add a node writing rule to the writer.
deba@165
  1225
    GraphWriter& node(const std::string& caption, const Node& node) {
deba@165
  1226
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@165
  1227
      Converter converter(_node_index);
alpar@209
  1228
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1229
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@165
  1230
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1231
      return *this;
deba@165
  1232
    }
deba@165
  1233
deba@165
  1234
    /// \brief Edge writing rule
deba@165
  1235
    ///
deba@165
  1236
    /// Add an edge writing rule to writer.
deba@165
  1237
    GraphWriter& edge(const std::string& caption, const Edge& edge) {
deba@165
  1238
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
deba@165
  1239
      Converter converter(_edge_index);
alpar@209
  1240
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1241
        new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
deba@165
  1242
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1243
      return *this;
deba@165
  1244
    }
deba@165
  1245
deba@165
  1246
    /// \brief Arc writing rule
deba@165
  1247
    ///
deba@165
  1248
    /// Add an arc writing rule to writer.
deba@165
  1249
    GraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@165
  1250
      typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
deba@165
  1251
      Converter converter(_graph, _edge_index);
alpar@209
  1252
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1253
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@165
  1254
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1255
      return *this;
deba@165
  1256
    }
deba@165
  1257
kpeter@192
  1258
    /// \name Section captions
deba@165
  1259
    /// @{
deba@165
  1260
kpeter@192
  1261
    /// \brief Add an additional caption to the \c \@nodes section
deba@165
  1262
    ///
kpeter@192
  1263
    /// Add an additional caption to the \c \@nodes section.
deba@165
  1264
    GraphWriter& nodes(const std::string& caption) {
deba@165
  1265
      _nodes_caption = caption;
deba@165
  1266
      return *this;
deba@165
  1267
    }
deba@165
  1268
kpeter@192
  1269
    /// \brief Add an additional caption to the \c \@arcs section
deba@165
  1270
    ///
kpeter@192
  1271
    /// Add an additional caption to the \c \@arcs section.
deba@165
  1272
    GraphWriter& edges(const std::string& caption) {
deba@165
  1273
      _edges_caption = caption;
deba@165
  1274
      return *this;
deba@165
  1275
    }
deba@165
  1276
kpeter@192
  1277
    /// \brief Add an additional caption to the \c \@attributes section
deba@165
  1278
    ///
kpeter@192
  1279
    /// Add an additional caption to the \c \@attributes section.
deba@165
  1280
    GraphWriter& attributes(const std::string& caption) {
deba@165
  1281
      _attributes_caption = caption;
deba@165
  1282
      return *this;
deba@165
  1283
    }
deba@165
  1284
deba@165
  1285
    /// \name Skipping section
deba@165
  1286
    /// @{
deba@165
  1287
deba@165
  1288
    /// \brief Skip writing the node set
deba@165
  1289
    ///
kpeter@192
  1290
    /// The \c \@nodes section will not be written to the stream.
deba@165
  1291
    GraphWriter& skipNodes() {
deba@165
  1292
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@185
  1293
      _skip_nodes = true;
deba@165
  1294
      return *this;
deba@165
  1295
    }
deba@165
  1296
deba@165
  1297
    /// \brief Skip writing edge set
deba@165
  1298
    ///
kpeter@192
  1299
    /// The \c \@edges section will not be written to the stream.
deba@165
  1300
    GraphWriter& skipEdges() {
deba@165
  1301
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
deba@185
  1302
      _skip_edges = true;
deba@165
  1303
      return *this;
deba@165
  1304
    }
deba@165
  1305
deba@165
  1306
    /// @}
deba@165
  1307
deba@165
  1308
  private:
deba@165
  1309
deba@165
  1310
    void writeNodes() {
deba@165
  1311
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@165
  1312
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1313
           it != _node_maps.end(); ++it) {
deba@165
  1314
        if (it->first == "label") {
alpar@209
  1315
          label = it->second;
alpar@209
  1316
          break;
alpar@209
  1317
        }
deba@165
  1318
      }
deba@165
  1319
deba@165
  1320
      *_os << "@nodes";
deba@165
  1321
      if (!_nodes_caption.empty()) {
alpar@209
  1322
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@165
  1323
      }
deba@165
  1324
      *_os << std::endl;
deba@165
  1325
deba@165
  1326
      if (label == 0) {
alpar@209
  1327
        *_os << "label" << '\t';
deba@165
  1328
      }
deba@165
  1329
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1330
           it != _node_maps.end(); ++it) {
alpar@209
  1331
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@165
  1332
      }
deba@165
  1333
      *_os << std::endl;
deba@165
  1334
deba@165
  1335
      std::vector<Node> nodes;
deba@165
  1336
      for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1337
        nodes.push_back(n);
deba@165
  1338
      }
alpar@209
  1339
deba@165
  1340
      if (label == 0) {
alpar@209
  1341
        IdMap<Graph, Node> id_map(_graph);
alpar@209
  1342
        _writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
alpar@209
  1343
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@165
  1344
      } else {
alpar@209
  1345
        label->sort(nodes);
deba@165
  1346
      }
deba@165
  1347
deba@165
  1348
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
alpar@209
  1349
        Node n = nodes[i];
alpar@209
  1350
        if (label == 0) {
alpar@209
  1351
          std::ostringstream os;
alpar@209
  1352
          os << _graph.id(n);
alpar@209
  1353
          _writer_bits::writeToken(*_os, os.str());
alpar@209
  1354
          *_os << '\t';
alpar@209
  1355
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
  1356
        }
alpar@209
  1357
        for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1358
             it != _node_maps.end(); ++it) {
alpar@209
  1359
          std::string value = it->second->get(n);
alpar@209
  1360
          _writer_bits::writeToken(*_os, value);
alpar@209
  1361
          if (it->first == "label") {
alpar@209
  1362
            _node_index.insert(std::make_pair(n, value));
alpar@209
  1363
          }
alpar@209
  1364
          *_os << '\t';
alpar@209
  1365
        }
alpar@209
  1366
        *_os << std::endl;
deba@165
  1367
      }
deba@165
  1368
    }
deba@165
  1369
deba@185
  1370
    void createNodeIndex() {
deba@185
  1371
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@185
  1372
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1373
           it != _node_maps.end(); ++it) {
deba@185
  1374
        if (it->first == "label") {
alpar@209
  1375
          label = it->second;
alpar@209
  1376
          break;
alpar@209
  1377
        }
deba@185
  1378
      }
deba@185
  1379
deba@185
  1380
      if (label == 0) {
alpar@209
  1381
        for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1382
          std::ostringstream os;
alpar@209
  1383
          os << _graph.id(n);
alpar@209
  1384
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
  1385
        }
deba@185
  1386
      } else {
alpar@209
  1387
        for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1388
          std::string value = label->get(n);
alpar@209
  1389
          _node_index.insert(std::make_pair(n, value));
alpar@209
  1390
        }
deba@185
  1391
      }
deba@185
  1392
    }
deba@185
  1393
deba@165
  1394
    void writeEdges() {
deba@165
  1395
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@165
  1396
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1397
           it != _edge_maps.end(); ++it) {
deba@165
  1398
        if (it->first == "label") {
alpar@209
  1399
          label = it->second;
alpar@209
  1400
          break;
alpar@209
  1401
        }
deba@165
  1402
      }
deba@165
  1403
deba@165
  1404
      *_os << "@edges";
deba@165
  1405
      if (!_edges_caption.empty()) {
alpar@209
  1406
        _writer_bits::writeToken(*_os << ' ', _edges_caption);
deba@165
  1407
      }
deba@165
  1408
      *_os << std::endl;
deba@165
  1409
deba@165
  1410
      *_os << '\t' << '\t';
deba@165
  1411
      if (label == 0) {
alpar@209
  1412
        *_os << "label" << '\t';
deba@165
  1413
      }
deba@165
  1414
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1415
           it != _edge_maps.end(); ++it) {
alpar@209
  1416
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@165
  1417
      }
deba@165
  1418
      *_os << std::endl;
deba@165
  1419
deba@165
  1420
      std::vector<Edge> edges;
deba@165
  1421
      for (EdgeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1422
        edges.push_back(n);
deba@165
  1423
      }
alpar@209
  1424
deba@165
  1425
      if (label == 0) {
alpar@209
  1426
        IdMap<Graph, Edge> id_map(_graph);
alpar@209
  1427
        _writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
alpar@209
  1428
        std::sort(edges.begin(), edges.end(), id_less);
deba@165
  1429
      } else {
alpar@209
  1430
        label->sort(edges);
deba@165
  1431
      }
deba@165
  1432
deba@165
  1433
      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
alpar@209
  1434
        Edge e = edges[i];
alpar@209
  1435
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
  1436
                                 find(_graph.u(e))->second);
alpar@209
  1437
        *_os << '\t';
alpar@209
  1438
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
  1439
                                 find(_graph.v(e))->second);
alpar@209
  1440
        *_os << '\t';
alpar@209
  1441
        if (label == 0) {
alpar@209
  1442
          std::ostringstream os;
alpar@209
  1443
          os << _graph.id(e);
alpar@209
  1444
          _writer_bits::writeToken(*_os, os.str());
alpar@209
  1445
          *_os << '\t';
alpar@209
  1446
          _edge_index.insert(std::make_pair(e, os.str()));
alpar@209
  1447
        }
alpar@209
  1448
        for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1449
             it != _edge_maps.end(); ++it) {
alpar@209
  1450
          std::string value = it->second->get(e);
alpar@209
  1451
          _writer_bits::writeToken(*_os, value);
alpar@209
  1452
          if (it->first == "label") {
alpar@209
  1453
            _edge_index.insert(std::make_pair(e, value));
alpar@209
  1454
          }
alpar@209
  1455
          *_os << '\t';
alpar@209
  1456
        }
alpar@209
  1457
        *_os << std::endl;
deba@165
  1458
      }
deba@165
  1459
    }
deba@165
  1460
deba@185
  1461
    void createEdgeIndex() {
deba@185
  1462
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@185
  1463
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1464
           it != _edge_maps.end(); ++it) {
deba@185
  1465
        if (it->first == "label") {
alpar@209
  1466
          label = it->second;
alpar@209
  1467
          break;
alpar@209
  1468
        }
deba@185
  1469
      }
deba@185
  1470
deba@185
  1471
      if (label == 0) {
alpar@209
  1472
        for (EdgeIt e(_graph); e != INVALID; ++e) {
alpar@209
  1473
          std::ostringstream os;
alpar@209
  1474
          os << _graph.id(e);
alpar@209
  1475
          _edge_index.insert(std::make_pair(e, os.str()));
alpar@209
  1476
        }
deba@185
  1477
      } else {
alpar@209
  1478
        for (EdgeIt e(_graph); e != INVALID; ++e) {
alpar@209
  1479
          std::string value = label->get(e);
alpar@209
  1480
          _edge_index.insert(std::make_pair(e, value));
alpar@209
  1481
        }
deba@185
  1482
      }
deba@185
  1483
    }
deba@185
  1484
deba@165
  1485
    void writeAttributes() {
deba@165
  1486
      if (_attributes.empty()) return;
deba@165
  1487
      *_os << "@attributes";
deba@165
  1488
      if (!_attributes_caption.empty()) {
alpar@209
  1489
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@165
  1490
      }
deba@165
  1491
      *_os << std::endl;
deba@165
  1492
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1493
           it != _attributes.end(); ++it) {
alpar@209
  1494
        _writer_bits::writeToken(*_os, it->first) << ' ';
alpar@209
  1495
        _writer_bits::writeToken(*_os, it->second->get());
alpar@209
  1496
        *_os << std::endl;
deba@165
  1497
      }
deba@165
  1498
    }
alpar@209
  1499
deba@165
  1500
  public:
alpar@209
  1501
alpar@209
  1502
    /// \name Execution of the writer
deba@165
  1503
    /// @{
deba@165
  1504
deba@165
  1505
    /// \brief Start the batch processing
deba@165
  1506
    ///
kpeter@192
  1507
    /// This function starts the batch processing.
deba@165
  1508
    void run() {
deba@165
  1509
      if (!_skip_nodes) {
alpar@209
  1510
        writeNodes();
deba@185
  1511
      } else {
alpar@209
  1512
        createNodeIndex();
deba@165
  1513
      }
alpar@209
  1514
      if (!_skip_edges) {
alpar@209
  1515
        writeEdges();
deba@185
  1516
      } else {
alpar@209
  1517
        createEdgeIndex();
deba@165
  1518
      }
deba@165
  1519
      writeAttributes();
deba@165
  1520
    }
deba@165
  1521
kpeter@192
  1522
    /// \brief Give back the stream of the writer
deba@165
  1523
    ///
kpeter@192
  1524
    /// Give back the stream of the writer
deba@165
  1525
    std::ostream& ostream() {
deba@165
  1526
      return *_os;
deba@165
  1527
    }
deba@165
  1528
deba@165
  1529
    /// @}
deba@165
  1530
  };
deba@165
  1531
kpeter@498
  1532
  /// \brief Return a \ref GraphWriter class
kpeter@498
  1533
  ///
kpeter@498
  1534
  /// This function just returns a \ref GraphWriter class.
kpeter@498
  1535
  /// \relates GraphWriter
kpeter@498
  1536
  template <typename Graph>
kpeter@498
  1537
  GraphWriter<Graph> graphWriter(const Graph& graph,
kpeter@498
  1538
                                 std::ostream& os) {
kpeter@498
  1539
    GraphWriter<Graph> tmp(graph, os);
kpeter@498
  1540
    return tmp;
kpeter@498
  1541
  }
kpeter@498
  1542
kpeter@498
  1543
  /// \brief Return a \ref GraphWriter class
kpeter@498
  1544
  ///
kpeter@498
  1545
  /// This function just returns a \ref GraphWriter class.
kpeter@498
  1546
  /// \relates GraphWriter
kpeter@498
  1547
  template <typename Graph>
kpeter@498
  1548
  GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn) {
kpeter@498
  1549
    GraphWriter<Graph> tmp(graph, fn);
kpeter@498
  1550
    return tmp;
kpeter@498
  1551
  }
kpeter@498
  1552
kpeter@498
  1553
  /// \brief Return a \ref GraphWriter class
kpeter@498
  1554
  ///
kpeter@498
  1555
  /// This function just returns a \ref GraphWriter class.
kpeter@498
  1556
  /// \relates GraphWriter
kpeter@498
  1557
  template <typename Graph>
kpeter@498
  1558
  GraphWriter<Graph> graphWriter(const Graph& graph, const char* fn) {
kpeter@498
  1559
    GraphWriter<Graph> tmp(graph, fn);
kpeter@498
  1560
    return tmp;
kpeter@498
  1561
  }
kpeter@498
  1562
deba@248
  1563
  class SectionWriter;
deba@248
  1564
deba@248
  1565
  SectionWriter sectionWriter(std::istream& is);
deba@248
  1566
  SectionWriter sectionWriter(const std::string& fn);
deba@248
  1567
  SectionWriter sectionWriter(const char* fn);
deba@248
  1568
deba@248
  1569
  /// \ingroup lemon_io
deba@248
  1570
  ///
deba@248
  1571
  /// \brief Section writer class
deba@248
  1572
  ///
deba@248
  1573
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
deba@248
  1574
  /// which contain any data in arbitrary format. Such sections can be
deba@248
  1575
  /// written with this class. A writing rule can be added to the
deba@248
  1576
  /// class with two different functions. With the \c sectionLines()
deba@248
  1577
  /// function a generator can write the section line-by-line, while
deba@248
  1578
  /// with the \c sectionStream() member the section can be written to
deba@248
  1579
  /// an output stream.
deba@248
  1580
  class SectionWriter {
deba@248
  1581
  private:
deba@248
  1582
deba@248
  1583
    std::ostream* _os;
deba@248
  1584
    bool local_os;
deba@248
  1585
deba@248
  1586
    typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
deba@248
  1587
    Sections;
deba@248
  1588
deba@248
  1589
    Sections _sections;
deba@248
  1590
deba@248
  1591
  public:
deba@248
  1592
deba@248
  1593
    /// \brief Constructor
deba@248
  1594
    ///
deba@248
  1595
    /// Construct a section writer, which writes to the given output
deba@248
  1596
    /// stream.
deba@248
  1597
    SectionWriter(std::ostream& os)
deba@248
  1598
      : _os(&os), local_os(false) {}
deba@248
  1599
deba@248
  1600
    /// \brief Constructor
deba@248
  1601
    ///
deba@248
  1602
    /// Construct a section writer, which writes into the given file.
deba@248
  1603
    SectionWriter(const std::string& fn)
deba@290
  1604
      : _os(new std::ofstream(fn.c_str())), local_os(true) {
deba@295
  1605
      if (!(*_os)) {
deba@295
  1606
        delete _os;
deba@295
  1607
        throw IoError("Cannot write file", fn);
deba@295
  1608
      }
deba@290
  1609
    }
deba@248
  1610
deba@248
  1611
    /// \brief Constructor
deba@248
  1612
    ///
deba@248
  1613
    /// Construct a section writer, which writes into the given file.
deba@248
  1614
    SectionWriter(const char* fn)
deba@290
  1615
      : _os(new std::ofstream(fn)), local_os(true) {
deba@295
  1616
      if (!(*_os)) {
deba@295
  1617
        delete _os;
deba@295
  1618
        throw IoError("Cannot write file", fn);
deba@295
  1619
      }
deba@290
  1620
    }
deba@248
  1621
deba@248
  1622
    /// \brief Destructor
deba@248
  1623
    ~SectionWriter() {
deba@248
  1624
      for (Sections::iterator it = _sections.begin();
deba@248
  1625
           it != _sections.end(); ++it) {
deba@248
  1626
        delete it->second;
deba@248
  1627
      }
deba@248
  1628
deba@248
  1629
      if (local_os) {
deba@248
  1630
        delete _os;
deba@248
  1631
      }
deba@248
  1632
deba@248
  1633
    }
deba@248
  1634
deba@248
  1635
  private:
deba@248
  1636
deba@248
  1637
    friend SectionWriter sectionWriter(std::ostream& os);
deba@248
  1638
    friend SectionWriter sectionWriter(const std::string& fn);
deba@248
  1639
    friend SectionWriter sectionWriter(const char* fn);
deba@248
  1640
deba@248
  1641
    SectionWriter(SectionWriter& other)
deba@248
  1642
      : _os(other._os), local_os(other.local_os) {
deba@248
  1643
deba@248
  1644
      other._os = 0;
deba@248
  1645
      other.local_os = false;
deba@248
  1646
deba@248
  1647
      _sections.swap(other._sections);
deba@248
  1648
    }
deba@248
  1649
deba@248
  1650
    SectionWriter& operator=(const SectionWriter&);
deba@248
  1651
deba@248
  1652
  public:
deba@248
  1653
deba@248
  1654
    /// \name Section writers
deba@248
  1655
    /// @{
deba@248
  1656
deba@248
  1657
    /// \brief Add a section writer with line oriented writing
deba@248
  1658
    ///
deba@248
  1659
    /// The first parameter is the type descriptor of the section, the
deba@248
  1660
    /// second is a generator with std::string values. At the writing
deba@248
  1661
    /// process, the returned \c std::string will be written into the
deba@248
  1662
    /// output file until it is an empty string.
deba@248
  1663
    ///
deba@248
  1664
    /// For example, an integer vector is written into a section.
deba@248
  1665
    ///\code
deba@248
  1666
    ///  @numbers
deba@248
  1667
    ///  12 45 23 78
deba@248
  1668
    ///  4 28 38 28
deba@248
  1669
    ///  23 6 16
deba@248
  1670
    ///\endcode
deba@248
  1671
    ///
deba@248
  1672
    /// The generator is implemented as a struct.
deba@248
  1673
    ///\code
deba@248
  1674
    ///  struct NumberSection {
deba@248
  1675
    ///    std::vector<int>::const_iterator _it, _end;
deba@248
  1676
    ///    NumberSection(const std::vector<int>& data)
deba@248
  1677
    ///      : _it(data.begin()), _end(data.end()) {}
deba@248
  1678
    ///    std::string operator()() {
deba@248
  1679
    ///      int rem_in_line = 4;
deba@248
  1680
    ///      std::ostringstream ls;
deba@248
  1681
    ///      while (rem_in_line > 0 && _it != _end) {
deba@248
  1682
    ///        ls << *(_it++) << ' ';
deba@248
  1683
    ///        --rem_in_line;
deba@248
  1684
    ///      }
deba@248
  1685
    ///      return ls.str();
deba@248
  1686
    ///    }
deba@248
  1687
    ///  };
deba@248
  1688
    ///
deba@248
  1689
    ///  // ...
deba@248
  1690
    ///
deba@248
  1691
    ///  writer.sectionLines("numbers", NumberSection(vec));
deba@248
  1692
    ///\endcode
deba@248
  1693
    template <typename Functor>
deba@248
  1694
    SectionWriter& sectionLines(const std::string& type, Functor functor) {
deba@248
  1695
      LEMON_ASSERT(!type.empty(), "Type is empty.");
deba@248
  1696
      _sections.push_back(std::make_pair(type,
deba@248
  1697
        new _writer_bits::LineSection<Functor>(functor)));
deba@248
  1698
      return *this;
deba@248
  1699
    }
deba@248
  1700
deba@248
  1701
deba@248
  1702
    /// \brief Add a section writer with stream oriented writing
deba@248
  1703
    ///
deba@248
  1704
    /// The first parameter is the type of the section, the second is
deba@248
  1705
    /// a functor, which takes a \c std::ostream& parameter. The
deba@248
  1706
    /// functor writes the section to the output stream.
deba@248
  1707
    /// \warning The last line must be closed with end-line character.
deba@248
  1708
    template <typename Functor>
deba@248
  1709
    SectionWriter& sectionStream(const std::string& type, Functor functor) {
deba@248
  1710
      LEMON_ASSERT(!type.empty(), "Type is empty.");
deba@248
  1711
      _sections.push_back(std::make_pair(type,
deba@248
  1712
         new _writer_bits::StreamSection<Functor>(functor)));
deba@248
  1713
      return *this;
deba@248
  1714
    }
deba@248
  1715
deba@248
  1716
    /// @}
deba@248
  1717
deba@248
  1718
  public:
deba@248
  1719
deba@248
  1720
deba@248
  1721
    /// \name Execution of the writer
deba@248
  1722
    /// @{
deba@248
  1723
deba@248
  1724
    /// \brief Start the batch processing
deba@248
  1725
    ///
deba@248
  1726
    /// This function starts the batch processing.
deba@248
  1727
    void run() {
deba@248
  1728
deba@248
  1729
      LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
deba@248
  1730
deba@248
  1731
      for (Sections::iterator it = _sections.begin();
deba@248
  1732
           it != _sections.end(); ++it) {
deba@248
  1733
        (*_os) << '@' << it->first << std::endl;
deba@248
  1734
        it->second->process(*_os);
deba@248
  1735
      }
deba@248
  1736
    }
deba@248
  1737
deba@248
  1738
    /// \brief Give back the stream of the writer
deba@248
  1739
    ///
deba@248
  1740
    /// Returns the stream of the writer
deba@248
  1741
    std::ostream& ostream() {
deba@248
  1742
      return *_os;
deba@248
  1743
    }
deba@248
  1744
deba@248
  1745
    /// @}
deba@248
  1746
deba@248
  1747
  };
deba@248
  1748
deba@248
  1749
  /// \brief Return a \ref SectionWriter class
deba@248
  1750
  ///
deba@248
  1751
  /// This function just returns a \ref SectionWriter class.
deba@248
  1752
  /// \relates SectionWriter
deba@248
  1753
  inline SectionWriter sectionWriter(std::ostream& os) {
deba@248
  1754
    SectionWriter tmp(os);
deba@248
  1755
    return tmp;
deba@248
  1756
  }
deba@248
  1757
deba@248
  1758
  /// \brief Return a \ref SectionWriter class
deba@248
  1759
  ///
deba@248
  1760
  /// This function just returns a \ref SectionWriter class.
deba@248
  1761
  /// \relates SectionWriter
deba@248
  1762
  inline SectionWriter sectionWriter(const std::string& fn) {
deba@248
  1763
    SectionWriter tmp(fn);
deba@248
  1764
    return tmp;
deba@248
  1765
  }
deba@248
  1766
deba@248
  1767
  /// \brief Return a \ref SectionWriter class
deba@248
  1768
  ///
deba@248
  1769
  /// This function just returns a \ref SectionWriter class.
deba@248
  1770
  /// \relates SectionWriter
deba@248
  1771
  inline SectionWriter sectionWriter(const char* fn) {
deba@248
  1772
    SectionWriter tmp(fn);
deba@248
  1773
    return tmp;
deba@248
  1774
  }
deba@127
  1775
}
deba@127
  1776
deba@127
  1777
#endif