lemon/lgf_writer.h
author Alpar Juttner <alpar@cs.elte.hu>
Thu, 24 Apr 2008 20:26:14 +0100
changeset 151 4d79daa40e9b
child 139 701c529ba737
permissions -rw-r--r--
Turn on built in Doxygen STL support
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@127
    74
    template <typename _Item>    
deba@127
    75
    class MapStorageBase {
deba@127
    76
    public:
deba@127
    77
      typedef _Item Item;
deba@127
    78
deba@127
    79
    public:
deba@127
    80
      MapStorageBase() {}
deba@127
    81
      virtual ~MapStorageBase() {}
deba@127
    82
deba@127
    83
      virtual std::string get(const Item& item) = 0;
deba@127
    84
      virtual void sort(std::vector<Item>&) = 0;
deba@127
    85
    };
deba@127
    86
deba@127
    87
    template <typename _Item, typename _Map, 
deba@127
    88
	      typename _Converter = DefaultConverter<typename _Map::Value> >
deba@127
    89
    class MapStorage : public MapStorageBase<_Item> {
deba@127
    90
    public:
deba@127
    91
      typedef _Map Map;
deba@127
    92
      typedef _Converter Converter;
deba@127
    93
      typedef _Item Item;
deba@127
    94
      
deba@127
    95
    private:
deba@127
    96
      const Map& _map;
deba@127
    97
      Converter _converter;
deba@127
    98
deba@127
    99
    public:
deba@127
   100
      MapStorage(const Map& map, const Converter& converter = Converter()) 
deba@127
   101
	: _map(map), _converter(converter) {}
deba@127
   102
      virtual ~MapStorage() {}
deba@127
   103
deba@127
   104
      virtual std::string get(const Item& item) {
deba@127
   105
	return _converter(_map[item]);
deba@127
   106
      }
deba@127
   107
      virtual void sort(std::vector<Item>& items) {
deba@127
   108
	MapLess<Map> less(_map);
deba@127
   109
	std::sort(items.begin(), items.end(), less);
deba@127
   110
      }
deba@127
   111
    };
deba@127
   112
deba@127
   113
    class ValueStorageBase {
deba@127
   114
    public:
deba@127
   115
      ValueStorageBase() {}
deba@127
   116
      virtual ~ValueStorageBase() {}
deba@127
   117
deba@127
   118
      virtual std::string get() = 0;      
deba@127
   119
    };
deba@127
   120
deba@127
   121
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
deba@127
   122
    class ValueStorage : public ValueStorageBase {
deba@127
   123
    public:
deba@127
   124
      typedef _Value Value;
deba@127
   125
      typedef _Converter Converter;
deba@127
   126
deba@127
   127
    private:
deba@127
   128
      const Value& _value;
deba@127
   129
      Converter _converter;
deba@127
   130
deba@127
   131
    public:
deba@127
   132
      ValueStorage(const Value& value, const Converter& converter = Converter())
deba@127
   133
 	: _value(value), _converter(converter) {}
deba@127
   134
deba@127
   135
      virtual std::string get() {
deba@127
   136
	return _converter(_value);
deba@127
   137
      }
deba@127
   138
    };
deba@127
   139
deba@127
   140
    template <typename Value>
deba@127
   141
    struct MapLookUpConverter {
deba@127
   142
      const std::map<Value, std::string>& _map;
deba@127
   143
      
deba@127
   144
      MapLookUpConverter(const std::map<Value, std::string>& map) 
deba@127
   145
	: _map(map) {}
deba@127
   146
      
deba@127
   147
      std::string operator()(const Value& str) {
deba@127
   148
	typename std::map<Value, std::string>::const_iterator it = 
deba@127
   149
	  _map.find(str);
deba@127
   150
	if (it == _map.end()) {
deba@127
   151
	  throw DataFormatError("Item not found");
deba@127
   152
	}
deba@127
   153
	return it->second;
deba@127
   154
      }
deba@127
   155
    };
deba@127
   156
deba@127
   157
    bool isWhiteSpace(char c) {
deba@127
   158
      return c == ' ' || c == '\t' || c == '\v' || 
deba@127
   159
        c == '\n' || c == '\r' || c == '\f'; 
deba@127
   160
    }
