lemon/lgf_writer.h
author Balazs Dezso <deba@inf.elte.hu>
Fri, 04 Jul 2008 15:21:48 +0200
changeset 189 a63ed81c57ba
parent 165 b4c336c27a03
child 190 1e6af6f0843c
permissions -rw-r--r--
Section readers moved to distinct class
deba@127
     1
/* -*- C++ -*-
deba@127
     2
 *
deba@127
     3
 * This file is a part of LEMON, a generic C++ optimization library
deba@127
     4
 *
deba@127
     5
 * Copyright (C) 2003-2008
deba@127
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@127
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@127
     8
 *
deba@127
     9
 * Permission to use, modify and distribute this software is granted
deba@127
    10
 * provided that this copyright notice appears in all copies. For
deba@127
    11
 * precise terms see the accompanying LICENSE file.
deba@127
    12
 *
deba@127
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@127
    14
 * express or implied, and with no claim as to its suitability for any
deba@127
    15
 * purpose.
deba@127
    16
 *
deba@127
    17
 */
deba@127
    18
deba@127
    19
///\ingroup lemon_io
deba@127
    20
///\file
deba@127
    21
///\brief 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@127
    36
#include <lemon/assert.h>
deba@127
    37
#include <lemon/graph_utils.h>
deba@127
    38
deba@127
    39
namespace lemon {
deba@127
    40
deba@127
    41
  namespace _writer_bits {
deba@127
    42
deba@127
    43
    template <typename Value>
deba@127
    44
    struct DefaultConverter {
deba@127
    45
      std::string operator()(const Value& value) {
deba@127
    46
	std::ostringstream os;
deba@127
    47
	os << value;
deba@127
    48
	return os.str();
deba@127
    49
      }
deba@127
    50
    };
deba@127
    51
deba@127
    52
    template <typename T>
deba@127
    53
    bool operator<(const T&, const T&) {
deba@127
    54
      throw DataFormatError("Label map is not comparable");
deba@127
    55
    }
deba@127
    56
deba@127
    57
    template <typename _Map>
deba@127
    58
    class MapLess {
deba@127
    59
    public:
deba@127
    60
      typedef _Map Map;
deba@127
    61
      typedef typename Map::Key Item;
deba@127
    62
deba@127
    63
    private:
deba@127
    64
      const Map& _map;
deba@127
    65
      
deba@127
    66
    public:
deba@127
    67
      MapLess(const Map& map) : _map(map) {}
deba@127
    68
deba@127
    69
      bool operator()(const Item& left, const Item& right) {
deba@127
    70
	return _map[left] < _map[right];
deba@127
    71
      }
deba@127
    72
    };
deba@127
    73
deba@165
    74
    template <typename _Graph, bool _dir, typename _Map>
deba@165
    75
    class GraphArcMapLess {
deba@165
    76
    public:
deba@165
    77
      typedef _Map Map;
deba@165
    78
      typedef _Graph Graph;
deba@165
    79
      typedef typename Graph::Edge Item;
deba@165
    80
deba@165
    81
    private:
deba@165
    82
      const Graph& _graph;
deba@165
    83
      const Map& _map;
deba@165
    84
      
deba@165
    85
    public:
deba@165
    86
      GraphArcMapLess(const Graph& graph, const Map& map) 
deba@165
    87
	: _graph(graph), _map(map) {}
deba@165
    88
deba@165
    89
      bool operator()(const Item& left, const Item& right) {
deba@165
    90
	return _map[_graph.direct(left, _dir)] < 
deba@165
    91
	  _map[_graph.direct(right, _dir)];
deba@165
    92
      }
deba@165
    93
    };
deba@165
    94
deba@127
    95
    template <typename _Item>    
deba@127
    96
    class MapStorageBase {
deba@127
    97
    public:
deba@127
    98
      typedef _Item Item;
deba@127
    99
deba@127
   100
    public:
deba@127
   101
      MapStorageBase() {}
deba@127
   102
      virtual ~MapStorageBase() {}
deba@127
   103
deba@127
   104
      virtual std::string get(const Item& item) = 0;
deba@127
   105
      virtual void sort(std::vector<Item>&) = 0;
deba@127
   106
    };
deba@127
   107
deba@127
   108
    template <typename _Item, typename _Map, 
deba@127
   109
	      typename _Converter = DefaultConverter<typename _Map::Value> >
deba@127
   110
    class MapStorage : public MapStorageBase<_Item> {
deba@127
   111
    public:
deba@127
   112
      typedef _Map Map;
deba@127
   113
      typedef _Converter Converter;
deba@127
   114
      typedef _Item Item;
deba@127
   115
      
deba@127
   116
    private:
deba@127
   117
      const Map& _map;
deba@127
   118
      Converter _converter;
deba@127
   119
deba@127
   120
    public:
deba@127
   121
      MapStorage(const Map& map, const Converter& converter = Converter()) 
deba@127
   122
	: _map(map), _converter(converter) {}
deba@127
   123
      virtual ~MapStorage() {}
deba@127
   124
deba@127
   125
      virtual std::string get(const Item& item) {
deba@127
   126
	return _converter(_map[item]);
deba@127
   127
      }
deba@127
   128
      virtual void sort(std::vector<Item>& items) {
deba@127
   129
	MapLess<Map> less(_map);
deba@127
   130
	std::sort(items.begin(), items.end(), less);
deba@127
   131
      }
deba@127
   132
    };
deba@127
   133
deba@165
   134
    template <typename _Graph, bool _dir, typename _Map, 
deba@165
   135
	      typename _Converter = DefaultConverter<typename _Map::Value> >
deba@165
   136
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
deba@165
   137
    public:
deba@165
   138
      typedef _Map Map;
deba@165
   139
      typedef _Converter Converter;
deba@165
   140
      typedef _Graph Graph;
deba@165
   141
      typedef typename Graph::Edge Item;
deba@165
   142
      static const bool dir = _dir;
deba@165
   143
      
deba@165
   144
    private:
deba@165
   145
      const Graph& _graph;
deba@165
   146
      const Map& _map;
deba@165
   147
      Converter _converter;
deba@165
   148
deba@165
   149
    public:
deba@165
   150
      GraphArcMapStorage(const Graph& graph, const Map& map,  
deba@165
   151
			 const Converter& converter = Converter()) 
deba@165
   152
	: _graph(graph), _map(map), _converter(converter) {}
deba@165
   153
      virtual ~GraphArcMapStorage() {}
deba@165
   154
deba@165
   155
      virtual std::string get(const Item& item) {
deba@165
   156
	return _converter(_map[_graph.direct(item, dir)]);
deba@165
   157
      }
deba@165
   158
      virtual void sort(std::vector<Item>& items) {
deba@165
   159
	GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
deba@165
   160
	std::sort(items.begin(), items.end(), less);
deba@165
   161
      }
deba@165
   162
    };
deba@165
   163
deba@127
   164
    class ValueStorageBase {
deba@127
   165
    public:
deba@127
   166
      ValueStorageBase() {}
deba@127
   167
      virtual ~ValueStorageBase() {}
deba@127
   168
deba@127
   169
      virtual std::string get() = 0;      
deba@127
   170
    };
deba@127
   171
deba@127
   172
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
deba@127
   173
    class ValueStorage : public ValueStorageBase {
deba@127
   174
    public:
deba@127
   175
      typedef _Value Value;
deba@127
   176
      typedef _Converter Converter;
deba@127
   177
deba@127
   178
    private:
deba@127
   179
      const Value& _value;
deba@127
   180
      Converter _converter;
deba@127
   181
deba@127
   182
    public:
deba@127
   183
      ValueStorage(const Value& value, const Converter& converter = Converter())
deba@127
   184
 	: _value(value), _converter(converter) {}
deba@127
   185
deba@127
   186
      virtual std::string get() {
deba@127
   187
	return _converter(_value);
deba@127
   188
      }
deba@127
   189
    };
deba@127
   190
deba@127
   191
    template <typename Value>
deba@127
   192
    struct MapLookUpConverter {
deba@127
   193
      const std::map<Value, std::string>& _map;
deba@127
   194
      
deba@127
   195
      MapLookUpConverter(const std::map<Value, std::string>& map) 
deba@127
   196
	: _map(map) {}
deba@127
   197
      
deba@127
   198
      std::string operator()(const Value& str) {
deba@127
   199
	typename std::map<Value, std::string>::const_iterator it = 
deba@127
   200
	  _map.find(str);
deba@127
   201
	if (it == _map.end()) {
deba@127
   202
	  throw DataFormatError("Item not found");
deba@127
   203
	}
deba@127
   204
	return it->second;
deba@127
   205
      }
deba@127
   206
    };
deba@127
   207
deba@165
   208
    template <typename Graph>
deba@165
   209
    struct GraphArcLookUpConverter {
deba@165
   210
      const Graph& _graph;
deba@165
   211
      const std::map<typename Graph::Edge, std::string>& _map;
deba@165
   212
      
deba@165
   213
      GraphArcLookUpConverter(const Graph& graph, 
deba@165
   214
			      const std::map<typename Graph::Edge, 
deba@165
   215
			                     std::string>& map) 
deba@165
   216
	: _graph(graph), _map(map) {}
deba@165
   217
      
deba@165
   218
      std::string operator()(const typename Graph::Arc& val) {
deba@165
   219
	typename std::map<typename Graph::Edge, std::string>
deba@165
   220
	  ::const_iterator it = _map.find(val);
deba@165
   221
	if (it == _map.end()) {
deba@165
   222
	  throw DataFormatError("Item not found");
deba@165
   223
	}
deba@165
   224
	return (_graph.direction(val) ? '+' : '-') + it->second;
deba@165
   225
      }
deba@165
   226
    };
deba@165
   227
deba@127
   228
    bool isWhiteSpace(char c) {
deba@127
   229
      return c == ' ' || c == '\t' || c == '\v' || 
deba@127
   230
        c == '\n' || c == '\r' || c == '\f'; 
deba@127
   231
    }
deba@127
   232
deba@127
   233
    bool isEscaped(char c) {
deba@127
   234
      return c == '\\' || c == '\"' || c == '\'' || 
deba@127
   235
	c == '\a' || c == '\b';
deba@127
   236
    }
deba@127
   237
deba@127
   238
    static void writeEscape(std::ostream& os, char c) {
deba@127
   239
      switch (c) {
deba@127
   240
      case '\\':
deba@127
   241
	os << "\\\\";
deba@127
   242
	return;
deba@127
   243
      case '\"':
deba@127
   244
	os << "\\\"";
deba@127
   245
	return;
deba@127
   246
      case '\a':
deba@127
   247
	os << "\\a";
deba@127
   248
	return;
deba@127
   249
      case '\b':
deba@127
   250
	os << "\\b";
deba@127
   251
	return;
deba@127
   252
      case '\f':
deba@127
   253
	os << "\\f";
deba@127
   254
	return;
deba@127
   255
      case '\r':
deba@127
   256
	os << "\\r";
deba@127
   257
	return;
deba@127
   258
      case '\n':
deba@127
   259
	os << "\\n";
deba@127
   260
	return;
deba@127
   261
      case '\t':
deba@127
   262
	os << "\\t";
deba@127
   263
	return;
deba@127
   264
      case '\v':
deba@127
   265
	os << "\\v";
deba@127
   266
	return;
deba@127
   267
      default:
deba@127
   268
	if (c < 0x20) {
deba@163
   269
	  std::ios::fmtflags flags = os.flags();
deba@127
   270
	  os << '\\' << std::oct << static_cast<int>(c);
deba@163
   271
	  os.flags(flags);
deba@127
   272
	} else {
deba@127
   273
	  os << c;
deba@127
   274
	}
deba@127
   275
	return;
deba@127
   276
      }     
deba@127
   277
    }
deba@127
   278
deba@127
   279
    bool requireEscape(const std::string& str) {
alpar@156
   280
      if (str.empty() || str[0] == '@') return true;
deba@127
   281
      std::istringstream is(str);
deba@127
   282
      char c;
deba@127
   283
      while (is.get(c)) {
deba@127
   284
	if (isWhiteSpace(c) || isEscaped(c)) {
deba@127
   285
	  return true;
deba@127
   286
	}
deba@127
   287
      }
deba@127
   288
      return false;
deba@127
   289
    }
deba@127
   290
    
deba@127
   291
    std::ostream& writeToken(std::ostream& os, const std::string& str) {
deba@127
   292
deba@127
   293
      if (requireEscape(str)) {
deba@127
   294
	os << '\"';
deba@127
   295
	for (std::string::const_iterator it = str.begin(); 
deba@127
   296
	     it != str.end(); ++it) {
deba@127
   297
	  writeEscape(os, *it);
deba@127
   298
	}	
deba@127
   299
	os << '\"';
deba@127
   300
      } else {
deba@127
   301
	os << str;
deba@127
   302
      }
deba@127
   303
      return os;
deba@127
   304
    }
deba@127
   305
deba@127
   306
  }
