src/lemon/lemon_writer.h
author deba
Sat, 14 May 2005 17:39:37 +0000
changeset 1421 7a21e1414c38
parent 1411 5d161e08bda8
child 1429 4283998fb2be
permissions -rw-r--r--
IO with undirected edgesets and undirected graphs.
Missing features:
InfoReader,
aliased edges in undir edgesets
deba@1409
     1
/* -*- C++ -*-
deba@1409
     2
 * src/lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library
deba@1409
     3
 *
deba@1409
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1409
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1409
     6
 *
deba@1409
     7
 * Permission to use, modify and distribute this software is granted
deba@1409
     8
 * provided that this copyright notice appears in all copies. For
deba@1409
     9
 * precise terms see the accompanying LICENSE file.
deba@1409
    10
 *
deba@1409
    11
 * This software is provided "AS IS" with no warranty of any kind,
deba@1409
    12
 * express or implied, and with no claim as to its suitability for any
deba@1409
    13
 * purpose.
deba@1409
    14
 *
deba@1409
    15
 */
deba@1409
    16
deba@1409
    17
///\ingroup io_group
deba@1409
    18
///\file
deba@1409
    19
///\brief Lemon Format writer.
deba@1409
    20
deba@1409
    21
#ifndef LEMON_LEMON_WRITER_H
deba@1409
    22
#define LEMON_LEMON_WRITER_H
deba@1409
    23
deba@1409
    24
#include <iostream>
deba@1409
    25
#include <fstream>
deba@1409
    26
#include <string>
deba@1409
    27
#include <vector>
deba@1409
    28
#include <algorithm>
deba@1409
    29
#include <map>
deba@1409
    30
#include <memory>
deba@1409
    31
deba@1409
    32
#include <lemon/error.h>
deba@1409
    33
#include <lemon/invalid.h>
deba@1421
    34
#include <lemon/graph_utils.h>
deba@1409
    35
#include <lemon/bits/item_writer.h>
deba@1421
    36
#include <lemon/utility.h>
deba@1421
    37
#include <lemon/maps.h>
deba@1409
    38
deba@1409
    39
deba@1409
    40
namespace lemon {
deba@1409
    41
deba@1409
    42
  /// \ingroup io_group
deba@1409
    43
  /// \brief Lemon Format writer class.
deba@1409
    44
  /// 
deba@1409
    45
  /// The Lemon Format contains several sections. We do not want to
deba@1409
    46
  /// determine what sections are in a lemon file we give only a framework
deba@1409
    47
  /// to write a section oriented format.
deba@1409
    48
  ///
deba@1409
    49
  /// In the Lemon Format each section starts with a line contains a \c \@
deba@1409
    50
  /// character on the first not white space position. This line is the
deba@1409
    51
  /// header line of the section. Each next lines belong to this section
deba@1409
    52
  /// while it does not starts with \c \@ character. This line can start a 
deba@1409
    53
  /// new section or if it can close the file with the \c \@end line.
deba@1409
    54
  /// The file format ignore the empty lines and it may contain comments
deba@1409
    55
  /// started with a \c # character to the end of the line. 
deba@1409
    56
  ///
deba@1409
    57
  /// The framework provides an abstract LemonWriter::SectionWriter class
deba@1409
    58
  /// what defines the interface of a SectionWriter. The SectionWriter
deba@1409
    59
  /// has the \c header() member function what gives back the header of the
deba@1409
    60
  /// section. After that it will be called the \c write() member which
deba@1409
    61
  /// should write the content of the section.
deba@1409
    62
  ///
deba@1409
    63
  /// \relates GraphWriter
deba@1409
    64
  /// \relates NodeSetWriter
deba@1409
    65
  /// \relates EdgeSetWriter
deba@1409
    66
  /// \relates NodesWriter
deba@1409
    67
  /// \relates EdgesWriter
deba@1409
    68
  /// \relates AttributeWriter
deba@1409
    69
  class LemonWriter {
deba@1409
    70
  public:
deba@1409
    71
deba@1409
    72
    /// \brief Abstract base class for writing a section.
deba@1409
    73
    ///
deba@1409
    74
    /// This class has an \c header() member function what gives back
deba@1409
    75
    /// the header line of the section. The \c write() member should
deba@1409
    76
    /// write the content of the section to the stream.
deba@1409
    77
    class SectionWriter {
deba@1409
    78
      friend class LemonWriter;
deba@1409
    79
    protected:
deba@1409
    80
      /// \brief Constructor for SectionWriter.
deba@1409
    81
      ///
deba@1409
    82
      /// Constructor for SectionWriter. It attach this writer to
deba@1409
    83
      /// the given LemonWriter.
deba@1409
    84
      SectionWriter(LemonWriter& writer) {
deba@1409
    85
	writer.attach(*this);
deba@1409
    86
      }
deba@1409
    87
deba@1409
    88
      /// \brief The header of section.
deba@1409
    89
      ///
deba@1409
    90
      /// It gives back the header of the section.
deba@1409
    91
      virtual std::string header() = 0;
deba@1409
    92
deba@1409
    93
      /// \brief  Writer function of the section.
deba@1409
    94
      ///
deba@1409
    95
      /// Write the content of the section.
deba@1409
    96
      virtual void write(std::ostream& os) = 0;
deba@1409
    97
    };
deba@1409
    98
deba@1409
    99
    /// \brief Constructor for LemonWriter.
deba@1409
   100
    ///
deba@1409
   101
    /// Constructor for LemonWriter which writes to the given stream.
deba@1409
   102
    LemonWriter(std::ostream& _os) 
deba@1409
   103
      : os(&_os), own_os(false) {}
deba@1409
   104
deba@1409
   105
    /// \brief Constructor for LemonWriter.
deba@1409
   106
    ///
deba@1409
   107
    /// Constructor for LemonWriter which writes to the given file.
deba@1409
   108
    LemonWriter(const std::string& filename) 
deba@1409
   109
      : os(0), own_os(true) {
deba@1409
   110
      os = new std::ofstream(filename.c_str());
deba@1409
   111
    }
deba@1409
   112
deba@1409
   113
    /// \brief Desctructor for LemonWriter.
deba@1409
   114
    ///
deba@1409
   115
    /// Desctructor for LemonWriter.
deba@1409
   116
    ~LemonWriter() {
deba@1409
   117
      if (own_os) {
deba@1409
   118
	delete os;
deba@1409
   119
      }
deba@1409
   120
    }
deba@1409
   121
deba@1409
   122
  private:
deba@1409
   123
    LemonWriter(const LemonWriter&);
deba@1409
   124
    void operator=(const LemonWriter&);
deba@1409
   125
deba@1409
   126
    void attach(SectionWriter& writer) {
deba@1409
   127
      writers.push_back(&writer);
deba@1409
   128
    }
deba@1409
   129
deba@1409
   130
  public:
deba@1409
   131
deba@1409
   132
    /// \brief Executes the LemonWriter.
deba@1409
   133
    /// 
deba@1409
   134
    /// It executes the LemonWriter.
deba@1409
   135
    void run() {
deba@1409
   136
      SectionWriters::iterator it;
deba@1409
   137
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
   138
	*os << (*it)->header() << std::endl;
deba@1409
   139
	(*it)->write(*os);
deba@1409
   140
      }
deba@1409
   141
      *os << "@end" << std::endl;
deba@1409
   142
    }
deba@1409
   143
deba@1409
   144
deba@1409
   145
  private:
deba@1409
   146
deba@1409
   147
    std::ostream* os;
deba@1409
   148
    bool own_os;
deba@1409
   149
deba@1409
   150
    typedef std::vector<SectionWriter*> SectionWriters;
deba@1409
   151
    SectionWriters writers;
deba@1409
   152
deba@1409
   153
  };
