lemon/lgf_writer.h
author Balazs Dezso <deba@inf.elte.hu>
Wed, 11 Jan 2012 22:43:50 +0100
changeset 1027 8b2b9e61d8ce
parent 1024 b84e68af8248
child 1030 4936be66d2f5
permissions -rw-r--r--
Remove asRedBludeNode() function (#69)
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@877
     5
 * Copyright (C) 2003-2010
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@598
   350
  template <typename DGR>
deba@190
   351
  class DigraphWriter;
deba@190
   352
deba@598
   353
  template <typename TDGR>
alpar@877
   354
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
deba@598
   355
                                   std::ostream& os = std::cout);
deba@598
   356
  template <typename TDGR>
deba@598
   357
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const std::string& fn);
deba@190
   358
deba@598
   359
  template <typename TDGR>
deba@598
   360
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn);
kpeter@498
   361
alpar@209
   362
alpar@156
   363
  /// \ingroup lemon_io
alpar@209
   364
  ///
kpeter@192
   365
  /// \brief \ref lgf-format "LGF" writer for directed graphs
alpar@156
   366
  ///
alpar@156
   367
  /// This utility writes an \ref lgf-format "LGF" file.
alpar@156
   368
  ///
alpar@156
   369
  /// The writing method does a batch processing. The user creates a
alpar@156
   370
  /// writer object, then various writing rules can be added to the
alpar@156
   371
  /// writer, and eventually the writing is executed with the \c run()
alpar@156
   372
  /// member function. A map writing rule can be added to the writer
alpar@156
   373
  /// with the \c nodeMap() or \c arcMap() members. An optional
deba@163
   374
  /// converter parameter can also be added as a standard functor
kpeter@192
   375
  /// converting from the value type of the map to \c std::string. If it
kpeter@192
   376
  /// is set, it will determine how the value type of the map is written to
deba@163
   377
  /// the output stream. If the functor is not set, then a default
deba@163
   378
  /// conversion will be used. The \c attribute(), \c node() and \c
deba@163
   379
  /// arc() functions are used to add attribute writing rules.
alpar@156
   380
  ///
alpar@156
   381
  ///\code
deba@598
   382
  /// DigraphWriter<DGR>(digraph, std::cout).
kpeter@192
   383
  ///   nodeMap("coordinates", coord_map).
kpeter@192
   384
  ///   nodeMap("size", size).
kpeter@192
   385
  ///   nodeMap("title", title).
kpeter@192
   386
  ///   arcMap("capacity", cap_map).
kpeter@192
   387
  ///   node("source", src).
kpeter@192
   388
  ///   node("target", trg).
kpeter@192
   389
  ///   attribute("caption", caption).
kpeter@192
   390
  ///   run();
alpar@156
   391
  ///\endcode
alpar@156
   392
  ///
alpar@156
   393
  ///
alpar@156
   394
  /// By default, the writer does not write additional captions to the
alpar@156
   395
  /// sections, but they can be give as an optional parameter of
alpar@156
   396
  /// the \c nodes(), \c arcs() or \c
alpar@156
   397
  /// attributes() functions.
alpar@156
   398
  ///
alpar@156
   399
  /// The \c skipNodes() and \c skipArcs() functions forbid the
deba@163
   400
  /// writing of the sections. If two arc sections should be written
deba@163
   401
  /// to the output, it can be done in two passes, the first pass
deba@163
   402
  /// writes the node section and the first arc section, then the
deba@163
   403
  /// second pass skips the node section and writes just the arc
deba@163
   404
  /// section to the stream. The output stream can be retrieved with
deba@163
   405
  /// the \c ostream() function, hence the second pass can append its
deba@163
   406
  /// output to the output of the first pass.
deba@598
   407
  template <typename DGR>
deba@127
   408
  class DigraphWriter {
deba@127
   409
  public:
deba@127
   410
deba@598
   411
    typedef DGR Digraph;
deba@598
   412
    TEMPLATE_DIGRAPH_TYPEDEFS(DGR);
alpar@209
   413
deba@127
   414
  private:
deba@127
   415
deba@127
   416
deba@127
   417
    std::ostream* _os;
deba@127
   418
    bool local_os;
deba@127
   419
deba@598
   420
    const DGR& _digraph;
deba@127
   421
deba@127
   422
    std::string _nodes_caption;
deba@127
   423
    std::string _arcs_caption;
deba@127
   424
    std::string _attributes_caption;
alpar@209
   425
deba@127
   426
    typedef std::map<Node, std::string> NodeIndex;
deba@127
   427
    NodeIndex _node_index;
deba@127
   428
    typedef std::map<Arc, std::string> ArcIndex;
deba@127
   429
    ArcIndex _arc_index;
deba@127
   430
alpar@209
   431
    typedef std::vector<std::pair<std::string,
alpar@209
   432
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
alpar@209
   433
    NodeMaps _node_maps;
deba@127
   434
alpar@209
   435
    typedef std::vector<std::pair<std::string,
deba@127
   436
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
deba@127
   437
    ArcMaps _arc_maps;
deba@127
   438
alpar@209
   439
    typedef std::vector<std::pair<std::string,
deba@127
   440
      _writer_bits::ValueStorageBase*> > Attributes;
deba@127
   441
    Attributes _attributes;
deba@127
   442
deba@127
   443
    bool _skip_nodes;
deba@127
   444
    bool _skip_arcs;
deba@127
   445
deba@127
   446
  public:
deba@127
   447
alpar@156
   448
    /// \brief Constructor
alpar@156
   449
    ///
alpar@156
   450
    /// Construct a directed graph writer, which writes to the given
alpar@156
   451
    /// output stream.
deba@598
   452
    DigraphWriter(const DGR& digraph, std::ostream& os = std::cout)
kpeter@293
   453
      : _os(&os), local_os(false), _digraph(digraph),
alpar@209
   454
        _skip_nodes(false), _skip_arcs(false) {}
deba@127
   455
alpar@156
   456
    /// \brief Constructor
alpar@156
   457
    ///
alpar@156
   458
    /// Construct a directed graph writer, which writes to the given
alpar@156
   459
    /// output file.
deba@598
   460
    DigraphWriter(const DGR& digraph, const std::string& fn)
deba@127
   461
      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
deba@290
   462
        _skip_nodes(false), _skip_arcs(false) {
deba@295
   463
      if (!(*_os)) {
deba@295
   464
        delete _os;
deba@295
   465
        throw IoError("Cannot write file", fn);
deba@295
   466
      }
deba@290
   467
    }
deba@127
   468
alpar@156
   469
    /// \brief Constructor
alpar@156
   470
    ///
alpar@156
   471
    /// Construct a directed graph writer, which writes to the given
alpar@156
   472
    /// output file.
deba@598
   473
    DigraphWriter(const DGR& digraph, const char* fn)
deba@127
   474
      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
deba@290
   475
        _skip_nodes(false), _skip_arcs(false) {
deba@295
   476
      if (!(*_os)) {
deba@295
   477
        delete _os;
deba@295
   478
        throw IoError("Cannot write file", fn);
deba@295
   479
      }
deba@290
   480
    }
deba@127
   481
alpar@156
   482
    /// \brief Destructor
deba@127
   483
    ~DigraphWriter() {
alpar@209
   484
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   485
           it != _node_maps.end(); ++it) {
alpar@209
   486
        delete it->second;
deba@127
   487
      }
deba@127
   488
alpar@209
   489
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   490
           it != _arc_maps.end(); ++it) {
alpar@209
   491
        delete it->second;
deba@127
   492
      }
deba@127
   493
alpar@209
   494
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
   495
           it != _attributes.end(); ++it) {
alpar@209
   496
        delete it->second;
deba@127
   497
      }
deba@127
   498
deba@127
   499
      if (local_os) {
alpar@209
   500
        delete _os;
deba@127
   501
      }
deba@127
   502
    }
deba@127
   503
deba@127
   504
  private:
deba@190
   505
deba@598
   506
    template <typename TDGR>
alpar@877
   507
    friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
deba@598
   508
                                             std::ostream& os);
deba@598
   509
    template <typename TDGR>
deba@598
   510
    friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
deba@598
   511
                                             const std::string& fn);
deba@598
   512
    template <typename TDGR>
deba@598
   513
    friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
deba@598
   514
                                             const char *fn);
deba@190
   515
alpar@209
   516
    DigraphWriter(DigraphWriter& other)
deba@190
   517
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
alpar@209
   518
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
deba@190
   519
deba@190
   520
      other._os = 0;
deba@190
   521
      other.local_os = false;
deba@190
   522
deba@190
   523
      _node_index.swap(other._node_index);
deba@190
   524
      _arc_index.swap(other._arc_index);
deba@190
   525
deba@190
   526
      _node_maps.swap(other._node_maps);
deba@190
   527
      _arc_maps.swap(other._arc_maps);
deba@190
   528
      _attributes.swap(other._attributes);
deba@190
   529
deba@190
   530
      _nodes_caption = other._nodes_caption;
deba@190
   531
      _arcs_caption = other._arcs_caption;
deba@190
   532
      _attributes_caption = other._attributes_caption;
deba@190
   533
    }
alpar@209
   534
deba@127
   535
    DigraphWriter& operator=(const DigraphWriter&);
deba@127
   536
deba@127
   537
  public:
deba@127
   538
kpeter@584
   539
    /// \name Writing Rules
alpar@156
   540
    /// @{
alpar@209
   541
kpeter@192
   542
    /// \brief Node map writing rule
alpar@156
   543
    ///
kpeter@192
   544
    /// Add a node map writing rule to the writer.
deba@127
   545
    template <typename Map>
deba@127
   546
    DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@127
   547
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
   548
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
   549
        new _writer_bits::MapStorage<Node, Map>(map);
deba@127
   550
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   551
      return *this;
deba@127
   552
    }
deba@127
   553
alpar@156
   554
    /// \brief Node map writing rule
alpar@156
   555
    ///
alpar@156
   556
    /// Add a node map writing rule with specialized converter to the
alpar@156
   557
    /// writer.
deba@127
   558
    template <typename Map, typename Converter>
alpar@209
   559
    DigraphWriter& nodeMap(const std::string& caption, const Map& map,
alpar@209
   560
                           const Converter& converter = Converter()) {
deba@127
   561
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
   562
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
   563
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@127
   564
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   565
      return *this;
deba@127
   566
    }
deba@127
   567
alpar@156
   568
    /// \brief Arc map writing rule
alpar@156
   569
    ///
alpar@156
   570
    /// Add an arc map writing rule to the writer.
deba@127
   571
    template <typename Map>
deba@127
   572
    DigraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@127
   573
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
   574
      _writer_bits::MapStorageBase<Arc>* storage =
alpar@209
   575
        new _writer_bits::MapStorage<Arc, Map>(map);
deba@127
   576
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   577
      return *this;
deba@127
   578
    }
deba@127
   579
alpar@156
   580
    /// \brief Arc map writing rule
alpar@156
   581
    ///
alpar@156
   582
    /// Add an arc map writing rule with specialized converter to the
alpar@156
   583
    /// writer.
deba@127
   584
    template <typename Map, typename Converter>
alpar@209
   585
    DigraphWriter& arcMap(const std::string& caption, const Map& map,
alpar@209
   586
                          const Converter& converter = Converter()) {
deba@127
   587
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
   588
      _writer_bits::MapStorageBase<Arc>* storage =
alpar@209
   589
        new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
deba@127
   590
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   591
      return *this;
deba@127
   592
    }
deba@127
   593
alpar@156
   594
    /// \brief Attribute writing rule
alpar@156
   595
    ///
alpar@156
   596
    /// Add an attribute writing rule to the writer.
deba@127
   597
    template <typename Value>
deba@127
   598
    DigraphWriter& attribute(const std::string& caption, const Value& value) {
alpar@209
   599
      _writer_bits::ValueStorageBase* storage =
alpar@209
   600
        new _writer_bits::ValueStorage<Value>(value);
deba@127
   601
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   602
      return *this;
deba@127
   603
    }
deba@127
   604
alpar@156
   605
    /// \brief Attribute writing rule
alpar@156
   606
    ///
alpar@156
   607
    /// Add an attribute writing rule with specialized converter to the
alpar@156
   608
    /// writer.
deba@127
   609
    template <typename Value, typename Converter>
alpar@209
   610
    DigraphWriter& attribute(const std::string& caption, const Value& value,
alpar@209
   611
                             const Converter& converter = Converter()) {
alpar@209
   612
      _writer_bits::ValueStorageBase* storage =
alpar@209
   613
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@127
   614
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   615
      return *this;
deba@127
   616
    }
deba@127
   617
alpar@156
   618
    /// \brief Node writing rule
alpar@156
   619
    ///
alpar@156
   620
    /// Add a node writing rule to the writer.
deba@127
   621
    DigraphWriter& node(const std::string& caption, const Node& node) {
deba@127
   622
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@127
   623
      Converter converter(_node_index);
alpar@209
   624
      _writer_bits::ValueStorageBase* storage =
alpar@209
   625
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@127
   626
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   627
      return *this;
deba@127
   628
    }
deba@127
   629
alpar@156
   630
    /// \brief Arc writing rule
alpar@156
   631
    ///
alpar@156
   632
    /// Add an arc writing rule to writer.
deba@127
   633
    DigraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@127
   634
      typedef _writer_bits::MapLookUpConverter<Arc> Converter;
deba@127
   635
      Converter converter(_arc_index);
