lemon/lgf_writer.h
author Balazs Dezso <deba@inf.elte.hu>
Sat, 31 May 2008 12:31:21 +0200
changeset 163 c82fd9568d75
parent 156 e561aa7675de
child 165 b4c336c27a03
permissions -rw-r--r--
Bug fixes and improvements in LGF IO
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@163
   198
	  std::ios::fmtflags flags = os.flags();
deba@127
   199
	  os << '\\' << std::oct << static_cast<int>(c);
deba@163
   200
	  os.flags(flags);
deba@127
   201
	} else {
deba@127
   202
	  os << c;
deba@127
   203
	}
deba@127
   204
	return;
deba@127
   205
      }     
deba@127
   206
    }
deba@127
   207
deba@127
   208
    bool requireEscape(const std::string& str) {
alpar@156
   209
      if (str.empty() || str[0] == '@') return true;
deba@127
   210
      std::istringstream is(str);
deba@127
   211
      char c;
deba@127
   212
      while (is.get(c)) {
deba@127
   213
	if (isWhiteSpace(c) || isEscaped(c)) {
deba@127
   214
	  return true;
deba@127
   215
	}
deba@127
   216
      }
deba@127
   217
      return false;
deba@127
   218
    }
deba@127
   219
    
deba@127
   220
    std::ostream& writeToken(std::ostream& os, const std::string& str) {
deba@127
   221
deba@127
   222
      if (requireEscape(str)) {
deba@127
   223
	os << '\"';
deba@127
   224
	for (std::string::const_iterator it = str.begin(); 
deba@127
   225
	     it != str.end(); ++it) {
deba@127
   226
	  writeEscape(os, *it);
deba@127
   227
	}	
deba@127
   228
	os << '\"';
deba@127
   229
      } else {
deba@127
   230
	os << str;
deba@127
   231
      }
deba@127
   232
      return os;
deba@127
   233
    }
deba@127
   234
deba@127
   235
  }
deba@127
   236
  
alpar@156
   237
  /// \ingroup lemon_io
alpar@156
   238
  ///  
alpar@156
   239
  /// \brief LGF writer for directed graphs
alpar@156
   240
  ///
alpar@156
   241
  /// This utility writes an \ref lgf-format "LGF" file.
alpar@156
   242
  ///
alpar@156
   243
  /// The writing method does a batch processing. The user creates a
alpar@156
   244
  /// writer object, then various writing rules can be added to the
alpar@156
   245
  /// writer, and eventually the writing is executed with the \c run()
alpar@156
   246
  /// member function. A map writing rule can be added to the writer
alpar@156
   247
  /// with the \c nodeMap() or \c arcMap() members. An optional
deba@163
   248
  /// converter parameter can also be added as a standard functor
deba@163
   249
  /// converting from the value type of the map to std::string. If it
deba@163
   250
  /// is set, it will determine how the map's value type is written to
deba@163
   251
  /// the output stream. If the functor is not set, then a default
deba@163
   252
  /// conversion will be used. The \c attribute(), \c node() and \c
deba@163
   253
  /// arc() functions are used to add attribute writing rules.
alpar@156
   254
  ///
alpar@156
   255
  ///\code
alpar@156
   256
  ///     DigraphWriter<Digraph>(std::cout, digraph).
alpar@156
   257
  ///       nodeMap("coordinates", coord_map).
alpar@156
   258
  ///       nodeMap("size", size).
alpar@156
   259
  ///       nodeMap("title", title).
alpar@156
   260
  ///       arcMap("capacity", cap_map).
alpar@156
   261
  ///       node("source", src).
alpar@156
   262
  ///       node("target", trg).
alpar@156
   263
  ///       attribute("caption", caption).
alpar@156
   264
  ///       run();
alpar@156
   265
  ///\endcode
alpar@156
   266
  ///
alpar@156
   267
  ///
alpar@156
   268
  /// By default, the writer does not write additional captions to the
alpar@156
   269
  /// sections, but they can be give as an optional parameter of
alpar@156
   270
  /// the \c nodes(), \c arcs() or \c
alpar@156
   271
  /// attributes() functions.
alpar@156
   272
  ///
alpar@156
   273
  /// The \c skipNodes() and \c skipArcs() functions forbid the
deba@163
   274
  /// writing of the sections. If two arc sections should be written
deba@163
   275
  /// to the output, it can be done in two passes, the first pass