deba@127
   161
deba@127
   162
    bool isEscaped(char c) {
deba@127
   163
      return c == '\\' || c == '\"' || c == '\'' || 
deba@127
   164
	c == '\a' || c == '\b';
deba@127
   165
    }
deba@127
   166
deba@127
   167
    static void writeEscape(std::ostream& os, char c) {
deba@127
   168
      switch (c) {
deba@127
   169
      case '\\':
deba@127
   170
	os << "\\\\";
deba@127
   171
	return;
deba@127
   172
      case '\"':
deba@127
   173
	os << "\\\"";
deba@127
   174
	return;
deba@127
   175
      case '\a':
deba@127
   176
	os << "\\a";
deba@127
   177
	return;
deba@127
   178
      case '\b':
deba@127
   179
	os << "\\b";
deba@127
   180
	return;
deba@127
   181
      case '\f':
deba@127
   182
	os << "\\f";
deba@127
   183
	return;
deba@127
   184
      case '\r':
deba@127
   185
	os << "\\r";
deba@127
   186
	return;
deba@127
   187
      case '\n':
deba@127
   188
	os << "\\n";
deba@127
   189
	return;
deba@127
   190
      case '\t':
deba@127
   191
	os << "\\t";
deba@127
   192
	return;
deba@127
   193
      case '\v':
deba@127
   194
	os << "\\v";
deba@127
   195
	return;
deba@127
   196
      default:
deba@127
   197
	if (c < 0x20) {
deba@127
   198
	  os << '\\' << std::oct << static_cast<int>(c);
deba@127
   199
	} else {
deba@127
   200
	  os << c;
deba@127
   201
	}
deba@127
   202
	return;
deba@127
   203
      }     
deba@127
   204
    }
deba@127
   205
deba@127
   206
    bool requireEscape(const std::string& str) {
deba@127
   207
      std::istringstream is(str);
deba@127
   208
      char c;
deba@127
   209
      while (is.get(c)) {
deba@127
   210
	if (isWhiteSpace(c) || isEscaped(c)) {
deba@127
   211
	  return true;
deba@127
   212
	}
deba@127
   213
      }
deba@127
   214
      return false;
deba@127
   215
    }
deba@127
   216
    
deba@127
   217
    std::ostream& writeToken(std::ostream& os, const std::string& str) {
deba@127
   218
deba@127
   219
      if (requireEscape(str)) {
deba@127
   220
	os << '\"';
deba@127
   221
	for (std::string::const_iterator it = str.begin(); 
deba@127
   222
	     it != str.end(); ++it) {
deba@127
   223
	  writeEscape(os, *it);
deba@127
   224
	}	
deba@127
   225
	os << '\"';
deba@127
   226
      } else {
deba@127
   227
	os << str;
deba@127
   228
      }
deba@127
   229
      return os;
deba@127
   230
    }
deba@127
   231
deba@127
   232
  }
deba@127
   233
  
deba@127
   234
  /// \e
deba@127
   235
  template <typename _Digraph>