alpar@209
   636
      _writer_bits::ValueStorageBase* storage =
alpar@209
   637
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@127
   638
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   639
      return *this;
deba@127
   640
    }
deba@127
   641
kpeter@584
   642
    /// \name Section Captions
alpar@156
   643
    /// @{
alpar@156
   644
kpeter@192
   645
    /// \brief Add an additional caption to the \c \@nodes section
alpar@156
   646
    ///
kpeter@192
   647
    /// Add an additional caption to the \c \@nodes section.
deba@127
   648
    DigraphWriter& nodes(const std::string& caption) {
deba@127
   649
      _nodes_caption = caption;
deba@127
   650
      return *this;
deba@127
   651
    }
deba@127
   652
kpeter@192
   653
    /// \brief Add an additional caption to the \c \@arcs section
alpar@156
   654
    ///
kpeter@192
   655
    /// Add an additional caption to the \c \@arcs section.
deba@127
   656
    DigraphWriter& arcs(const std::string& caption) {
deba@127
   657
      _arcs_caption = caption;
deba@127
   658
      return *this;
deba@127
   659
    }
deba@127
   660
kpeter@192
   661
    /// \brief Add an additional caption to the \c \@attributes section
alpar@156
   662
    ///
kpeter@192
   663
    /// Add an additional caption to the \c \@attributes section.
deba@127
   664
    DigraphWriter& attributes(const std::string& caption) {
deba@127
   665
      _attributes_caption = caption;
deba@127
   666
      return *this;
deba@127
   667
    }
deba@127
   668
kpeter@584
   669
    /// \name Skipping Section
alpar@156
   670
    /// @{
alpar@156
   671
alpar@156
   672
    /// \brief Skip writing the node set
alpar@156
   673
    ///
kpeter@192
   674
    /// The \c \@nodes section will not be written to the stream.
deba@127
   675
    DigraphWriter& skipNodes() {
deba@127
   676
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@185
   677
      _skip_nodes = true;
deba@127
   678
      return *this;
deba@127
   679
    }
deba@127
   680
alpar@156
   681
    /// \brief Skip writing arc set
alpar@156
   682
    ///
kpeter@192
   683
    /// The \c \@arcs section will not be written to the stream.
deba@127
   684
    DigraphWriter& skipArcs() {
deba@127
   685
      LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
deba@185
   686
      _skip_arcs = true;
deba@127
   687
      return *this;
deba@127
   688
    }
deba@127
   689
alpar@156
   690
    /// @}
alpar@156
   691
deba@127
   692
  private:
deba@127
   693
deba@127
   694
    void writeNodes() {
deba@127
   695
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@127
   696
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   697
           it != _node_maps.end(); ++it) {
deba@127
   698
        if (it->first == "label") {
alpar@209
   699
          label = it->second;
alpar@209
   700
          break;
alpar@209
   701
        }
deba@127
   702
      }
deba@127
   703
deba@127
   704
      *_os << "@nodes";
deba@127
   705
      if (!_nodes_caption.empty()) {
alpar@209
   706
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@127
   707
      }
deba@127
   708
      *_os << std::endl;
deba@127
   709
deba@127
   710
      if (label == 0) {
alpar@209
   711
        *_os << "label" << '\t';
deba@127
   712
      }
deba@127
   713
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   714
           it != _node_maps.end(); ++it) {
alpar@209
   715
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@127
   716
      }
deba@127
   717
      *_os << std::endl;
deba@127
   718
deba@127
   719
      std::vector<Node> nodes;
deba@127
   720
      for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   721
        nodes.push_back(n);
deba@127
   722
      }
alpar@209
   723
deba@127
   724
      if (label == 0) {
deba@598
   725
        IdMap<DGR, Node> id_map(_digraph);
deba@598
   726
        _writer_bits::MapLess<IdMap<DGR, Node> > id_less(id_map);
alpar@209
   727
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@127
   728
      } else {
alpar@209
   729
        label->sort(nodes);
deba@127
   730
      }
deba@127
   731
deba@127
   732
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
alpar@209
   733
        Node n = nodes[i];
alpar@209
   734
        if (label == 0) {
alpar@209
   735
          std::ostringstream os;
alpar@209
   736
          os << _digraph.id(n);
alpar@209
   737
          _writer_bits::writeToken(*_os, os.str());
alpar@209
   738
          *_os << '\t';
alpar@209
   739
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
   740
        }
alpar@209
   741
        for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   742
             it != _node_maps.end(); ++it) {
alpar@209
   743
          std::string value = it->second->get(n);
alpar@209
   744
          _writer_bits::writeToken(*_os, value);
alpar@209
   745
          if (it->first == "label") {
alpar@209
   746
            _node_index.insert(std::make_pair(n, value));
alpar@209
   747
          }
alpar@209
   748
          *_os << '\t';
alpar@209
   749
        }
alpar@209
   750
        *_os << std::endl;
deba@127
   751
      }
deba@127
   752
    }
deba@127
   753
deba@185
   754
    void createNodeIndex() {
deba@185
   755
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@185
   756
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   757
           it != _node_maps.end(); ++it) {
deba@185
   758
        if (it->first == "label") {
alpar@209
   759
          label = it->second;
alpar@209
   760
          break;
alpar@209
   761
        }
deba@185
   762
      }
deba@185
   763
deba@185
   764
      if (label == 0) {
alpar@209
   765
        for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   766
          std::ostringstream os;
alpar@209
   767
          os << _digraph.id(n);
alpar@209
   768
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
   769
        }
deba@185
   770
      } else {
alpar@209
   771
        for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   772
          std::string value = label->get(n);
alpar@209
   773
          _node_index.insert(std::make_pair(n, value));
alpar@209
   774
        }
deba@185
   775
      }
deba@185
   776
    }
deba@185
   777
deba@127
   778
    void writeArcs() {
deba@127
   779
      _writer_bits::MapStorageBase<Arc>* label = 0;
deba@127
   780
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   781
           it != _arc_maps.end(); ++it) {
deba@127
   782
        if (it->first == "label") {
alpar@209
   783
          label = it->second;
alpar@209
   784
          break;
alpar@209
   785
        }
deba@127
   786
      }
deba@127
   787
deba@127
   788
      *_os << "@arcs";
deba@127
   789
      if (!_arcs_caption.empty()) {
alpar@209
   790
        _writer_bits::writeToken(*_os << ' ', _arcs_caption);
deba@127
   791
      }
deba@127
   792
      *_os << std::endl;
deba@127
   793
deba@127
   794
      *_os << '\t' << '\t';
deba@127
   795
      if (label == 0) {
alpar@209
   796
        *_os << "label" << '\t';
deba@127
   797
      }
deba@127
   798
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   799
           it != _arc_maps.end(); ++it) {
alpar@209
   800
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@127
   801
      }
deba@127
   802
      *_os << std::endl;
deba@127
   803
deba@127
   804
      std::vector<Arc> arcs;
deba@127
   805
      for (ArcIt n(_digraph); n != INVALID; ++n) {
alpar@209
   806
        arcs.push_back(n);
deba@127
   807
      }
alpar@209
   808
deba@127
   809
      if (label == 0) {
deba@598
   810
        IdMap<DGR, Arc> id_map(_digraph);
deba@598
   811
        _writer_bits::MapLess<IdMap<DGR, Arc> > id_less(id_map);
alpar@209
   812
        std::sort(arcs.begin(), arcs.end(), id_less);
deba@127
   813
      } else {
alpar@209
   814
        label->sort(arcs);
deba@127
   815
      }
deba@127
   816
deba@127
   817
      for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
alpar@209
   818
        Arc a = arcs[i];
alpar@209
   819
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
   820
                                 find(_digraph.source(a))->second);
alpar@209
   821
        *_os << '\t';
alpar@209
   822
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
   823
                                 find(_digraph.target(a))->second);
alpar@209
   824
        *_os << '\t';
alpar@209
   825
        if (label == 0) {
alpar@209
   826
          std::ostringstream os;
alpar@209
   827
          os << _digraph.id(a);
alpar@209
   828
          _writer_bits::writeToken(*_os, os.str());
alpar@209
   829
          *_os << '\t';
alpar@209
   830
          _arc_index.insert(std::make_pair(a, os.str()));
alpar@209
   831
        }
alpar@209
   832
        for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   833
             it != _arc_maps.end(); ++it) {
alpar@209
   834
          std::string value = it->second->get(a);
alpar@209
   835
          _writer_bits::writeToken(*_os, value);
alpar@209
   836
          if (it->first == "label") {
alpar@209
   837
            _arc_index.insert(std::make_pair(a, value));
alpar@209
   838
          }
alpar@209
   839
          *_os << '\t';
alpar@209
   840
        }
alpar@209
   841
        *_os << std::endl;
deba@127
   842
      }
deba@127
   843
    }
deba@127
   844
deba@185
   845
    void createArcIndex() {
deba@185
   846
      _writer_bits::MapStorageBase<Arc>* label = 0;
deba@185
   847
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   848
           it != _arc_maps.end(); ++it) {
deba@185
   849
        if (it->first == "label") {
alpar@209
   850
          label = it->second;
alpar@209
   851
          break;
alpar@209
   852
        }
deba@185
   853
      }
deba@185
   854
deba@185
   855
      if (label == 0) {
alpar@209
   856
        for (ArcIt a(_digraph); a != INVALID; ++a) {
alpar@209
   857
          std::ostringstream os;
alpar@209
   858
          os << _digraph.id(a);
alpar@209
   859
          _arc_index.insert(std::make_pair(a, os.str()));
alpar@209
   860
        }
deba@185
   861
      } else {
alpar@209
   862
        for (ArcIt a(_digraph); a != INVALID; ++a) {
alpar@209
   863
          std::string value = label->get(a);
alpar@209
   864
          _arc_index.insert(std::make_pair(a, value));
alpar@209
   865
        }
deba@185
   866
      }
deba@185
   867
    }
deba@185
   868
deba@127
   869
    void writeAttributes() {
deba@127
   870
      if (_attributes.empty()) return;
deba@127
   871
      *_os << "@attributes";
deba@127
   872
      if (!_attributes_caption.empty()) {
alpar@209
   873
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@127
   874
      }
deba@127
   875
      *_os << std::endl;
deba@127
   876
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
   877
           it != _attributes.end(); ++it) {
alpar@209
   878
        _writer_bits::writeToken(*_os, it->first) << ' ';
alpar@209
   879
        _writer_bits::writeToken(*_os, it->second->get());
alpar@209
   880
        *_os << std::endl;
deba@127
   881
      }
deba@127
   882
    }
alpar@209
   883
deba@127
   884
  public:
alpar@209
   885
kpeter@584
   886
    /// \name Execution of the Writer
alpar@156
   887
    /// @{
alpar@156
   888
alpar@156
   889
    /// \brief Start the batch processing
alpar@156
   890
    ///
kpeter@192
   891
    /// This function starts the batch processing.
deba@127
   892
    void run() {
deba@127
   893
      if (!_skip_nodes) {
alpar@209
   894
        writeNodes();
deba@185
   895
      } else {
alpar@209
   896
        createNodeIndex();
deba@127
   897
      }
alpar@209
   898
      if (!_skip_arcs) {
alpar@209
   899
        writeArcs();
deba@185
   900
      } else {
alpar@209
   901
        createArcIndex();
deba@127
   902
      }
deba@127
   903
      writeAttributes();
deba@127
   904
    }
deba@127
   905
kpeter@192
   906
    /// \brief Give back the stream of the writer
alpar@156
   907
    ///
kpeter@192
   908
    /// Give back the stream of the writer.
alpar@156
   909
    std::ostream& ostream() {
deba@127
   910
      return *_os;
deba@127
   911
    }
alpar@156
   912
alpar@156
   913
    /// @}
deba@127
   914
  };
deba@127
   915
deba@598
   916
  /// \ingroup lemon_io
deba@598
   917
  ///
kpeter@498
   918
  /// \brief Return a \ref DigraphWriter class
kpeter@498
   919
  ///
alpar@877
   920
  /// This function just returns a \ref DigraphWriter class.
deba@598
   921
  ///
deba@598
   922
  /// With this function a digraph can be write to a file or output
deba@598
   923
  /// stream in \ref lgf-format "LGF" format with several maps and
deba@598
   924
  /// attributes. For example, with the following code a network flow
deba@598
   925
  /// problem can be written to the standard output, i.e. a digraph
deba@598
   926
  /// with a \e capacity map on the arcs and \e source and \e target
deba@598
   927
  /// nodes:
deba@598
   928
  ///
deba@598
   929
  ///\code
deba@598
   930
  ///ListDigraph digraph;
deba@598
   931
  ///ListDigraph::ArcMap<int> cap(digraph);
deba@598
   932
  ///ListDigraph::Node src, trg;
deba@598
   933
  ///  // Setting the capacity map and source and target nodes
deba@598
   934
  ///digraphWriter(digraph, std::cout).
deba@598
   935
  ///  arcMap("capacity", cap).
deba@598
   936
  ///  node("source", src).
deba@598
   937
  ///  node("target", trg).
deba@598
   938
  ///  run();
deba@598
   939
  ///\endcode
deba@598
   940
  ///
deba@598
   941
  /// For a complete documentation, please see the \ref DigraphWriter
deba@598
   942
  /// class documentation.
deba@598
   943
  /// \warning Don't forget to put the \ref DigraphWriter::run() "run()"
deba@598
   944
  /// to the end of the parameter list.