deba@163
   276
  /// writes the node section and the first arc section, then the
deba@163
   277
  /// second pass skips the node section and writes just the arc
deba@163
   278
  /// section to the stream. The output stream can be retrieved with
deba@163
   279
  /// the \c ostream() function, hence the second pass can append its
deba@163
   280
  /// output to the output of the first pass.
deba@127
   281
  template <typename _Digraph>
deba@127
   282
  class DigraphWriter {
deba@127
   283
  public:
deba@127
   284
deba@127
   285
    typedef _Digraph Digraph;
deba@148
   286
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
deba@127
   287
    
deba@127
   288
  private:
deba@127
   289
deba@127
   290
deba@127
   291
    std::ostream* _os;
deba@127
   292
    bool local_os;
deba@127
   293
deba@127
   294
    Digraph& _digraph;
deba@127
   295
deba@127
   296
    std::string _nodes_caption;
deba@127
   297
    std::string _arcs_caption;
deba@127
   298
    std::string _attributes_caption;
deba@127
   299
    
deba@127
   300
    typedef std::map<Node, std::string> NodeIndex;
deba@127
   301
    NodeIndex _node_index;
deba@127
   302
    typedef std::map<Arc, std::string> ArcIndex;
deba@127
   303
    ArcIndex _arc_index;
deba@127
   304
deba@127
   305
    typedef std::vector<std::pair<std::string, 
deba@127
   306
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;    
deba@127
   307
    NodeMaps _node_maps; 
deba@127
   308
deba@127
   309
    typedef std::vector<std::pair<std::string, 
deba@127
   310
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
deba@127
   311
    ArcMaps _arc_maps;
deba@127
   312
deba@127
   313
    typedef std::vector<std::pair<std::string, 
deba@127
   314
      _writer_bits::ValueStorageBase*> > Attributes;
deba@127
   315
    Attributes _attributes;
deba@127
   316
deba@127
   317
    bool _skip_nodes;
deba@127
   318
    bool _skip_arcs;
deba@127
   319
deba@127
   320
  public:
deba@127
   321
alpar@156
   322
    /// \brief Constructor
alpar@156
   323
    ///
alpar@156
   324
    /// Construct a directed graph writer, which writes to the given
alpar@156
   325
    /// output stream.
deba@127
   326
    DigraphWriter(std::ostream& is, Digraph& digraph) 
deba@127
   327
      : _os(&is), local_os(false), _digraph(digraph),
deba@127
   328
	_skip_nodes(false), _skip_arcs(false) {}
deba@127
   329
alpar@156
   330
    /// \brief Constructor
alpar@156
   331
    ///
alpar@156
   332
    /// Construct a directed graph writer, which writes to the given
alpar@156
   333
    /// output file.
deba@127
   334
    DigraphWriter(const std::string& fn, Digraph& digraph) 
deba@127
   335
      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
deba@127
   336
	_skip_nodes(false), _skip_arcs(false) {}
deba@127
   337
alpar@156
   338
    /// \brief Constructor
alpar@156
   339
    ///
alpar@156
   340
    /// Construct a directed graph writer, which writes to the given
alpar@156
   341
    /// output file.
deba@127
   342
    DigraphWriter(const char* fn, Digraph& digraph) 
deba@127
   343
      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
deba@127
   344
	_skip_nodes(false), _skip_arcs(false) {}
deba@127
   345
alpar@156
   346
    /// \brief Copy constructor
alpar@156
   347
    ///
alpar@156
   348
    /// The copy constructor transfers all data from the other writer,
alpar@156
   349
    /// therefore the copied writer will not be usable more. 
deba@127
   350
    DigraphWriter(DigraphWriter& other) 
deba@127
   351
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
deba@127
   352
	_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
deba@127
   353
deba@163
   354
      other._os = 0;
deba@127
   355
      other.local_os = false;
deba@127
   356
deba@127
   357
      _node_index.swap(other._node_index);
deba@127
   358
      _arc_index.swap(other._arc_index);
deba@127
   359
deba@127
   360
      _node_maps.swap(other._node_maps);
deba@127
   361
      _arc_maps.swap(other._arc_maps);
deba@127
   362
      _attributes.swap(other._attributes);
deba@127
   363
deba@127
   364
      _nodes_caption = other._nodes_caption;
deba@127
   365
      _arcs_caption = other._arcs_caption;
deba@127
   366
      _attributes_caption = other._attributes_caption;
deba@127
   367
    }