deba@127
   307
  
alpar@156
   308
  /// \ingroup lemon_io
alpar@156
   309
  ///  
alpar@156
   310
  /// \brief LGF writer for directed graphs
alpar@156
   311
  ///
alpar@156
   312
  /// This utility writes an \ref lgf-format "LGF" file.
alpar@156
   313
  ///
alpar@156
   314
  /// The writing method does a batch processing. The user creates a
alpar@156
   315
  /// writer object, then various writing rules can be added to the
alpar@156
   316
  /// writer, and eventually the writing is executed with the \c run()
alpar@156
   317
  /// member function. A map writing rule can be added to the writer
alpar@156
   318
  /// with the \c nodeMap() or \c arcMap() members. An optional
deba@163
   319
  /// converter parameter can also be added as a standard functor
deba@163
   320
  /// converting from the value type of the map to std::string. If it
deba@163
   321
  /// is set, it will determine how the map's value type is written to
deba@163
   322
  /// the output stream. If the functor is not set, then a default
deba@163
   323
  /// conversion will be used. The \c attribute(), \c node() and \c
deba@163
   324
  /// arc() functions are used to add attribute writing rules.
alpar@156
   325
  ///
alpar@156
   326
  ///\code
alpar@156
   327
  ///     DigraphWriter<Digraph>(std::cout, digraph).
alpar@156
   328
  ///       nodeMap("coordinates", coord_map).
alpar@156
   329
  ///       nodeMap("size", size).
alpar@156
   330
  ///       nodeMap("title", title).
alpar@156
   331
  ///       arcMap("capacity", cap_map).
alpar@156
   332
  ///       node("source", src).
alpar@156
   333
  ///       node("target", trg).
alpar@156
   334
  ///       attribute("caption", caption).
alpar@156
   335
  ///       run();
alpar@156
   336
  ///\endcode
alpar@156
   337
  ///
alpar@156
   338
  ///
alpar@156
   339
  /// By default, the writer does not write additional captions to the
alpar@156
   340
  /// sections, but they can be give as an optional parameter of
alpar@156
   341
  /// the \c nodes(), \c arcs() or \c
alpar@156
   342
  /// attributes() functions.
alpar@156
   343
  ///
alpar@156
   344
  /// The \c skipNodes() and \c skipArcs() functions forbid the
deba@163
   345
  /// writing of the sections. If two arc sections should be written
deba@163
   346
  /// to the output, it can be done in two passes, the first pass
deba@163
   347
  /// writes the node section and the first arc section, then the
deba@163
   348
  /// second pass skips the node section and writes just the arc
deba@163
   349
  /// section to the stream. The output stream can be retrieved with
deba@163
   350
  /// the \c ostream() function, hence the second pass can append its
deba@163
   351
  /// output to the output of the first pass.
deba@127
   352
  template <typename _Digraph>