kpeter@498
   945
  /// \relates DigraphWriter
deba@598
   946
  /// \sa digraphWriter(const TDGR& digraph, const std::string& fn)
deba@598
   947
  /// \sa digraphWriter(const TDGR& digraph, const char* fn)
deba@598
   948
  template <typename TDGR>
deba@598
   949
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, std::ostream& os) {
deba@598
   950
    DigraphWriter<TDGR> tmp(digraph, os);
kpeter@498
   951
    return tmp;
kpeter@498
   952
  }
kpeter@498
   953
kpeter@498
   954
  /// \brief Return a \ref DigraphWriter class
kpeter@498
   955
  ///
kpeter@498
   956
  /// This function just returns a \ref DigraphWriter class.
kpeter@498
   957
  /// \relates DigraphWriter
deba@598
   958
  /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
deba@598
   959
  template <typename TDGR>
alpar@877
   960
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
deba@598
   961
                                    const std::string& fn) {
deba@598
   962
    DigraphWriter<TDGR> tmp(digraph, fn);
kpeter@498
   963
    return tmp;
kpeter@498
   964
  }
kpeter@498
   965
kpeter@498
   966
  /// \brief Return a \ref DigraphWriter class
kpeter@498
   967
  ///
kpeter@498
   968
  /// This function just returns a \ref DigraphWriter class.
kpeter@498
   969
  /// \relates DigraphWriter
deba@598
   970
  /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
deba@598
   971
  template <typename TDGR>
deba@598
   972
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn) {
deba@598
   973
    DigraphWriter<TDGR> tmp(digraph, fn);
kpeter@498
   974
    return tmp;
kpeter@498
   975
  }
kpeter@498
   976
deba@598
   977
  template <typename GR>
ladanyi@303
   978
  class GraphWriter;
ladanyi@303
   979
deba@598
   980
  template <typename TGR>
deba@598
   981
  GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os = std::cout);
deba@598
   982
  template <typename TGR>
deba@598
   983
  GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn);
deba@598
   984
  template <typename TGR>
deba@598
   985
  GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn);
deba@165
   986
deba@165
   987
  /// \ingroup lemon_io
alpar@209
   988
  ///
deba@1024
   989
  /// \brief \ref lgf-format "LGF" writer for undirected graphs
deba@165
   990
  ///
deba@165
   991
  /// This utility writes an \ref lgf-format "LGF" file.
kpeter@192
   992
  ///
kpeter@192
   993
  /// It can be used almost the same way as \c DigraphWriter.
kpeter@192
   994
  /// The only difference is that this class can handle edges and
kpeter@192
   995
  /// edge maps as well as arcs and arc maps.
deba@201
   996
  ///
deba@201
   997
  /// The arc maps are written into the file as two columns, the
deba@201
   998
  /// caption of the columns are the name of the map prefixed with \c
deba@201
   999
  /// '+' and \c '-'. The arcs are written into the \c \@attributes
deba@201
  1000
  /// section as a \c '+' or a \c '-' prefix (depends on the direction
deba@201
  1001
  /// of the arc) and the label of corresponding edge.
kpeter@559
  1002
  template <typename GR>
deba@165
  1003
  class GraphWriter {
deba@165
  1004
  public:
deba@165
  1005
kpeter@559
  1006
    typedef GR Graph;
deba@598
  1007
    TEMPLATE_GRAPH_TYPEDEFS(GR);
alpar@209
  1008
deba@165
  1009
  private:
deba@165
  1010
deba@165
  1011
deba@165
  1012
    std::ostream* _os;
deba@165
  1013
    bool local_os;
deba@165
  1014
deba@598
  1015
    const GR& _graph;
deba@165
  1016
deba@165
  1017
    std::string _nodes_caption;
deba@165
  1018
    std::string _edges_caption;
deba@165
  1019
    std::string _attributes_caption;
alpar@209
  1020
deba@165
  1021
    typedef std::map<Node, std::string> NodeIndex;
deba@165
  1022
    NodeIndex _node_index;
deba@165
  1023
    typedef std::map<Edge, std::string> EdgeIndex;
deba@165
  1024
    EdgeIndex _edge_index;
deba@165
  1025
alpar@209
  1026
    typedef std::vector<std::pair<std::string,
alpar@209
  1027
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
alpar@209
  1028
    NodeMaps _node_maps;
deba@165
  1029
alpar@209
  1030
    typedef std::vector<std::pair<std::string,
deba@165
  1031
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
deba@165
  1032
    EdgeMaps _edge_maps;
deba@165
  1033
alpar@209
  1034
    typedef std::vector<std::pair<std::string,
deba@165
  1035
      _writer_bits::ValueStorageBase*> > Attributes;
deba@165
  1036
    Attributes _attributes;
deba@165
  1037
deba@165
  1038
    bool _skip_nodes;
deba@165
  1039
    bool _skip_edges;
deba@165
  1040
deba@165
  1041
  public:
deba@165
  1042
deba@165
  1043
    /// \brief Constructor
deba@165
  1044
    ///
deba@1024
  1045
    /// Construct an undirected graph writer, which writes to the
deba@1024
  1046
    /// given output stream.
deba@598
  1047
    GraphWriter(const GR& graph, std::ostream& os = std::cout)
kpeter@293
  1048
      : _os(&os), local_os(false), _graph(graph),
alpar@209
  1049
        _skip_nodes(false), _skip_edges(false) {}
deba@165
  1050
deba@165
  1051
    /// \brief Constructor
deba@165
  1052
    ///
deba@1024
  1053
    /// Construct a undirected graph writer, which writes to the given
deba@165
  1054
    /// output file.
deba@598
  1055
    GraphWriter(const GR& graph, const std::string& fn)
deba@165
  1056
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
deba@290
  1057
        _skip_nodes(false), _skip_edges(false) {
deba@295
  1058
      if (!(*_os)) {
deba@295
  1059
        delete _os;
deba@295
  1060
        throw IoError("Cannot write file", fn);
deba@295
  1061
      }
deba@290
  1062
    }
deba@165
  1063
deba@165
  1064
    /// \brief Constructor
deba@165
  1065
    ///
deba@1024
  1066
    /// Construct a undirected graph writer, which writes to the given
deba@165
  1067
    /// output file.
deba@598
  1068
    GraphWriter(const GR& graph, const char* fn)
deba@165
  1069
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
deba@290
  1070
        _skip_nodes(false), _skip_edges(false) {
deba@295
  1071
      if (!(*_os)) {
deba@295
  1072
        delete _os;
deba@295
  1073
        throw IoError("Cannot write file", fn);
deba@295
  1074
      }
deba@290
  1075
    }
deba@165
  1076
deba@165
  1077
    /// \brief Destructor
deba@165
  1078
    ~GraphWriter() {
alpar@209
  1079
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1080
           it != _node_maps.end(); ++it) {
alpar@209
  1081
        delete it->second;
deba@165
  1082
      }
deba@165
  1083
alpar@209
  1084
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1085
           it != _edge_maps.end(); ++it) {
alpar@209
  1086
        delete it->second;
deba@165
  1087
      }
deba@165
  1088
alpar@209
  1089
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1090
           it != _attributes.end(); ++it) {
alpar@209
  1091
        delete it->second;
deba@165
  1092
      }
deba@165
  1093
deba@165
  1094
      if (local_os) {
alpar@209
  1095
        delete _os;
deba@165
  1096
      }
deba@165
  1097
    }
alpar@209
  1098
deba@190
  1099
  private:
deba@165
  1100
deba@598
  1101
    template <typename TGR>
deba@598
  1102
    friend GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os);
deba@598
  1103
    template <typename TGR>
alpar@877
  1104
    friend GraphWriter<TGR> graphWriter(const TGR& graph,
deba@598
  1105
                                        const std::string& fn);
deba@598
  1106
    template <typename TGR>
deba@598
  1107
    friend GraphWriter<TGR> graphWriter(const TGR& graph, const char *fn);
alpar@877
  1108
alpar@209
  1109
    GraphWriter(GraphWriter& other)
deba@190
  1110
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
alpar@209
  1111
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
deba@190
  1112
deba@190
  1113
      other._os = 0;
deba@190
  1114
      other.local_os = false;
deba@190
  1115
deba@190
  1116
      _node_index.swap(other._node_index);
deba@190
  1117
      _edge_index.swap(other._edge_index);
deba@190
  1118
deba@190
  1119
      _node_maps.swap(other._node_maps);
deba@190
  1120
      _edge_maps.swap(other._edge_maps);
deba@190
  1121
      _attributes.swap(other._attributes);
deba@190
  1122
deba@190
  1123
      _nodes_caption = other._nodes_caption;
deba@190
  1124
      _edges_caption = other._edges_caption;
deba@190
  1125
      _attributes_caption = other._attributes_caption;
deba@190
  1126
    }
deba@190
  1127
deba@165
  1128
    GraphWriter& operator=(const GraphWriter&);
deba@165
  1129
deba@165
  1130
  public:
deba@165
  1131
kpeter@584
  1132
    /// \name Writing Rules
deba@165
  1133
    /// @{
alpar@209
  1134
kpeter@192
  1135
    /// \brief Node map writing rule
deba@165
  1136
    ///
kpeter@192
  1137
    /// Add a node map writing rule to the writer.
deba@165
  1138
    template <typename Map>
deba@165
  1139
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@165
  1140
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
  1141
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
  1142
        new _writer_bits::MapStorage<Node, Map>(map);
deba@165
  1143
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1144
      return *this;
deba@165
  1145
    }
deba@165
  1146
deba@165
  1147
    /// \brief Node map writing rule
deba@165
  1148
    ///
deba@165
  1149
    /// Add a node map writing rule with specialized converter to the
deba@165
  1150
    /// writer.
deba@165
  1151
    template <typename Map, typename Converter>
alpar@209
  1152
    GraphWriter& nodeMap(const std::string& caption, const Map& map,
alpar@209
  1153
                           const Converter& converter = Converter()) {
deba@165
  1154
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
  1155
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
  1156
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@165
  1157
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1158
      return *this;
deba@165
  1159
    }
deba@165
  1160
deba@165
  1161
    /// \brief Edge map writing rule
deba@165
  1162
    ///
deba@165
  1163
    /// Add an edge map writing rule to the writer.
deba@165
  1164
    template <typename Map>
deba@165
  1165
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
deba@165
  1166
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
alpar@209
  1167
      _writer_bits::MapStorageBase<Edge>* storage =
alpar@209
  1168
        new _writer_bits::MapStorage<Edge, Map>(map);
deba@165
  1169
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1170
      return *this;
deba@165
  1171
    }
deba@165
  1172
deba@165
  1173
    /// \brief Edge map writing rule
deba@165
  1174
    ///
deba@165
  1175
    /// Add an edge map writing rule with specialized converter to the
deba@165
  1176
    /// writer.
deba@165
  1177
    template <typename Map, typename Converter>
alpar@209
  1178
    GraphWriter& edgeMap(const std::string& caption, const Map& map,
alpar@209
  1179
                          const Converter& converter = Converter()) {
deba@165
  1180
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
alpar@209
  1181
      _writer_bits::MapStorageBase<Edge>* storage =
alpar@209
  1182
        new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
deba@165
  1183
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1184
      return *this;
deba@165
  1185
    }
deba@165
  1186
deba@165
  1187
    /// \brief Arc map writing rule
deba@165
  1188
    ///
deba@165
  1189
    /// Add an arc map writing rule to the writer.
deba@165
  1190
    template <typename Map>
deba@165
  1191
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@165
  1192
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
  1193
      _writer_bits::MapStorageBase<Edge>* forward_storage =
deba@598
  1194
        new _writer_bits::GraphArcMapStorage<GR, true, Map>(_graph, map);
deba@165
  1195
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
alpar@209
  1196
      _writer_bits::MapStorageBase<Edge>* backward_storage =
deba@598
  1197
        new _writer_bits::GraphArcMapStorage<GR, false, Map>(_graph, map);
deba@165
  1198
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1199
      return *this;
deba@165
  1200
    }
deba@165
  1201
deba@165
  1202
    /// \brief Arc map writing rule
deba@165
  1203
    ///
deba@165
  1204
    /// Add an arc map writing rule with specialized converter to the
deba@165
  1205
    /// writer.
deba@165
  1206
    template <typename Map, typename Converter>
alpar@209
  1207
    GraphWriter& arcMap(const std::string& caption, const Map& map,
alpar@209
  1208
                          const Converter& converter = Converter()) {
deba@165
  1209
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
  1210
      _writer_bits::MapStorageBase<Edge>* forward_storage =
deba@598
  1211
        new _writer_bits::GraphArcMapStorage<GR, true, Map, Converter>
alpar@209
  1212
        (_graph, map, converter);
deba@165
  1213
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
alpar@209
  1214
      _writer_bits::MapStorageBase<Edge>* backward_storage =
deba@598
  1215
        new _writer_bits::GraphArcMapStorage<GR, false, Map, Converter>
alpar@209
  1216
        (_graph, map, converter);
deba@165
  1217
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1218
      return *this;
deba@165
  1219
    }
deba@165
  1220
deba@165
  1221
    /// \brief Attribute writing rule
deba@165
  1222
    ///
deba@165
  1223
    /// Add an attribute writing rule to the writer.
deba@165
  1224
    template <typename Value>
deba@165
  1225
    GraphWriter& attribute(const std::string& caption, const Value& value) {
alpar@209
  1226
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1227
        new _writer_bits::ValueStorage<Value>(value);
deba@165
  1228
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1229
      return *this;
deba@165
  1230
    }