deba@127
   368
alpar@156
   369
    /// \brief Destructor
deba@127
   370
    ~DigraphWriter() {
deba@127
   371
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
deba@127
   372
	   it != _node_maps.end(); ++it) {
deba@127
   373
	delete it->second;
deba@127
   374
      }
deba@127
   375
deba@127
   376
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
deba@127
   377
	   it != _arc_maps.end(); ++it) {
deba@127
   378
	delete it->second;
deba@127
   379
      }
deba@127
   380
deba@127
   381
      for (typename Attributes::iterator it = _attributes.begin(); 
deba@127
   382
	   it != _attributes.end(); ++it) {
deba@127
   383
	delete it->second;
deba@127
   384
      }
deba@127
   385
deba@127
   386
      if (local_os) {
deba@127
   387
	delete _os;
deba@127
   388
      }
deba@127
   389
    }
deba@127
   390
deba@127
   391
  private:
deba@127
   392
    
deba@127
   393
    DigraphWriter& operator=(const DigraphWriter&);
deba@127
   394
deba@127
   395
  public:
deba@127
   396
alpar@156
   397
    /// \name Writing rules
alpar@156
   398
    /// @{
alpar@156
   399
    
alpar@156
   400
    /// \brief Node map reading rule
alpar@156
   401
    ///
alpar@156
   402
    /// Add a node map reading rule to the writer.
deba@127
   403
    template <typename Map>
deba@127
   404
    DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@127
   405
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@127
   406
      _writer_bits::MapStorageBase<Node>* storage = 
deba@127
   407
	new _writer_bits::MapStorage<Node, Map>(map);
deba@127
   408
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   409
      return *this;
deba@127
   410
    }
deba@127
   411
alpar@156
   412
    /// \brief Node map writing rule
alpar@156
   413
    ///
alpar@156
   414
    /// Add a node map writing rule with specialized converter to the
alpar@156
   415
    /// writer.
deba@127
   416
    template <typename Map, typename Converter>
deba@127
   417
    DigraphWriter& nodeMap(const std::string& caption, const Map& map, 
deba@127
   418
			   const Converter& converter = Converter()) {
deba@127
   419
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@127
   420
      _writer_bits::MapStorageBase<Node>* storage = 
deba@127
   421
	new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@127
   422
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   423
      return *this;
deba@127
   424
    }
deba@127
   425
alpar@156
   426
    /// \brief Arc map writing rule
alpar@156
   427
    ///
alpar@156
   428
    /// Add an arc map writing rule to the writer.
deba@127
   429
    template <typename Map>
deba@127
   430
    DigraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@127
   431
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@127
   432
      _writer_bits::MapStorageBase<Arc>* storage = 
deba@127
   433
	new _writer_bits::MapStorage<Arc, Map>(map);
deba@127
   434
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   435
      return *this;
deba@127
   436
    }
deba@127
   437
alpar@156
   438
    /// \brief Arc map writing rule
alpar@156
   439
    ///
alpar@156
   440
    /// Add an arc map writing rule with specialized converter to the
alpar@156
   441
    /// writer.
deba@127
   442
    template <typename Map, typename Converter>
deba@127
   443
    DigraphWriter& arcMap(const std::string& caption, const Map& map, 
deba@127
   444
			  const Converter& converter = Converter()) {
deba@127
   445
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@127
   446
      _writer_bits::MapStorageBase<Arc>* storage = 
deba@127
   447
	new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
deba@127
   448
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   449
      return *this;
deba@127
   450
    }
deba@127
   451
alpar@156
   452
    /// \brief Attribute writing rule
alpar@156
   453
    ///
alpar@156
   454
    /// Add an attribute writing rule to the writer.
deba@127
   455
    template <typename Value>
deba@127
   456
    DigraphWriter& attribute(const std::string& caption, const Value& value) {
deba@127
   457
      _writer_bits::ValueStorageBase* storage = 
deba@127
   458
	new _writer_bits::ValueStorage<Value>(value);
deba@127
   459
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   460
      return *this;
deba@127
   461
    }
deba@127
   462
alpar@156
   463
    /// \brief Attribute writing rule
alpar@156
   464
    ///
alpar@156
   465
    /// Add an attribute writing rule with specialized converter to the