deba@127
   353
  class DigraphWriter {
deba@127
   354
  public:
deba@127
   355
deba@127
   356
    typedef _Digraph Digraph;
deba@148
   357
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
deba@127
   358
    
deba@127
   359
  private:
deba@127
   360
deba@127
   361
deba@127
   362
    std::ostream* _os;
deba@127
   363
    bool local_os;
deba@127
   364
deba@127
   365
    Digraph& _digraph;
deba@127
   366
deba@127
   367
    std::string _nodes_caption;
deba@127
   368
    std::string _arcs_caption;
deba@127
   369
    std::string _attributes_caption;
deba@127
   370
    
deba@127
   371
    typedef std::map<Node, std::string> NodeIndex;
deba@127
   372
    NodeIndex _node_index;
deba@127
   373
    typedef std::map<Arc, std::string> ArcIndex;
deba@127
   374
    ArcIndex _arc_index;
deba@127
   375
deba@127
   376
    typedef std::vector<std::pair<std::string, 
deba@127
   377
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;    
deba@127
   378
    NodeMaps _node_maps; 
deba@127
   379
deba@127
   380
    typedef std::vector<std::pair<std::string, 
deba@127
   381
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
deba@127
   382
    ArcMaps _arc_maps;
deba@127
   383
deba@127
   384
    typedef std::vector<std::pair<std::string, 
deba@127
   385
      _writer_bits::ValueStorageBase*> > Attributes;
deba@127
   386
    Attributes _attributes;
deba@127
   387
deba@127
   388
    bool _skip_nodes;
deba@127
   389
    bool _skip_arcs;
deba@127
   390
deba@127
   391
  public:
deba@127
   392
alpar@156
   393
    /// \brief Constructor
alpar@156
   394
    ///
alpar@156
   395
    /// Construct a directed graph writer, which writes to the given
alpar@156
   396
    /// output stream.
deba@127
   397
    DigraphWriter(std::ostream& is, Digraph& digraph) 
deba@127
   398
      : _os(&is), local_os(false), _digraph(digraph),
deba@127
   399
	_skip_nodes(false), _skip_arcs(false) {}
deba@127
   400
alpar@156
   401
    /// \brief Constructor
alpar@156
   402
    ///
alpar@156
   403
    /// Construct a directed graph writer, which writes to the given
alpar@156
   404
    /// output file.
deba@127
   405
    DigraphWriter(const std::string& fn, Digraph& digraph) 
deba@127
   406
      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
deba@127
   407
	_skip_nodes(false), _skip_arcs(false) {}
deba@127
   408
alpar@156
   409
    /// \brief Constructor
alpar@156
   410
    ///
alpar@156
   411
    /// Construct a directed graph writer, which writes to the given
alpar@156
   412
    /// output file.
deba@127
   413
    DigraphWriter(const char* fn, Digraph& digraph) 
deba@127
   414
      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
deba@127
   415
	_skip_nodes(false), _skip_arcs(false) {}
deba@127
   416
alpar@156
   417
    /// \brief Copy constructor
alpar@156
   418
    ///
alpar@156
   419
    /// The copy constructor transfers all data from the other writer,
alpar@156
   420
    /// therefore the copied writer will not be usable more. 
deba@127
   421
    DigraphWriter(DigraphWriter& other) 
deba@127
   422
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
deba@127
   423
	_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
deba@127
   424
deba@163
   425
      other._os = 0;
deba@127
   426
      other.local_os = false;
deba@127
   427
deba@127
   428
      _node_index.swap(other._node_index);
deba@127
   429
      _arc_index.swap(other._arc_index);
deba@127
   430
deba@127
   431
      _node_maps.swap(other._node_maps);
deba@127
   432
      _arc_maps.swap(other._arc_maps);
deba@127
   433
      _attributes.swap(other._attributes);
deba@127
   434
deba@127
   435
      _nodes_caption = other._nodes_caption;
deba@127
   436
      _arcs_caption = other._arcs_caption;
deba@127
   437
      _attributes_caption = other._attributes_caption;
deba@127
   438
    }
deba@127
   439
alpar@156
   440
    /// \brief Destructor
deba@127
   441
    ~DigraphWriter() {
deba@127
   442
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
deba@127
   443
	   it != _node_maps.end(); ++it) {
deba@127
   444
	delete it->second;
deba@127
   445
      }
deba@127
   446
deba@127
   447
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
deba@127
   448
	   it != _arc_maps.end(); ++it) {
deba@127
   449
	delete it->second;
deba@127
   450
      }
deba@127
   451
deba@127
   452
      for (typename Attributes::iterator it = _attributes.begin(); 
deba@127
   453
	   it != _attributes.end(); ++it) {
deba@127
   454
	delete it->second;
deba@127
   455
      }
deba@127
   456
deba@127
   457
      if (local_os) {
deba@127
   458
	delete _os;
deba@127
   459
      }
deba@127
   460
    }
deba@127
   461
deba@127
   462
  private:
deba@127
   463
    
deba@127
   464
    DigraphWriter& operator=(const DigraphWriter&);
deba@127
   465
deba@127
   466
  public:
deba@127
   467
alpar@156
   468
    /// \name Writing rules
alpar@156
   469
    /// @{
alpar@156
   470
    
alpar@156
   471
    /// \brief Node map reading rule
alpar@156
   472
    ///
alpar@156
   473
    /// Add a node map reading rule to the writer.
deba@127
   474
    template <typename Map>
deba@127
   475
    DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@127
   476
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@127
   477
      _writer_bits::MapStorageBase<Node>* storage = 
deba@127
   478
	new _writer_bits::MapStorage<Node, Map>(map);
deba@127
   479
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   480
      return *this;
deba@127
   481
    }
deba@127
   482
alpar@156
   483
    /// \brief Node map writing rule
alpar@156
   484
    ///
alpar@156
   485
    /// Add a node map writing rule with specialized converter to the
alpar@156
   486
    /// writer.
deba@127
   487
    template <typename Map, typename Converter>
deba@127
   488
    DigraphWriter& nodeMap(const std::string& caption, const Map& map, 
deba@127
   489
			   const Converter& converter = Converter()) {
deba@127
   490
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@127
   491
      _writer_bits::MapStorageBase<Node>* storage = 
deba@127
   492
	new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@127
   493
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   494
      return *this;
deba@127
   495
    }
deba@127
   496
alpar@156
   497
    /// \brief Arc map writing rule
alpar@156
   498
    ///
alpar@156
   499
    /// Add an arc map writing rule to the writer.
deba@127
   500
    template <typename Map>
deba@127
   501
    DigraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@127
   502
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@127
   503
      _writer_bits::MapStorageBase<Arc>* storage = 
deba@127
   504
	new _writer_bits::MapStorage<Arc, Map>(map);
deba@127
   505
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   506
      return *this;
deba@127
   507
    }
deba@127
   508
alpar@156
   509
    /// \brief Arc map writing rule
alpar@156
   510
    ///
alpar@156
   511
    /// Add an arc map writing rule with specialized converter to the
alpar@156
   512
    /// writer.
deba@127
   513
    template <typename Map, typename Converter>
deba@127
   514
    DigraphWriter& arcMap(const std::string& caption, const Map& map, 
deba@127
   515
			  const Converter& converter = Converter()) {
deba@127
   516
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@127
   517
      _writer_bits::MapStorageBase<Arc>* storage = 
deba@127
   518
	new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
deba@127
   519
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   520
      return *this;
deba@127
   521
    }
deba@127
   522
alpar@156
   523
    /// \brief Attribute writing rule
alpar@156
   524
    ///
alpar@156
   525
    /// Add an attribute writing rule to the writer.
deba@127
   526
    template <typename Value>
deba@127
   527
    DigraphWriter& attribute(const std::string& caption, const Value& value) {
deba@127
   528
      _writer_bits::ValueStorageBase* storage = 
deba@127
   529
	new _writer_bits::ValueStorage<Value>(value);
deba@127
   530
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   531
      return *this;
deba@127
   532
    }
deba@127
   533
alpar@156
   534
    /// \brief Attribute writing rule
alpar@156
   535
    ///
alpar@156
   536
    /// Add an attribute writing rule with specialized converter to the
alpar@156
   537
    /// writer.
deba@127
   538
    template <typename Value, typename Converter>
deba@127
   539
    DigraphWriter& attribute(const std::string& caption, const Value& value, 
deba@127
   540
			     const Converter& converter = Converter()) {
deba@127
   541
      _writer_bits::ValueStorageBase* storage = 
deba@127
   542
	new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@127
   543
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   544
      return *this;
deba@127
   545
    }
deba@127
   546
alpar@156
   547
    /// \brief Node writing rule
alpar@156
   548
    ///