deba@1409
   154
deba@1409
   155
  /// \brief Helper class for implementing the common SectionWriters.
deba@1409
   156
  ///
deba@1409
   157
  /// Helper class for implementing the common SectionWriters.
deba@1409
   158
  class CommonSectionWriterBase : public LemonWriter::SectionWriter {
deba@1409
   159
    typedef LemonWriter::SectionWriter Parent;
deba@1409
   160
  protected:
deba@1409
   161
    
deba@1409
   162
    /// \brief Constructor for CommonSectionWriterBase.
deba@1409
   163
    ///
deba@1409
   164
    /// Constructor for CommonSectionWriterBase. It attach this writer to
deba@1409
   165
    /// the given LemonWriter.
deba@1409
   166
    CommonSectionWriterBase(LemonWriter& _writer) 
deba@1409
   167
      : Parent(_writer) {}
deba@1409
   168
deba@1409
   169
    template <typename _Item>    
deba@1409
   170
    class WriterBase {
deba@1409
   171
    public:
deba@1409
   172
      typedef _Item Item;
deba@1409
   173
deba@1409
   174
      virtual ~WriterBase() {}
deba@1409
   175
deba@1409
   176
      virtual void write(std::ostream& os, const Item& item) = 0;
deba@1409
   177
    };
deba@1409
   178
deba@1409
   179
deba@1409
   180
    template <typename _Item, typename _Map, typename _Writer>
deba@1409
   181
    class MapWriter : public WriterBase<_Item> {
deba@1409
   182
    public:
deba@1409
   183
      typedef _Map Map;
deba@1409
   184
      typedef _Writer Writer;
deba@1409
   185
      typedef typename Writer::Value Value;
deba@1409
   186
      typedef _Item Item;
deba@1409
   187
      
deba@1421
   188
      typename SmartConstReference<Map>::Type map;
deba@1409
   189
      Writer writer;
deba@1409
   190
deba@1409
   191
      MapWriter(const Map& _map, const Writer& _writer) 
deba@1409
   192
	: map(_map), writer(_writer) {}
deba@1409
   193
deba@1409
   194
      virtual ~MapWriter() {}
deba@1409
   195
deba@1409
   196
      virtual void write(std::ostream& os, const Item& item) {
deba@1409
   197
	Value value = map[item];
deba@1409
   198
	writer.write(os, value);
deba@1409
   199
      }
deba@1409
   200
deba@1409
   201
    };
deba@1409
   202
deba@1409
   203
deba@1409
   204
    class ValueWriterBase {
deba@1409
   205
    public:
deba@1409
   206
      virtual void write(std::ostream&) = 0;
deba@1409
   207
    };
deba@1409
   208
deba@1409
   209
    template <typename _Value, typename _Writer>
deba@1409
   210
    class ValueWriter : public ValueWriterBase {
deba@1409
   211
    public:
deba@1409
   212
      typedef _Value Value;
deba@1409
   213
      typedef _Writer Writer;
deba@1409
   214
deba@1409
   215
      ValueWriter(const Value& _value, const Writer& _writer)
deba@1409
   216
 	: value(_value), writer(_writer) {}
deba@1409
   217
deba@1409
   218
      virtual void write(std::ostream& os) {
deba@1411
   219
	writer.write(os, value);
deba@1409
   220
      }
deba@1409
   221
    private:
deba@1409
   222
      const Value& value;
deba@1409
   223
      Writer writer;
deba@1409
   224
    };
deba@1409
   225
    
deba@1409
   226
deba@1409
   227
    template <typename _Item>
deba@1409
   228
    class IdWriterBase {
deba@1409
   229
    public:
deba@1409
   230
      typedef _Item Item;
deba@1409
   231
      virtual void write(std::ostream&, const Item&) const = 0;
deba@1409
   232
    };
deba@1409
   233
deba@1409
   234
    template <typename _Item, typename _BoxedIdWriter>
deba@1409
   235
    class IdWriter : public IdWriterBase<_Item> {
deba@1409
   236
    public:
deba@1409
   237
      typedef _Item Item;
deba@1409
   238
      typedef _BoxedIdWriter BoxedIdWriter;
deba@1409
   239
deba@1409
   240
      const BoxedIdWriter& idWriter;
deba@1409
   241
deba@1409
   242
      IdWriter(const BoxedIdWriter& _idWriter) 
deba@1409
   243
	: idWriter(_idWriter) {}
deba@1409
   244
deba@1409
   245
      virtual void write(std::ostream& os, const Item& item) const {
deba@1409
   246
	return idWriter.writeId(os, item);
deba@1409
   247
      }
deba@1409
   248
    };
deba@1409
   249
  };
deba@1409
   250
deba@1409
   251
  /// \ingroup io_group
deba@1409
   252
  /// \brief SectionWriter for writing a graph's nodeset.
deba@1409
   253
  ///
deba@1409
   254
  /// The lemon format can store multiple graph nodesets with several maps.
deba@1409
   255
  /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
deba@1409
   256
  /// \c nodeset_id may be empty.
deba@1409
   257
  ///
deba@1409
   258
  /// The first line of the section contains the names of the maps separated
deba@1409
   259
  /// with white spaces. Each next lines describes a node in the nodeset, and
deba@1409
   260
  /// contains the mapped values for each map.
deba@1409
   261
  ///
deba@1409
   262
  /// If the nodeset contains an \c "id" named map then it will be regarded
deba@1409
   263
  /// as id map. This map should contain only unique values and when the 
deba@1409
   264
  /// \c writeId() member will be called with a node it will write it's id.
deba@1409
   265
  /// Otherwise if the \c _forceIdMap constructor parameter is true then
deba@1409
   266
  /// the id map will be the id in the graph.
deba@1409
   267
  ///
deba@1409
   268
  /// \relates LemonWriter
deba@1409
   269
  template <typename _Graph, typename _Traits = DefaultWriterTraits>