deba@165
  1231
deba@165
  1232
    /// \brief Attribute writing rule
deba@165
  1233
    ///
deba@165
  1234
    /// Add an attribute writing rule with specialized converter to the
deba@165
  1235
    /// writer.
deba@165
  1236
    template <typename Value, typename Converter>
alpar@209
  1237
    GraphWriter& attribute(const std::string& caption, const Value& value,
alpar@209
  1238
                             const Converter& converter = Converter()) {
alpar@209
  1239
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1240
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@165
  1241
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1242
      return *this;
deba@165
  1243
    }
deba@165
  1244
deba@165
  1245
    /// \brief Node writing rule
deba@165
  1246
    ///
deba@165
  1247
    /// Add a node writing rule to the writer.
deba@165
  1248
    GraphWriter& node(const std::string& caption, const Node& node) {
deba@165
  1249
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@165
  1250
      Converter converter(_node_index);
alpar@209
  1251
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1252
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@165
  1253
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1254
      return *this;
deba@165
  1255
    }
deba@165
  1256
deba@165
  1257
    /// \brief Edge writing rule
deba@165
  1258
    ///
deba@165
  1259
    /// Add an edge writing rule to writer.
deba@165
  1260
    GraphWriter& edge(const std::string& caption, const Edge& edge) {
deba@165
  1261
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
deba@165
  1262
      Converter converter(_edge_index);
alpar@209
  1263
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1264
        new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
deba@165
  1265
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1266
      return *this;
deba@165
  1267
    }
deba@165
  1268
deba@165
  1269
    /// \brief Arc writing rule
deba@165
  1270
    ///
deba@165
  1271
    /// Add an arc writing rule to writer.
deba@165
  1272
    GraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@598
  1273
      typedef _writer_bits::GraphArcLookUpConverter<GR> Converter;
deba@165
  1274
      Converter converter(_graph, _edge_index);
alpar@209
  1275
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1276
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@165
  1277
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1278
      return *this;
deba@165
  1279
    }
deba@165
  1280
kpeter@584
  1281
    /// \name Section Captions
deba@165
  1282
    /// @{
deba@165
  1283
kpeter@192
  1284
    /// \brief Add an additional caption to the \c \@nodes section
deba@165
  1285
    ///
kpeter@192
  1286
    /// Add an additional caption to the \c \@nodes section.
deba@165
  1287
    GraphWriter& nodes(const std::string& caption) {
deba@165
  1288
      _nodes_caption = caption;
deba@165
  1289
      return *this;
deba@165
  1290
    }
deba@165
  1291
deba@1024
  1292
    /// \brief Add an additional caption to the \c \@edges section
deba@165
  1293
    ///
deba@1024
  1294
    /// Add an additional caption to the \c \@edges section.
deba@165
  1295
    GraphWriter& edges(const std::string& caption) {
deba@165
  1296
      _edges_caption = caption;
deba@165
  1297
      return *this;
deba@165
  1298
    }
deba@165
  1299
kpeter@192
  1300
    /// \brief Add an additional caption to the \c \@attributes section
deba@165
  1301
    ///
kpeter@192
  1302
    /// Add an additional caption to the \c \@attributes section.
deba@165
  1303
    GraphWriter& attributes(const std::string& caption) {
deba@165
  1304
      _attributes_caption = caption;
deba@165
  1305
      return *this;
deba@165
  1306
    }
deba@165
  1307
kpeter@584
  1308
    /// \name Skipping Section
deba@165
  1309
    /// @{
deba@165
  1310
deba@165
  1311
    /// \brief Skip writing the node set
deba@165
  1312
    ///
kpeter@192
  1313
    /// The \c \@nodes section will not be written to the stream.
deba@165
  1314
    GraphWriter& skipNodes() {
deba@165
  1315
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@185
  1316
      _skip_nodes = true;
deba@165
  1317
      return *this;
deba@165
  1318
    }
deba@165
  1319
deba@165
  1320
    /// \brief Skip writing edge set
deba@165
  1321
    ///
kpeter@192
  1322
    /// The \c \@edges section will not be written to the stream.
deba@165
  1323
    GraphWriter& skipEdges() {
deba@165
  1324
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
deba@185
  1325
      _skip_edges = true;
deba@165
  1326
      return *this;
deba@165
  1327
    }
deba@165
  1328
deba@165
  1329
    /// @}
deba@165
  1330
deba@165
  1331
  private:
deba@165
  1332
deba@165
  1333
    void writeNodes() {
deba@165
  1334
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@165
  1335
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1336
           it != _node_maps.end(); ++it) {
deba@165
  1337
        if (it->first == "label") {
alpar@209
  1338
          label = it->second;
alpar@209
  1339
          break;
alpar@209
  1340
        }
deba@165
  1341
      }
deba@165
  1342
deba@165
  1343
      *_os << "@nodes";
deba@165
  1344
      if (!_nodes_caption.empty()) {
alpar@209
  1345
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@165
  1346
      }
deba@165
  1347
      *_os << std::endl;
deba@165
  1348
deba@165
  1349
      if (label == 0) {
alpar@209
  1350
        *_os << "label" << '\t';
deba@165
  1351
      }
deba@165
  1352
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1353
           it != _node_maps.end(); ++it) {
alpar@209
  1354
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@165
  1355
      }
deba@165
  1356
      *_os << std::endl;
deba@165
  1357
deba@165
  1358
      std::vector<Node> nodes;
deba@165
  1359
      for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1360
        nodes.push_back(n);
deba@165
  1361
      }
alpar@209
  1362
deba@165
  1363
      if (label == 0) {
deba@598
  1364
        IdMap<GR, Node> id_map(_graph);
deba@598
  1365
        _writer_bits::MapLess<IdMap<GR, Node> > id_less(id_map);
alpar@209
  1366
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@165
  1367
      } else {
alpar@209
  1368
        label->sort(nodes);
deba@165
  1369
      }
deba@165
  1370
deba@165
  1371
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
alpar@209
  1372
        Node n = nodes[i];
alpar@209
  1373
        if (label == 0) {
alpar@209
  1374
          std::ostringstream os;
alpar@209
  1375
          os << _graph.id(n);
alpar@209
  1376
          _writer_bits::writeToken(*_os, os.str());
alpar@209
  1377
          *_os << '\t';
alpar@209
  1378
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
  1379
        }
alpar@209
  1380
        for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1381
             it != _node_maps.end(); ++it) {
alpar@209
  1382
          std::string value = it->second->get(n);
alpar@209
  1383
          _writer_bits::writeToken(*_os, value);
alpar@209
  1384
          if (it->first == "label") {
alpar@209
  1385
            _node_index.insert(std::make_pair(n, value));
alpar@209
  1386
          }
alpar@209
  1387
          *_os << '\t';
alpar@209
  1388
        }
alpar@209
  1389
        *_os << std::endl;
deba@165
  1390
      }
deba@165
  1391
    }
deba@165
  1392
deba@185
  1393
    void createNodeIndex() {
deba@185
  1394
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@185
  1395
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1396
           it != _node_maps.end(); ++it) {
deba@185
  1397
        if (it->first == "label") {
alpar@209
  1398
          label = it->second;
alpar@209
  1399
          break;
alpar@209
  1400
        }
deba@185
  1401
      }
deba@185
  1402
deba@185
  1403
      if (label == 0) {
alpar@209
  1404
        for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1405
          std::ostringstream os;
alpar@209
  1406
          os << _graph.id(n);
alpar@209
  1407
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
  1408
        }
deba@185
  1409
      } else {
alpar@209
  1410
        for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1411
          std::string value = label->get(n);
alpar@209
  1412
          _node_index.insert(std::make_pair(n, value));
alpar@209
  1413
        }
deba@185
  1414
      }
deba@185
  1415
    }
deba@185
  1416
deba@165
  1417
    void writeEdges() {
deba@165
  1418
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@165
  1419
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1420
           it != _edge_maps.end(); ++it) {
deba@165
  1421
        if (it->first == "label") {
alpar@209
  1422
          label = it->second;
alpar@209
  1423
          break;
alpar@209
  1424
        }
deba@165
  1425
      }
deba@165
  1426
deba@165
  1427
      *_os << "@edges";
deba@165
  1428
      if (!_edges_caption.empty()) {
alpar@209
  1429
        _writer_bits::writeToken(*_os << ' ', _edges_caption);
deba@165
  1430
      }
deba@165
  1431
      *_os << std::endl;
deba@165
  1432
deba@165
  1433
      *_os << '\t' << '\t';
deba@165
  1434
      if (label == 0) {
alpar@209
  1435
        *_os << "label" << '\t';
deba@165
  1436
      }
deba@165
  1437
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1438
           it != _edge_maps.end(); ++it) {
alpar@209
  1439
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@165
  1440
      }
deba@165
  1441
      *_os << std::endl;
deba@165
  1442
deba@165
  1443
      std::vector<Edge> edges;
deba@165
  1444
      for (EdgeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1445
        edges.push_back(n);
deba@165
  1446
      }
alpar@209
  1447
deba@165
  1448
      if (label == 0) {
deba@598
  1449
        IdMap<GR, Edge> id_map(_graph);
deba@598
  1450
        _writer_bits::MapLess<IdMap<GR, Edge> > id_less(id_map);
alpar@209
  1451
        std::sort(edges.begin(), edges.end(), id_less);
deba@165
  1452
      } else {
alpar@209
  1453
        label->sort(edges);
deba@165
  1454
      }
deba@165
  1455
deba@165
  1456
      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
alpar@209
  1457
        Edge e = edges[i];
alpar@209
  1458
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
  1459
                                 find(_graph.u(e))->second);
alpar@209
  1460
        *_os << '\t';
alpar@209
  1461
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
  1462
                                 find(_graph.v(e))->second);
alpar@209
  1463
        *_os << '\t';
alpar@209
  1464
        if (label == 0) {
alpar@209
  1465
          std::ostringstream os;
alpar@209
  1466
          os << _graph.id(e);
alpar@209
  1467
          _writer_bits::writeToken(*_os, os.str());
alpar@209
  1468
          *_os << '\t';
alpar@209
  1469
          _edge_index.insert(std::make_pair(e, os.str()));
alpar@209
  1470
        }
alpar@209
  1471
        for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1472
             it != _edge_maps.end(); ++it) {
alpar@209
  1473
          std::string value = it->second->get(e);
alpar@209
  1474
          _writer_bits::writeToken(*_os, value);
alpar@209
  1475
          if (it->first == "label") {
alpar@209
  1476
            _edge_index.insert(std::make_pair(e, value));
alpar@209
  1477
          }
alpar@209
  1478
          *_os << '\t';
alpar@209
  1479
        }
alpar@209
  1480
        *_os << std::endl;
deba@165
  1481
      }
deba@165
  1482
    }
deba@165
  1483
deba@185
  1484
    void createEdgeIndex() {
deba@185
  1485
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@185
  1486
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1487
           it != _edge_maps.end(); ++it) {
deba@185
  1488
        if (it->first == "label") {
alpar@209
  1489
          label = it->second;
alpar@209
  1490
          break;
alpar@209
  1491
        }
deba@185
  1492
      }
deba@185
  1493
deba@185
  1494
      if (label == 0) {
alpar@209
  1495
        for (EdgeIt e(_graph); e != INVALID; ++e) {
alpar@209
  1496
          std::ostringstream os;
alpar@209
  1497
          os << _graph.id(e);
alpar@209
  1498
          _edge_index.insert(std::make_pair(e, os.str()));
alpar@209
  1499
        }
deba@185
  1500
      } else {
alpar@209
  1501
        for (EdgeIt e(_graph); e != INVALID; ++e) {
alpar@209
  1502
          std::string value = label->get(e);
alpar@209
  1503
          _edge_index.insert(std::make_pair(e, value));
alpar@209
  1504
        }
deba@185
  1505
      }
deba@185
  1506
    }
deba@185
  1507
deba@165
  1508
    void writeAttributes() {
deba@165
  1509
      if (_attributes.empty()) return;
deba@165
  1510
      *_os << "@attributes";
deba@165
  1511
      if (!_attributes_caption.empty()) {
alpar@209
  1512
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@165
  1513
      }
deba@165
  1514
      *_os << std::endl;
deba@165
  1515
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1516
           it != _attributes.end(); ++it) {
alpar@209
  1517
        _writer_bits::writeToken(*_os, it->first) << ' ';
alpar@209
  1518
        _writer_bits::writeToken(*_os, it->second->get());
alpar@209
  1519
        *_os << std::endl;
deba@165
  1520
      }
deba@165
  1521
    }
alpar@209
  1522
deba@165
  1523
  public:
alpar@209
  1524
kpeter@584
  1525
    /// \name Execution of the Writer
deba@165
  1526
    /// @{
deba@165
  1527
deba@165
  1528
    /// \brief Start the batch processing
deba@165
  1529
    ///
kpeter@192
  1530
    /// This function starts the batch processing.
deba@165
  1531
    void run() {
deba@165
  1532
      if (!_skip_nodes) {
alpar@209
  1533
        writeNodes();
deba@185
  1534
      } else {
alpar@209
  1535
        createNodeIndex();
deba@165
  1536
      }
alpar@209
  1537
      if (!_skip_edges) {
alpar@209
  1538
        writeEdges();
deba@185
  1539
      } else {
alpar@209
  1540
        createEdgeIndex();
deba@165
  1541
      }
deba@165
  1542
      writeAttributes();
deba@165
  1543
    }