alpar@156
   549
    /// Add a node writing rule to the writer.
deba@127
   550
    DigraphWriter& node(const std::string& caption, const Node& node) {
deba@127
   551
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@127
   552
      Converter converter(_node_index);
deba@127
   553
      _writer_bits::ValueStorageBase* storage = 
deba@127
   554
	new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@127
   555
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   556
      return *this;
deba@127
   557
    }
deba@127
   558
alpar@156
   559
    /// \brief Arc writing rule
alpar@156
   560
    ///
alpar@156
   561
    /// Add an arc writing rule to writer.
deba@127
   562
    DigraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@127
   563
      typedef _writer_bits::MapLookUpConverter<Arc> Converter;
deba@127
   564
      Converter converter(_arc_index);
deba@127
   565
      _writer_bits::ValueStorageBase* storage = 
deba@127
   566
	new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@127
   567
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   568
      return *this;
deba@127
   569
    }
deba@127
   570
alpar@156
   571
    /// \name Select section by name
alpar@156
   572
    /// @{
alpar@156
   573
alpar@156
   574
    /// \brief Set \c \@nodes section to be read
alpar@156
   575
    ///
alpar@156
   576
    /// Set \c \@nodes section to be read
deba@127
   577
    DigraphWriter& nodes(const std::string& caption) {
deba@127
   578
      _nodes_caption = caption;
deba@127
   579
      return *this;
deba@127
   580
    }
deba@127
   581
alpar@156
   582
    /// \brief Set \c \@arcs section to be read
alpar@156
   583
    ///
alpar@156
   584
    /// Set \c \@arcs section to be read
deba@127
   585
    DigraphWriter& arcs(const std::string& caption) {
deba@127
   586
      _arcs_caption = caption;
deba@127
   587
      return *this;
deba@127
   588
    }
deba@127
   589
alpar@156
   590
    /// \brief Set \c \@attributes section to be read
alpar@156
   591
    ///
alpar@156
   592
    /// Set \c \@attributes section to be read
deba@127
   593
    DigraphWriter& attributes(const std::string& caption) {
deba@127
   594
      _attributes_caption = caption;
deba@127
   595
      return *this;
deba@127
   596
    }
deba@127
   597
alpar@156
   598
    /// \name Skipping section
alpar@156
   599
    /// @{
alpar@156
   600
alpar@156
   601
    /// \brief Skip writing the node set
alpar@156
   602
    ///
alpar@156
   603
    /// The \c \@nodes section will be not written to the stream.
deba@127
   604
    DigraphWriter& skipNodes() {
deba@127
   605
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@185
   606
      _skip_nodes = true;
deba@127
   607
      return *this;
deba@127
   608
    }
deba@127
   609
alpar@156
   610
    /// \brief Skip writing arc set
alpar@156
   611
    ///
alpar@156
   612
    /// The \c \@arcs section will be not written to the stream.
deba@127
   613
    DigraphWriter& skipArcs() {
deba@127
   614
      LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
deba@185
   615
      _skip_arcs = true;
deba@127
   616
      return *this;
deba@127
   617
    }
deba@127
   618
alpar@156
   619
    /// @}
alpar@156
   620
deba@127
   621
  private:
deba@127
   622
deba@127
   623
    void writeNodes() {
deba@127
   624
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@127
   625
      for (typename NodeMaps::iterator it = _node_maps.begin();
deba@127
   626
	   it != _node_maps.end(); ++it) {
deba@127
   627
        if (it->first == "label") {
deba@127
   628
	  label = it->second;
deba@127
   629
	  break;
deba@127
   630
	}
deba@127
   631
      }
deba@127
   632
deba@127
   633
      *_os << "@nodes";
deba@127
   634
      if (!_nodes_caption.empty()) {
alpar@156
   635
	_writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@127
   636
      }
deba@127
   637
      *_os << std::endl;
deba@127
   638
deba@127
   639
      if (label == 0) {
deba@127
   640
	*_os << "label" << '\t';
deba@127
   641
      }
deba@127
   642
      for (typename NodeMaps::iterator it = _node_maps.begin();
deba@127
   643
	   it != _node_maps.end(); ++it) {
alpar@156
   644
	_writer_bits::writeToken(*_os, it->first) << '\t';
deba@127
   645
      }
deba@127
   646
      *_os << std::endl;
deba@127
   647
deba@127
   648
      std::vector<Node> nodes;
deba@127
   649
      for (NodeIt n(_digraph); n != INVALID; ++n) {
deba@127
   650
	nodes.push_back(n);
deba@127
   651
      }
deba@127
   652
      
deba@127
   653
      if (label == 0) {
deba@127
   654
	IdMap<Digraph, Node> id_map(_digraph);
deba@127
   655
	_writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
deba@127
   656
	std::sort(nodes.begin(), nodes.end(), id_less);
deba@127
   657
      } else {
deba@127
   658
	label->sort(nodes);
deba@127
   659
      }
deba@127
   660
deba@127
   661
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
deba@127
   662
	Node n = nodes[i];
deba@127
   663
	if (label == 0) {
deba@127
   664
	  std::ostringstream os;
deba@127
   665
	  os << _digraph.id(n);
deba@127
   666
	  _writer_bits::writeToken(*_os, os.str());
deba@127
   667
	  *_os << '\t';
deba@127
   668
	  _node_index.insert(std::make_pair(n, os.str()));
deba@127
   669
	}
deba@127
   670
	for (typename NodeMaps::iterator it = _node_maps.begin();
deba@127
   671
	     it != _node_maps.end(); ++it) {
deba@127
   672
	  std::string value = it->second->get(n);
deba@127
   673
	  _writer_bits::writeToken(*_os, value);
deba@127
   674
	  if (it->first == "label") {
deba@127
   675
	    _node_index.insert(std::make_pair(n, value));
deba@127
   676
	  }
deba@127
   677
	  *_os << '\t';
deba@127
   678
	}
deba@127
   679
	*_os << std::endl;
deba@127
   680
      }
deba@127
   681
    }
deba@127
   682
deba@185
   683
    void createNodeIndex() {
deba@185
   684
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@185
   685
      for (typename NodeMaps::iterator it = _node_maps.begin();
deba@185
   686
	   it != _node_maps.end(); ++it) {
deba@185
   687
        if (it->first == "label") {
deba@185
   688
	  label = it->second;
deba@185
   689
	  break;
deba@185
   690
	}
deba@185
   691
      }
deba@185
   692
deba@185
   693
      if (label == 0) {
deba@185
   694
	for (NodeIt n(_digraph); n != INVALID; ++n) {
deba@185
   695
	  std::ostringstream os;
deba@185
   696
	  os << _digraph.id(n);
deba@185
   697
	  _node_index.insert(std::make_pair(n, os.str()));	  
deba@185
   698
	}	
deba@185
   699
      } else {
deba@185
   700
	for (NodeIt n(_digraph); n != INVALID; ++n) {
deba@185
   701
	  std::string value = label->get(n);	  
deba@185
   702
	  _node_index.insert(std::make_pair(n, value));
deba@185
   703
	}
deba@185
   704
      }
deba@185
   705
    }
deba@185
   706