deba@1409
   270
  class NodeSetWriter : public CommonSectionWriterBase {
deba@1409
   271
    typedef CommonSectionWriterBase Parent;
deba@1409
   272
  public:
deba@1409
   273
deba@1409
   274
    typedef _Graph Graph;
deba@1409
   275
    typedef _Traits Traits;
deba@1409
   276
    typedef typename Graph::Node Item;
deba@1409
   277
deba@1409
   278
    /// \brief Constructor.
deba@1409
   279
    ///
deba@1409
   280
    /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
deba@1409
   281
    /// attach it into the given LemonWriter. If the \c _forceIdMap
deba@1409
   282
    /// parameter is true then the writer will write own id map when
deba@1409
   283
    /// the user does not give "id" named map.
deba@1409
   284
    NodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
deba@1409
   285
		  const std::string& _id = std::string(), 
deba@1409
   286
		  bool _forceIdMap = true) 
deba@1409
   287
      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap), 
deba@1409
   288
	graph(_graph), id(_id) {}
deba@1409
   289
deba@1409
   290
    /// \brief Destructor.
deba@1409
   291
    ///
deba@1409
   292
    /// Destructor for NodeSetWriter.
deba@1409
   293
    virtual ~NodeSetWriter() {
deba@1409
   294
      typename MapWriters::iterator it;
deba@1409
   295
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
   296
	delete it->second;
deba@1409
   297
      }
deba@1409
   298
    }
deba@1409
   299
deba@1409
   300
  private:
deba@1409
   301
    NodeSetWriter(const NodeSetWriter&);
deba@1409
   302
    void operator=(const NodeSetWriter&);
deba@1409
   303
  
deba@1409
   304
  public:
deba@1409
   305
deba@1409
   306
    /// \brief Add a new node map writer command for the writer.
deba@1409
   307
    ///
deba@1409
   308
    /// Add a new node map writer command for the writer.
deba@1409
   309
    template <typename Map>
deba@1421
   310
    NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
deba@1421
   311
      return writeNodeMap<typename Traits::
deba@1409
   312
	template Writer<typename Map::Value>, Map>(name, map);
deba@1409
   313
    }
deba@1409
   314
deba@1409
   315
    /// \brief Add a new node map writer command for the writer.
deba@1409
   316
    ///
deba@1409
   317
    /// Add a new node map writer command for the writer.
deba@1409
   318
    template <typename Writer, typename Map>
deba@1421
   319
    NodeSetWriter& writeNodeMap(std::string name, const Map& map, 
deba@1421
   320
			    const Writer& writer = Writer()) {
deba@1409
   321
      writers.push_back(
deba@1409
   322
	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
deba@1409
   323
      return *this;
deba@1409
   324
    }
deba@1409
   325
deba@1409
   326
  protected:
deba@1409
   327
deba@1409
   328
    /// \brief The header of the section.
deba@1409
   329
    ///
deba@1409
   330
    /// It gives back the header of the section.
deba@1409
   331
    virtual std::string header() {
deba@1409
   332
      return "@nodeset " + id;
deba@1409
   333
    }
deba@1409
   334
deba@1409
   335
    /// \brief  Writer function of the section.
deba@1409
   336
    ///
deba@1409
   337
    /// Write the content of the section.
deba@1409
   338
    virtual void write(std::ostream& os) {
deba@1409
   339
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   340
	if (writers[i].first == "id") {
deba@1409
   341
	  idMap = writers[i].second;
deba@1409
   342
	  forceIdMap = false;
deba@1409
   343
	  break;
deba@1409
   344
	}
deba@1409
   345
      }
deba@1409
   346
      if (forceIdMap) {
deba@1409
   347
	os << "id\t";
deba@1409
   348
      }
deba@1409
   349
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   350
	os << writers[i].first << '\t';
deba@1409
   351
      }
deba@1409
   352
      os << std::endl;
deba@1409
   353
      for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
deba@1409
   354
	if (forceIdMap) {
deba@1409
   355
	  os << graph.id(it) << '\t';
deba@1409
   356
	}
deba@1409
   357
	for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   358
	  writers[i].second->write(os, it);
deba@1409
   359
	  os << '\t';
deba@1409
   360
	}
deba@1409
   361
	os << std::endl;
deba@1409
   362
      }
deba@1409
   363
    }
deba@1409
   364
deba@1409
   365
  public:
deba@1409
   366
deba@1409
   367
    /// \brief Returns true if the nodeset can write the ids of the nodes.
deba@1409
   368
    ///
deba@1409
   369
    /// Returns true if the nodeset can write the ids of the nodes.
deba@1409
   370
    /// It is possible only if an "id" named map was written or the 
deba@1409
   371
    /// \c _forceIdMap constructor parameter was true.
deba@1409
   372
    bool isIdWriter() const {
deba@1409
   373
      return idMap != 0 || forceIdMap;
deba@1409
   374
    }
deba@1409
   375
deba@1409
   376
    /// \brief Write the id of the given node.
deba@1409
   377
    ///
deba@1409
   378
    /// It writes the id of the given node. If there was written an "id"
deba@1409
   379
    /// named map then it will write the map value belongs to the node.
deba@1409
   380
    /// Otherwise if the \c forceId parameter was true it will write
deba@1409
   381
    /// its id in the graph. 
deba@1409
   382
    void writeId(std::ostream& os, const Item& item) const {
deba@1409
   383
      if (forceIdMap) {
deba@1409
   384
	os << graph.id(item);
deba@1409
   385
      } else {
deba@1409
   386
	idMap->write(os, item);
deba@1409
   387
      }
deba@1409
   388
    }
deba@1409
   389
deba@1409
   390
  private:
deba@1409
   391
deba@1409
   392
    typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
deba@1409
   393
    MapWriters writers;
deba@1409
   394
deba@1409
   395
    WriterBase<Item>* idMap;
deba@1409
   396
    bool forceIdMap;
deba@1409
   397
   
deba@1421
   398
    typename SmartConstReference<Graph>::Type graph;   
deba@1409
   399
    std::string id;
deba@1409
   400
deba@1409
   401
  };
deba@1409
   402
deba@1409
   403
  /// \ingroup io_group
deba@1421
   404
  /// \brief SectionWriter for writing a graph's edgesets.
deba@1409
   405
  ///
deba@1421
   406
  /// The lemon format can store multiple graph edgesets with several maps. 
deba@1409
   407
  /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
deba@1409
   408
  /// \c edgeset_id may be empty.
deba@1409
   409
  ///
deba@1409
   410
  /// The first line of the section contains the names of the maps separated
deba@1409
   411
  /// with white spaces. Each next lines describes a edge in the edgeset. The
deba@1409
   412
  /// line contains the source and the target nodes' id and the mapped 
deba@1409
   413
  /// values for each map.