alpar@156
   466
    /// writer.
deba@127
   467
    template <typename Value, typename Converter>
deba@127
   468
    DigraphWriter& attribute(const std::string& caption, const Value& value, 
deba@127
   469
			     const Converter& converter = Converter()) {
deba@127
   470
      _writer_bits::ValueStorageBase* storage = 
deba@127
   471
	new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@127
   472
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   473
      return *this;
deba@127
   474
    }
deba@127
   475
alpar@156
   476
    /// \brief Node writing rule
alpar@156
   477
    ///
alpar@156
   478
    /// Add a node writing rule to the writer.
deba@127
   479
    DigraphWriter& node(const std::string& caption, const Node& node) {
deba@127
   480
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@127
   481
      Converter converter(_node_index);
deba@127
   482
      _writer_bits::ValueStorageBase* storage = 
deba@127
   483
	new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@127
   484
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   485
      return *this;
deba@127
   486
    }
deba@127
   487
alpar@156
   488
    /// \brief Arc writing rule
alpar@156
   489
    ///
alpar@156
   490
    /// Add an arc writing rule to writer.
deba@127
   491
    DigraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@127
   492
      typedef _writer_bits::MapLookUpConverter<Arc> Converter;
deba@127
   493
      Converter converter(_arc_index);
deba@127
   494
      _writer_bits::ValueStorageBase* storage = 
deba@127
   495
	new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@127
   496
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   497
      return *this;
deba@127
   498
    }
deba@127
   499
alpar@156
   500
    /// \name Select section by name
alpar@156
   501
    /// @{
alpar@156
   502
alpar@156
   503
    /// \brief Set \c \@nodes section to be read
alpar@156
   504
    ///
alpar@156
   505
    /// Set \c \@nodes section to be read
deba@127
   506
    DigraphWriter& nodes(const std::string& caption) {
deba@127
   507
      _nodes_caption = caption;
deba@127
   508
      return *this;
deba@127
   509
    }
deba@127
   510
alpar@156
   511
    /// \brief Set \c \@arcs section to be read
alpar@156
   512
    ///
alpar@156
   513
    /// Set \c \@arcs section to be read
deba@127
   514
    DigraphWriter& arcs(const std::string& caption) {
deba@127
   515
      _arcs_caption = caption;
deba@127
   516
      return *this;
deba@127
   517
    }
deba@127
   518
alpar@156
   519
    /// \brief Set \c \@attributes section to be read
alpar@156
   520
    ///
alpar@156
   521
    /// Set \c \@attributes section to be read
deba@127
   522
    DigraphWriter& attributes(const std::string& caption) {
deba@127
   523
      _attributes_caption = caption;
deba@127
   524
      return *this;
deba@127
   525
    }
deba@127
   526
alpar@156
   527
    /// \name Skipping section
alpar@156
   528
    /// @{
alpar@156
   529
alpar@156
   530
    /// \brief Skip writing the node set
alpar@156
   531
    ///
alpar@156
   532
    /// The \c \@nodes section will be not written to the stream.
deba@127
   533
    DigraphWriter& skipNodes() {
deba@127
   534
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@127
   535
      return *this;
deba@127
   536
    }
deba@127
   537
alpar@156
   538
    /// \brief Skip writing arc set
alpar@156
   539
    ///
alpar@156
   540
    /// The \c \@arcs section will be not written to the stream.
deba@127
   541
    DigraphWriter& skipArcs() {
deba@127
   542
      LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
deba@127
   543
      return *this;
deba@127
   544
    }
deba@127
   545
alpar@156
   546
    /// @}
alpar@156
   547
deba@127
   548
  private:
deba@127
   549