deba@127
   236
  class DigraphWriter {
deba@127
   237
  public:
deba@127
   238
deba@127
   239
    typedef _Digraph Digraph;
deba@127
   240
    GRAPH_TYPEDEFS(typename Digraph);
deba@127
   241
    
deba@127
   242
  private:
deba@127
   243
deba@127
   244
deba@127
   245
    std::ostream* _os;
deba@127
   246
    bool local_os;
deba@127
   247
deba@127
   248
    Digraph& _digraph;
deba@127
   249
deba@127
   250
    std::string _nodes_caption;
deba@127
   251
    std::string _arcs_caption;
deba@127
   252
    std::string _attributes_caption;
deba@127
   253
    
deba@127
   254
    typedef std::map<Node, std::string> NodeIndex;
deba@127
   255
    NodeIndex _node_index;
deba@127
   256
    typedef std::map<Arc, std::string> ArcIndex;
deba@127
   257
    ArcIndex _arc_index;
deba@127
   258
deba@127
   259
    typedef std::vector<std::pair<std::string, 
deba@127
   260
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;    
deba@127
   261
    NodeMaps _node_maps; 
deba@127
   262
deba@127
   263
    typedef std::vector<std::pair<std::string, 
deba@127
   264
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
deba@127
   265
    ArcMaps _arc_maps;
deba@127
   266
deba@127
   267
    typedef std::vector<std::pair<std::string, 
deba@127
   268
      _writer_bits::ValueStorageBase*> > Attributes;
deba@127
   269
    Attributes _attributes;
deba@127
   270
deba@127
   271
    bool _skip_nodes;
deba@127
   272
    bool _skip_arcs;
deba@127
   273
deba@127
   274
  public:
deba@127
   275
deba@127
   276
    /// \e
deba@127
   277
    DigraphWriter(std::ostream& is, Digraph& digraph) 
deba@127
   278
      : _os(&is), local_os(false), _digraph(digraph),
deba@127
   279
	_skip_nodes(false), _skip_arcs(false) {}
deba@127
   280
deba@127
   281
    /// \e
deba@127
   282
    DigraphWriter(const std::string& fn, Digraph& digraph) 
deba@127
   283
      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
deba@127
   284
	_skip_nodes(false), _skip_arcs(false) {}
deba@127
   285
deba@127
   286
    /// \e
deba@127
   287
    DigraphWriter(const char* fn, Digraph& digraph) 
deba@127
   288
      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
deba@127
   289
	_skip_nodes(false), _skip_arcs(false) {}
deba@127
   290
deba@127
   291
    DigraphWriter(DigraphWriter& other) 
deba@127
   292
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
deba@127
   293
	_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
deba@127
   294
deba@127
   295
      other.is = 0;
deba@127
   296
      other.local_os = false;
deba@127
   297
deba@127
   298
      _node_index.swap(other._node_index);
deba@127
   299
      _arc_index.swap(other._arc_index);
deba@127
   300
deba@127
   301
      _node_maps.swap(other._node_maps);
deba@127
   302
      _arc_maps.swap(other._arc_maps);
deba@127
   303
      _attributes.swap(other._attributes);
deba@127
   304
deba@127
   305
      _nodes_caption = other._nodes_caption;
deba@127
   306
      _arcs_caption = other._arcs_caption;
deba@127
   307
      _attributes_caption = other._attributes_caption;
deba@127
   308
    }
deba@127
   309
deba@127
   310
    /// \e
deba@127
   311
    ~DigraphWriter() {
deba@127
   312
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
deba@127
   313
	   it != _node_maps.end(); ++it) {
deba@127
   314
	delete it->second;
deba@127
   315
      }
deba@127
   316
deba@127
   317
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
deba@127
   318
	   it != _arc_maps.end(); ++it) {
deba@127
   319
	delete it->second;
deba@127
   320
      }
deba@127
   321
deba@127
   322
      for (typename Attributes::iterator it = _attributes.begin(); 
deba@127
   323
	   it != _attributes.end(); ++it) {
deba@127
   324
	delete it->second;
deba@127
   325
      }
deba@127
   326
deba@127
   327
      if (local_os) {
deba@127
   328
	delete _os;
deba@127
   329
      }
deba@127
   330
    }
deba@127
   331
deba@127
   332
  private:
deba@127
   333
    
deba@127
   334
    DigraphWriter& operator=(const DigraphWriter&);
deba@127
   335
deba@127
   336
  public:
deba@127
   337
deba@127
   338
    /// \e
deba@127
   339
    template <typename Map>
deba@127
   340
    DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@127
   341
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@127
   342
      _writer_bits::MapStorageBase<Node>* storage = 
deba@127
   343
	new _writer_bits::MapStorage<Node, Map>(map);
deba@127
   344
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   345
      return *this;
deba@127
   346
    }
deba@127
   347
deba@127
   348
    /// \e
deba@127
   349
    template <typename Map, typename Converter>
deba@127
   350
    DigraphWriter& nodeMap(const std::string& caption, const Map& map, 
deba@127
   351
			   const Converter& converter = Converter()) {
deba@127
   352
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@127
   353
      _writer_bits::MapStorageBase<Node>* storage = 
deba@127
   354
	new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@127
   355
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   356
      return *this;
deba@127
   357
    }