deba@1409
   414
  ///
deba@1409
   415
  /// If the edgeset contains an \c "id" named map then it will be regarded
deba@1409
   416
  /// as id map. This map should contain only unique values and when the 
deba@1421
   417
  /// \c writeId() member will be called with an edge it will write it's id.
deba@1409
   418
  /// Otherwise if the \c _forceIdMap constructor parameter is true then
deba@1409
   419
  /// the id map will be the id in the graph.
deba@1409
   420
  ///
deba@1409
   421
  /// The edgeset writer needs a node id writer to identify which nodes
deba@1409
   422
  /// have to be connected. If a NodeSetWriter can write the nodes' id,
deba@1409
   423
  /// it will be able to use with this class.
deba@1409
   424
  ///
deba@1409
   425
  /// \relates LemonWriter
deba@1409
   426
  template <typename _Graph, typename _Traits = DefaultWriterTraits>
deba@1409
   427
  class EdgeSetWriter : public CommonSectionWriterBase {
deba@1409
   428
    typedef CommonSectionWriterBase Parent;
deba@1409
   429
  public:
deba@1409
   430
deba@1409
   431
    typedef _Graph Graph;
deba@1409
   432
    typedef _Traits Traits;
deba@1409
   433
    typedef typename Graph::Edge Item;
deba@1409
   434
deba@1409
   435
    /// \brief Constructor.
deba@1409
   436
    ///
deba@1409
   437
    /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
deba@1409
   438
    /// attach it into the given LemonWriter. It will write node ids by
deba@1409
   439
    /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true 
deba@1421
   440
    /// then the writer will write own id map if the user does not give 
deba@1409
   441
    /// "id" named map.
deba@1409
   442
    template <typename NodeIdWriter>
deba@1409
   443
    EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
deba@1409
   444
		  const NodeIdWriter& _nodeIdWriter, 
deba@1409
   445
		  const std::string& _id = std::string(),
deba@1409
   446
		  bool _forceIdMap = true)
deba@1409
   447
      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
deba@1409
   448
	graph(_graph), id(_id),
deba@1409
   449
	nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
deba@1409
   450
		     (_nodeIdWriter)) {} 
deba@1409
   451
deba@1409
   452
    /// \brief Destructor.
deba@1409
   453
    ///
deba@1409
   454
    /// Destructor for EdgeSetWriter.
deba@1409
   455
    virtual ~EdgeSetWriter() {
deba@1409
   456
      typename MapWriters::iterator it;
deba@1409
   457
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
   458
	delete it->second;
deba@1409
   459
      }
deba@1409
   460
    }
deba@1409
   461
deba@1409
   462
  private:
deba@1409
   463
    EdgeSetWriter(const EdgeSetWriter&);
deba@1409
   464
    void operator=(const EdgeSetWriter&);
deba@1409
   465
deba@1409
   466
  public:
deba@1409
   467
deba@1421
   468
    /// \brief Add a new edge map writer command for the writer.
deba@1409
   469
    ///
deba@1421
   470
    /// Add a new edge map writer command for the writer.
deba@1409
   471
    template <typename Map>
deba@1421
   472
    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
deba@1421
   473
      return writeEdgeMap<typename Traits::
deba@1409
   474
	template Writer<typename Map::Value>, Map>(name, map);
deba@1409
   475
    }
deba@1409
   476
deba@1421
   477
    /// \brief Add a new edge map writer command for the writer.
deba@1409
   478
    ///
deba@1421
   479
    /// Add a new edge map writer command for the writer.
deba@1409
   480
    template <typename Writer, typename Map>
deba@1421
   481
    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map, 
deba@1421
   482
			    const Writer& writer = Writer()) {
deba@1409
   483
      writers.push_back(
deba@1409
   484
	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
deba@1409
   485
      return *this;
deba@1409
   486
    }
deba@1409
   487
deba@1409
   488
  protected:
deba@1409
   489
deba@1409
   490
    /// \brief The header of the section.
deba@1409
   491
    ///
deba@1409
   492
    /// It gives back the header of the section.
deba@1409
   493
    virtual std::string header() {
deba@1409
   494
      return "@edgeset " + id;
deba@1409
   495
    }
deba@1409
   496
deba@1409
   497
    /// \brief  Writer function of the section.
deba@1409
   498
    ///
deba@1409
   499
    /// Write the content of the section.
deba@1409
   500
    virtual void write(std::ostream& os) {
deba@1409
   501
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   502
	if (writers[i].first == "id") {
deba@1409
   503
	  idMap = writers[i].second;
deba@1409
   504
	  forceIdMap = false;
deba@1409
   505
	  break;
deba@1409
   506
	}
deba@1409
   507
      }
deba@1409
   508
      os << "\t\t";
deba@1409
   509
      if (forceIdMap) {
deba@1409
   510
	os << "id\t";
deba@1409
   511
      }
deba@1409
   512
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   513
	os << writers[i].first << '\t';
deba@1409
   514
      }
deba@1409
   515
      os << std::endl;
deba@1409
   516
      for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
deba@1409
   517
	nodeIdWriter->write(os, graph.source(it));
deba@1409
   518
	os << '\t';
deba@1409
   519
	nodeIdWriter->write(os, graph.target(it));
deba@1409
   520
	os << '\t';
deba@1409
   521
	if (forceIdMap) {
deba@1409
   522
	  os << graph.id(it) << '\t';
deba@1409
   523
	}
deba@1409
   524
	for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   525
	  writers[i].second->write(os, it);
deba@1409
   526
	  os << '\t';
deba@1409
   527
	}
deba@1409
   528
	os << std::endl;
deba@1409
   529
      }
deba@1409
   530
    }
deba@1409
   531
deba@1409
   532
  public:
deba@1409
   533
deba@1409
   534
    /// \brief Returns true if the edgeset can write the ids of the edges.
deba@1409
   535
    ///
deba@1409
   536
    /// Returns true if the edgeset can write the ids of the edges.
deba@1409
   537
    /// It is possible only if an "id" named map was written or the 
deba@1409
   538
    /// \c _forceIdMap constructor parameter was true.
deba@1409
   539
    bool isIdWriter() const {
deba@1409
   540
      return forceIdMap || idMap != 0;
deba@1409
   541
    }
deba@1409
   542
deba@1409
   543
    /// \brief Write the id of the given edge.
deba@1409
   544
    ///
deba@1409
   545
    /// It writes the id of the given edge. If there was written an "id"
deba@1409
   546
    /// named map then it will write the map value belongs to the edge.
deba@1409
   547
    /// Otherwise if the \c forceId parameter was true it will write
deba@1409
   548
    /// its id in the graph. 
deba@1409
   549
    void writeId(std::ostream& os, const Item& item) const {
deba@1409
   550
      if (forceIdMap) {
deba@1409
   551
	os << graph.id(item);
deba@1409
   552
      } else {
deba@1409
   553
	idMap->write(os, item);
deba@1409
   554
      }
deba@1409
   555
    } 