deba@127
   707
    void writeArcs() {
deba@127
   708
      _writer_bits::MapStorageBase<Arc>* label = 0;
deba@127
   709
      for (typename ArcMaps::iterator it = _arc_maps.begin();
deba@127
   710
	   it != _arc_maps.end(); ++it) {
deba@127
   711
        if (it->first == "label") {
deba@127
   712
	  label = it->second;
deba@127
   713
	  break;
deba@127
   714
	}
deba@127
   715
      }
deba@127
   716
deba@127
   717
      *_os << "@arcs";
deba@127
   718
      if (!_arcs_caption.empty()) {
alpar@156
   719
	_writer_bits::writeToken(*_os << ' ', _arcs_caption);
deba@127
   720
      }
deba@127
   721
      *_os << std::endl;
deba@127
   722
deba@127
   723
      *_os << '\t' << '\t';
deba@127
   724
      if (label == 0) {
deba@127
   725
	*_os << "label" << '\t';
deba@127
   726
      }
deba@127
   727
      for (typename ArcMaps::iterator it = _arc_maps.begin();
deba@127
   728
	   it != _arc_maps.end(); ++it) {
alpar@156
   729
	_writer_bits::writeToken(*_os, it->first) << '\t';
deba@127
   730
      }
deba@127
   731
      *_os << std::endl;
deba@127
   732
deba@127
   733
      std::vector<Arc> arcs;
deba@127
   734
      for (ArcIt n(_digraph); n != INVALID; ++n) {
deba@127
   735
	arcs.push_back(n);
deba@127
   736
      }
deba@127
   737
      
deba@127
   738
      if (label == 0) {
deba@127
   739
	IdMap<Digraph, Arc> id_map(_digraph);
deba@127
   740
	_writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
deba@127
   741
	std::sort(arcs.begin(), arcs.end(), id_less);
deba@127
   742
      } else {
deba@127
   743
	label->sort(arcs);
deba@127
   744
      }
deba@127
   745
deba@127
   746
      for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
deba@127
   747
	Arc a = arcs[i];
deba@127
   748
	_writer_bits::writeToken(*_os, _node_index.
deba@127
   749
				 find(_digraph.source(a))->second);
deba@127
   750
	*_os << '\t';
deba@127
   751
	_writer_bits::writeToken(*_os, _node_index.
deba@127
   752
				 find(_digraph.target(a))->second);
deba@127
   753
	*_os << '\t';
deba@127
   754
	if (label == 0) {
deba@127
   755
	  std::ostringstream os;
deba@127
   756
	  os << _digraph.id(a);
deba@127
   757
	  _writer_bits::writeToken(*_os, os.str());
deba@127
   758
	  *_os << '\t';
deba@127
   759
	  _arc_index.insert(std::make_pair(a, os.str()));
deba@127
   760
	}
deba@127
   761
	for (typename ArcMaps::iterator it = _arc_maps.begin();
deba@127
   762
	     it != _arc_maps.end(); ++it) {
deba@127
   763
	  std::string value = it->second->get(a);
deba@127
   764
	  _writer_bits::writeToken(*_os, value);
deba@127
   765
	  if (it->first == "label") {
deba@127
   766
	    _arc_index.insert(std::make_pair(a, value));
deba@127
   767
	  }
deba@127
   768
	  *_os << '\t';
deba@127
   769
	}
deba@127
   770
	*_os << std::endl;
deba@127
   771
      }
deba@127
   772
    }
deba@127
   773
deba@185
   774
    void createArcIndex() {
deba@185
   775
      _writer_bits::MapStorageBase<Arc>* label = 0;
deba@185
   776
      for (typename ArcMaps::iterator it = _arc_maps.begin();
deba@185
   777
	   it != _arc_maps.end(); ++it) {
deba@185
   778
        if (it->first == "label") {
deba@185
   779
	  label = it->second;
deba@185
   780
	  break;
deba@185
   781
	}
deba@185
   782
      }
deba@185
   783
deba@185
   784
      if (label == 0) {
deba@185
   785
	for (ArcIt a(_digraph); a != INVALID; ++a) {
deba@185
   786
	  std::ostringstream os;
deba@185
   787
	  os << _digraph.id(a);
deba@185
   788
	  _arc_index.insert(std::make_pair(a, os.str()));	  
deba@185
   789
	}	
deba@185
   790
      } else {
deba@185
   791
	for (ArcIt a(_digraph); a != INVALID; ++a) {
deba@185
   792
	  std::string value = label->get(a);	  
deba@185
   793
	  _arc_index.insert(std::make_pair(a, value));
deba@185
   794
	}
deba@185
   795
      }
deba@185
   796
    }
deba@185
   797
deba@127
   798
    void writeAttributes() {
deba@127
   799
      if (_attributes.empty()) return;
deba@127
   800
      *_os << "@attributes";
deba@127
   801
      if (!_attributes_caption.empty()) {
alpar@156
   802
	_writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@127
   803
      }
deba@127
   804
      *_os << std::endl;
deba@127
   805
      for (typename Attributes::iterator it = _attributes.begin();
deba@127
   806
	   it != _attributes.end(); ++it) {
alpar@156
   807
	_writer_bits::writeToken(*_os, it->first) << ' ';
deba@127
   808
	_writer_bits::writeToken(*_os, it->second->get());
deba@127
   809
	*_os << std::endl;
deba@127
   810
      }
deba@127
   811
    }
deba@127
   812
    
deba@127
   813
  public:
deba@127
   814
    
alpar@156
   815
    /// \name Execution of the writer    
alpar@156
   816
    /// @{
alpar@156
   817
alpar@156
   818
    /// \brief Start the batch processing
alpar@156
   819
    ///
alpar@156
   820
    /// This function starts the batch processing
deba@127
   821
    void run() {
deba@127
   822
      if (!_skip_nodes) {
deba@127
   823
	writeNodes();
deba@185
   824
      } else {
deba@185
   825
	createNodeIndex();
deba@127
   826
      }
deba@127
   827
      if (!_skip_arcs) {      
deba@127
   828
	writeArcs();
deba@185
   829
      } else {
deba@185
   830
	createArcIndex();
deba@127
   831
      }
deba@127
   832
      writeAttributes();
deba@127
   833
    }
deba@127
   834
alpar@156
   835
    /// \brief Gives back the stream of the writer
alpar@156
   836
    ///
alpar@156
   837
    /// Gives back the stream of the writer
alpar@156
   838
    std::ostream& ostream() {
deba@127
   839
      return *_os;
deba@127
   840
    }
alpar@156
   841
alpar@156
   842
    /// @}
deba@127
   843
  };
deba@127
   844
alpar@156
   845
  /// \relates DigraphWriter
deba@127
   846
  template <typename Digraph>
deba@163
   847
  DigraphWriter<Digraph> digraphWriter(std::ostream& os, Digraph& digraph) {
deba@163
   848
    DigraphWriter<Digraph> tmp(os, digraph);
deba@163
   849
    return tmp;
deba@127
   850
  }
deba@127
   851
alpar@156
   852
  /// \relates DigraphWriter
deba@127
   853
  template <typename Digraph>
deba@127
   854
  DigraphWriter<Digraph> digraphWriter(const std::string& fn, 
deba@127
   855
				       Digraph& digraph) {
deba@163
   856
    DigraphWriter<Digraph> tmp(fn, digraph);
deba@163
   857
    return tmp;
deba@127
   858
  }
deba@127
   859
alpar@156
   860
  /// \relates DigraphWriter
deba@127
   861
  template <typename Digraph>
deba@127
   862
  DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) {
deba@163
   863
    DigraphWriter<Digraph> tmp(fn, digraph);
deba@163
   864
    return tmp;
deba@127
   865
  }
deba@165
   866
deba@165
   867
  /// \ingroup lemon_io
deba@165
   868
  ///  
deba@165
   869
  /// \brief LGF writer for directed graphs
deba@165
   870
  ///
deba@165
   871
  /// This utility writes an \ref lgf-format "LGF" file.
deba@165
   872
  template <typename _Graph>