deba@127
   358
deba@127
   359
    /// \e
deba@127
   360
    template <typename Map>
deba@127
   361
    DigraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@127
   362
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@127
   363
      _writer_bits::MapStorageBase<Arc>* storage = 
deba@127
   364
	new _writer_bits::MapStorage<Arc, Map>(map);
deba@127
   365
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   366
      return *this;
deba@127
   367
    }
deba@127
   368
deba@127
   369
    /// \e
deba@127
   370
    template <typename Map, typename Converter>
deba@127
   371
    DigraphWriter& arcMap(const std::string& caption, const Map& map, 
deba@127
   372
			  const Converter& converter = Converter()) {
deba@127
   373
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@127
   374
      _writer_bits::MapStorageBase<Arc>* storage = 
deba@127
   375
	new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
deba@127
   376
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   377
      return *this;
deba@127
   378
    }
deba@127
   379
deba@127
   380
    /// \e
deba@127
   381
    template <typename Value>
deba@127
   382
    DigraphWriter& attribute(const std::string& caption, const Value& value) {
deba@127
   383
      _writer_bits::ValueStorageBase* storage = 
deba@127
   384
	new _writer_bits::ValueStorage<Value>(value);
deba@127
   385
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   386
      return *this;
deba@127
   387
    }
deba@127
   388
deba@127
   389
    /// \e
deba@127
   390
    template <typename Value, typename Converter>
deba@127
   391
    DigraphWriter& attribute(const std::string& caption, const Value& value, 
deba@127
   392
			     const Converter& converter = Converter()) {
deba@127
   393
      _writer_bits::ValueStorageBase* storage = 
deba@127
   394
	new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@127
   395
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   396
      return *this;
deba@127
   397
    }
deba@127
   398
deba@127
   399
    /// \e
deba@127
   400
    DigraphWriter& node(const std::string& caption, const Node& node) {
deba@127
   401
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@127
   402
      Converter converter(_node_index);
deba@127
   403
      _writer_bits::ValueStorageBase* storage = 
deba@127
   404
	new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@127
   405
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   406
      return *this;
deba@127
   407
    }
deba@127
   408
deba@127
   409
    /// \e
deba@127
   410
    DigraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@127
   411
      typedef _writer_bits::MapLookUpConverter<Arc> Converter;
deba@127
   412
      Converter converter(_arc_index);
deba@127
   413
      _writer_bits::ValueStorageBase* storage = 
deba@127
   414
	new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@127
   415
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   416
      return *this;
deba@127
   417
    }
deba@127
   418
deba@127
   419
    /// \e
deba@127
   420
    DigraphWriter& nodes(const std::string& caption) {
deba@127
   421
      _nodes_caption = caption;
deba@127
   422
      return *this;
deba@127
   423
    }
deba@127
   424
deba@127
   425
    /// \e
deba@127
   426
    DigraphWriter& arcs(const std::string& caption) {
deba@127
   427
      _arcs_caption = caption;
deba@127
   428
      return *this;
deba@127
   429
    }
deba@127
   430
deba@127
   431
    /// \e
deba@127
   432
    DigraphWriter& attributes(const std::string& caption) {
deba@127
   433
      _attributes_caption = caption;
deba@127
   434
      return *this;
deba@127
   435
    }
deba@127
   436
deba@127
   437
    DigraphWriter& skipNodes() {
deba@127
   438
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@127
   439
      return *this;
deba@127
   440
    }
deba@127
   441
deba@127
   442
    DigraphWriter& skipArcs() {
deba@127
   443
      LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
deba@127
   444
      return *this;
deba@127
   445
    }
deba@127
   446
deba@127
   447
  private:
deba@127
   448