deba@1409
   556
deba@1409
   557
  private:
deba@1409
   558
deba@1409
   559
    typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
deba@1409
   560
    MapWriters writers;
deba@1409
   561
deba@1409
   562
    WriterBase<Item>* idMap;
deba@1409
   563
    bool forceIdMap;
deba@1409
   564
   
deba@1421
   565
    typename SmartConstReference<Graph>::Type graph;   
deba@1421
   566
    std::string id;
deba@1421
   567
deba@1421
   568
    std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
deba@1421
   569
  };
deba@1421
   570
deba@1421
   571
  /// \ingroup io_group
deba@1421
   572
  /// \brief SectionWriter for writing a undirected edgeset.
deba@1421
   573
  ///
deba@1421
   574
  /// The lemon format can store multiple undirected edgesets with several 
deba@1421
   575
  /// maps. The undirected edgeset section's header line is \c \@undiredgeset 
deba@1421
   576
  /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
deba@1421
   577
  ///
deba@1421
   578
  /// The first line of the section contains the names of the maps separated
deba@1421
   579
  /// with white spaces. Each next lines describes an undirected edge in the 
deba@1421
   580
  /// edgeset. The line contains the two connected nodes' id and the mapped 
deba@1421
   581
  /// values for each undirected map.
deba@1421
   582
  ///
deba@1421
   583
  /// The section can handle the directed as a syntactical sugar. Two
deba@1421
   584
  /// undirected edge map describes one directed edge map. This two maps
deba@1421
   585
  /// are the forward map and the backward map and the names of this map
deba@1421
   586
  /// is near the same just with a prefix \c '+' or \c '-' character 
deba@1421
   587
  /// difference.
deba@1421
   588
  ///
deba@1421
   589
  /// If the edgeset contains an \c "id" named map then it will be regarded
deba@1421
   590
  /// as id map. This map should contain only unique values and when the 
deba@1421
   591
  /// \c writeId() member will be called with an undirected edge it will 
deba@1421
   592
  /// write it's id. Otherwise if the \c _forceIdMap constructor parameter
deba@1421
   593
  /// is true then the id map will be the id in the graph.
deba@1421
   594
  ///
deba@1421
   595
  /// The undirected edgeset writer needs a node id writer to identify 
deba@1421
   596
  /// which nodes have to be connected. If a NodeSetWriter can write the 
deba@1421
   597
  /// nodes' id, it will be able to use with this class.
deba@1421
   598
  ///
deba@1421
   599
  /// \relates LemonWriter
deba@1421
   600
  template <typename _Graph, typename _Traits = DefaultWriterTraits>
deba@1421
   601
  class UndirEdgeSetWriter : public CommonSectionWriterBase {
deba@1421
   602
    typedef CommonSectionWriterBase Parent;
deba@1421
   603
  public:
deba@1421
   604
deba@1421
   605
    typedef _Graph Graph;
deba@1421
   606
    typedef _Traits Traits;
deba@1421
   607
    typedef typename Graph::UndirEdge Item;
deba@1421
   608
deba@1421
   609
    /// \brief Constructor.
deba@1421
   610
    ///
deba@1421
   611
    /// Constructor for UndirEdgeSetWriter. It creates the UndirEdgeSetWriter
deba@1421
   612
    /// and attach it into the given LemonWriter. It will write node ids by
deba@1421
   613
    /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true 
deba@1421
   614
    /// then the writer will write own id map if the user does not give 
deba@1421
   615
    /// "id" named map.
deba@1421
   616
    template <typename NodeIdWriter>
deba@1421
   617
    UndirEdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
deba@1421
   618
		       const NodeIdWriter& _nodeIdWriter, 
deba@1421
   619
		       const std::string& _id = std::string(),
deba@1421
   620
		       bool _forceIdMap = true)
deba@1421
   621
      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
deba@1421
   622
	graph(_graph), id(_id),
deba@1421
   623
	nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
deba@1421
   624
		     (_nodeIdWriter)) {} 
deba@1421
   625
deba@1421
   626
    /// \brief Destructor.
deba@1421
   627
    ///
deba@1421
   628
    /// Destructor for UndirEdgeSetWriter.
deba@1421
   629
    virtual ~UndirEdgeSetWriter() {
deba@1421
   630
      typename MapWriters::iterator it;
deba@1421
   631
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1421
   632
	delete it->second;
deba@1421
   633
      }
deba@1421
   634
    }
deba@1421
   635
deba@1421
   636
  private:
deba@1421
   637
    UndirEdgeSetWriter(const UndirEdgeSetWriter&);
deba@1421
   638
    void operator=(const UndirEdgeSetWriter&);
deba@1421
   639
deba@1421
   640
  public:
deba@1421
   641
deba@1421
   642
    /// \brief Add a new undirected edge map writer command for the writer.
deba@1421
   643
    ///
deba@1421
   644
    /// Add a new undirected map writer command for the writer.
deba@1421
   645
    template <typename Map>
deba@1421
   646
    UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map) {
deba@1421
   647
      return writeUndirEdgeMap<typename Traits::
deba@1421
   648
	template Writer<typename Map::Value>, Map>(name, map);
deba@1421
   649
    }
deba@1421
   650
deba@1421
   651
    /// \brief Add a new undirected map writer command for the writer.
deba@1421
   652
    ///
deba@1421
   653
    /// Add a new undirected map writer command for the writer.
deba@1421
   654
    template <typename Writer, typename Map>
deba@1421
   655
    UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map, 
deba@1421
   656
					  const Writer& writer = Writer()) {
deba@1421
   657
      writers.push_back(
deba@1421
   658
	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
deba@1421
   659
      return *this;
deba@1421
   660
    }
deba@1421
   661
deba@1421
   662
    /// \brief Add a new directed edge map writer command for the writer.
deba@1421
   663
    ///
deba@1421
   664
    /// Add a new directed map writer command for the writer.
deba@1421
   665
    template <typename Map>
deba@1421
   666
    UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
deba@1421
   667
      writeUndirEdgeMap("+" + name, composeMap(forwardMap(graph), map));
deba@1421
   668
      writeUndirEdgeMap("-" + name, composeMap(backwardMap(graph), map));
deba@1421
   669
      return *this;
deba@1421
   670
    }
deba@1421
   671
deba@1421
   672
    /// \brief Add a new directed map writer command for the writer.
deba@1421
   673
    ///
deba@1421
   674
    /// Add a new directed map writer command for the writer.
deba@1421
   675
    template <typename Writer, typename Map>
deba@1421
   676
    UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map, 