deba@165
  1544
kpeter@192
  1545
    /// \brief Give back the stream of the writer
deba@165
  1546
    ///
kpeter@192
  1547
    /// Give back the stream of the writer
deba@165
  1548
    std::ostream& ostream() {
deba@165
  1549
      return *_os;
deba@165
  1550
    }
deba@165
  1551
deba@165
  1552
    /// @}
deba@165
  1553
  };
deba@165
  1554
deba@598
  1555
  /// \ingroup lemon_io
deba@598
  1556
  ///
kpeter@498
  1557
  /// \brief Return a \ref GraphWriter class
kpeter@498
  1558
  ///
alpar@877
  1559
  /// This function just returns a \ref GraphWriter class.
deba@598
  1560
  ///
deba@598
  1561
  /// With this function a graph can be write to a file or output
deba@598
  1562
  /// stream in \ref lgf-format "LGF" format with several maps and
deba@598
  1563
  /// attributes. For example, with the following code a weighted
deba@598
  1564
  /// matching problem can be written to the standard output, i.e. a
deba@598
  1565
  /// graph with a \e weight map on the edges:
deba@598
  1566
  ///
deba@598
  1567
  ///\code
deba@598
  1568
  ///ListGraph graph;
deba@598
  1569
  ///ListGraph::EdgeMap<int> weight(graph);
deba@598
  1570
  ///  // Setting the weight map
deba@598
  1571
  ///graphWriter(graph, std::cout).
deba@598
  1572
  ///  edgeMap("weight", weight).
deba@598
  1573
  ///  run();
deba@598
  1574
  ///\endcode
deba@598
  1575
  ///
deba@598
  1576
  /// For a complete documentation, please see the \ref GraphWriter
deba@598
  1577
  /// class documentation.
deba@598
  1578
  /// \warning Don't forget to put the \ref GraphWriter::run() "run()"
deba@598
  1579
  /// to the end of the parameter list.
kpeter@498
  1580
  /// \relates GraphWriter
deba@598
  1581
  /// \sa graphWriter(const TGR& graph, const std::string& fn)
deba@598
  1582
  /// \sa graphWriter(const TGR& graph, const char* fn)
deba@598
  1583
  template <typename TGR>
deba@598
  1584
  GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os) {
deba@598
  1585
    GraphWriter<TGR> tmp(graph, os);
kpeter@498
  1586
    return tmp;
kpeter@498
  1587
  }
kpeter@498
  1588
kpeter@498
  1589
  /// \brief Return a \ref GraphWriter class
kpeter@498
  1590
  ///
kpeter@498
  1591
  /// This function just returns a \ref GraphWriter class.
kpeter@498
  1592
  /// \relates GraphWriter
deba@598
  1593
  /// \sa graphWriter(const TGR& graph, std::ostream& os)
deba@598
  1594
  template <typename TGR>
deba@598
  1595
  GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn) {
deba@598
  1596
    GraphWriter<TGR> tmp(graph, fn);
kpeter@498
  1597
    return tmp;
kpeter@498
  1598
  }
kpeter@498
  1599
kpeter@498
  1600
  /// \brief Return a \ref GraphWriter class
kpeter@498
  1601
  ///
kpeter@498
  1602
  /// This function just returns a \ref GraphWriter class.
kpeter@498
  1603
  /// \relates GraphWriter
deba@598
  1604
  /// \sa graphWriter(const TGR& graph, std::ostream& os)
deba@598
  1605
  template <typename TGR>
deba@598
  1606
  GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn) {
deba@598
  1607
    GraphWriter<TGR> tmp(graph, fn);
kpeter@498
  1608
    return tmp;
kpeter@498
  1609
  }
kpeter@498
  1610
deba@1024
  1611
  template <typename BGR>
deba@1024
  1612
  class BpGraphWriter;
deba@1024
  1613
deba@1024
  1614
  template <typename TBGR>
deba@1024
  1615
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
deba@1024
  1616
                                    std::ostream& os = std::cout);
deba@1024
  1617
  template <typename TBGR>
deba@1024
  1618
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn);
deba@1024
  1619
  template <typename TBGR>
deba@1024
  1620
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn);
deba@1024
  1621
deba@1024
  1622
  /// \ingroup lemon_io
deba@1024
  1623
  ///
deba@1024
  1624
  /// \brief \ref lgf-format "LGF" writer for undirected bipartite graphs
deba@1024
  1625
  ///
deba@1024
  1626
  /// This utility writes an \ref lgf-format "LGF" file.
deba@1024
  1627
  ///
deba@1024
  1628
  /// It can be used almost the same way as \c GraphWriter, but it
deba@1024
  1629
  /// reads the red and blue nodes from separate sections, and these
deba@1024
  1630
  /// sections can contain different set of maps.
deba@1024
  1631
  ///
deba@1026
  1632
  /// The red and blue node maps are written to the corresponding
deba@1024
  1633
  /// sections. The node maps are written to both of these sections
deba@1024
  1634
  /// with the same map name.
deba@1024
  1635
  template <typename BGR>
deba@1024
  1636
  class BpGraphWriter {
deba@1024
  1637
  public:
deba@1024
  1638
deba@1024
  1639
    typedef BGR BpGraph;
deba@1024
  1640
    TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
deba@1024
  1641
deba@1024
  1642
  private:
deba@1024
  1643
deba@1024
  1644
deba@1024
  1645
    std::ostream* _os;
deba@1024
  1646
    bool local_os;
deba@1024
  1647
deba@1024
  1648
    const BGR& _graph;
deba@1024
  1649
deba@1024
  1650
    std::string _nodes_caption;
deba@1024
  1651
    std::string _edges_caption;
deba@1024
  1652
    std::string _attributes_caption;
deba@1024
  1653
deba@1024
  1654
    typedef std::map<Node, std::string> NodeIndex;
deba@1024
  1655
    NodeIndex _node_index;
deba@1024
  1656
    typedef std::map<Edge, std::string> EdgeIndex;
deba@1024
  1657
    EdgeIndex _edge_index;
deba@1024
  1658
deba@1024
  1659
    typedef std::vector<std::pair<std::string,
deba@1024
  1660
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
deba@1024
  1661
    NodeMaps _red_maps;
deba@1024
  1662
    NodeMaps _blue_maps;
deba@1024
  1663
deba@1024
  1664
    typedef std::vector<std::pair<std::string,
deba@1024
  1665
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
deba@1024
  1666
    EdgeMaps _edge_maps;
deba@1024
  1667
deba@1024
  1668
    typedef std::vector<std::pair<std::string,
deba@1024
  1669
      _writer_bits::ValueStorageBase*> > Attributes;
deba@1024
  1670
    Attributes _attributes;
deba@1024
  1671
deba@1024
  1672
    bool _skip_nodes;
deba@1024
  1673
    bool _skip_edges;
deba@1024
  1674
deba@1024
  1675
  public:
deba@1024
  1676
deba@1024
  1677
    /// \brief Constructor
deba@1024
  1678
    ///
deba@1024
  1679
    /// Construct a bipartite graph writer, which writes to the given
deba@1024
  1680
    /// output stream.
deba@1024
  1681
    BpGraphWriter(const BGR& graph, std::ostream& os = std::cout)
deba@1024
  1682
      : _os(&os), local_os(false), _graph(graph),
deba@1024
  1683
        _skip_nodes(false), _skip_edges(false) {}
deba@1024
  1684
deba@1024
  1685
    /// \brief Constructor
deba@1024
  1686
    ///
deba@1024
  1687
    /// Construct a bipartite graph writer, which writes to the given
deba@1024
  1688
    /// output file.
deba@1024
  1689
    BpGraphWriter(const BGR& graph, const std::string& fn)
deba@1024
  1690
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
deba@1024
  1691
        _skip_nodes(false), _skip_edges(false) {
deba@1024
  1692
      if (!(*_os)) {
deba@1024
  1693
        delete _os;
deba@1024
  1694
        throw IoError("Cannot write file", fn);
deba@1024
  1695
      }
deba@1024
  1696
    }
deba@1024
  1697
deba@1024
  1698
    /// \brief Constructor
deba@1024
  1699
    ///
deba@1024
  1700
    /// Construct a bipartite graph writer, which writes to the given
deba@1024
  1701
    /// output file.
deba@1024
  1702
    BpGraphWriter(const BGR& graph, const char* fn)
deba@1024
  1703
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
deba@1024
  1704
        _skip_nodes(false), _skip_edges(false) {
deba@1024
  1705
      if (!(*_os)) {
deba@1024
  1706
        delete _os;
deba@1024
  1707
        throw IoError("Cannot write file", fn);
deba@1024
  1708
      }
deba@1024
  1709
    }
deba@1024
  1710
deba@1024
  1711
    /// \brief Destructor
deba@1024
  1712
    ~BpGraphWriter() {
deba@1024
  1713
      for (typename NodeMaps::iterator it = _red_maps.begin();
deba@1024
  1714
           it != _red_maps.end(); ++it) {
deba@1024
  1715
        delete it->second;
deba@1024
  1716
      }
deba@1024
  1717
deba@1024
  1718
      for (typename NodeMaps::iterator it = _blue_maps.begin();
deba@1024
  1719
           it != _blue_maps.end(); ++it) {
deba@1024
  1720
        delete it->second;
deba@1024
  1721
      }
deba@1024
  1722
deba@1024
  1723
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  1724
           it != _edge_maps.end(); ++it) {
deba@1024
  1725
        delete it->second;
deba@1024
  1726
      }
deba@1024
  1727
deba@1024
  1728
      for (typename Attributes::iterator it = _attributes.begin();
deba@1024
  1729
           it != _attributes.end(); ++it) {
deba@1024
  1730
        delete it->second;
deba@1024
  1731
      }
deba@1024
  1732
deba@1024
  1733
      if (local_os) {
deba@1024
  1734
        delete _os;
deba@1024
  1735
      }
deba@1024
  1736
    }
deba@1024
  1737
deba@1024
  1738
  private:
deba@1024
  1739
deba@1024
  1740
    template <typename TBGR>
deba@1024
  1741
    friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
deba@1024
  1742
                                             std::ostream& os);
deba@1024
  1743
    template <typename TBGR>
deba@1024
  1744
    friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
deba@1024
  1745
                                             const std::string& fn);
deba@1024
  1746
    template <typename TBGR>
deba@1024
  1747
    friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char *fn);
deba@1024
  1748
deba@1024
  1749
    BpGraphWriter(BpGraphWriter& other)
deba@1024
  1750
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
deba@1024
  1751
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
deba@1024
  1752
deba@1024
  1753
      other._os = 0;
deba@1024
  1754
      other.local_os = false;
deba@1024
  1755
deba@1024
  1756
      _node_index.swap(other._node_index);
deba@1024
  1757
      _edge_index.swap(other._edge_index);
deba@1024
  1758
deba@1024
  1759
      _red_maps.swap(other._red_maps);
deba@1024
  1760
      _blue_maps.swap(other._blue_maps);
deba@1024
  1761
      _edge_maps.swap(other._edge_maps);
deba@1024
  1762
      _attributes.swap(other._attributes);
deba@1024
  1763
deba@1024
  1764
      _nodes_caption = other._nodes_caption;
deba@1024
  1765
      _edges_caption = other._edges_caption;
deba@1024
  1766
      _attributes_caption = other._attributes_caption;
deba@1024
  1767
    }
deba@1024
  1768
deba@1024
  1769
    BpGraphWriter& operator=(const BpGraphWriter&);
deba@1024
  1770
deba@1024
  1771
  public:
deba@1024
  1772
deba@1024
  1773
    /// \name Writing Rules
deba@1024
  1774
    /// @{
deba@1024
  1775
deba@1024
  1776
    /// \brief Node map writing rule
deba@1024
  1777
    ///
deba@1024
  1778
    /// Add a node map writing rule to the writer.
deba@1024
  1779
    template <typename Map>
deba@1024
  1780
    BpGraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@1024
  1781
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@1024
  1782
      _writer_bits::MapStorageBase<Node>* red_storage =
deba@1024
  1783
        new _writer_bits::MapStorage<Node, Map>(map);
deba@1024
  1784
      _red_maps.push_back(std::make_pair(caption, red_storage));
deba@1024
  1785
      _writer_bits::MapStorageBase<Node>* blue_storage =
deba@1024
  1786
        new _writer_bits::MapStorage<Node, Map>(map);
deba@1024
  1787
      _blue_maps.push_back(std::make_pair(caption, blue_storage));
deba@1024
  1788
      return *this;
deba@1024
  1789
    }
deba@1024
  1790
deba@1024
  1791
    /// \brief Node map writing rule
deba@1024
  1792
    ///
deba@1024
  1793
    /// Add a node map writing rule with specialized converter to the
deba@1024
  1794
    /// writer.
deba@1024
  1795
    template <typename Map, typename Converter>
deba@1024
  1796
    BpGraphWriter& nodeMap(const std::string& caption, const Map& map,
deba@1024
  1797
                           const Converter& converter = Converter()) {
deba@1024
  1798
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@1024
  1799
      _writer_bits::MapStorageBase<Node>* red_storage =
deba@1024
  1800
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@1024
  1801
      _red_maps.push_back(std::make_pair(caption, red_storage));
deba@1024
  1802
      _writer_bits::MapStorageBase<Node>* blue_storage =
deba@1024
  1803
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@1024
  1804
      _blue_maps.push_back(std::make_pair(caption, blue_storage));
deba@1024
  1805
      return *this;
deba@1024
  1806
    }