deba@127
   449
    void writeNodes() {
deba@127
   450
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@127
   451
      for (typename NodeMaps::iterator it = _node_maps.begin();
deba@127
   452
	   it != _node_maps.end(); ++it) {
deba@127
   453
        if (it->first == "label") {
deba@127
   454
	  label = it->second;
deba@127
   455
	  break;
deba@127
   456
	}
deba@127
   457
      }
deba@127
   458
deba@127
   459
      *_os << "@nodes";
deba@127
   460
      if (!_nodes_caption.empty()) {
deba@127
   461
	*_os << ' ' << _nodes_caption;
deba@127
   462
      }
deba@127
   463
      *_os << std::endl;
deba@127
   464
deba@127
   465
      if (label == 0) {
deba@127
   466
	*_os << "label" << '\t';
deba@127
   467
      }
deba@127
   468
      for (typename NodeMaps::iterator it = _node_maps.begin();
deba@127
   469
	   it != _node_maps.end(); ++it) {
deba@127
   470
	*_os << it->first << '\t';
deba@127
   471
      }
deba@127
   472
      *_os << std::endl;
deba@127
   473
deba@127
   474
      std::vector<Node> nodes;
deba@127
   475
      for (NodeIt n(_digraph); n != INVALID; ++n) {
deba@127
   476
	nodes.push_back(n);
deba@127
   477
      }
deba@127
   478
      
deba@127
   479
      if (label == 0) {
deba@127
   480
	IdMap<Digraph, Node> id_map(_digraph);
deba@127
   481
	_writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
deba@127
   482
	std::sort(nodes.begin(), nodes.end(), id_less);
deba@127
   483
      } else {
deba@127
   484
	label->sort(nodes);
deba@127
   485
      }
deba@127
   486
deba@127
   487
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
deba@127
   488
	Node n = nodes[i];
deba@127
   489
	if (label == 0) {
deba@127
   490
	  std::ostringstream os;
deba@127
   491
	  os << _digraph.id(n);
deba@127
   492
	  _writer_bits::writeToken(*_os, os.str());
deba@127
   493
	  *_os << '\t';
deba@127
   494
	  _node_index.insert(std::make_pair(n, os.str()));
deba@127
   495
	}
deba@127
   496
	for (typename NodeMaps::iterator it = _node_maps.begin();
deba@127
   497
	     it != _node_maps.end(); ++it) {
deba@127
   498
	  std::string value = it->second->get(n);
deba@127
   499
	  _writer_bits::writeToken(*_os, value);
deba@127
   500
	  if (it->first == "label") {
deba@127
   501
	    _node_index.insert(std::make_pair(n, value));
deba@127
   502
	  }
deba@127
   503
	  *_os << '\t';
deba@127
   504
	}
deba@127
   505
	*_os << std::endl;
deba@127
   506
      }
deba@127
   507
    }
deba@127
   508