deba@1421
   677
				     const Writer& writer = Writer()) {
deba@1421
   678
      writeUndirEdge("+" + name, composeMap(forwardMap(graph), map), writer);
deba@1421
   679
      writeUndirEdge("-" + name, composeMap(forwardMap(graph), map), writer);
deba@1421
   680
      return *this;
deba@1421
   681
    }
deba@1421
   682
deba@1421
   683
  protected:
deba@1421
   684
deba@1421
   685
    /// \brief The header of the section.
deba@1421
   686
    ///
deba@1421
   687
    /// It gives back the header of the section.
deba@1421
   688
    virtual std::string header() {
deba@1421
   689
      return "@undiredgeset " + id;
deba@1421
   690
    }
deba@1421
   691
deba@1421
   692
    /// \brief  Writer function of the section.
deba@1421
   693
    ///
deba@1421
   694
    /// Write the content of the section.
deba@1421
   695
    virtual void write(std::ostream& os) {
deba@1421
   696
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1421
   697
	if (writers[i].first == "id") {
deba@1421
   698
	  idMap = writers[i].second;
deba@1421
   699
	  forceIdMap = false;
deba@1421
   700
	  break;
deba@1421
   701
	}
deba@1421
   702
      }
deba@1421
   703
      os << "\t\t";
deba@1421
   704
      if (forceIdMap) {
deba@1421
   705
	os << "id\t";
deba@1421
   706
      }
deba@1421
   707
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1421
   708
	os << writers[i].first << '\t';
deba@1421
   709
      }
deba@1421
   710
      os << std::endl;
deba@1421
   711
      for (typename Graph::UndirEdgeIt it(graph); it != INVALID; ++it) {
deba@1421
   712
	nodeIdWriter->write(os, graph.source(it));
deba@1421
   713
	os << '\t';
deba@1421
   714
	nodeIdWriter->write(os, graph.target(it));
deba@1421
   715
	os << '\t';
deba@1421
   716
	if (forceIdMap) {
deba@1421
   717
	  os << graph.id(it) << '\t';
deba@1421
   718
	}
deba@1421
   719
	for (int i = 0; i < (int)writers.size(); ++i) {
deba@1421
   720
	  writers[i].second->write(os, it);
deba@1421
   721
	  os << '\t';
deba@1421
   722
	}
deba@1421
   723
	os << std::endl;
deba@1421
   724
      }
deba@1421
   725
    }
deba@1421
   726
deba@1421
   727
  public:
deba@1421
   728
deba@1421
   729
    /// \brief Returns true if the undirected edgeset can write the ids of 
deba@1421
   730
    /// the edges.
deba@1421
   731
    ///
deba@1421
   732
    /// Returns true if the undirected edgeset can write the ids of the 
deba@1421
   733
    /// undirected edges. It is possible only if an "id" named map was 
deba@1421
   734
    /// written or the \c _forceIdMap constructor parameter was true.
deba@1421
   735
    bool isIdWriter() const {
deba@1421
   736
      return forceIdMap || idMap != 0;
deba@1421
   737
    }
deba@1421
   738
deba@1421
   739
    /// \brief Write the id of the given undirected edge.
deba@1421
   740
    ///
deba@1421
   741
    /// It writes the id of the given undirected edge. If there was written 
deba@1421
   742
    /// an "id" named map then it will write the map value belongs to the 
deba@1421
   743
    /// undirected edge. Otherwise if the \c forceId parameter was true it 
deba@1421
   744
    /// will write its id in the graph. 
deba@1421
   745
    void writeId(std::ostream& os, const Item& item) const {
deba@1421
   746
      if (forceIdMap) {
deba@1421
   747
	os << graph.id(item);
deba@1421
   748
      } else {
deba@1421
   749
	idMap->write(os, item);
deba@1421
   750
      }
deba@1421
   751
    } 
deba@1421
   752
deba@1421
   753
  private:
deba@1421
   754
deba@1421
   755
    typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
deba@1421
   756
    MapWriters writers;
deba@1421
   757
deba@1421
   758
    WriterBase<Item>* idMap;
deba@1421
   759
    bool forceIdMap;
deba@1421
   760
   
deba@1421
   761
    typename SmartConstReference<Graph>::Type graph;   
deba@1409
   762
    std::string id;
deba@1409
   763
deba@1409
   764
    std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
deba@1409
   765
  };
deba@1409
   766
deba@1409
   767
  /// \ingroup io_group
deba@1409
   768
  /// \brief SectionWriter for writing labeled nodes.
deba@1409
   769
  ///
deba@1409
   770
  /// The nodes section's header line is \c \@nodes \c nodes_id, but the
deba@1409
   771
  /// \c nodes_id may be empty.
deba@1409
   772
  ///
deba@1409
   773
  /// Each line in the section contains the label of the node and 
deba@1409
   774
  /// then the node id. 
deba@1409
   775
  ///
deba@1409
   776
  /// \relates LemonWriter
deba@1409
   777
  template <typename _Graph>
deba@1409
   778
  class NodeWriter : public CommonSectionWriterBase {
deba@1409
   779
    typedef CommonSectionWriterBase Parent;
deba@1409
   780
    typedef _Graph Graph;
deba@1409
   781
    typedef typename Graph::Node Item;
deba@1409
   782
  public:
deba@1409
   783
    
deba@1409
   784
    /// \brief Constructor.
deba@1409
   785
    ///
deba@1409
   786
    /// Constructor for NodeWriter. It creates the NodeWriter and
deba@1409
   787
    /// attach it into the given LemonWriter. The given \c _IdWriter
deba@1409
   788
    /// will write the nodes' id what can be a nodeset writer.
deba@1409
   789
    template <typename _IdWriter>
deba@1409
   790
    NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
deba@1409
   791
	       const std::string& _id = std::string()) 
deba@1409
   792
      : Parent(_writer), id(_id), 
deba@1409
   793
	idWriter(new IdWriter<typename Graph::Node, _IdWriter>(_idWriter)) {} 
deba@1409
   794
deba@1409
   795
    /// \brief Destructor.
deba@1409
   796
    ///
deba@1409
   797
    /// Destructor for NodeWriter.
deba@1409
   798
    virtual ~NodeWriter() {}
deba@1409
   799
deba@1409
   800
  private:
deba@1409
   801
    NodeWriter(const NodeWriter&);
deba@1409
   802
    void operator=(const NodeWriter&);
deba@1409
   803
deba@1409
   804
  public:
deba@1409
   805
deba@1409
   806
    /// \brief Add a node writer command for the NodeWriter.
deba@1409
   807
    ///
deba@1409
   808
    /// Add a node writer command for the NodeWriter.
deba@1409
   809
    void writeNode(const std::string& name, const Item& item) {
deba@1409
   810
      writers.push_back(make_pair(name, &item));
deba@1409
   811
    }
deba@1409
   812
deba@1409
   813
  protected:
deba@1409
   814
deba@1409
   815
    /// \brief Header checking function.