deba@1024
  1807
deba@1026
  1808
    /// \brief Red node map writing rule
deba@1024
  1809
    ///
deba@1026
  1810
    /// Add a red node map writing rule to the writer.
deba@1024
  1811
    template <typename Map>
deba@1026
  1812
    BpGraphWriter& redNodeMap(const std::string& caption, const Map& map) {
deba@1024
  1813
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@1024
  1814
      _writer_bits::MapStorageBase<Node>* storage =
deba@1024
  1815
        new _writer_bits::MapStorage<Node, Map>(map);
deba@1024
  1816
      _red_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1817
      return *this;
deba@1024
  1818
    }
deba@1024
  1819
deba@1026
  1820
    /// \brief Red node map writing rule
deba@1024
  1821
    ///
deba@1026
  1822
    /// Add a red node map writing rule with specialized converter to the
deba@1024
  1823
    /// writer.
deba@1024
  1824
    template <typename Map, typename Converter>
deba@1026
  1825
    BpGraphWriter& redNodeMap(const std::string& caption, const Map& map,
deba@1026
  1826
                              const Converter& converter = Converter()) {
deba@1024
  1827
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@1024
  1828
      _writer_bits::MapStorageBase<Node>* storage =
deba@1024
  1829
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@1024
  1830
      _red_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1831
      return *this;
deba@1024
  1832
    }
deba@1024
  1833
deba@1026
  1834
    /// \brief Blue node map writing rule
deba@1024
  1835
    ///
deba@1026
  1836
    /// Add a blue node map writing rule to the writer.
deba@1024
  1837
    template <typename Map>
deba@1026
  1838
    BpGraphWriter& blueNodeMap(const std::string& caption, const Map& map) {
deba@1024
  1839
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@1024
  1840
      _writer_bits::MapStorageBase<Node>* storage =
deba@1024
  1841
        new _writer_bits::MapStorage<Node, Map>(map);
deba@1024
  1842
      _blue_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1843
      return *this;
deba@1024
  1844
    }
deba@1024
  1845
deba@1026
  1846
    /// \brief Blue node map writing rule
deba@1024
  1847
    ///
deba@1026
  1848
    /// Add a blue node map writing rule with specialized converter to the
deba@1024
  1849
    /// writer.
deba@1024
  1850
    template <typename Map, typename Converter>
deba@1026
  1851
    BpGraphWriter& blueNodeMap(const std::string& caption, const Map& map,
deba@1026
  1852
                               const Converter& converter = Converter()) {
deba@1024
  1853
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@1024
  1854
      _writer_bits::MapStorageBase<Node>* storage =
deba@1024
  1855
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@1024
  1856
      _blue_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1857
      return *this;
deba@1024
  1858
    }
deba@1024
  1859
deba@1024
  1860
    /// \brief Edge map writing rule
deba@1024
  1861
    ///
deba@1024
  1862
    /// Add an edge map writing rule to the writer.
deba@1024
  1863
    template <typename Map>
deba@1024
  1864
    BpGraphWriter& edgeMap(const std::string& caption, const Map& map) {
deba@1024
  1865
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@1024
  1866
      _writer_bits::MapStorageBase<Edge>* storage =
deba@1024
  1867
        new _writer_bits::MapStorage<Edge, Map>(map);
deba@1024
  1868
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1869
      return *this;
deba@1024
  1870
    }
deba@1024
  1871
deba@1024
  1872
    /// \brief Edge map writing rule
deba@1024
  1873
    ///
deba@1024
  1874
    /// Add an edge map writing rule with specialized converter to the
deba@1024
  1875
    /// writer.
deba@1024
  1876
    template <typename Map, typename Converter>
deba@1024
  1877
    BpGraphWriter& edgeMap(const std::string& caption, const Map& map,
deba@1024
  1878
                          const Converter& converter = Converter()) {
deba@1024
  1879
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@1024
  1880
      _writer_bits::MapStorageBase<Edge>* storage =
deba@1024
  1881
        new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
deba@1024
  1882
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1883
      return *this;
deba@1024
  1884
    }
deba@1024
  1885
deba@1024
  1886
    /// \brief Arc map writing rule
deba@1024
  1887
    ///
deba@1024
  1888
    /// Add an arc map writing rule to the writer.
deba@1024
  1889
    template <typename Map>
deba@1024
  1890
    BpGraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@1024
  1891
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@1024
  1892
      _writer_bits::MapStorageBase<Edge>* forward_storage =
deba@1024
  1893
        new _writer_bits::GraphArcMapStorage<BGR, true, Map>(_graph, map);
deba@1024
  1894
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
deba@1024
  1895
      _writer_bits::MapStorageBase<Edge>* backward_storage =
deba@1024
  1896
        new _writer_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
deba@1024
  1897
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@1024
  1898
      return *this;
deba@1024
  1899
    }
deba@1024
  1900
deba@1024
  1901
    /// \brief Arc map writing rule
deba@1024
  1902
    ///
deba@1024
  1903
    /// Add an arc map writing rule with specialized converter to the
deba@1024
  1904
    /// writer.
deba@1024
  1905
    template <typename Map, typename Converter>
deba@1024
  1906
    BpGraphWriter& arcMap(const std::string& caption, const Map& map,
deba@1024
  1907
                          const Converter& converter = Converter()) {
deba@1024
  1908
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@1024
  1909
      _writer_bits::MapStorageBase<Edge>* forward_storage =
deba@1024
  1910
        new _writer_bits::GraphArcMapStorage<BGR, true, Map, Converter>
deba@1024
  1911
        (_graph, map, converter);
deba@1024
  1912
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
deba@1024
  1913
      _writer_bits::MapStorageBase<Edge>* backward_storage =
deba@1024
  1914
        new _writer_bits::GraphArcMapStorage<BGR, false, Map, Converter>
deba@1024
  1915
        (_graph, map, converter);
deba@1024
  1916
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@1024
  1917
      return *this;
deba@1024
  1918
    }
deba@1024
  1919
deba@1024
  1920
    /// \brief Attribute writing rule
deba@1024
  1921
    ///
deba@1024
  1922
    /// Add an attribute writing rule to the writer.
deba@1024
  1923
    template <typename Value>
deba@1024
  1924
    BpGraphWriter& attribute(const std::string& caption, const Value& value) {
deba@1024
  1925
      _writer_bits::ValueStorageBase* storage =
deba@1024
  1926
        new _writer_bits::ValueStorage<Value>(value);
deba@1024
  1927
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  1928
      return *this;
deba@1024
  1929
    }
deba@1024
  1930
deba@1024
  1931
    /// \brief Attribute writing rule
deba@1024
  1932
    ///
deba@1024
  1933
    /// Add an attribute writing rule with specialized converter to the
deba@1024
  1934
    /// writer.
deba@1024
  1935
    template <typename Value, typename Converter>
deba@1024
  1936
    BpGraphWriter& attribute(const std::string& caption, const Value& value,
deba@1024
  1937
                             const Converter& converter = Converter()) {
deba@1024
  1938
      _writer_bits::ValueStorageBase* storage =
deba@1024
  1939
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@1024
  1940
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  1941
      return *this;
deba@1024
  1942
    }
deba@1024
  1943
deba@1024
  1944
    /// \brief Node writing rule
deba@1024
  1945
    ///
deba@1024
  1946
    /// Add a node writing rule to the writer.
deba@1024
  1947
    BpGraphWriter& node(const std::string& caption, const Node& node) {
deba@1024
  1948
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@1024
  1949
      Converter converter(_node_index);
deba@1024
  1950
      _writer_bits::ValueStorageBase* storage =
deba@1024
  1951
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@1024
  1952
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  1953
      return *this;
deba@1024
  1954
    }
deba@1024
  1955
deba@1024
  1956
    /// \brief Edge writing rule
deba@1024
  1957
    ///
deba@1024
  1958
    /// Add an edge writing rule to writer.
deba@1024
  1959
    BpGraphWriter& edge(const std::string& caption, const Edge& edge) {
deba@1024
  1960
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
deba@1024
  1961
      Converter converter(_edge_index);
deba@1024
  1962
      _writer_bits::ValueStorageBase* storage =
deba@1024
  1963
        new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
deba@1024
  1964
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  1965
      return *this;
deba@1024
  1966
    }
deba@1024
  1967
deba@1024
  1968
    /// \brief Arc writing rule
deba@1024
  1969
    ///
deba@1024
  1970
    /// Add an arc writing rule to writer.
deba@1024
  1971
    BpGraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@1024
  1972
      typedef _writer_bits::GraphArcLookUpConverter<BGR> Converter;
deba@1024
  1973
      Converter converter(_graph, _edge_index);
deba@1024
  1974
      _writer_bits::ValueStorageBase* storage =
deba@1024
  1975
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@1024
  1976
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  1977
      return *this;
deba@1024
  1978
    }
deba@1024
  1979
deba@1024
  1980
    /// \name Section Captions
deba@1024
  1981
    /// @{
deba@1024
  1982
deba@1024
  1983
    /// \brief Add an additional caption to the \c \@red_nodes and
deba@1024
  1984
    /// \c \@blue_nodes section
deba@1024
  1985
    ///
deba@1024
  1986
    /// Add an additional caption to the \c \@red_nodes and \c
deba@1024
  1987
    /// \@blue_nodes section.
deba@1024
  1988
    BpGraphWriter& nodes(const std::string& caption) {
deba@1024
  1989
      _nodes_caption = caption;
deba@1024
  1990
      return *this;
deba@1024
  1991
    }
deba@1024
  1992
deba@1024
  1993
    /// \brief Add an additional caption to the \c \@edges section
deba@1024
  1994
    ///
deba@1024
  1995
    /// Add an additional caption to the \c \@edges section.
deba@1024
  1996
    BpGraphWriter& edges(const std::string& caption) {
deba@1024
  1997
      _edges_caption = caption;
deba@1024
  1998
      return *this;
deba@1024
  1999
    }
deba@1024
  2000
deba@1024
  2001
    /// \brief Add an additional caption to the \c \@attributes section
deba@1024
  2002
    ///
deba@1024
  2003
    /// Add an additional caption to the \c \@attributes section.
deba@1024
  2004
    BpGraphWriter& attributes(const std::string& caption) {
deba@1024
  2005
      _attributes_caption = caption;
deba@1024
  2006
      return *this;
deba@1024
  2007
    }
deba@1024
  2008
deba@1024
  2009
    /// \name Skipping Section
deba@1024
  2010
    /// @{
deba@1024
  2011
deba@1024
  2012
    /// \brief Skip writing the node set
deba@1024
  2013
    ///
deba@1024
  2014
    /// The \c \@red_nodes and \c \@blue_nodes section will not be
deba@1024
  2015
    /// written to the stream.
deba@1024
  2016
    BpGraphWriter& skipNodes() {
deba@1024
  2017
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@1024
  2018
      _skip_nodes = true;
deba@1024
  2019
      return *this;
deba@1024
  2020
    }
deba@1024
  2021
deba@1024
  2022
    /// \brief Skip writing edge set
deba@1024
  2023
    ///
deba@1024
  2024
    /// The \c \@edges section will not be written to the stream.
deba@1024
  2025
    BpGraphWriter& skipEdges() {
deba@1024
  2026
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
deba@1024
  2027
      _skip_edges = true;
deba@1024
  2028
      return *this;
deba@1024
  2029
    }
deba@1024
  2030
deba@1024
  2031
    /// @}
deba@1024
  2032
deba@1024
  2033
  private:
deba@1024
  2034
deba@1024
  2035
    void writeRedNodes() {
deba@1024
  2036
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@1024
  2037
      for (typename NodeMaps::iterator it = _red_maps.begin();
deba@1024
  2038
           it != _red_maps.end(); ++it) {
deba@1024
  2039
        if (it->first == "label") {
deba@1024
  2040
          label = it->second;
deba@1024
  2041
          break;
deba@1024
  2042
        }
deba@1024
  2043
      }
deba@1024
  2044
deba@1024
  2045
      *_os << "@red_nodes";
deba@1024
  2046
      if (!_nodes_caption.empty()) {
deba@1024
  2047
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@1024
  2048
      }
deba@1024
  2049
      *_os << std::endl;
deba@1024
  2050
deba@1024
  2051
      if (label == 0) {
deba@1024
  2052
        *_os << "label" << '\t';
deba@1024
  2053
      }
deba@1024
  2054
      for (typename NodeMaps::iterator it = _red_maps.begin();
deba@1024
  2055
           it != _red_maps.end(); ++it) {
deba@1024
  2056
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@1024
  2057
      }
deba@1024
  2058
      *_os << std::endl;
deba@1024
  2059
deba@1024
  2060
      std::vector<Node> nodes;
deba@1026
  2061
      for (RedNodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2062
        nodes.push_back(n);
deba@1024
  2063
      }
deba@1024
  2064
deba@1024
  2065
      if (label == 0) {
deba@1024
  2066
        IdMap<BGR, Node> id_map(_graph);
deba@1024
  2067
        _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
deba@1024
  2068
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@1024
  2069
      } else {
deba@1024
  2070
        label->sort(nodes);
deba@1024
  2071
      }
deba@1024
  2072
deba@1024
  2073
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
deba@1024
  2074
        Node n = nodes[i];
deba@1024
  2075
        if (label == 0) {
deba@1024
  2076
          std::ostringstream os;
deba@1024
  2077
          os << _graph.id(n);
deba@1024
  2078
          _writer_bits::writeToken(*_os, os.str());
deba@1024
  2079
          *_os << '\t';
deba@1024
  2080
          _node_index.insert(std::make_pair(n, os.str()));
deba@1024
  2081
        }
deba@1024
  2082
        for (typename NodeMaps::iterator it = _red_maps.begin();
deba@1024
  2083
             it != _red_maps.end(); ++it) {
deba@1024
  2084
          std::string value = it->second->get(n);
deba@1024
  2085
          _writer_bits::writeToken(*_os, value);
deba@1024
  2086
          if (it->first == "label") {
deba@1024
  2087
            _node_index.insert(std::make_pair(n, value));
deba@1024
  2088
          }
deba@1024
  2089
          *_os << '\t';
deba@1024
  2090
        }
deba@1024
  2091
        *_os << std::endl;
deba@1024
  2092
      }
