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