deba@127
   509
    void writeArcs() {
deba@127
   510
      _writer_bits::MapStorageBase<Arc>* label = 0;
deba@127
   511
      for (typename ArcMaps::iterator it = _arc_maps.begin();
deba@127
   512
	   it != _arc_maps.end(); ++it) {
deba@127
   513
        if (it->first == "label") {
deba@127
   514
	  label = it->second;
deba@127
   515
	  break;
deba@127
   516
	}
deba@127
   517
      }
deba@127
   518
deba@127
   519
      *_os << "@arcs";
deba@127
   520
      if (!_arcs_caption.empty()) {
deba@127
   521
	*_os << ' ' << _arcs_caption;
deba@127
   522
      }
deba@127
   523
      *_os << std::endl;
deba@127
   524
deba@127
   525
      *_os << '\t' << '\t';
deba@127
   526
      if (label == 0) {
deba@127
   527
	*_os << "label" << '\t';
deba@127
   528
      }
deba@127
   529
      for (typename ArcMaps::iterator it = _arc_maps.begin();
deba@127
   530
	   it != _arc_maps.end(); ++it) {
deba@127
   531
	*_os << it->first << '\t';
deba@127
   532
      }
deba@127
   533
      *_os << std::endl;
deba@127
   534
deba@127
   535
      std::vector<Arc> arcs;
deba@127
   536
      for (ArcIt n(_digraph); n != INVALID; ++n) {
deba@127
   537
	arcs.push_back(n);
deba@127
   538
      }
deba@127
   539
      
deba@127
   540
      if (label == 0) {
deba@127
   541
	IdMap<Digraph, Arc> id_map(_digraph);
deba@127
   542
	_writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
deba@127
   543
	std::sort(arcs.begin(), arcs.end(), id_less);
deba@127
   544
      } else {
deba@127
   545
	label->sort(arcs);
deba@127
   546
      }
deba@127
   547
deba@127
   548
      for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
deba@127
   549
	Arc a = arcs[i];
deba@127
   550
	_writer_bits::writeToken(*_os, _node_index.
deba@127
   551
				 find(_digraph.source(a))->second);
deba@127
   552
	*_os << '\t';
deba@127
   553
	_writer_bits::writeToken(*_os, _node_index.
deba@127
   554
				 find(_digraph.target(a))->second);
deba@127
   555
	*_os << '\t';
deba@127
   556
	if (label == 0) {
deba@127
   557
	  std::ostringstream os;
deba@127
   558
	  os << _digraph.id(a);
deba@127
   559
	  _writer_bits::writeToken(*_os, os.str());
deba@127
   560
	  *_os << '\t';
deba@127
   561
	  _arc_index.insert(std::make_pair(a, os.str()));
deba@127
   562
	}
deba@127
   563
	for (typename ArcMaps::iterator it = _arc_maps.begin();
deba@127
   564
	     it != _arc_maps.end(); ++it) {
deba@127
   565
	  std::string value = it->second->get(a);
deba@127
   566
	  _writer_bits::writeToken(*_os, value);
deba@127
   567
	  if (it->first == "label") {
deba@127
   568
	    _arc_index.insert(std::make_pair(a, value));
deba@127
   569
	  }
deba@127
   570
	  *_os << '\t';
deba@127
   571
	}
deba@127
   572
	*_os << std::endl;
deba@127
   573
      }
deba@127
   574
    }
deba@127
   575
deba@127
   576
    void writeAttributes() {
deba@127
   577
      if (_attributes.empty()) return;
deba@127
   578
      *_os << "@attributes";
deba@127
   579
      if (!_attributes_caption.empty()) {
deba@127
   580
	*_os << ' ' << _attributes_caption;
deba@127
   581
      }
deba@127
   582
      *_os << std::endl;
deba@127
   583
      for (typename Attributes::iterator it = _attributes.begin();
deba@127
   584
	   it != _attributes.end(); ++it) {
deba@127
   585
	*_os << it->first << ' ';
deba@127
   586
	_writer_bits::writeToken(*_os, it->second->get());
deba@127
   587
	*_os << std::endl;
deba@127
   588
      }
deba@127
   589
    }
deba@127
   590
    
deba@127
   591
  public:
deba@127
   592
    
deba@127
   593
    /// \e
deba@127
   594
    void run() {
deba@127
   595
      if (!_skip_nodes) {
deba@127
   596
	writeNodes();
deba@127
   597
      }
deba@127
   598
      if (!_skip_arcs) {      
deba@127
   599
	writeArcs();
deba@127
   600
      }
deba@127
   601
      writeAttributes();
deba@127
   602
    }
deba@127
   603
deba@127
   604
    /// \e
deba@127
   605
    std::ostream& stream() {
deba@127
   606
      return *_os;
deba@127
   607
    }
deba@127
   608
  };
deba@127
   609
deba@127
   610
  template <typename Digraph>
deba@127
   611
  DigraphWriter<Digraph> digraphWriter(std::istream& is, Digraph& digraph) {
deba@127
   612
    return DigraphWriter<Digraph>(is, digraph);
deba@127
   613
  }
deba@127
   614
deba@127
   615
  template <typename Digraph>
deba@127
   616
  DigraphWriter<Digraph> digraphWriter(const std::string& fn, 
deba@127
   617
				       Digraph& digraph) {
deba@127
   618
    return DigraphWriter<Digraph>(fn, digraph);
deba@127
   619
  }
deba@127
   620
deba@127
   621
  template <typename Digraph>
deba@127
   622
  DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) {
deba@127
   623
    return DigraphWriter<Digraph>(fn, digraph);
deba@127
   624
  }
deba@127
   625
}
deba@127
   626
deba@127
   627
#endif