deba@1024
  2093
    }
deba@1024
  2094
deba@1024
  2095
    void writeBlueNodes() {
deba@1024
  2096
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@1024
  2097
      for (typename NodeMaps::iterator it = _blue_maps.begin();
deba@1024
  2098
           it != _blue_maps.end(); ++it) {
deba@1024
  2099
        if (it->first == "label") {
deba@1024
  2100
          label = it->second;
deba@1024
  2101
          break;
deba@1024
  2102
        }
deba@1024
  2103
      }
deba@1024
  2104
deba@1024
  2105
      *_os << "@blue_nodes";
deba@1024
  2106
      if (!_nodes_caption.empty()) {
deba@1024
  2107
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@1024
  2108
      }
deba@1024
  2109
      *_os << std::endl;
deba@1024
  2110
deba@1024
  2111
      if (label == 0) {
deba@1024
  2112
        *_os << "label" << '\t';
deba@1024
  2113
      }
deba@1024
  2114
      for (typename NodeMaps::iterator it = _blue_maps.begin();
deba@1024
  2115
           it != _blue_maps.end(); ++it) {
deba@1024
  2116
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@1024
  2117
      }
deba@1024
  2118
      *_os << std::endl;
deba@1024
  2119
deba@1024
  2120
      std::vector<Node> nodes;
deba@1026
  2121
      for (BlueNodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2122
        nodes.push_back(n);
deba@1024
  2123
      }
deba@1024
  2124
deba@1024
  2125
      if (label == 0) {
deba@1024
  2126
        IdMap<BGR, Node> id_map(_graph);
deba@1024
  2127
        _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
deba@1024
  2128
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@1024
  2129
      } else {
deba@1024
  2130
        label->sort(nodes);
deba@1024
  2131
      }
deba@1024
  2132
deba@1024
  2133
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
deba@1024
  2134
        Node n = nodes[i];
deba@1024
  2135
        if (label == 0) {
deba@1024
  2136
          std::ostringstream os;
deba@1024
  2137
          os << _graph.id(n);
deba@1024
  2138
          _writer_bits::writeToken(*_os, os.str());
deba@1024
  2139
          *_os << '\t';
deba@1024
  2140
          _node_index.insert(std::make_pair(n, os.str()));
deba@1024
  2141
        }
deba@1024
  2142
        for (typename NodeMaps::iterator it = _blue_maps.begin();
deba@1024
  2143
             it != _blue_maps.end(); ++it) {
deba@1024
  2144
          std::string value = it->second->get(n);
deba@1024
  2145
          _writer_bits::writeToken(*_os, value);
deba@1024
  2146
          if (it->first == "label") {
deba@1024
  2147
            _node_index.insert(std::make_pair(n, value));
deba@1024
  2148
          }
deba@1024
  2149
          *_os << '\t';
deba@1024
  2150
        }
deba@1024
  2151
        *_os << std::endl;
deba@1024
  2152
      }
deba@1024
  2153
    }
deba@1024
  2154
deba@1024
  2155
    void createRedNodeIndex() {
deba@1024
  2156
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@1024
  2157
      for (typename NodeMaps::iterator it = _red_maps.begin();
deba@1024
  2158
           it != _red_maps.end(); ++it) {
deba@1024
  2159
        if (it->first == "label") {
deba@1024
  2160
          label = it->second;
deba@1024
  2161
          break;
deba@1024
  2162
        }
deba@1024
  2163
      }
deba@1024
  2164
deba@1024
  2165
      if (label == 0) {
deba@1024
  2166
        for (NodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2167
          std::ostringstream os;
deba@1024
  2168
          os << _graph.id(n);
deba@1024
  2169
          _node_index.insert(std::make_pair(n, os.str()));
deba@1024
  2170
        }
deba@1024
  2171
      } else {
deba@1024
  2172
        for (NodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2173
          std::string value = label->get(n);
deba@1024
  2174
          _node_index.insert(std::make_pair(n, value));
deba@1024
  2175
        }
deba@1024
  2176
      }
deba@1024
  2177
    }
deba@1024
  2178
deba@1024
  2179
    void createBlueNodeIndex() {
deba@1024
  2180
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@1024
  2181
      for (typename NodeMaps::iterator it = _blue_maps.begin();
deba@1024
  2182
           it != _blue_maps.end(); ++it) {
deba@1024
  2183
        if (it->first == "label") {
deba@1024
  2184
          label = it->second;
deba@1024
  2185
          break;
deba@1024
  2186
        }
deba@1024
  2187
      }
deba@1024
  2188
deba@1024
  2189
      if (label == 0) {
deba@1024
  2190
        for (NodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2191
          std::ostringstream os;
deba@1024
  2192
          os << _graph.id(n);
deba@1024
  2193
          _node_index.insert(std::make_pair(n, os.str()));
deba@1024
  2194
        }
deba@1024
  2195
      } else {
deba@1024
  2196
        for (NodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2197
          std::string value = label->get(n);
deba@1024
  2198
          _node_index.insert(std::make_pair(n, value));
deba@1024
  2199
        }
deba@1024
  2200
      }
deba@1024
  2201
    }
deba@1024
  2202
deba@1024
  2203
    void writeEdges() {
deba@1024
  2204
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@1024
  2205
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  2206
           it != _edge_maps.end(); ++it) {
deba@1024
  2207
        if (it->first == "label") {
deba@1024
  2208
          label = it->second;
deba@1024
  2209
          break;
deba@1024
  2210
        }
deba@1024
  2211
      }
deba@1024
  2212
deba@1024
  2213
      *_os << "@edges";
deba@1024
  2214
      if (!_edges_caption.empty()) {
deba@1024
  2215
        _writer_bits::writeToken(*_os << ' ', _edges_caption);
deba@1024
  2216
      }
deba@1024
  2217
      *_os << std::endl;
deba@1024
  2218
deba@1024
  2219
      *_os << '\t' << '\t';
deba@1024
  2220
      if (label == 0) {
deba@1024
  2221
        *_os << "label" << '\t';
deba@1024
  2222
      }
deba@1024
  2223
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  2224
           it != _edge_maps.end(); ++it) {
deba@1024
  2225
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@1024
  2226
      }
deba@1024
  2227
      *_os << std::endl;
deba@1024
  2228
deba@1024
  2229
      std::vector<Edge> edges;
deba@1024
  2230
      for (EdgeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2231
        edges.push_back(n);
deba@1024
  2232
      }
deba@1024
  2233
deba@1024
  2234
      if (label == 0) {
deba@1024
  2235
        IdMap<BGR, Edge> id_map(_graph);
deba@1024
  2236
        _writer_bits::MapLess<IdMap<BGR, Edge> > id_less(id_map);
deba@1024
  2237
        std::sort(edges.begin(), edges.end(), id_less);
deba@1024
  2238
      } else {
deba@1024
  2239
        label->sort(edges);
deba@1024
  2240
      }
deba@1024
  2241
deba@1024
  2242
      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
deba@1024
  2243
        Edge e = edges[i];
deba@1024
  2244
        _writer_bits::writeToken(*_os, _node_index.
deba@1024
  2245
                                 find(_graph.redNode(e))->second);
deba@1024
  2246
        *_os << '\t';
deba@1024
  2247
        _writer_bits::writeToken(*_os, _node_index.
deba@1024
  2248
                                 find(_graph.blueNode(e))->second);
deba@1024
  2249
        *_os << '\t';
deba@1024
  2250
        if (label == 0) {
deba@1024
  2251
          std::ostringstream os;
deba@1024
  2252
          os << _graph.id(e);
deba@1024
  2253
          _writer_bits::writeToken(*_os, os.str());
deba@1024
  2254
          *_os << '\t';
deba@1024
  2255
          _edge_index.insert(std::make_pair(e, os.str()));
deba@1024
  2256
        }
deba@1024
  2257
        for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  2258
             it != _edge_maps.end(); ++it) {
deba@1024
  2259
          std::string value = it->second->get(e);
deba@1024
  2260
          _writer_bits::writeToken(*_os, value);
deba@1024
  2261
          if (it->first == "label") {
deba@1024
  2262
            _edge_index.insert(std::make_pair(e, value));
deba@1024
  2263
          }
deba@1024
  2264
          *_os << '\t';
deba@1024
  2265
        }
deba@1024
  2266
        *_os << std::endl;
deba@1024
  2267
      }
deba@1024
  2268
    }
deba@1024
  2269
deba@1024
  2270
    void createEdgeIndex() {
deba@1024
  2271
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@1024
  2272
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  2273
           it != _edge_maps.end(); ++it) {
deba@1024
  2274
        if (it->first == "label") {
deba@1024
  2275
          label = it->second;
deba@1024
  2276
          break;
deba@1024
  2277
        }
deba@1024
  2278
      }
deba@1024
  2279
deba@1024
  2280
      if (label == 0) {
deba@1024
  2281
        for (EdgeIt e(_graph); e != INVALID; ++e) {
deba@1024
  2282
          std::ostringstream os;
deba@1024
  2283
          os << _graph.id(e);
deba@1024
  2284
          _edge_index.insert(std::make_pair(e, os.str()));
deba@1024
  2285
        }
deba@1024
  2286
      } else {
deba@1024
  2287
        for (EdgeIt e(_graph); e != INVALID; ++e) {
deba@1024
  2288
          std::string value = label->get(e);
deba@1024
  2289
          _edge_index.insert(std::make_pair(e, value));
deba@1024
  2290
        }
deba@1024
  2291
      }
deba@1024
  2292
    }
deba@1024
  2293
deba@1024
  2294
    void writeAttributes() {
deba@1024
  2295
      if (_attributes.empty()) return;
deba@1024
  2296
      *_os << "@attributes";
deba@1024
  2297
      if (!_attributes_caption.empty()) {
deba@1024
  2298
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@1024
  2299
      }
deba@1024
  2300
      *_os << std::endl;
deba@1024
  2301
      for (typename Attributes::iterator it = _attributes.begin();
deba@1024
  2302
           it != _attributes.end(); ++it) {
deba@1024
  2303
        _writer_bits::writeToken(*_os, it->first) << ' ';
deba@1024
  2304
        _writer_bits::writeToken(*_os, it->second->get());
deba@1024
  2305
        *_os << std::endl;
deba@1024
  2306
      }
deba@1024
  2307
    }
deba@1024
  2308
deba@1024
  2309
  public:
deba@1024
  2310
deba@1024
  2311
    /// \name Execution of the Writer
deba@1024
  2312
    /// @{
deba@1024
  2313
deba@1024
  2314
    /// \brief Start the batch processing
deba@1024
  2315
    ///
deba@1024
  2316
    /// This function starts the batch processing.
deba@1024
  2317
    void run() {
deba@1024
  2318
      if (!_skip_nodes) {
deba@1024
  2319
        writeRedNodes();
deba@1024
  2320
        writeBlueNodes();
deba@1024
  2321
      } else {
deba@1024
  2322
        createRedNodeIndex();
deba@1024
  2323
        createBlueNodeIndex();
deba@1024
  2324
      }
deba@1024
  2325
      if (!_skip_edges) {
deba@1024
  2326
        writeEdges();
deba@1024
  2327
      } else {
deba@1024
  2328
        createEdgeIndex();
deba@1024
  2329
      }
deba@1024
  2330
      writeAttributes();
deba@1024
  2331
    }
deba@1024
  2332
deba@1024
  2333
    /// \brief Give back the stream of the writer
deba@1024
  2334
    ///
deba@1024
  2335
    /// Give back the stream of the writer
deba@1024
  2336
    std::ostream& ostream() {
deba@1024
  2337
      return *_os;
deba@1024
  2338
    }
deba@1024
  2339
deba@1024
  2340
    /// @}
deba@1024
  2341
  };
deba@1024
  2342
deba@1024
  2343
  /// \ingroup lemon_io
deba@1024
  2344
  ///
deba@1024
  2345
  /// \brief Return a \ref BpGraphWriter class
deba@1024
  2346
  ///
deba@1024
  2347
  /// This function just returns a \ref BpGraphWriter class.
deba@1024
  2348
  ///
deba@1024
  2349
  /// With this function a bipartite graph can be write to a file or output
deba@1024
  2350
  /// stream in \ref lgf-format "LGF" format with several maps and
deba@1024
  2351
  /// attributes. For example, with the following code a bipartite
deba@1024
  2352
  /// weighted matching problem can be written to the standard output,
deba@1024
  2353
  /// i.e. a graph with a \e weight map on the edges:
deba@1024
  2354
  ///
deba@1024
  2355
  ///\code