deba@1409
   816
    ///
deba@1421
   817
    /// It gives back true when the header line start with \c \@nodes,
deba@1409
   818
    /// and the header line's id and the writer's id are the same.
deba@1409
   819
    virtual std::string header() {
deba@1409
   820
      return "@nodes " + id;
deba@1409
   821
    }
deba@1409
   822
deba@1409
   823
    /// \brief  Writer function of the section.
deba@1409
   824
    ///
deba@1409
   825
    /// Write the content of the section.
deba@1409
   826
    virtual void write(std::ostream& os) {
deba@1409
   827
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   828
	os << writers[i].first << ' ';
deba@1409
   829
	idWriter->write(os, *(writers[i].second));
deba@1409
   830
	os << std::endl;
deba@1409
   831
      }
deba@1409
   832
    }
deba@1409
   833
    
deba@1409
   834
  private:
deba@1409
   835
deba@1409
   836
    std::string id;
deba@1409
   837
deba@1409
   838
    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
deba@1409
   839
    ItemWriters writers;
deba@1409
   840
    std::auto_ptr<IdWriterBase<Item> > idWriter;
deba@1409
   841
  };
deba@1409
   842
deba@1409
   843
  /// \ingroup io_group
deba@1421
   844
  /// \brief SectionWriter for writing labeled edges.
deba@1409
   845
  ///
deba@1409
   846
  /// The edges section's header line is \c \@edges \c edges_id, but the
deba@1409
   847
  /// \c edges_id may be empty.
deba@1409
   848
  ///
deba@1409
   849
  /// Each line in the section contains the label of the edge and 
deba@1409
   850
  /// then the edge id. 
deba@1409
   851
  ///
deba@1409
   852
  /// \relates LemonWriter
deba@1409
   853
  template <typename _Graph>
deba@1409
   854
  class EdgeWriter : public CommonSectionWriterBase {
deba@1409
   855
    typedef CommonSectionWriterBase Parent;
deba@1409
   856
    typedef _Graph Graph;
deba@1409
   857
    typedef typename Graph::Edge Item;
deba@1409
   858
  public:
deba@1409
   859
    
deba@1409
   860
    /// \brief Constructor.
deba@1409
   861
    ///
deba@1409
   862
    /// Constructor for EdgeWriter. It creates the EdgeWriter and
deba@1409
   863
    /// attach it into the given LemonWriter. The given \c _IdWriter
deba@1409
   864
    /// will write the edges' id what can be a edgeset writer.
deba@1409
   865
    template <typename _IdWriter>
deba@1409
   866
    EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
deba@1409
   867
	       const std::string& _id = std::string()) 
deba@1409
   868
      : Parent(_writer), id(_id), 
deba@1409
   869
	idWriter(new IdWriter<typename Graph::Edge, _IdWriter>(_idWriter)) {} 
deba@1409
   870
deba@1409
   871
    /// \brief Destructor.
deba@1409
   872
    ///
deba@1409
   873
    /// Destructor for EdgeWriter.
deba@1409
   874
    virtual ~EdgeWriter() {}
deba@1409
   875
  private:
deba@1409
   876
    EdgeWriter(const EdgeWriter&);
deba@1409
   877
    void operator=(const EdgeWriter&);
deba@1409
   878
deba@1409
   879
  public:
deba@1409
   880
deba@1421
   881
    /// \brief Add an edge writer command for the EdgeWriter.
deba@1409
   882
    ///
deba@1421
   883
    /// Add an edge writer command for the EdgeWriter.
deba@1409
   884
    void writeEdge(const std::string& name, const Item& item) {
deba@1409
   885
      writers.push_back(make_pair(name, &item));
deba@1409
   886
    }
deba@1409
   887
deba@1409
   888
  protected:
deba@1409
   889
deba@1409
   890
    /// \brief Header checking function.
deba@1409
   891
    ///
deba@1421
   892
    /// It gives back true when the header line start with \c \@edges,
deba@1421
   893
    /// and the header line's id and the writer's id are the same.
deba@1421
   894
    virtual std::string header() {
deba@1421
   895
      return "@edges " + id;
deba@1421
   896
    }
deba@1421
   897
deba@1421
   898
    /// \brief  Writer function of the section.
deba@1421
   899
    ///
deba@1421
   900
    /// Write the content of the section.
deba@1421
   901
    virtual void write(std::ostream& os) {
deba@1421
   902
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1421
   903
	os << writers[i].first << ' ';
deba@1421
   904
	idWriter->write(os, *(writers[i].second));
deba@1421
   905
	os << std::endl;
deba@1421
   906
      }
deba@1421
   907
    }
deba@1421
   908
    
deba@1421
   909
  private:
deba@1421
   910
deba@1421
   911
    std::string id;
deba@1421
   912
deba@1421
   913
    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
deba@1421
   914
    ItemWriters writers;
deba@1421
   915
deba@1421
   916
    std::auto_ptr<IdWriterBase<Item> > idWriter;
deba@1421
   917
  };
deba@1421
   918
deba@1421
   919
  /// \ingroup io_group
deba@1421
   920
  /// \brief SectionWriter for writing labeled undirected edges.
deba@1421
   921
  ///
deba@1421
   922
  /// The undirected edges section's header line is \c \@undiredges 
deba@1421
   923
  /// \c undiredges_id, but the \c undiredges_id may be empty.
deba@1421
   924
  ///
deba@1421
   925
  /// Each line in the section contains the label of the undirected edge and 
deba@1421
   926
  /// then the undirected edge id. 
deba@1421
   927
  ///
deba@1421
   928
  /// \relates LemonWriter
deba@1421
   929
  template <typename _Graph>
deba@1421
   930
  class UndirEdgeWriter : public CommonSectionWriterBase {
deba@1421
   931
    typedef CommonSectionWriterBase Parent;
deba@1421
   932
    typedef _Graph Graph;
deba@1421
   933
    typedef typename Graph::UndirEdge Item;
deba@1421
   934
  public:
deba@1421
   935
    
deba@1421
   936
    /// \brief Constructor.
deba@1421
   937
    ///
deba@1421
   938
    /// Constructor for UndirEdgeWriter. It creates the UndirEdgeWriter and
deba@1421
   939
    /// attach it into the given LemonWriter. The given \c _IdWriter
deba@1421
   940
    /// will write the undirected edges' id what can be an undirected 
deba@1421
   941
    /// edgeset writer.
deba@1421
   942
    template <typename _IdWriter>
deba@1421
   943
    UndirEdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
deba@1421
   944
	       const std::string& _id = std::string()) 
deba@1421
   945
      : Parent(_writer), id(_id), 
deba@1421
   946
	idWriter(new IdWriter<typename Graph::UndirEdge, _IdWriter>
deba@1421
   947
		 (_idWriter)) {} 