deba@165
   873
  class GraphWriter {
deba@165
   874
  public:
deba@165
   875
deba@165
   876
    typedef _Graph Graph;
deba@165
   877
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
deba@165
   878
    
deba@165
   879
  private:
deba@165
   880
deba@165
   881
deba@165
   882
    std::ostream* _os;
deba@165
   883
    bool local_os;
deba@165
   884
deba@165
   885
    Graph& _graph;
deba@165
   886
deba@165
   887
    std::string _nodes_caption;
deba@165
   888
    std::string _edges_caption;
deba@165
   889
    std::string _attributes_caption;
deba@165
   890
    
deba@165
   891
    typedef std::map<Node, std::string> NodeIndex;
deba@165
   892
    NodeIndex _node_index;
deba@165
   893
    typedef std::map<Edge, std::string> EdgeIndex;
deba@165
   894
    EdgeIndex _edge_index;
deba@165
   895
deba@165
   896
    typedef std::vector<std::pair<std::string, 
deba@165
   897
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;    
deba@165
   898
    NodeMaps _node_maps; 
deba@165
   899
deba@165
   900
    typedef std::vector<std::pair<std::string, 
deba@165
   901
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
deba@165
   902
    EdgeMaps _edge_maps;
deba@165
   903
deba@165
   904
    typedef std::vector<std::pair<std::string, 
deba@165
   905
      _writer_bits::ValueStorageBase*> > Attributes;
deba@165
   906
    Attributes _attributes;
deba@165
   907
deba@165
   908
    bool _skip_nodes;
deba@165
   909
    bool _skip_edges;
deba@165
   910
deba@165
   911
  public:
deba@165
   912
deba@165
   913
    /// \brief Constructor
deba@165
   914
    ///
deba@165
   915
    /// Construct a directed graph writer, which writes to the given
deba@165
   916
    /// output stream.
deba@165
   917
    GraphWriter(std::ostream& is, Graph& graph) 
deba@165
   918
      : _os(&is), local_os(false), _graph(graph),
deba@165
   919
	_skip_nodes(false), _skip_edges(false) {}
deba@165
   920
deba@165
   921
    /// \brief Constructor
deba@165
   922
    ///
deba@165
   923
    /// Construct a directed graph writer, which writes to the given
deba@165
   924
    /// output file.
deba@165
   925
    GraphWriter(const std::string& fn, Graph& graph) 
deba@165
   926
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
deba@165
   927
	_skip_nodes(false), _skip_edges(false) {}
deba@165
   928
deba@165
   929
    /// \brief Constructor
deba@165
   930
    ///
deba@165
   931
    /// Construct a directed graph writer, which writes to the given
deba@165
   932
    /// output file.
deba@165
   933
    GraphWriter(const char* fn, Graph& graph) 
deba@165
   934
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
deba@165
   935
	_skip_nodes(false), _skip_edges(false) {}
deba@165
   936
deba@165
   937
    /// \brief Copy constructor
deba@165
   938
    ///
deba@165
   939
    /// The copy constructor transfers all data from the other writer,
deba@165
   940
    /// therefore the copied writer will not be usable more. 
deba@165
   941
    GraphWriter(GraphWriter& other) 
deba@165
   942
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
deba@165
   943
	_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
deba@165
   944
deba@165
   945
      other._os = 0;
deba@165
   946
      other.local_os = false;
deba@165
   947
deba@165
   948
      _node_index.swap(other._node_index);
deba@165
   949
      _edge_index.swap(other._edge_index);
deba@165
   950
deba@165
   951
      _node_maps.swap(other._node_maps);
deba@165
   952
      _edge_maps.swap(other._edge_maps);
deba@165
   953
      _attributes.swap(other._attributes);
deba@165
   954
deba@165
   955
      _nodes_caption = other._nodes_caption;
deba@165
   956
      _edges_caption = other._edges_caption;
deba@165
   957
      _attributes_caption = other._attributes_caption;
deba@165
   958
    }
deba@165
   959
deba@165
   960
    /// \brief Destructor
deba@165
   961
    ~GraphWriter() {
deba@165
   962
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
deba@165
   963
	   it != _node_maps.end(); ++it) {
deba@165
   964
	delete it->second;
deba@165
   965
      }
deba@165
   966
deba@165
   967
      for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
deba@165
   968
	   it != _edge_maps.end(); ++it) {
deba@165
   969
	delete it->second;
deba@165
   970
      }
deba@165
   971
deba@165
   972
      for (typename Attributes::iterator it = _attributes.begin(); 
deba@165
   973
	   it != _attributes.end(); ++it) {
deba@165
   974
	delete it->second;
deba@165
   975
      }
deba@165
   976
deba@165
   977
      if (local_os) {
deba@165
   978
	delete _os;
deba@165
   979
      }
deba@165
   980
    }
deba@165
   981
deba@165
   982
  private:
deba@165
   983
    
deba@165
   984
    GraphWriter& operator=(const GraphWriter&);
deba@165
   985
deba@165
   986
  public:
deba@165
   987
deba@165
   988
    /// \name Writing rules
deba@165
   989
    /// @{
deba@165
   990
    
deba@165
   991
    /// \brief Node map reading rule
deba@165
   992
    ///
deba@165
   993
    /// Add a node map reading rule to the writer.
deba@165
   994
    template <typename Map>
deba@165
   995
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@165
   996
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@165
   997
      _writer_bits::MapStorageBase<Node>* storage = 
deba@165
   998
	new _writer_bits::MapStorage<Node, Map>(map);
deba@165
   999
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1000
      return *this;
deba@165
  1001
    }
deba@165
  1002
deba@165
  1003
    /// \brief Node map writing rule
deba@165
  1004
    ///
deba@165
  1005
    /// Add a node map writing rule with specialized converter to the
deba@165
  1006
    /// writer.
deba@165
  1007
    template <typename Map, typename Converter>
deba@165
  1008
    GraphWriter& nodeMap(const std::string& caption, const Map& map, 
deba@165
  1009
			   const Converter& converter = Converter()) {
deba@165
  1010
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@165
  1011
      _writer_bits::MapStorageBase<Node>* storage = 
deba@165
  1012
	new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@165
  1013
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1014
      return *this;
deba@165
  1015
    }
deba@165
  1016
deba@165
  1017
    /// \brief Edge map writing rule
deba@165
  1018
    ///
deba@165
  1019
    /// Add an edge map writing rule to the writer.
deba@165
  1020
    template <typename Map>
deba@165
  1021
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
deba@165
  1022
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@165
  1023
      _writer_bits::MapStorageBase<Edge>* storage = 
deba@165
  1024
	new _writer_bits::MapStorage<Edge, Map>(map);
deba@165
  1025
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1026
      return *this;
deba@165
  1027
    }
deba@165
  1028
deba@165
  1029
    /// \brief Edge map writing rule
deba@165
  1030
    ///
deba@165
  1031
    /// Add an edge map writing rule with specialized converter to the
deba@165
  1032
    /// writer.
deba@165
  1033
    template <typename Map, typename Converter>
deba@165
  1034
    GraphWriter& edgeMap(const std::string& caption, const Map& map, 
deba@165
  1035
			  const Converter& converter = Converter()) {
deba@165
  1036
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@165
  1037
      _writer_bits::MapStorageBase<Edge>* storage = 
deba@165
  1038
	new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
deba@165
  1039
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1040
      return *this;
deba@165
  1041
    }
deba@165
  1042
deba@165
  1043
    /// \brief Arc map writing rule
deba@165
  1044
    ///
deba@165
  1045
    /// Add an arc map writing rule to the writer.
deba@165
  1046
    template <typename Map>
deba@165
  1047
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@165
  1048
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@165
  1049
      _writer_bits::MapStorageBase<Edge>* forward_storage = 
deba@165
  1050
	new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
deba@165
  1051
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
deba@165
  1052
      _writer_bits::MapStorageBase<Edge>* backward_storage = 
deba@165
  1053
	new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
deba@165
  1054
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1055
      return *this;
deba@165
  1056
    }
deba@165
  1057
deba@165
  1058
    /// \brief Arc map writing rule
deba@165
  1059
    ///
deba@165
  1060
    /// Add an arc map writing rule with specialized converter to the
deba@165
  1061
    /// writer.
deba@165
  1062
    template <typename Map, typename Converter>
deba@165
  1063
    GraphWriter& arcMap(const std::string& caption, const Map& map, 
deba@165
  1064
			  const Converter& converter = Converter()) {
deba@165
  1065
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@165
  1066
      _writer_bits::MapStorageBase<Edge>* forward_storage = 
deba@165
  1067
	new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
deba@165
  1068
	(_graph, map, converter);
deba@165
  1069
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
deba@165
  1070
      _writer_bits::MapStorageBase<Edge>* backward_storage = 
deba@165
  1071
	new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
deba@165
  1072
	(_graph, map, converter);
deba@165
  1073
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1074
      return *this;
deba@165
  1075
    }
deba@165
  1076
deba@165
  1077
    /// \brief Attribute writing rule
deba@165
  1078
    ///
deba@165
  1079
    /// Add an attribute writing rule to the writer.
deba@165
  1080
    template <typename Value>
deba@165
  1081
    GraphWriter& attribute(const std::string& caption, const Value& value) {
deba@165
  1082
      _writer_bits::ValueStorageBase* storage = 
deba@165
  1083
	new _writer_bits::ValueStorage<Value>(value);
deba@165
  1084
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1085
      return *this;
deba@165
  1086
    }