deba@1024
  2356
  ///ListBpGraph graph;
deba@1024
  2357
  ///ListBpGraph::EdgeMap<int> weight(graph);
deba@1024
  2358
  ///  // Setting the weight map
deba@1024
  2359
  ///bpGraphWriter(graph, std::cout).
deba@1024
  2360
  ///  edgeMap("weight", weight).
deba@1024
  2361
  ///  run();
deba@1024
  2362
  ///\endcode
deba@1024
  2363
  ///
deba@1024
  2364
  /// For a complete documentation, please see the \ref BpGraphWriter
deba@1024
  2365
  /// class documentation.
deba@1024
  2366
  /// \warning Don't forget to put the \ref BpGraphWriter::run() "run()"
deba@1024
  2367
  /// to the end of the parameter list.
deba@1024
  2368
  /// \relates BpGraphWriter
deba@1024
  2369
  /// \sa bpGraphWriter(const TBGR& graph, const std::string& fn)
deba@1024
  2370
  /// \sa bpGraphWriter(const TBGR& graph, const char* fn)
deba@1024
  2371
  template <typename TBGR>
deba@1024
  2372
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, std::ostream& os) {
deba@1024
  2373
    BpGraphWriter<TBGR> tmp(graph, os);
deba@1024
  2374
    return tmp;
deba@1024
  2375
  }
deba@1024
  2376
deba@1024
  2377
  /// \brief Return a \ref BpGraphWriter class
deba@1024
  2378
  ///
deba@1024
  2379
  /// This function just returns a \ref BpGraphWriter class.
deba@1024
  2380
  /// \relates BpGraphWriter
deba@1024
  2381
  /// \sa graphWriter(const TBGR& graph, std::ostream& os)
deba@1024
  2382
  template <typename TBGR>
deba@1024
  2383
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn) {
deba@1024
  2384
    BpGraphWriter<TBGR> tmp(graph, fn);
deba@1024
  2385
    return tmp;
deba@1024
  2386
  }
deba@1024
  2387
deba@1024
  2388
  /// \brief Return a \ref BpGraphWriter class
deba@1024
  2389
  ///
deba@1024
  2390
  /// This function just returns a \ref BpGraphWriter class.
deba@1024
  2391
  /// \relates BpGraphWriter
deba@1024
  2392
  /// \sa graphWriter(const TBGR& graph, std::ostream& os)
deba@1024
  2393
  template <typename TBGR>
deba@1024
  2394
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn) {
deba@1024
  2395
    BpGraphWriter<TBGR> tmp(graph, fn);
deba@1024
  2396
    return tmp;
deba@1024
  2397
  }
deba@1024
  2398
deba@248
  2399
  class SectionWriter;
deba@248
  2400
deba@248
  2401
  SectionWriter sectionWriter(std::istream& is);
deba@248
  2402
  SectionWriter sectionWriter(const std::string& fn);
deba@248
  2403
  SectionWriter sectionWriter(const char* fn);
deba@248
  2404
deba@248
  2405
  /// \ingroup lemon_io
deba@248
  2406
  ///
deba@248
  2407
  /// \brief Section writer class
deba@248
  2408
  ///
deba@248
  2409
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
deba@248
  2410
  /// which contain any data in arbitrary format. Such sections can be
deba@248
  2411
  /// written with this class. A writing rule can be added to the
deba@248
  2412
  /// class with two different functions. With the \c sectionLines()
deba@248
  2413
  /// function a generator can write the section line-by-line, while
deba@248
  2414
  /// with the \c sectionStream() member the section can be written to
deba@248
  2415
  /// an output stream.
deba@248
  2416
  class SectionWriter {
deba@248
  2417
  private:
deba@248
  2418
deba@248
  2419
    std::ostream* _os;
deba@248
  2420
    bool local_os;
deba@248
  2421
deba@248
  2422
    typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
deba@248
  2423
    Sections;
deba@248
  2424
deba@248
  2425
    Sections _sections;
deba@248
  2426
deba@248
  2427
  public:
deba@248
  2428
deba@248
  2429
    /// \brief Constructor
deba@248
  2430
    ///
deba@248
  2431
    /// Construct a section writer, which writes to the given output
deba@248
  2432
    /// stream.
deba@248
  2433
    SectionWriter(std::ostream& os)
deba@248
  2434
      : _os(&os), local_os(false) {}
deba@248
  2435
deba@248
  2436
    /// \brief Constructor
deba@248
  2437
    ///
deba@248
  2438
    /// Construct a section writer, which writes into the given file.
deba@248
  2439
    SectionWriter(const std::string& fn)
deba@290
  2440
      : _os(new std::ofstream(fn.c_str())), local_os(true) {
deba@295
  2441
      if (!(*_os)) {
deba@295
  2442
        delete _os;
deba@295
  2443
        throw IoError("Cannot write file", fn);
deba@295
  2444
      }
deba@290
  2445
    }
deba@248
  2446
deba@248
  2447
    /// \brief Constructor
deba@248
  2448
    ///
deba@248
  2449
    /// Construct a section writer, which writes into the given file.
deba@248
  2450
    SectionWriter(const char* fn)
deba@290
  2451
      : _os(new std::ofstream(fn)), local_os(true) {
deba@295
  2452
      if (!(*_os)) {
deba@295
  2453
        delete _os;
deba@295
  2454
        throw IoError("Cannot write file", fn);
deba@295
  2455
      }
deba@290
  2456
    }
deba@248
  2457
deba@248
  2458
    /// \brief Destructor
deba@248
  2459
    ~SectionWriter() {
deba@248
  2460
      for (Sections::iterator it = _sections.begin();
deba@248
  2461
           it != _sections.end(); ++it) {
deba@248
  2462
        delete it->second;
deba@248
  2463
      }
deba@248
  2464
deba@248
  2465
      if (local_os) {
deba@248
  2466
        delete _os;
deba@248
  2467
      }
deba@248
  2468
deba@248
  2469
    }
deba@248
  2470
deba@248
  2471
  private:
deba@248
  2472
deba@248
  2473
    friend SectionWriter sectionWriter(std::ostream& os);
deba@248
  2474
    friend SectionWriter sectionWriter(const std::string& fn);
deba@248
  2475
    friend SectionWriter sectionWriter(const char* fn);
deba@248
  2476
deba@248
  2477
    SectionWriter(SectionWriter& other)
deba@248
  2478
      : _os(other._os), local_os(other.local_os) {
deba@248
  2479
deba@248
  2480
      other._os = 0;
deba@248
  2481
      other.local_os = false;
deba@248
  2482
deba@248
  2483
      _sections.swap(other._sections);
deba@248
  2484
    }
deba@248
  2485
deba@248
  2486
    SectionWriter& operator=(const SectionWriter&);
deba@248
  2487
deba@248
  2488
  public:
deba@248
  2489
kpeter@584
  2490
    /// \name Section Writers
deba@248
  2491
    /// @{
deba@248
  2492
deba@248
  2493
    /// \brief Add a section writer with line oriented writing
deba@248
  2494
    ///
deba@248
  2495
    /// The first parameter is the type descriptor of the section, the
deba@248
  2496
    /// second is a generator with std::string values. At the writing
deba@248
  2497
    /// process, the returned \c std::string will be written into the
deba@248
  2498
    /// output file until it is an empty string.
deba@248
  2499
    ///
deba@248
  2500
    /// For example, an integer vector is written into a section.
deba@248
  2501
    ///\code
deba@248
  2502
    ///  @numbers
deba@248
  2503
    ///  12 45 23 78
deba@248
  2504
    ///  4 28 38 28
deba@248
  2505
    ///  23 6 16
deba@248
  2506
    ///\endcode
deba@248
  2507
    ///
deba@248
  2508
    /// The generator is implemented as a struct.
deba@248
  2509
    ///\code
deba@248
  2510
    ///  struct NumberSection {
deba@248
  2511
    ///    std::vector<int>::const_iterator _it, _end;
deba@248
  2512
    ///    NumberSection(const std::vector<int>& data)
deba@248
  2513
    ///      : _it(data.begin()), _end(data.end()) {}
deba@248
  2514
    ///    std::string operator()() {
deba@248
  2515
    ///      int rem_in_line = 4;
deba@248
  2516
    ///      std::ostringstream ls;
deba@248
  2517
    ///      while (rem_in_line > 0 && _it != _end) {
deba@248
  2518
    ///        ls << *(_it++) << ' ';
deba@248
  2519
    ///        --rem_in_line;
deba@248
  2520
    ///      }
deba@248
  2521
    ///      return ls.str();
deba@248
  2522
    ///    }
deba@248
  2523
    ///  };
deba@248
  2524
    ///
deba@248
  2525
    ///  // ...
deba@248
  2526
    ///
deba@248
  2527
    ///  writer.sectionLines("numbers", NumberSection(vec));
deba@248
  2528
    ///\endcode
deba@248
  2529
    template <typename Functor>
deba@248
  2530
    SectionWriter& sectionLines(const std::string& type, Functor functor) {
deba@248
  2531
      LEMON_ASSERT(!type.empty(), "Type is empty.");
deba@248
  2532
      _sections.push_back(std::make_pair(type,
deba@248
  2533
        new _writer_bits::LineSection<Functor>(functor)));
deba@248
  2534
      return *this;
deba@248
  2535
    }
deba@248
  2536
deba@248
  2537
deba@248
  2538
    /// \brief Add a section writer with stream oriented writing
deba@248
  2539
    ///
deba@248
  2540
    /// The first parameter is the type of the section, the second is
deba@248
  2541
    /// a functor, which takes a \c std::ostream& parameter. The
deba@248
  2542
    /// functor writes the section to the output stream.
deba@248
  2543
    /// \warning The last line must be closed with end-line character.
deba@248
  2544
    template <typename Functor>
deba@248
  2545
    SectionWriter& sectionStream(const std::string& type, Functor functor) {
deba@248
  2546
      LEMON_ASSERT(!type.empty(), "Type is empty.");
deba@248
  2547
      _sections.push_back(std::make_pair(type,
deba@248
  2548
         new _writer_bits::StreamSection<Functor>(functor)));
deba@248
  2549
      return *this;
deba@248
  2550
    }
deba@248
  2551
deba@248
  2552
    /// @}
deba@248
  2553
deba@248
  2554
  public:
deba@248
  2555
deba@248
  2556
kpeter@584
  2557
    /// \name Execution of the Writer
deba@248
  2558
    /// @{
deba@248
  2559
deba@248
  2560
    /// \brief Start the batch processing
deba@248
  2561
    ///
deba@248
  2562
    /// This function starts the batch processing.
deba@248
  2563
    void run() {
deba@248
  2564
deba@248
  2565
      LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
deba@248
  2566
deba@248
  2567
      for (Sections::iterator it = _sections.begin();
deba@248
  2568
           it != _sections.end(); ++it) {
deba@248
  2569
        (*_os) << '@' << it->first << std::endl;
deba@248
  2570
        it->second->process(*_os);
deba@248
  2571
      }
deba@248
  2572
    }
deba@248
  2573
deba@248
  2574
    /// \brief Give back the stream of the writer
deba@248
  2575
    ///
deba@248
  2576
    /// Returns the stream of the writer
deba@248
  2577
    std::ostream& ostream() {
deba@248
  2578
      return *_os;
deba@248
  2579
    }
deba@248
  2580
deba@248
  2581
    /// @}
deba@248
  2582
deba@248
  2583
  };
deba@248
  2584
deba@598
  2585
  /// \ingroup lemon_io
deba@598
  2586
  ///
deba@248
  2587
  /// \brief Return a \ref SectionWriter class
deba@248
  2588
  ///
deba@248
  2589
  /// This function just returns a \ref SectionWriter class.
deba@598
  2590
  ///
deba@598
  2591
  /// Please see SectionWriter documentation about the custom section
deba@598
  2592
  /// output.
deba@598
  2593
  ///
deba@248
  2594
  /// \relates SectionWriter
deba@598
  2595
  /// \sa sectionWriter(const std::string& fn)
deba@598
  2596
  /// \sa sectionWriter(const char *fn)
deba@248
  2597
  inline SectionWriter sectionWriter(std::ostream& os) {
deba@248
  2598
    SectionWriter tmp(os);
deba@248
  2599
    return tmp;
deba@248
  2600
  }
deba@248
  2601
deba@248
  2602
  /// \brief Return a \ref SectionWriter class
deba@248
  2603
  ///
deba@248
  2604
  /// This function just returns a \ref SectionWriter class.
deba@248
  2605
  /// \relates SectionWriter
deba@598
  2606
  /// \sa sectionWriter(std::ostream& os)
deba@248
  2607
  inline SectionWriter sectionWriter(const std::string& fn) {
deba@248
  2608
    SectionWriter tmp(fn);
deba@248
  2609
    return tmp;
deba@248
  2610
  }
deba@248
  2611
deba@248
  2612
  /// \brief Return a \ref SectionWriter class
deba@248
  2613
  ///
deba@248
  2614
  /// This function just returns a \ref SectionWriter class.
deba@248
  2615
  /// \relates SectionWriter
deba@598
  2616
  /// \sa sectionWriter(std::ostream& os)
deba@248
  2617
  inline SectionWriter sectionWriter(const char* fn) {
deba@248
  2618
    SectionWriter tmp(fn);
deba@248
  2619
    return tmp;
deba@248
  2620
  }
deba@127
  2621
}
deba@127
  2622
deba@127
  2623
#endif