deba@1421
   948
deba@1421
   949
    /// \brief Destructor.
deba@1421
   950
    ///
deba@1421
   951
    /// Destructor for UndirEdgeWriter.
deba@1421
   952
    virtual ~UndirEdgeWriter() {}
deba@1421
   953
  private:
deba@1421
   954
    UndirEdgeWriter(const UndirEdgeWriter&);
deba@1421
   955
    void operator=(const UndirEdgeWriter&);
deba@1421
   956
deba@1421
   957
  public:
deba@1421
   958
deba@1421
   959
    /// \brief Add an undirected edge writer command for the UndirEdgeWriter.
deba@1421
   960
    ///
deba@1421
   961
    /// Add an edge writer command for the UndirEdgeWriter.
deba@1421
   962
    void writeUndirEdge(const std::string& name, const Item& item) {
deba@1421
   963
      writers.push_back(make_pair(name, &item));
deba@1421
   964
    }
deba@1421
   965
deba@1421
   966
  protected:
deba@1421
   967
deba@1421
   968
    /// \brief Header checking function.
deba@1421
   969
    ///
deba@1421
   970
    /// It gives back true when the header line start with \c \@undiredges,
deba@1409
   971
    /// and the header line's id and the writer's id are the same.
deba@1409
   972
    virtual std::string header() {
deba@1409
   973
      return "@edges " + id;
deba@1409
   974
    }
deba@1409
   975
deba@1409
   976
    /// \brief  Writer function of the section.
deba@1409
   977
    ///
deba@1409
   978
    /// Write the content of the section.
deba@1409
   979
    virtual void write(std::ostream& os) {
deba@1409
   980
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   981
	os << writers[i].first << ' ';
deba@1409
   982
	idWriter->write(os, *(writers[i].second));
deba@1409
   983
	os << std::endl;
deba@1409
   984
      }
deba@1409
   985
    }
deba@1409
   986
    
deba@1409
   987
  private:
deba@1409
   988
deba@1409
   989
    std::string id;
deba@1409
   990
deba@1409
   991
    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
deba@1409
   992
    ItemWriters writers;
deba@1409
   993
deba@1409
   994
    std::auto_ptr<IdWriterBase<Item> > idWriter;
deba@1409
   995
  };
deba@1409
   996
deba@1409
   997
  /// \ingroup io_group
deba@1409
   998
  /// \brief SectionWriter for attributes.
deba@1409
   999
  ///
deba@1409
  1000
  /// The lemon format can store multiple attribute set. Each set has
deba@1409
  1001
  /// the header line \c \@attributes \c attributeset_id, but the 
deba@1409
  1002
  /// attributeset_id may be empty.
deba@1409
  1003
  ///
deba@1409
  1004
  /// The attributeset section contains several lines. Each of them starts
deba@1409
  1005
  /// with the name of attribute and then the value.
deba@1409
  1006
  ///
deba@1409
  1007
  /// \relates LemonWriter
deba@1409
  1008
  template <typename _Traits = DefaultWriterTraits>
deba@1409
  1009
  class AttributeWriter : public CommonSectionWriterBase {
deba@1409
  1010
    typedef CommonSectionWriterBase Parent;
deba@1409
  1011
    typedef _Traits Traits; 
deba@1409
  1012
  public:
deba@1409
  1013
    /// \brief Constructor.
deba@1409
  1014
    ///
deba@1409
  1015
    /// Constructor for AttributeWriter. It creates the AttributeWriter and
deba@1409
  1016
    /// attach it into the given LemonWriter.
deba@1409
  1017
    AttributeWriter(LemonWriter& _writer, 
deba@1409
  1018
		    const std::string& _id = std::string()) 
deba@1409
  1019
      : Parent(_writer), id(_id) {}
deba@1409
  1020
deba@1409
  1021
    /// \brief Destructor.
deba@1409
  1022
    ///
deba@1409
  1023
    /// Destructor for AttributeWriter.
deba@1409
  1024
    virtual ~AttributeWriter() {
deba@1409
  1025
      typename Writers::iterator it;
deba@1409
  1026
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
  1027
	delete it->second;
deba@1409
  1028
      }
deba@1409
  1029
    }
deba@1409
  1030
deba@1409
  1031
  private:
deba@1409
  1032
    AttributeWriter(const AttributeWriter&);
deba@1409
  1033
    void operator=(AttributeWriter&);
deba@1409
  1034
deba@1409
  1035
  public:
deba@1409
  1036
    /// \brief Add an attribute writer command for the writer.
deba@1409
  1037
    ///
deba@1409
  1038
    /// Add an attribute writer command for the writer.
deba@1409
  1039
    template <typename Value>
deba@1409
  1040
    AttributeWriter& writeAttribute(const std::string& id, 
deba@1409
  1041
				    const Value& value) {
deba@1409
  1042
      return 
deba@1409
  1043
	writeAttribute<typename Traits::template Writer<Value> >(id, value);
deba@1409
  1044
    }
deba@1409
  1045
deba@1409
  1046
    /// \brief Add an attribute writer command for the writer.
deba@1409
  1047
    ///
deba@1409
  1048
    /// Add an attribute writer command for the writer.
deba@1409
  1049
    template <typename Writer, typename Value>
deba@1409
  1050
    AttributeWriter& writeAttribute(const std::string& name, 
deba@1409
  1051
				    const Value& value,
deba@1409
  1052
				    const Writer& writer = Writer()) {
deba@1409
  1053
      writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
deba@1409
  1054
      			       (value, writer)));
deba@1409
  1055
      return *this;
deba@1409
  1056
    }
deba@1409
  1057
deba@1409
  1058
  protected:
deba@1409
  1059
deba@1409
  1060
    /// \brief The header of section.
deba@1409
  1061
    ///
deba@1409
  1062
    /// It gives back the header of the section.
deba@1409
  1063
    std::string header() {
deba@1409
  1064
      return "@attributes " + id;
deba@1409
  1065
    }
deba@1409
  1066
deba@1409
  1067
    /// \brief  Writer function of the section.
deba@1409
  1068
    ///
deba@1409
  1069
    /// Write the content of the section.
deba@1409
  1070
    void write(std::ostream& os) {
deba@1409
  1071
      typename Writers::iterator it;
deba@1409
  1072
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
  1073
	os << it->first << ' ';
deba@1409
  1074
	it->second->write(os);
deba@1409
  1075
	os << std::endl;
deba@1409
  1076
      }
deba@1409
  1077
    }    
deba@1409
  1078
deba@1409
  1079
  private:
deba@1409
  1080
    std::string id;
deba@1409
  1081
deba@1409
  1082
    typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;
deba@1409
  1083
    Writers writers;  
deba@1409
  1084
  };
deba@1409
  1085
deba@1409
  1086
deba@1409
  1087
}
deba@1409
  1088
#endif