deba@165
  1087
deba@165
  1088
    /// \brief Attribute writing rule
deba@165
  1089
    ///
deba@165
  1090
    /// Add an attribute writing rule with specialized converter to the
deba@165
  1091
    /// writer.
deba@165
  1092
    template <typename Value, typename Converter>
deba@165
  1093
    GraphWriter& attribute(const std::string& caption, const Value& value, 
deba@165
  1094
			     const Converter& converter = Converter()) {
deba@165
  1095
      _writer_bits::ValueStorageBase* storage = 
deba@165
  1096
	new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@165
  1097
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1098
      return *this;
deba@165
  1099
    }
deba@165
  1100
deba@165
  1101
    /// \brief Node writing rule
deba@165
  1102
    ///
deba@165
  1103
    /// Add a node writing rule to the writer.
deba@165
  1104
    GraphWriter& node(const std::string& caption, const Node& node) {
deba@165
  1105
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@165
  1106
      Converter converter(_node_index);
deba@165
  1107
      _writer_bits::ValueStorageBase* storage = 
deba@165
  1108
	new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@165
  1109
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1110
      return *this;
deba@165
  1111
    }
deba@165
  1112
deba@165
  1113
    /// \brief Edge writing rule
deba@165
  1114
    ///
deba@165
  1115
    /// Add an edge writing rule to writer.
deba@165
  1116
    GraphWriter& edge(const std::string& caption, const Edge& edge) {
deba@165
  1117
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
deba@165
  1118
      Converter converter(_edge_index);
deba@165
  1119
      _writer_bits::ValueStorageBase* storage = 
deba@165
  1120
	new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
deba@165
  1121
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1122
      return *this;
deba@165
  1123
    }
deba@165
  1124
deba@165
  1125
    /// \brief Arc writing rule
deba@165
  1126
    ///
deba@165
  1127
    /// Add an arc writing rule to writer.
deba@165
  1128
    GraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@165
  1129
      typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
deba@165
  1130
      Converter converter(_graph, _edge_index);
deba@165
  1131
      _writer_bits::ValueStorageBase* storage = 
deba@165
  1132
	new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@165
  1133
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1134
      return *this;
deba@165
  1135
    }
deba@165
  1136
deba@165
  1137
    /// \name Select section by name
deba@165
  1138
    /// @{
deba@165
  1139
deba@165
  1140
    /// \brief Set \c \@nodes section to be read
deba@165
  1141
    ///
deba@165
  1142
    /// Set \c \@nodes section to be read
deba@165
  1143
    GraphWriter& nodes(const std::string& caption) {
deba@165
  1144
      _nodes_caption = caption;
deba@165
  1145
      return *this;
deba@165
  1146
    }
deba@165
  1147
deba@165
  1148
    /// \brief Set \c \@edges section to be read
deba@165
  1149
    ///
deba@165
  1150
    /// Set \c \@edges section to be read
deba@165
  1151
    GraphWriter& edges(const std::string& caption) {
deba@165
  1152
      _edges_caption = caption;
deba@165
  1153
      return *this;
deba@165
  1154
    }
deba@165
  1155
deba@165
  1156
    /// \brief Set \c \@attributes section to be read
deba@165
  1157
    ///
deba@165
  1158
    /// Set \c \@attributes section to be read
deba@165
  1159
    GraphWriter& attributes(const std::string& caption) {
deba@165
  1160
      _attributes_caption = caption;
deba@165
  1161
      return *this;
deba@165
  1162
    }
deba@165
  1163
deba@165
  1164
    /// \name Skipping section
deba@165
  1165
    /// @{
deba@165
  1166
deba@165
  1167
    /// \brief Skip writing the node set
deba@165
  1168
    ///
deba@165
  1169
    /// The \c \@nodes section will be not written to the stream.
deba@165
  1170
    GraphWriter& skipNodes() {
deba@165
  1171
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@185
  1172
      _skip_nodes = true;
deba@165
  1173
      return *this;
deba@165
  1174
    }
deba@165
  1175
deba@165
  1176
    /// \brief Skip writing edge set
deba@165
  1177
    ///
deba@165
  1178
    /// The \c \@edges section will be not written to the stream.
deba@165
  1179
    GraphWriter& skipEdges() {
deba@165
  1180
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
deba@185
  1181
      _skip_edges = true;
deba@165
  1182
      return *this;
deba@165
  1183
    }
deba@165
  1184
deba@165
  1185
    /// @}
deba@165
  1186
deba@165
  1187
  private:
deba@165
  1188
deba@165
  1189
    void writeNodes() {
deba@165
  1190
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@165
  1191
      for (typename NodeMaps::iterator it = _node_maps.begin();
deba@165
  1192
	   it != _node_maps.end(); ++it) {
deba@165
  1193
        if (it->first == "label") {
deba@165
  1194
	  label = it->second;
deba@165
  1195
	  break;
deba@165
  1196
	}
deba@165
  1197
      }
deba@165
  1198
deba@165
  1199
      *_os << "@nodes";
deba@165
  1200
      if (!_nodes_caption.empty()) {
deba@165
  1201
	_writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@165
  1202
      }
deba@165
  1203
      *_os << std::endl;
deba@165
  1204
deba@165
  1205
      if (label == 0) {
deba@165
  1206
	*_os << "label" << '\t';
deba@165
  1207
      }
deba@165
  1208
      for (typename NodeMaps::iterator it = _node_maps.begin();
deba@165
  1209
	   it != _node_maps.end(); ++it) {
deba@165
  1210
	_writer_bits::writeToken(*_os, it->first) << '\t';
deba@165
  1211
      }
deba@165
  1212
      *_os << std::endl;
deba@165
  1213
deba@165
  1214
      std::vector<Node> nodes;
deba@165
  1215
      for (NodeIt n(_graph); n != INVALID; ++n) {
deba@165
  1216
	nodes.push_back(n);
deba@165
  1217
      }
deba@165
  1218
      
deba@165
  1219
      if (label == 0) {
deba@165
  1220
	IdMap<Graph, Node> id_map(_graph);
deba@165
  1221
	_writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
deba@165
  1222
	std::sort(nodes.begin(), nodes.end(), id_less);
deba@165
  1223
      } else {
deba@165
  1224
	label->sort(nodes);
deba@165
  1225
      }
deba@165
  1226
deba@165
  1227
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
deba@165
  1228
	Node n = nodes[i];
deba@165
  1229
	if (label == 0) {
deba@165
  1230
	  std::ostringstream os;
deba@165
  1231
	  os << _graph.id(n);
deba@165
  1232
	  _writer_bits::writeToken(*_os, os.str());
deba@165
  1233
	  *_os << '\t';
deba@165
  1234
	  _node_index.insert(std::make_pair(n, os.str()));
deba@165
  1235
	}
deba@165
  1236
	for (typename NodeMaps::iterator it = _node_maps.begin();
deba@165
  1237
	     it != _node_maps.end(); ++it) {
deba@165
  1238
	  std::string value = it->second->get(n);
deba@165
  1239
	  _writer_bits::writeToken(*_os, value);
deba@165
  1240
	  if (it->first == "label") {
deba@165
  1241
	    _node_index.insert(std::make_pair(n, value));
deba@165
  1242
	  }
deba@165
  1243
	  *_os << '\t';
deba@165
  1244
	}
deba@165
  1245
	*_os << std::endl;
deba@165
  1246
      }
deba@165
  1247
    }
deba@165
  1248
deba@185
  1249
    void createNodeIndex() {
deba@185
  1250
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@185
  1251
      for (typename NodeMaps::iterator it = _node_maps.begin();
deba@185
  1252
	   it != _node_maps.end(); ++it) {
deba@185
  1253
        if (it->first == "label") {
deba@185
  1254
	  label = it->second;
deba@185
  1255
	  break;
deba@185
  1256
	}
deba@185
  1257
      }
deba@185
  1258
deba@185
  1259
      if (label == 0) {
deba@185
  1260
	for (NodeIt n(_graph); n != INVALID; ++n) {
deba@185
  1261
	  std::ostringstream os;
deba@185
  1262
	  os << _graph.id(n);
deba@185
  1263
	  _node_index.insert(std::make_pair(n, os.str()));	  
deba@185
  1264
	}	
deba@185
  1265
      } else {
deba@185
  1266
	for (NodeIt n(_graph); n != INVALID; ++n) {
deba@185
  1267
	  std::string value = label->get(n);	  
deba@185
  1268
	  _node_index.insert(std::make_pair(n, value));
deba@185
  1269
	}
deba@185
  1270
      }
deba@185
  1271
    }