deba@127
   550
    void writeNodes() {
deba@127
   551
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@127
   552
      for (typename NodeMaps::iterator it = _node_maps.begin();
deba@127
   553
	   it != _node_maps.end(); ++it) {
deba@127
   554
        if (it->first == "label") {
deba@127
   555
	  label = it->second;
deba@127
   556
	  break;
deba@127
   557
	}
deba@127
   558
      }
deba@127
   559
deba@127
   560
      *_os << "@nodes";
deba@127
   561
      if (!_nodes_caption.empty()) {
alpar@156
   562
	_writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@127
   563
      }
deba@127
   564
      *_os << std::endl;
deba@127
   565
deba@127
   566
      if (label == 0) {
deba@127
   567
	*_os << "label" << '\t';
deba@127
   568
      }
deba@127
   569
      for (typename NodeMaps::iterator it = _node_maps.begin();
deba@127
   570
	   it != _node_maps.end(); ++it) {
alpar@156
   571
	_writer_bits::writeToken(*_os, it->first) << '\t';
deba@127
   572
      }
deba@127
   573
      *_os << std::endl;
deba@127
   574
deba@127
   575
      std::vector<Node> nodes;
deba@127
   576
      for (NodeIt n(_digraph); n != INVALID; ++n) {
deba@127
   577
	nodes.push_back(n);
deba@127
   578
      }
deba@127
   579
      
deba@127
   580
      if (label == 0) {
deba@127
   581
	IdMap<Digraph, Node> id_map(_digraph);
deba@127
   582
	_writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
deba@127
   583
	std::sort(nodes.begin(), nodes.end(), id_less);
deba@127
   584
      } else {
deba@127
   585
	label->sort(nodes);
deba@127
   586
      }
deba@127
   587
deba@127
   588
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
deba@127
   589
	Node n = nodes[i];
deba@127
   590
	if (label == 0) {
deba@127
   591
	  std::ostringstream os;
deba@127
   592
	  os << _digraph.id(n);
deba@127
   593
	  _writer_bits::writeToken(*_os, os.str());
deba@127
   594
	  *_os << '\t';
deba@127
   595
	  _node_index.insert(std::make_pair(n, os.str()));
deba@127
   596
	}
deba@127
   597
	for (typename NodeMaps::iterator it = _node_maps.begin();
deba@127
   598
	     it != _node_maps.end(); ++it) {
deba@127
   599
	  std::string value = it->second->get(n);
deba@127
   600
	  _writer_bits::writeToken(*_os, value);
deba@127
   601
	  if (it->first == "label") {
deba@127
   602
	    _node_index.insert(std::make_pair(n, value));
deba@127
   603
	  }
deba@127
   604
	  *_os << '\t';
deba@127
   605
	}
deba@127
   606
	*_os << std::endl;
deba@127
   607
      }
deba@127
   608
    }
deba@127
   609
deba@127
   610
    void writeArcs() {
deba@127
   611
      _writer_bits::MapStorageBase<Arc>* label = 0;
deba@127
   612
      for (typename ArcMaps::iterator it = _arc_maps.begin();
deba@127
   613
	   it != _arc_maps.end(); ++it) {
deba@127
   614
        if (it->first == "label") {
deba@127
   615
	  label = it->second;
deba@127
   616
	  break;
deba@127
   617
	}
deba@127
   618
      }
deba@127
   619
deba@127
   620
      *_os << "@arcs";
deba@127
   621
      if (!_arcs_caption.empty()) {
alpar@156
   622
	_writer_bits::writeToken(*_os << ' ', _arcs_caption);
deba@127
   623
      }
deba@127
   624
      *_os << std::endl;
deba@127
   625
deba@127
   626
      *_os << '\t' << '\t';
deba@127
   627
      if (label == 0) {
deba@127
   628
	*_os << "label" << '\t';
deba@127
   629
      }
deba@127
   630
      for (typename ArcMaps::iterator it = _arc_maps.begin();
deba@127
   631
	   it != _arc_maps.end(); ++it) {
alpar@156
   632
	_writer_bits::writeToken(*_os, it->first) << '\t';
deba@127
   633
      }
deba@127
   634
      *_os << std::endl;
deba@127
   635
deba@127
   636
      std::vector<Arc> arcs;
deba@127
   637
      for (ArcIt n(_digraph); n != INVALID; ++n) {
deba@127
   638
	arcs.push_back(n);
deba@127
   639
      }
deba@127
   640
      
deba@127
   641
      if (label == 0) {
deba@127
   642
	IdMap<Digraph, Arc> id_map(_digraph);
deba@127
   643
	_writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
deba@127
   644
	std::sort(arcs.begin(), arcs.end(), id_less);
deba@127
   645
      } else {
deba@127
   646
	label->sort(arcs);
deba@127
   647
      }
deba@127
   648
deba@127
   649
      for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
deba@127
   650
	Arc a = arcs[i];
deba@127
   651
	_writer_bits::writeToken(*_os, _node_index.
deba@127
   652
				 find(_digraph.source(a))->second);
deba@127
   653
	*_os << '\t';
deba@127
   654
	_writer_bits::writeToken(*_os, _node_index.
deba@127
   655
				 find(_digraph.target(a))->second);
deba@127
   656
	*_os << '\t';
deba@127
   657
	if (label == 0) {
deba@127
   658
	  std::ostringstream os;
deba@127
   659
	  os << _digraph.id(a);
deba@127
   660
	  _writer_bits::writeToken(*_os, os.str());
deba@127
   661
	  *_os << '\t';
deba@127
   662
	  _arc_index.insert(std::make_pair(a, os.str()));
deba@127
   663
	}
deba@127
   664
	for (typename ArcMaps::iterator it = _arc_maps.begin();
deba@127
   665
	     it != _arc_maps.end(); ++it) {
deba@127
   666
	  std::string value = it->second->get(a);
deba@127
   667
	  _writer_bits::writeToken(*_os, value);
deba@127
   668
	  if (it->first == "label") {
deba@127
   669
	    _arc_index.insert(std::make_pair(a, value));
deba@127
   670
	  }
deba@127
   671
	  *_os << '\t';
deba@127
   672
	}
deba@127
   673
	*_os << std::endl;
deba@127
   674
      }
deba@127
   675
    }
deba@127
   676
deba@127
   677
    void writeAttributes() {
deba@127
   678
      if (_attributes.empty()) return;
deba@127
   679
      *_os << "@attributes";
deba@127
   680
      if (!_attributes_caption.empty()) {
alpar@156
   681
	_writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@127
   682
      }
deba@127
   683
      *_os << std::endl;
deba@127
   684
      for (typename Attributes::iterator it = _attributes.begin();
deba@127
   685
	   it != _attributes.end(); ++it) {
alpar@156
   686
	_writer_bits::writeToken(*_os, it->first) << ' ';
deba@127
   687
	_writer_bits::writeToken(*_os, it->second->get());
deba@127
   688
	*_os << std::endl;
deba@127
   689
      }
deba@127
   690
    }
deba@127
   691
    
deba@127
   692
  public:
deba@127
   693
    
alpar@156
   694
    /// \name Execution of the writer    
alpar@156
   695
    /// @{
alpar@156
   696
alpar@156
   697
    /// \brief Start the batch processing
alpar@156
   698
    ///
alpar@156
   699
    /// This function starts the batch processing
deba@127
   700
    void run() {
deba@127
   701
      if (!_skip_nodes) {
deba@127
   702
	writeNodes();
deba@127
   703
      }
deba@127
   704
      if (!_skip_arcs) {      
deba@127
   705
	writeArcs();
deba@127
   706
      }
deba@127
   707
      writeAttributes();
deba@127
   708
    }
deba@127
   709
alpar@156
   710
    /// \brief Gives back the stream of the writer
alpar@156
   711
    ///
alpar@156
   712
    /// Gives back the stream of the writer
alpar@156
   713
    std::ostream& ostream() {
deba@127
   714
      return *_os;
deba@127
   715
    }
alpar@156
   716
alpar@156
   717
    /// @}
deba@127
   718
  };
deba@127
   719
alpar@156
   720
  /// \relates DigraphWriter
deba@127
   721
  template <typename Digraph>
deba@163
   722
  DigraphWriter<Digraph> digraphWriter(std::ostream& os, Digraph& digraph) {
deba@163
   723
    DigraphWriter<Digraph> tmp(os, digraph);
deba@163
   724
    return tmp;
deba@127
   725
  }
deba@127
   726
alpar@156
   727
  /// \relates DigraphWriter
deba@127
   728
  template <typename Digraph>
deba@127
   729
  DigraphWriter<Digraph> digraphWriter(const std::string& fn, 
deba@127
   730
				       Digraph& digraph) {
deba@163
   731
    DigraphWriter<Digraph> tmp(fn, digraph);
deba@163
   732
    return tmp;
deba@127
   733
  }
deba@127
   734
alpar@156
   735
  /// \relates DigraphWriter
deba@127
   736
  template <typename Digraph>
deba@127
   737
  DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) {
deba@163
   738
    DigraphWriter<Digraph> tmp(fn, digraph);
deba@163
   739
    return tmp;
deba@127
   740
  }
deba@127
   741
}
deba@127
   742
deba@127
   743
#endif