deba@185
  1272
deba@165
  1273
    void writeEdges() {
deba@165
  1274
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@165
  1275
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@165
  1276
	   it != _edge_maps.end(); ++it) {
deba@165
  1277
        if (it->first == "label") {
deba@165
  1278
	  label = it->second;
deba@165
  1279
	  break;
deba@165
  1280
	}
deba@165
  1281
      }
deba@165
  1282
deba@165
  1283
      *_os << "@edges";
deba@165
  1284
      if (!_edges_caption.empty()) {
deba@165
  1285
	_writer_bits::writeToken(*_os << ' ', _edges_caption);
deba@165
  1286
      }
deba@165
  1287
      *_os << std::endl;
deba@165
  1288
deba@165
  1289
      *_os << '\t' << '\t';
deba@165
  1290
      if (label == 0) {
deba@165
  1291
	*_os << "label" << '\t';
deba@165
  1292
      }
deba@165
  1293
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@165
  1294
	   it != _edge_maps.end(); ++it) {
deba@165
  1295
	_writer_bits::writeToken(*_os, it->first) << '\t';
deba@165
  1296
      }
deba@165
  1297
      *_os << std::endl;
deba@165
  1298
deba@165
  1299
      std::vector<Edge> edges;
deba@165
  1300
      for (EdgeIt n(_graph); n != INVALID; ++n) {
deba@165
  1301
	edges.push_back(n);
deba@165
  1302
      }
deba@165
  1303
      
deba@165
  1304
      if (label == 0) {
deba@165
  1305
	IdMap<Graph, Edge> id_map(_graph);
deba@165
  1306
	_writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
deba@165
  1307
	std::sort(edges.begin(), edges.end(), id_less);
deba@165
  1308
      } else {
deba@165
  1309
	label->sort(edges);
deba@165
  1310
      }
deba@165
  1311
deba@165
  1312
      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
deba@165
  1313
	Edge e = edges[i];
deba@165
  1314
	_writer_bits::writeToken(*_os, _node_index.
deba@165
  1315
				 find(_graph.u(e))->second);
deba@165
  1316
	*_os << '\t';
deba@165
  1317
	_writer_bits::writeToken(*_os, _node_index.
deba@165
  1318
				 find(_graph.v(e))->second);
deba@165
  1319
	*_os << '\t';
deba@165
  1320
	if (label == 0) {
deba@165
  1321
	  std::ostringstream os;
deba@165
  1322
	  os << _graph.id(e);
deba@165
  1323
	  _writer_bits::writeToken(*_os, os.str());
deba@165
  1324
	  *_os << '\t';
deba@165
  1325
	  _edge_index.insert(std::make_pair(e, os.str()));
deba@165
  1326
	}
deba@165
  1327
	for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@165
  1328
	     it != _edge_maps.end(); ++it) {
deba@165
  1329
	  std::string value = it->second->get(e);
deba@165
  1330
	  _writer_bits::writeToken(*_os, value);
deba@165
  1331
	  if (it->first == "label") {
deba@165
  1332
	    _edge_index.insert(std::make_pair(e, value));
deba@165
  1333
	  }
deba@165
  1334
	  *_os << '\t';
deba@165
  1335
	}
deba@165
  1336
	*_os << std::endl;
deba@165
  1337
      }
deba@165
  1338
    }
deba@165
  1339
deba@185
  1340
    void createEdgeIndex() {
deba@185
  1341
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@185
  1342
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@185
  1343
	   it != _edge_maps.end(); ++it) {
deba@185
  1344
        if (it->first == "label") {
deba@185
  1345
	  label = it->second;
deba@185
  1346
	  break;
deba@185
  1347
	}
deba@185
  1348
      }
deba@185
  1349
deba@185
  1350
      if (label == 0) {
deba@185
  1351
	for (EdgeIt e(_graph); e != INVALID; ++e) {
deba@185
  1352
	  std::ostringstream os;
deba@185
  1353
	  os << _graph.id(e);
deba@185
  1354
	  _edge_index.insert(std::make_pair(e, os.str()));	  
deba@185
  1355
	}	
deba@185
  1356
      } else {
deba@185
  1357
	for (EdgeIt e(_graph); e != INVALID; ++e) {
deba@185
  1358
	  std::string value = label->get(e);	  
deba@185
  1359
	  _edge_index.insert(std::make_pair(e, value));
deba@185
  1360
	}
deba@185
  1361
      }
deba@185
  1362
    }
deba@185
  1363
deba@165
  1364
    void writeAttributes() {
deba@165
  1365
      if (_attributes.empty()) return;
deba@165
  1366
      *_os << "@attributes";
deba@165
  1367
      if (!_attributes_caption.empty()) {
deba@165
  1368
	_writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@165
  1369
      }
deba@165
  1370
      *_os << std::endl;
deba@165
  1371
      for (typename Attributes::iterator it = _attributes.begin();
deba@165
  1372
	   it != _attributes.end(); ++it) {
deba@165
  1373
	_writer_bits::writeToken(*_os, it->first) << ' ';
deba@165
  1374
	_writer_bits::writeToken(*_os, it->second->get());
deba@165
  1375
	*_os << std::endl;
deba@165
  1376
      }
deba@165
  1377
    }
deba@165
  1378
    
deba@165
  1379
  public:
deba@165
  1380
    
deba@165
  1381
    /// \name Execution of the writer    
deba@165
  1382
    /// @{
deba@165
  1383
deba@165
  1384
    /// \brief Start the batch processing
deba@165
  1385
    ///
deba@165
  1386
    /// This function starts the batch processing
deba@165
  1387
    void run() {
deba@165
  1388
      if (!_skip_nodes) {
deba@165
  1389
	writeNodes();
deba@185
  1390
      } else {
deba@185
  1391
	createNodeIndex();
deba@165
  1392
      }
deba@165
  1393
      if (!_skip_edges) {      
deba@165
  1394
	writeEdges();
deba@185
  1395
      } else {
deba@185
  1396
	createEdgeIndex();
deba@165
  1397
      }
deba@165
  1398
      writeAttributes();
deba@165
  1399
    }
deba@165
  1400
deba@165
  1401
    /// \brief Gives back the stream of the writer
deba@165
  1402
    ///
deba@165
  1403
    /// Gives back the stream of the writer
deba@165
  1404
    std::ostream& ostream() {
deba@165
  1405
      return *_os;
deba@165
  1406
    }
deba@165
  1407
deba@165
  1408
    /// @}
deba@165
  1409
  };
deba@165
  1410
deba@165
  1411
  /// \relates GraphWriter
deba@165
  1412
  template <typename Graph>
deba@165
  1413
  GraphWriter<Graph> graphWriter(std::ostream& os, Graph& graph) {
deba@165
  1414
    GraphWriter<Graph> tmp(os, graph);
deba@165
  1415
    return tmp;
deba@165
  1416
  }
deba@165
  1417
deba@165
  1418
  /// \relates GraphWriter
deba@165
  1419
  template <typename Graph>
deba@165
  1420
  GraphWriter<Graph> graphWriter(const std::string& fn, Graph& graph) {
deba@165
  1421
    GraphWriter<Graph> tmp(fn, graph);
deba@165
  1422
    return tmp;
deba@165
  1423
  }
deba@165
  1424
deba@165
  1425
  /// \relates GraphWriter
deba@165
  1426
  template <typename Graph>
deba@165
  1427
  GraphWriter<Graph> graphWriter(const char* fn, Graph& graph) {
deba@165
  1428
    GraphWriter<Graph> tmp(fn, graph);
deba@165
  1429
    return tmp;
deba@165
  1430
  }
deba@127
  1431
}
deba@127
  1432
deba@127
  1433
#endif