lemon/lemon_writer.h
author alpar
Thu, 01 Mar 2007 16:03:36 +0000
changeset 2379 248152674a9e
parent 2260 4274224f8a7d
child 2386 81b47fc5c444
permissions -rw-r--r--
Prescaling can be turned off
deba@1409
     1
/* -*- C++ -*-
deba@1409
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@1956
     5
 * Copyright (C) 2003-2006
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1409
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1409
     8
 *
deba@1409
     9
 * Permission to use, modify and distribute this software is granted
deba@1409
    10
 * provided that this copyright notice appears in all copies. For
deba@1409
    11
 * precise terms see the accompanying LICENSE file.
deba@1409
    12
 *
deba@1409
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@1409
    14
 * express or implied, and with no claim as to its suitability for any
deba@1409
    15
 * purpose.
deba@1409
    16
 *
deba@1409
    17
 */
deba@1409
    18
deba@2084
    19
///\ingroup lemon_io
deba@1409
    20
///\file
deba@1409
    21
///\brief Lemon Format writer.
deba@1409
    22
deba@1409
    23
#ifndef LEMON_LEMON_WRITER_H
deba@1409
    24
#define LEMON_LEMON_WRITER_H
deba@1409
    25
deba@1409
    26
#include <iostream>
deba@1409
    27
#include <fstream>
deba@1409
    28
#include <string>
deba@1409
    29
#include <vector>
deba@1409
    30
#include <algorithm>
deba@1409
    31
#include <map>
deba@1409
    32
#include <memory>
deba@1409
    33
deba@1409
    34
#include <lemon/error.h>
deba@1993
    35
#include <lemon/bits/invalid.h>
deba@1421
    36
#include <lemon/graph_utils.h>
deba@1409
    37
#include <lemon/bits/item_writer.h>
deba@1993
    38
#include <lemon/bits/utility.h>
deba@1421
    39
#include <lemon/maps.h>
alpar@2207
    40
#include <lemon/dim2.h>
deba@1409
    41
deba@1476
    42
#include <lemon/concept_check.h>
alpar@2260
    43
#include <lemon/concepts/maps.h>
deba@1476
    44
deba@1409
    45
deba@1409
    46
namespace lemon {
deba@1409
    47
deba@1476
    48
  namespace _writer_bits {
deba@1476
    49
    
deba@2101
    50
    template <typename T>
deba@2101
    51
    bool operator<(T, T) {
deba@2101
    52
      throw DataFormatError("Label is not comparable");
deba@2101
    53
    }
deba@2101
    54
deba@2101
    55
    template <typename T>
deba@2101
    56
    struct Less {
deba@2101
    57
      bool operator()(const T& p, const T& q) const {
deba@2101
    58
	return p < q;
deba@2101
    59
      }
deba@2101
    60
    };
deba@2101
    61
deba@2101
    62
    template <typename Map>
deba@2101
    63
    struct ComposeLess {
deba@2101
    64
      ComposeLess(const Map& _map) : map(_map), less() {}
deba@2101
    65
deba@2101
    66
      bool operator()(const typename Map::Key& p, 
deba@2101
    67
                      const typename Map::Key& q) const {
deba@2101
    68
	return less(map[p], map[q]);
deba@2101
    69
      }
deba@2101
    70
      const Map& map;
deba@2101
    71
      Less<typename Map::Value> less;
deba@2101
    72
    };
deba@2101
    73
deba@1476
    74
    template <typename Item>
deba@1901
    75
    class ItemLabelWriter {
deba@1476
    76
    public:
deba@1476
    77
deba@1901
    78
      bool isLabelWriter() { return true; }
deba@1476
    79
deba@1901
    80
      void writeLabel(std::ostream&, const Item&) {}
deba@1476
    81
      
deba@1901
    82
      template <class _ItemLabelWriter>
deba@1476
    83
      struct Constraints {
deba@1476
    84
	void constraints() {
deba@1901
    85
	  bool b = writer.isLabelWriter();
deba@1476
    86
	  ignore_unused_variable_warning(b);
deba@1901
    87
	  writer.writeLabel(os, item);
deba@1476
    88
	}
deba@1901
    89
	_ItemLabelWriter& writer;
deba@1476
    90
	std::ostream& os;
deba@1492
    91
	const Item& item;
deba@1492
    92
      };
deba@1492
    93
deba@1492
    94
    };
deba@1492
    95
deba@1492
    96
    template <typename Item>
deba@1492
    97
    class ItemWriter {
deba@1492
    98
    public:
deba@1492
    99
deba@1492
   100
      void write(std::ostream&, const Item&) {}
deba@1492
   101
      
deba@1492
   102
      template <class _ItemWriter>
deba@1492
   103
      struct Constraints {
deba@1492
   104
	void constraints() {
deba@1492
   105
	  writer.write(os, item);
deba@1492
   106
	}
deba@1492
   107
	_ItemWriter& writer;
deba@1492
   108
	std::ostream& os;
deba@1492
   109
	const Item& item;
deba@1476
   110
      };
deba@1476
   111
deba@1476
   112
    };
deba@1476
   113
deba@1705
   114
    template <typename Map>
deba@1705
   115
    struct Ref { typedef const Map& Type; };
deba@1705
   116
deba@1705
   117
    template <typename Graph, typename Map>
deba@1705
   118
    class ForwardComposeMap {
deba@1705
   119
    public:
klao@1909
   120
      typedef typename Graph::UEdge Key;
deba@1705
   121
      typedef typename Map::Value Value;
deba@1705
   122
deba@1705
   123
      ForwardComposeMap(const Graph& _graph, const Map& _map) 
deba@1705
   124
	: graph(_graph), map(_map) {}
deba@1705
   125
      
deba@1705
   126
      Value operator[](const Key& key) {
deba@1705
   127
	return map[graph.direct(key, false)];
deba@1705
   128
      }
deba@1705
   129
deba@1705
   130
    private:
deba@1705
   131
      typename Ref<Map>::Type map;
deba@1705
   132
      const Graph& graph;
deba@1705
   133
    };
deba@1705
   134
deba@1705
   135
    template <typename Graph, typename Map>
deba@1705
   136
    ForwardComposeMap<Graph, Map>
deba@1705
   137
    forwardComposeMap(const Graph& graph, const Map& map) {
deba@1705
   138
      return ForwardComposeMap<Graph, Map>(graph, map);
deba@1705
   139
    }
deba@1705
   140
deba@1705
   141
    template <typename Graph, typename Map>
deba@1705
   142
    class BackwardComposeMap {
deba@1705
   143
    public:
klao@1909
   144
      typedef typename Graph::UEdge Key;
deba@1705
   145
      typedef typename Map::Value Value;
deba@1705
   146
deba@1705
   147
      BackwardComposeMap(const Graph& _graph, const Map& _map) 
deba@1705
   148
	: graph(_graph), map(_map) {}
deba@1705
   149
      
deba@1705
   150
      Value operator[](const Key& key) {
deba@1705
   151
	return map[graph.direct(key, false)];
deba@1705
   152
      }
deba@1705
   153
deba@1705
   154
    private:
deba@1705
   155
      typename Ref<Map>::Type map;
deba@1705
   156
      const Graph& graph;
deba@1705
   157
    };
deba@1705
   158
deba@1705
   159
    template <typename Graph, typename Map>
deba@1705
   160
    BackwardComposeMap<Graph, Map>
deba@1705
   161
    backwardComposeMap(const Graph& graph, const Map& map) {
deba@1705
   162
      return BackwardComposeMap<Graph, Map>(graph, map);
deba@1705
   163
    }
deba@1705
   164
deba@1705
   165
    template <typename Graph, typename Map>
deba@1705
   166
    struct Ref<ForwardComposeMap<Graph, Map> > { 
deba@1705
   167
      typedef ForwardComposeMap<Graph, Map> Type;
deba@1705
   168
    };
deba@1705
   169
deba@1705
   170
    template <typename Graph, typename Map>
deba@1705
   171
    struct Ref<BackwardComposeMap<Graph, Map> > { 
deba@1705
   172
      typedef BackwardComposeMap<Graph, Map> Type; 
deba@1705
   173
    };
deba@1705
   174
deba@1705
   175
    template <typename Map>
alpar@2207
   176
    struct Ref<dim2::XMap<Map> > { 
alpar@2207
   177
      typedef dim2::XMap<Map> Type;
deba@1705
   178
    };
deba@1705
   179
    template <typename Map>
alpar@2207
   180
    struct Ref<dim2::ConstXMap<Map> > { 
alpar@2207
   181
      typedef dim2::ConstXMap<Map> Type;
deba@1705
   182
    };
deba@1705
   183
deba@1705
   184
    template <typename Map>
alpar@2207
   185
    struct Ref<dim2::YMap<Map> > { 
alpar@2207
   186
      typedef dim2::YMap<Map> Type;
deba@1705
   187
    };
deba@1705
   188
    template <typename Map>
alpar@2207
   189
    struct Ref<dim2::ConstYMap<Map> > { 
alpar@2207
   190
      typedef dim2::ConstYMap<Map> Type;
deba@1705
   191
    };
deba@1705
   192
deba@1845
   193
deba@1845
   194
    template <typename _Item>    
deba@1845
   195
    class MapWriterBase {
deba@1845
   196
    public:
deba@1845
   197
      typedef _Item Item;
deba@1845
   198
deba@1845
   199
      virtual ~MapWriterBase() {}
deba@1845
   200
deba@1852
   201
      virtual void write(std::ostream& os, const Item& item) const = 0;
deba@2101
   202
      virtual void sortByMap(std::vector<Item>&) const = 0;
deba@1845
   203
    };
deba@1845
   204
deba@1845
   205
deba@1845
   206
    template <typename _Item, typename _Map, typename _Writer>
deba@1845
   207
    class MapWriter : public MapWriterBase<_Item> {
deba@1845
   208
    public:
deba@1845
   209
      typedef _Map Map;
deba@1845
   210
      typedef _Writer Writer;
deba@1845
   211
      typedef typename Writer::Value Value;
deba@1845
   212
      typedef _Item Item;
deba@1845
   213
      
deba@1845
   214
      typename _writer_bits::Ref<Map>::Type map;
deba@1845
   215
      Writer writer;
deba@1845
   216
deba@1845
   217
      MapWriter(const Map& _map, const Writer& _writer) 
deba@1845
   218
	: map(_map), writer(_writer) {}
deba@1845
   219
deba@1845
   220
      virtual ~MapWriter() {}
deba@1845
   221
deba@1852
   222
      virtual void write(std::ostream& os, const Item& item) const {
deba@1845
   223
	Value value = map[item];
deba@1845
   224
	writer.write(os, value);
deba@1845
   225
      }
deba@1845
   226
deba@2101
   227
      virtual void sortByMap(std::vector<Item>& items) const {
deba@2101
   228
        ComposeLess<Map> less(map);
deba@2101
   229
        std::sort(items.begin(), items.end(), less);
deba@2101
   230
      }
deba@2101
   231
deba@1845
   232
    };
deba@1845
   233
deba@1845
   234
deba@1845
   235
    class ValueWriterBase {
deba@1845
   236
    public:
deba@1845
   237
      virtual ~ValueWriterBase() {}
deba@1845
   238
      virtual void write(std::ostream&) = 0;
deba@1845
   239
    };
deba@1845
   240
deba@1845
   241
    template <typename _Value, typename _Writer>
deba@1845
   242
    class ValueWriter : public ValueWriterBase {
deba@1845
   243
    public:
deba@1845
   244
      typedef _Value Value;
deba@1845
   245
      typedef _Writer Writer;
deba@1845
   246
deba@1845
   247
      ValueWriter(const Value& _value, const Writer& _writer)
deba@1845
   248
 	: value(_value), writer(_writer) {}
deba@1845
   249
deba@1845
   250
      virtual void write(std::ostream& os) {
deba@1845
   251
	writer.write(os, value);
deba@1845
   252
      }
deba@1845
   253
    private:
deba@1845
   254
      const Value& value;
deba@1845
   255
      Writer writer;
deba@1845
   256
    };
deba@1845
   257
    
deba@1845
   258
deba@1845
   259
    template <typename _Item>
deba@1901
   260
    class LabelWriterBase {
deba@1845
   261
    public:
deba@1845
   262
      typedef _Item Item;
deba@1901
   263
      virtual ~LabelWriterBase() {}
deba@1845
   264
      virtual void write(std::ostream&, const Item&) const = 0;
deba@1901
   265
      virtual bool isLabelWriter() const = 0;
deba@1845
   266
    };
deba@1845
   267
deba@1901
   268
    template <typename _Item, typename _BoxedLabelWriter>
deba@1901
   269
    class LabelWriter : public LabelWriterBase<_Item> {
deba@1845
   270
    public:
deba@1845
   271
      typedef _Item Item;
deba@1901
   272
      typedef _BoxedLabelWriter BoxedLabelWriter;
deba@1845
   273
deba@1901
   274
      const BoxedLabelWriter& labelWriter;
deba@1845
   275
deba@1901
   276
      LabelWriter(const BoxedLabelWriter& _labelWriter) 
deba@1901
   277
	: labelWriter(_labelWriter) {}
deba@1845
   278
deba@1845
   279
      virtual void write(std::ostream& os, const Item& item) const {
deba@1901
   280
	labelWriter.writeLabel(os, item);
deba@1845
   281
      }
deba@1845
   282
deba@1901
   283
      virtual bool isLabelWriter() const {
deba@1901
   284
	return labelWriter.isLabelWriter();
deba@1845
   285
      }
deba@1845
   286
    };
deba@1845
   287
deba@1476
   288
  }
deba@1476
   289
deba@2084
   290
  /// \ingroup lemon_io
deba@1409
   291
  /// \brief Lemon Format writer class.
deba@1409
   292
  /// 
deba@1409
   293
  /// The Lemon Format contains several sections. We do not want to
deba@1409
   294
  /// determine what sections are in a lemon file we give only a framework
deba@1409
   295
  /// to write a section oriented format.
deba@1409
   296
  ///
deba@1409
   297
  /// In the Lemon Format each section starts with a line contains a \c \@
deba@1409
   298
  /// character on the first not white space position. This line is the
deba@1409
   299
  /// header line of the section. Each next lines belong to this section
deba@1409
   300
  /// while it does not starts with \c \@ character. This line can start a 
deba@1409
   301
  /// new section or if it can close the file with the \c \@end line.
deba@1409
   302
  /// The file format ignore the empty lines and it may contain comments
deba@1409
   303
  /// started with a \c # character to the end of the line. 
deba@1409
   304
  ///
deba@1409
   305
  /// The framework provides an abstract LemonWriter::SectionWriter class
deba@1409
   306
  /// what defines the interface of a SectionWriter. The SectionWriter
deba@1409
   307
  /// has the \c header() member function what gives back the header of the
deba@1409
   308
  /// section. After that it will be called the \c write() member which
deba@1409
   309
  /// should write the content of the section.
deba@1409
   310
  ///
deba@1409
   311
  /// \relates GraphWriter
deba@1409
   312
  /// \relates NodeSetWriter
deba@1409
   313
  /// \relates EdgeSetWriter
deba@1409
   314
  /// \relates NodesWriter
deba@1409
   315
  /// \relates EdgesWriter
deba@1409
   316
  /// \relates AttributeWriter
deba@1409
   317
  class LemonWriter {
deba@1409
   318
  public:
deba@1409
   319
deba@1409
   320
    /// \brief Abstract base class for writing a section.
deba@1409
   321
    ///
deba@1409
   322
    /// This class has an \c header() member function what gives back
deba@1409
   323
    /// the header line of the section. The \c write() member should
deba@1409
   324
    /// write the content of the section to the stream.
deba@1409
   325
    class SectionWriter {
deba@1409
   326
      friend class LemonWriter;
deba@1409
   327
    protected:
deba@1409
   328
      /// \brief Constructor for SectionWriter.
deba@1409
   329
      ///
deba@1409
   330
      /// Constructor for SectionWriter. It attach this writer to
deba@1409
   331
      /// the given LemonWriter.
deba@1409
   332
      SectionWriter(LemonWriter& writer) {
deba@1409
   333
	writer.attach(*this);
deba@1409
   334
      }
alpar@1494
   335
      
alpar@1494
   336
      virtual ~SectionWriter() {}
deba@1409
   337
deba@1409
   338
      /// \brief The header of section.
deba@1409
   339
      ///
deba@1409
   340
      /// It gives back the header of the section.
deba@1409
   341
      virtual std::string header() = 0;
deba@1409
   342
deba@2084
   343
      /// \brief Writer function of the section.
deba@1409
   344
      ///
deba@1409
   345
      /// Write the content of the section.
deba@1409
   346
      virtual void write(std::ostream& os) = 0;
deba@2084
   347
      
deba@2084
   348
      /// \brief Gives back true when the section should be written.
deba@2084
   349
      ///
deba@2084
   350
      /// Gives back true when the section should be written.
deba@2084
   351
      virtual bool valid() { return true; }
deba@1409
   352
    };
deba@1409
   353
deba@1409
   354
    /// \brief Constructor for LemonWriter.
deba@1409
   355
    ///
deba@1409
   356
    /// Constructor for LemonWriter which writes to the given stream.
deba@1409
   357
    LemonWriter(std::ostream& _os) 
deba@1409
   358
      : os(&_os), own_os(false) {}
deba@1409
   359
deba@1409
   360
    /// \brief Constructor for LemonWriter.
deba@1409
   361
    ///
deba@1409
   362
    /// Constructor for LemonWriter which writes to the given file.
deba@1409
   363
    LemonWriter(const std::string& filename) 
deba@1409
   364
      : os(0), own_os(true) {
deba@1409
   365
      os = new std::ofstream(filename.c_str());
deba@1409
   366
    }
deba@1409
   367
deba@1409
   368
    /// \brief Desctructor for LemonWriter.
deba@1409
   369
    ///
deba@1409
   370
    /// Desctructor for LemonWriter.
deba@1409
   371
    ~LemonWriter() {
deba@1409
   372
      if (own_os) {
deba@1409
   373
	delete os;
deba@1409
   374
      }
deba@1409
   375
    }
deba@1409
   376
deba@1409
   377
  private:
deba@1409
   378
    LemonWriter(const LemonWriter&);
deba@1409
   379
    void operator=(const LemonWriter&);
deba@1409
   380
deba@1409
   381
    void attach(SectionWriter& writer) {
deba@1409
   382
      writers.push_back(&writer);
deba@1409
   383
    }
deba@1409
   384
deba@1409
   385
  public:
deba@1409
   386
deba@1409
   387
    /// \brief Executes the LemonWriter.
deba@1409
   388
    /// 
deba@1409
   389
    /// It executes the LemonWriter.
deba@1409
   390
    void run() {
deba@1409
   391
      SectionWriters::iterator it;
deba@1409
   392
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@2084
   393
        if ((*it)->valid()) {
deba@2084
   394
          *os << (*it)->header() << std::endl;
deba@2084
   395
          (*it)->write(*os);
deba@2084
   396
        }
deba@1409
   397
      }
deba@1409
   398
      *os << "@end" << std::endl;
deba@1409
   399
    }
deba@1409
   400
deba@1409
   401
deba@1409
   402
  private:
deba@1409
   403
deba@1409
   404
    std::ostream* os;
deba@1409
   405
    bool own_os;
deba@1409
   406
deba@1409
   407
    typedef std::vector<SectionWriter*> SectionWriters;
deba@1409
   408
    SectionWriters writers;
deba@1409
   409
deba@1409
   410
  };
deba@1409
   411
deba@2016
   412
  /// \ingroup section_io
deba@1409
   413
  /// \brief SectionWriter for writing a graph's nodeset.
deba@1409
   414
  ///
deba@1409
   415
  /// The lemon format can store multiple graph nodesets with several maps.
deba@1901
   416
  /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but 
deba@1901
   417
  /// the \c nodeset_name may be empty.
deba@1409
   418
  ///
deba@1409
   419
  /// The first line of the section contains the names of the maps separated
deba@1409
   420
  /// with white spaces. Each next lines describes a node in the nodeset, and
deba@1409
   421
  /// contains the mapped values for each map.
deba@1409
   422
  ///
deba@1901
   423
  /// If the nodeset contains an \c "label" named map then it will be regarded
deba@1901
   424
  /// as label map. This map should contain only unique values and when the 
deba@1901
   425
  /// \c writeLabel() member will be called with a node it will write it's 
deba@1901
   426
  /// label. Otherwise if the \c _forceLabelMap constructor parameter is true 
deba@2101
   427
  /// then the label map will be the id in the graph. In addition if the
deba@2101
   428
  /// the \c _sortByLabel is true then the writer will write the edges
deba@2101
   429
  /// sorted by the labels.
deba@1409
   430
  ///
deba@1409
   431
  /// \relates LemonWriter
deba@1409
   432
  template <typename _Graph, typename _Traits = DefaultWriterTraits>
deba@1845
   433
  class NodeSetWriter : public LemonWriter::SectionWriter {
deba@1845
   434
    typedef LemonWriter::SectionWriter Parent;
deba@1409
   435
  public:
deba@1409
   436
deba@1409
   437
    typedef _Graph Graph;
deba@1409
   438
    typedef _Traits Traits;
deba@1429
   439
    typedef typename Graph::Node Node;
deba@1409
   440
deba@1409
   441
    /// \brief Constructor.
deba@1409
   442
    ///
deba@1409
   443
    /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
deba@1901
   444
    /// attach it into the given LemonWriter. If the \c _forceLabelMap
deba@1901
   445
    /// parameter is true then the writer will write own label map when
deba@2101
   446
    /// the user does not give "label" named map. In addition if the
deba@2101
   447
    /// the \c _sortByLabel is true then the writer will write the edges
deba@2101
   448
    /// sorted by the labels.
deba@1409
   449
    NodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
deba@1901
   450
		  const std::string& _name = std::string(), 
deba@2101
   451
		  bool _forceLabelMap = true, bool _sortByLabel = true) 
deba@1901
   452
      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), 
deba@2101
   453
	sortByLabel(_sortByLabel), graph(_graph), name(_name) {}
deba@1409
   454
deba@1409
   455
    /// \brief Destructor.
deba@1409
   456
    ///
deba@1409
   457
    /// Destructor for NodeSetWriter.
deba@1409
   458
    virtual ~NodeSetWriter() {
deba@1409
   459
      typename MapWriters::iterator it;
deba@1409
   460
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
   461
	delete it->second;
deba@1409
   462
      }
deba@1409
   463
    }
deba@1409
   464
deba@1409
   465
  private:
deba@1409
   466
    NodeSetWriter(const NodeSetWriter&);
deba@1409
   467
    void operator=(const NodeSetWriter&);
deba@1409
   468
  
deba@1409
   469
  public:
deba@1409
   470
deba@1409
   471
    /// \brief Add a new node map writer command for the writer.
deba@1409
   472
    ///
deba@1409
   473
    /// Add a new node map writer command for the writer.
deba@1409
   474
    template <typename Map>
deba@1421
   475
    NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
deba@1421
   476
      return writeNodeMap<typename Traits::
deba@1409
   477
	template Writer<typename Map::Value>, Map>(name, map);
deba@1409
   478
    }
deba@1409
   479
deba@1409
   480
    /// \brief Add a new node map writer command for the writer.
deba@1409
   481
    ///
deba@1409
   482
    /// Add a new node map writer command for the writer.
deba@1409
   483
    template <typename Writer, typename Map>
deba@1421
   484
    NodeSetWriter& writeNodeMap(std::string name, const Map& map, 
deba@1421
   485
			    const Writer& writer = Writer()) {
alpar@2260
   486
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@1492
   487
      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
deba@1409
   488
      writers.push_back(
deba@1845
   489
	make_pair(name, new _writer_bits::
deba@1845
   490
		  MapWriter<Node, Map, Writer>(map, writer)));
deba@1409
   491
      return *this;
deba@1409
   492
    }
deba@1409
   493
deba@1409
   494
  protected:
deba@1409
   495
deba@1409
   496
    /// \brief The header of the section.
deba@1409
   497
    ///
deba@1409
   498
    /// It gives back the header of the section.
deba@1409
   499
    virtual std::string header() {
deba@1901
   500
      return "@nodeset " + name;
deba@1409
   501
    }
deba@1409
   502
deba@1409
   503
    /// \brief  Writer function of the section.
deba@1409
   504
    ///
deba@1409
   505
    /// Write the content of the section.
deba@1409
   506
    virtual void write(std::ostream& os) {
deba@1409
   507
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@2084
   508
	if (writers[i].first == "label") {
deba@1901
   509
	  labelMap = writers[i].second;
deba@1901
   510
	  forceLabelMap = false;
deba@1409
   511
	  break;
deba@1409
   512
	}
deba@1409
   513
      }
deba@2101
   514
      std::vector<Node> items;
deba@2101
   515
      for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
deba@2101
   516
        items.push_back(it);
deba@2101
   517
      }
deba@2101
   518
      if (sortByLabel) {
deba@2101
   519
        if (labelMap) {
deba@2101
   520
          labelMap->sortByMap(items);
deba@2101
   521
        } else {
deba@2101
   522
          typedef IdMap<Graph, Node> Map;
deba@2101
   523
          Map map(graph);
deba@2101
   524
          _writer_bits::ComposeLess<Map> less(map);
deba@2101
   525
          std::sort(items.begin(), items.end(), less);
deba@2101
   526
        }
deba@2101
   527
      }
deba@1901
   528
      if (forceLabelMap) {
deba@1901
   529
	os << "label\t";
deba@1409
   530
      }
deba@1409
   531
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   532
	os << writers[i].first << '\t';
deba@1409
   533
      }
deba@1409
   534
      os << std::endl;
deba@2101
   535
      for (typename std::vector<Node>::iterator it = items.begin();
deba@2101
   536
           it != items.end(); ++it) {
deba@1901
   537
	if (forceLabelMap) {
deba@2101
   538
	  os << graph.id(*it) << '\t';
deba@1409
   539
	}
deba@1409
   540
	for (int i = 0; i < (int)writers.size(); ++i) {
deba@2101
   541
	  writers[i].second->write(os, *it);
deba@1409
   542
	  os << '\t';
deba@1409
   543
	}
deba@1409
   544
	os << std::endl;
deba@1409
   545
      }
deba@1409
   546
    }
deba@1409
   547
deba@1409
   548
  public:
deba@1409
   549
deba@1901
   550
    /// \brief Returns true if the nodeset can write the labels of the nodes.
deba@1409
   551
    ///
deba@1901
   552
    /// Returns true if the nodeset can write the labels of the nodes.
deba@1901
   553
    /// It is possible only if an "label" named map was written or the 
deba@1901
   554
    /// \c _forceLabelMap constructor parameter was true.
deba@1901
   555
    bool isLabelWriter() const {
deba@1901
   556
      return labelMap != 0 || forceLabelMap;
deba@1409
   557
    }
deba@1409
   558
deba@1901
   559
    /// \brief Write the label of the given node.
deba@1409
   560
    ///
deba@1901
   561
    /// It writes the label of the given node. If there was written an "label"
deba@1409
   562
    /// named map then it will write the map value belongs to the node.
deba@1901
   563
    /// Otherwise if the \c forceLabel parameter was true it will write
deba@1901
   564
    /// its label in the graph. 
deba@1901
   565
    void writeLabel(std::ostream& os, const Node& item) const {
deba@1901
   566
      if (forceLabelMap) {
deba@1409
   567
	os << graph.id(item);
deba@1409
   568
      } else {
deba@1901
   569
	labelMap->write(os, item);
deba@1409
   570
      }
deba@1409
   571
    }
deba@1409
   572
deba@1409
   573
  private:
deba@1409
   574
deba@1845
   575
    typedef std::vector<std::pair<std::string, _writer_bits::
deba@1845
   576
				  MapWriterBase<Node>*> > MapWriters;
deba@1409
   577
    MapWriters writers;
deba@1409
   578
deba@1901
   579
    _writer_bits::MapWriterBase<Node>* labelMap;
deba@1901
   580
    bool forceLabelMap;
deba@2101
   581
    bool sortByLabel;
deba@1409
   582
   
deba@1705
   583
    const Graph& graph;   
deba@1901
   584
    std::string name;
deba@1409
   585
deba@1409
   586
  };
deba@1409
   587
deba@2016
   588
  /// \ingroup section_io
deba@1421
   589
  /// \brief SectionWriter for writing a graph's edgesets.
deba@1409
   590
  ///
deba@1421
   591
  /// The lemon format can store multiple graph edgesets with several maps. 
deba@1901
   592
  /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but 
deba@1901
   593
  /// the \c edgeset_name may be empty.
deba@1409
   594
  ///
deba@1409
   595
  /// The first line of the section contains the names of the maps separated
deba@1409
   596
  /// with white spaces. Each next lines describes a edge in the edgeset. The
deba@1901
   597
  /// line contains the source and the target nodes' label and the mapped 
deba@1409
   598
  /// values for each map.
deba@1409
   599
  ///
deba@1901
   600
  /// If the edgeset contains an \c "label" named map then it will be regarded
deba@1901
   601
  /// as label map. This map should contain only unique values and when the 
deba@1901
   602
  /// \c writeLabel() member will be called with an edge it will write it's 
deba@1901
   603
  /// label. Otherwise if the \c _forceLabelMap constructor parameter is true 
deba@2101
   604
  /// then the label map will be the id in the graph. In addition if the
deba@2101
   605
  /// the \c _sortByLabel is true then the writer will write the edges
deba@2101
   606
  /// sorted by the labels.
deba@1409
   607
  ///
deba@1901
   608
  /// The edgeset writer needs a node label writer to identify which nodes
deba@1901
   609
  /// have to be connected. If a NodeSetWriter can write the nodes' label,
deba@1409
   610
  /// it will be able to use with this class.
deba@1409
   611
  ///
deba@1409
   612
  /// \relates LemonWriter
deba@1409
   613
  template <typename _Graph, typename _Traits = DefaultWriterTraits>
deba@1845
   614
  class EdgeSetWriter : public LemonWriter::SectionWriter {
deba@1845
   615
    typedef LemonWriter::SectionWriter Parent;
deba@1409
   616
  public:
deba@1409
   617
deba@1409
   618
    typedef _Graph Graph;
deba@1409
   619
    typedef _Traits Traits;
deba@1429
   620
    typedef typename Graph::Node Node;
deba@1429
   621
    typedef typename Graph::Edge Edge;
deba@1409
   622
deba@1409
   623
    /// \brief Constructor.
deba@1409
   624
    ///
deba@2101
   625
    /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter
deba@2101
   626
    /// and attach it into the given LemonWriter. It will write node
deba@2101
   627
    /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap
deba@2101
   628
    /// parameter is true then the writer will write own label map if
deba@2101
   629
    /// the user does not give "label" named map. In addition if the
deba@2101
   630
    /// the \c _sortByLabel is true then the writer will write the
deba@2101
   631
    /// edges sorted by the labels.
deba@1901
   632
    template <typename NodeLabelWriter>
deba@1409
   633
    EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
deba@1901
   634
		  const NodeLabelWriter& _nodeLabelWriter, 
deba@1901
   635
		  const std::string& _name = std::string(),
deba@2101
   636
		  bool _forceLabelMap = true, bool _sortByLabel = true)
deba@1901
   637
      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
deba@2101
   638
	sortByLabel(_sortByLabel), graph(_graph), name(_name) {
deba@1901
   639
      checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
deba@1901
   640
      nodeLabelWriter.reset(new _writer_bits::
deba@1901
   641
			 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
deba@1476
   642
    } 
deba@1409
   643
deba@1409
   644
    /// \brief Destructor.
deba@1409
   645
    ///
deba@1409
   646
    /// Destructor for EdgeSetWriter.
deba@1409
   647
    virtual ~EdgeSetWriter() {
deba@1409
   648
      typename MapWriters::iterator it;
deba@1409
   649
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
   650
	delete it->second;
deba@1409
   651
      }
deba@1409
   652
    }
deba@1409
   653
deba@1409
   654
  private:
deba@1409
   655
    EdgeSetWriter(const EdgeSetWriter&);
deba@1409
   656
    void operator=(const EdgeSetWriter&);
deba@1409
   657
deba@1409
   658
  public:
deba@1409
   659
deba@1421
   660
    /// \brief Add a new edge map writer command for the writer.
deba@1409
   661
    ///
deba@1421
   662
    /// Add a new edge map writer command for the writer.
deba@1409
   663
    template <typename Map>
deba@1421
   664
    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
deba@1421
   665
      return writeEdgeMap<typename Traits::
deba@1409
   666
	template Writer<typename Map::Value>, Map>(name, map);
deba@1409
   667
    }
deba@1409
   668
deba@1421
   669
    /// \brief Add a new edge map writer command for the writer.
deba@1409
   670
    ///
deba@1421
   671
    /// Add a new edge map writer command for the writer.
deba@1409
   672
    template <typename Writer, typename Map>
deba@1421
   673
    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map, 
deba@1421
   674
			    const Writer& writer = Writer()) {
alpar@2260
   675
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@1492
   676
      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
deba@1409
   677
      writers.push_back(
deba@1845
   678
	make_pair(name, new _writer_bits::
deba@1845
   679
		  MapWriter<Edge, Map, Writer>(map, writer)));
deba@1409
   680
      return *this;
deba@1409
   681
    }
deba@1409
   682
deba@1409
   683
  protected:
deba@1409
   684
deba@1409
   685
    /// \brief The header of the section.
deba@1409
   686
    ///
deba@1409
   687
    /// It gives back the header of the section.
deba@1409
   688
    virtual std::string header() {
deba@1901
   689
      return "@edgeset " + name;
deba@1409
   690
    }
deba@1409
   691
deba@1409
   692
    /// \brief  Writer function of the section.
deba@1409
   693
    ///
deba@1409
   694
    /// Write the content of the section.
deba@1409
   695
    virtual void write(std::ostream& os) {
deba@1901
   696
      if (!nodeLabelWriter->isLabelWriter()) {
deba@1901
   697
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
   698
      }
deba@1409
   699
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@2084
   700
	if (writers[i].first == "label") {
deba@1901
   701
	  labelMap = writers[i].second;
deba@1901
   702
	  forceLabelMap = false;
deba@1409
   703
	  break;
deba@1409
   704
	}
deba@1409
   705
      }
deba@2101
   706
      std::vector<Edge> items;
deba@2101
   707
      for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
deba@2101
   708
        items.push_back(it);
deba@2101
   709
      }
deba@2101
   710
      if (sortByLabel) {
deba@2101
   711
        if (labelMap) {
deba@2101
   712
          labelMap->sortByMap(items);
deba@2101
   713
        } else {
deba@2101
   714
          typedef IdMap<Graph, Edge> Map;
deba@2101
   715
          Map map(graph);
deba@2101
   716
          _writer_bits::ComposeLess<Map> less(map);
deba@2101
   717
          std::sort(items.begin(), items.end(), less);
deba@2101
   718
        }
deba@2101
   719
      }
deba@1409
   720
      os << "\t\t";
deba@1901
   721
      if (forceLabelMap) {
deba@1901
   722
	os << "label\t";
deba@1409
   723
      }
deba@1409
   724
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   725
	os << writers[i].first << '\t';
deba@1409
   726
      }
deba@1409
   727
      os << std::endl;
deba@2101
   728
      for (typename std::vector<Edge>::iterator it = items.begin();
deba@2101
   729
           it != items.end(); ++it) {
deba@2101
   730
	nodeLabelWriter->write(os, graph.source(*it));
deba@1409
   731
	os << '\t';
deba@2101
   732
	nodeLabelWriter->write(os, graph.target(*it));
deba@1409
   733
	os << '\t';
deba@1901
   734
	if (forceLabelMap) {
deba@2101
   735
	  os << graph.id(*it) << '\t';
deba@1409
   736
	}
deba@1409
   737
	for (int i = 0; i < (int)writers.size(); ++i) {
deba@2101
   738
	  writers[i].second->write(os, *it);
deba@1409
   739
	  os << '\t';
deba@1409
   740
	}
deba@1409
   741
	os << std::endl;
deba@1409
   742
      }
deba@1409
   743
    }
deba@1409
   744
deba@1409
   745
  public:
deba@1409
   746
deba@1901
   747
    /// \brief Returns true if the edgeset can write the labels of the edges.
deba@1409
   748
    ///
deba@1901
   749
    /// Returns true if the edgeset can write the labels of the edges.
deba@1901
   750
    /// It is possible only if an "label" named map was written or the 
deba@1901
   751
    /// \c _forceLabelMap constructor parameter was true.
deba@1901
   752
    bool isLabelWriter() const {
deba@1901
   753
      return forceLabelMap || labelMap != 0;
deba@1409
   754
    }
deba@1409
   755
deba@1901
   756
    /// \brief Write the label of the given edge.
deba@1409
   757
    ///
deba@1901
   758
    /// It writes the label of the given edge. If there was written an "label"
deba@1409
   759
    /// named map then it will write the map value belongs to the edge.
deba@1901
   760
    /// Otherwise if the \c forceLabel parameter was true it will write
deba@1901
   761
    /// its label in the graph. 
deba@1901
   762
    void writeLabel(std::ostream& os, const Edge& item) const {
deba@1901
   763
      if (forceLabelMap) {
deba@1409
   764
	os << graph.id(item);
deba@1409
   765
      } else {
deba@1901
   766
	labelMap->write(os, item);
deba@1409
   767
      }
deba@1409
   768
    } 
deba@1409
   769
deba@1409
   770
  private:
deba@1409
   771
deba@1845
   772
    typedef std::vector<std::pair<std::string, _writer_bits::
deba@1845
   773
				  MapWriterBase<Edge>*> > MapWriters;
deba@1409
   774
    MapWriters writers;
deba@1409
   775
deba@1901
   776
    _writer_bits::MapWriterBase<Edge>* labelMap;
deba@1901
   777
    bool forceLabelMap;
deba@2101
   778
    bool sortByLabel;
deba@1409
   779
   
deba@1705
   780
    const Graph& graph;   
deba@1901
   781
    std::string name;
deba@1421
   782
deba@1901
   783
    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
deba@1421
   784
  };
deba@1421
   785
deba@2016
   786
  /// \ingroup section_io
deba@1421
   787
  /// \brief SectionWriter for writing a undirected edgeset.
deba@1421
   788
  ///
deba@1421
   789
  /// The lemon format can store multiple undirected edgesets with several 
klao@1909
   790
  /// maps. The undirected edgeset section's header line is \c \@uedgeset 
klao@1909
   791
  /// \c uedgeset_name, but the \c uedgeset_name may be empty.
deba@1421
   792
  ///
deba@1421
   793
  /// The first line of the section contains the names of the maps separated
deba@1421
   794
  /// with white spaces. Each next lines describes an undirected edge in the 
deba@1901
   795
  /// edgeset. The line contains the two connected nodes' label and the mapped 
deba@1421
   796
  /// values for each undirected map.
deba@1421
   797
  ///
deba@1421
   798
  /// The section can handle the directed as a syntactical sugar. Two
deba@1421
   799
  /// undirected edge map describes one directed edge map. This two maps
deba@1421
   800
  /// are the forward map and the backward map and the names of this map
deba@1421
   801
  /// is near the same just with a prefix \c '+' or \c '-' character 
deba@1421
   802
  /// difference.
deba@1421
   803
  ///
deba@2101
   804
  /// If the edgeset contains an \c "label" named map then it will be
deba@2101
   805
  /// regarded as label map. This map should contain only unique
deba@2101
   806
  /// values and when the \c writeLabel() member will be called with
deba@2101
   807
  /// an undirected edge it will write it's label. Otherwise if the \c
deba@2101
   808
  /// _forceLabelMap constructor parameter is true then the label map
deba@2101
   809
  /// will be the id in the graph.  In addition if the the \c
deba@2101
   810
  /// _sortByLabel is true then the writer will write the edges sorted
deba@2101
   811
  /// by the labels.
deba@1421
   812
  ///
deba@1901
   813
  /// The undirected edgeset writer needs a node label writer to identify 
deba@1421
   814
  /// which nodes have to be connected. If a NodeSetWriter can write the 
deba@1901
   815
  /// nodes' label, it will be able to use with this class.
deba@1421
   816
  ///
deba@1421
   817
  /// \relates LemonWriter
deba@1421
   818
  template <typename _Graph, typename _Traits = DefaultWriterTraits>
klao@1909
   819
  class UEdgeSetWriter : public LemonWriter::SectionWriter {
deba@1845
   820
    typedef LemonWriter::SectionWriter Parent;
deba@1421
   821
  public:
deba@1421
   822
deba@1421
   823
    typedef _Graph Graph;
deba@1421
   824
    typedef _Traits Traits;
deba@1429
   825
    typedef typename Graph::Node Node;
deba@1429
   826
    typedef typename Graph::Edge Edge;
klao@1909
   827
    typedef typename Graph::UEdge UEdge;
deba@1421
   828
deba@1421
   829
    /// \brief Constructor.
deba@1421
   830
    ///
klao@1909
   831
    /// Constructor for UEdgeSetWriter. It creates the UEdgeSetWriter
deba@2101
   832
    /// and attach it into the given LemonWriter. It will write node
deba@2101
   833
    /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap
deba@2101
   834
    /// parameter is true then the writer will write own label map if
deba@2101
   835
    /// the user does not give "label" named map. In addition if the
deba@2101
   836
    /// the \c _sortByLabel is true then the writer will write the
deba@2101
   837
    /// edges sorted by the labels.
deba@1901
   838
    template <typename NodeLabelWriter>
klao@1909
   839
    UEdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
deba@1901
   840
		       const NodeLabelWriter& _nodeLabelWriter, 
deba@1901
   841
		       const std::string& _name = std::string(),
deba@2101
   842
		       bool _forceLabelMap = true, bool _sortByLabel = true)
deba@1901
   843
      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
deba@2101
   844
	sortByLabel(_sortByLabel), graph(_graph), name(_name) {
deba@1901
   845
      checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
deba@1901
   846
      nodeLabelWriter.reset(new _writer_bits::
deba@1901
   847
			 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
deba@1476
   848
    } 
deba@1421
   849
deba@1421
   850
    /// \brief Destructor.
deba@1421
   851
    ///
klao@1909
   852
    /// Destructor for UEdgeSetWriter.
klao@1909
   853
    virtual ~UEdgeSetWriter() {
deba@1421
   854
      typename MapWriters::iterator it;
deba@1421
   855
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1421
   856
	delete it->second;
deba@1421
   857
      }
deba@1421
   858
    }
deba@1421
   859
deba@1421
   860
  private:
klao@1909
   861
    UEdgeSetWriter(const UEdgeSetWriter&);
klao@1909
   862
    void operator=(const UEdgeSetWriter&);
deba@1421
   863
deba@1421
   864
  public:
deba@1421
   865
deba@1421
   866
    /// \brief Add a new undirected edge map writer command for the writer.
deba@1421
   867
    ///
deba@1421
   868
    /// Add a new undirected map writer command for the writer.
deba@1421
   869
    template <typename Map>
klao@1909
   870
    UEdgeSetWriter& writeUEdgeMap(std::string name, const Map& map) {
klao@1909
   871
      return writeUEdgeMap<typename Traits::
deba@1421
   872
	template Writer<typename Map::Value>, Map>(name, map);
deba@1421
   873
    }
deba@1421
   874
deba@1421
   875
    /// \brief Add a new undirected map writer command for the writer.
deba@1421
   876
    ///
deba@1421
   877
    /// Add a new undirected map writer command for the writer.
deba@1421
   878
    template <typename Writer, typename Map>
klao@1909
   879
    UEdgeSetWriter& writeUEdgeMap(std::string name, const Map& map, 
deba@2282
   880
                                  const Writer& writer = Writer()) {
alpar@2260
   881
      checkConcept<concepts::ReadMap<UEdge, typename Map::Value>, Map>();
deba@1492
   882
      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
deba@1421
   883
      writers.push_back(
deba@1845
   884
	make_pair(name, new _writer_bits::
klao@1909
   885
		  MapWriter<UEdge, Map, Writer>(map, writer)));
deba@1421
   886
      return *this;
deba@1421
   887
    }
deba@1421
   888
deba@1421
   889
    /// \brief Add a new directed edge map writer command for the writer.
deba@1421
   890
    ///
deba@1421
   891
    /// Add a new directed map writer command for the writer.
deba@1421
   892
    template <typename Map>
klao@1909
   893
    UEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
deba@1492
   894
      return writeEdgeMap<typename Traits::
deba@1492
   895
	template Writer<typename Map::Value>, Map>(name, map);
deba@1421
   896
    }
deba@1421
   897
deba@1421
   898
    /// \brief Add a new directed map writer command for the writer.
deba@1421
   899
    ///
deba@1421
   900
    /// Add a new directed map writer command for the writer.
deba@1421
   901
    template <typename Writer, typename Map>
klao@1909
   902
    UEdgeSetWriter& writeEdgeMap(std::string name, const Map& map, 
deba@2282
   903
                                 const Writer& writer = Writer()) {
alpar@2260
   904
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@1492
   905
      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
deba@2282
   906
      writeUEdgeMap("+" + name, 
deba@2282
   907
                    _writer_bits::forwardComposeMap(graph, map), writer);
deba@2282
   908
      writeUEdgeMap("-" + name, 
deba@2282
   909
                    _writer_bits::backwardComposeMap(graph, map), writer);
deba@1421
   910
      return *this;
deba@1421
   911
    }
deba@1421
   912
deba@1421
   913
  protected:
deba@1421
   914
deba@1421
   915
    /// \brief The header of the section.
deba@1421
   916
    ///
deba@1421
   917
    /// It gives back the header of the section.
deba@1421
   918
    virtual std::string header() {
klao@1909
   919
      return "@uedgeset " + name;
deba@1421
   920
    }
deba@1421
   921
deba@1421
   922
    /// \brief  Writer function of the section.
deba@1421
   923
    ///
deba@1421
   924
    /// Write the content of the section.
deba@1421
   925
    virtual void write(std::ostream& os) {
deba@1901
   926
      if (!nodeLabelWriter->isLabelWriter()) {
deba@1901
   927
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
   928
      }
deba@1421
   929
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1901
   930
	if (writers[i].first == "label") {
deba@1901
   931
	  labelMap = writers[i].second;
deba@1901
   932
	  forceLabelMap = false;
deba@1421
   933
	  break;
deba@1421
   934
	}
deba@1421
   935
      }
deba@2101
   936
      std::vector<UEdge> items;
deba@2101
   937
      for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) {
deba@2101
   938
        items.push_back(it);
deba@2101
   939
      }
deba@2101
   940
      if (sortByLabel) {
deba@2101
   941
        if (labelMap) {
deba@2101
   942
          labelMap->sortByMap(items);
deba@2101
   943
        } else {
deba@2101
   944
          typedef IdMap<Graph, UEdge> Map;
deba@2101
   945
          Map map(graph);
deba@2101
   946
          _writer_bits::ComposeLess<Map> less(map);
deba@2101
   947
          std::sort(items.begin(), items.end(), less);
deba@2101
   948
        }
deba@2101
   949
      }
deba@1421
   950
      os << "\t\t";
deba@1901
   951
      if (forceLabelMap) {
deba@1901
   952
	os << "label\t";
deba@1421
   953
      }
deba@1421
   954
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1421
   955
	os << writers[i].first << '\t';
deba@1421
   956
      }
deba@1421
   957
      os << std::endl;
deba@2282
   958
      for (typename std::vector<UEdge>::iterator it = items.begin();
deba@2101
   959
           it != items.end(); ++it) {
deba@2101
   960
	nodeLabelWriter->write(os, graph.source(*it));
deba@1421
   961
	os << '\t';
deba@2101
   962
	nodeLabelWriter->write(os, graph.target(*it));
deba@1421
   963
	os << '\t';
deba@1901
   964
	if (forceLabelMap) {
deba@2101
   965
	  os << graph.id(*it) << '\t';
deba@1421
   966
	}
deba@1421
   967
	for (int i = 0; i < (int)writers.size(); ++i) {
deba@2101
   968
	  writers[i].second->write(os, *it);
deba@1421
   969
	  os << '\t';
deba@1421
   970
	}
deba@1421
   971
	os << std::endl;
deba@1421
   972
      }
deba@1421
   973
    }
deba@1421
   974
deba@1421
   975
  public:
deba@1421
   976
deba@1901
   977
    /// \brief Returns true if the undirected edgeset can write the labels of 
deba@1421
   978
    /// the edges.
deba@1421
   979
    ///
deba@1901
   980
    /// Returns true if the undirected edgeset can write the labels of the 
deba@1901
   981
    /// undirected edges. It is possible only if an "label" named map was 
deba@1901
   982
    /// written or the \c _forceLabelMap constructor parameter was true.
deba@1901
   983
    bool isLabelWriter() const {
deba@1901
   984
      return forceLabelMap || labelMap != 0;
deba@1421
   985
    }
deba@1421
   986
deba@1901
   987
    /// \brief Write the label of the given undirected edge.
deba@1421
   988
    ///
deba@1901
   989
    /// It writes the label of the given undirected edge. If there was written 
deba@1901
   990
    /// an "label" named map then it will write the map value belongs to the 
deba@1901
   991
    /// undirected edge. Otherwise if the \c forceLabel parameter was true it 
deba@1421
   992
    /// will write its id in the graph. 
klao@1909
   993
    void writeLabel(std::ostream& os, const UEdge& item) const {
deba@1901
   994
      if (forceLabelMap) {
deba@1429
   995
	os << graph.id(item);
deba@1429
   996
      } else {
deba@1901
   997
	labelMap->write(os, item);
deba@1429
   998
      }
deba@1429
   999
    } 
deba@1429
  1000
deba@1901
  1001
    /// \brief Write the label of the given edge.
deba@1429
  1002
    ///
deba@1901
  1003
    /// It writes the label of the given edge. If there was written 
deba@1901
  1004
    /// an "label" named map then it will write the map value belongs to the 
deba@1901
  1005
    /// edge. Otherwise if the \c forceLabel parameter was true it 
deba@1429
  1006
    /// will write its id in the graph. If the edge is forward map
deba@1429
  1007
    /// then its prefix character is \c '+' elsewhere \c '-'.
deba@1901
  1008
    void writeLabel(std::ostream& os, const Edge& item) const {
deba@1690
  1009
      if (graph.direction(item)) {
deba@1429
  1010
	os << "+ ";
deba@1429
  1011
      } else {
deba@1429
  1012
	os << "- ";
deba@1429
  1013
      }
deba@1901
  1014
      if (forceLabelMap) {
deba@1421
  1015
	os << graph.id(item);
deba@1421
  1016
      } else {
deba@1901
  1017
	labelMap->write(os, item);
deba@1421
  1018
      }
deba@1421
  1019
    } 
deba@1421
  1020
deba@1421
  1021
  private:
deba@1421
  1022
deba@1845
  1023
    typedef std::vector<std::pair<std::string, _writer_bits::
klao@1909
  1024
				  MapWriterBase<UEdge>*> > MapWriters;
deba@1421
  1025
    MapWriters writers;
deba@1421
  1026
klao@1909
  1027
    _writer_bits::MapWriterBase<UEdge>* labelMap;
deba@1901
  1028
    bool forceLabelMap;
deba@2101
  1029
    bool sortByLabel;
deba@1421
  1030
   
deba@1705
  1031
    const Graph& graph;   
deba@1901
  1032
    std::string name;
deba@1409
  1033
deba@1901
  1034
    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
deba@1409
  1035
  };
deba@1409
  1036
deba@2016
  1037
  /// \ingroup section_io
deba@1901
  1038
  /// \brief SectionWriter for writing named nodes.
deba@1409
  1039
  ///
deba@1901
  1040
  /// The nodes section's header line is \c \@nodes \c nodes_name, but the
deba@1901
  1041
  /// \c nodes_name may be empty.
deba@1409
  1042
  ///
deba@1901
  1043
  /// Each line in the section contains the name of the node and 
deba@1901
  1044
  /// then the node label. 
deba@1409
  1045
  ///
deba@1409
  1046
  /// \relates LemonWriter
deba@1409
  1047
  template <typename _Graph>
deba@1845
  1048
  class NodeWriter : public LemonWriter::SectionWriter {
deba@1845
  1049
    typedef LemonWriter::SectionWriter Parent;
deba@1409
  1050
    typedef _Graph Graph;
deba@1429
  1051
    typedef typename Graph::Node Node;
deba@1409
  1052
  public:
deba@1409
  1053
    
deba@1409
  1054
    /// \brief Constructor.
deba@1409
  1055
    ///
deba@1409
  1056
    /// Constructor for NodeWriter. It creates the NodeWriter and
deba@1901
  1057
    /// attach it into the given LemonWriter. The given \c _LabelWriter
deba@1901
  1058
    /// will write the nodes' label what can be a nodeset writer.
deba@1901
  1059
    template <typename _LabelWriter>
deba@1901
  1060
    NodeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
deba@1901
  1061
	       const std::string& _name = std::string()) 
deba@1901
  1062
      : Parent(_writer), name(_name) {
deba@1901
  1063
      checkConcept<_writer_bits::ItemLabelWriter<Node>, _LabelWriter>();
deba@1901
  1064
      labelWriter.reset(new _writer_bits::LabelWriter<Node, _LabelWriter>
deba@1901
  1065
                        (_labelWriter));
deba@1476
  1066
    }
deba@1476
  1067
deba@1409
  1068
deba@1409
  1069
    /// \brief Destructor.
deba@1409
  1070
    ///
deba@1409
  1071
    /// Destructor for NodeWriter.
deba@1409
  1072
    virtual ~NodeWriter() {}
deba@1409
  1073
deba@1409
  1074
  private:
deba@1409
  1075
    NodeWriter(const NodeWriter&);
deba@1409
  1076
    void operator=(const NodeWriter&);
deba@1409
  1077
deba@1409
  1078
  public:
deba@1409
  1079
deba@1409
  1080
    /// \brief Add a node writer command for the NodeWriter.
deba@1409
  1081
    ///
deba@1409
  1082
    /// Add a node writer command for the NodeWriter.
deba@1429
  1083
    void writeNode(const std::string& name, const Node& item) {
deba@1409
  1084
      writers.push_back(make_pair(name, &item));
deba@1409
  1085
    }
deba@1409
  1086
deba@1409
  1087
  protected:
deba@1409
  1088
deba@1901
  1089
    /// \brief The header of the section.
deba@1409
  1090
    ///
deba@1901
  1091
    /// It gives back the header of the section.
deba@1409
  1092
    virtual std::string header() {
deba@1901
  1093
      return "@nodes " + name;
deba@1409
  1094
    }
deba@1409
  1095
deba@1409
  1096
    /// \brief  Writer function of the section.
deba@1409
  1097
    ///
deba@1409
  1098
    /// Write the content of the section.
deba@1409
  1099
    virtual void write(std::ostream& os) {
deba@1901
  1100
      if (!labelWriter->isLabelWriter()) {
deba@1901
  1101
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
  1102
      }
deba@1409
  1103
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
  1104
	os << writers[i].first << ' ';
deba@1901
  1105
	labelWriter->write(os, *(writers[i].second));
deba@1409
  1106
	os << std::endl;
deba@1409
  1107
      }
deba@1409
  1108
    }
deba@2084
  1109
deba@2084
  1110
    /// \brief Gives back true when the section should be written.
deba@2084
  1111
    ///
deba@2084
  1112
    /// Gives back true when the section should be written.
deba@2084
  1113
    virtual bool valid() { return !writers.empty(); }
deba@1409
  1114
    
deba@1409
  1115
  private:
deba@1409
  1116
deba@1901
  1117
    std::string name;
deba@1409
  1118
deba@1429
  1119
    typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
deba@1429
  1120
    NodeWriters writers;
deba@1901
  1121
    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > labelWriter;
deba@1409
  1122
  };
deba@1409
  1123
deba@2016
  1124
  /// \ingroup section_io
deba@1901
  1125
  /// \brief SectionWriter for writing named edges.
deba@1409
  1126
  ///
deba@1901
  1127
  /// The edges section's header line is \c \@edges \c edges_name, but the
deba@1901
  1128
  /// \c edges_name may be empty.
deba@1409
  1129
  ///
deba@1901
  1130
  /// Each line in the section contains the name of the edge and 
deba@1901
  1131
  /// then the edge label. 
deba@1409
  1132
  ///
deba@1409
  1133
  /// \relates LemonWriter
deba@1409
  1134
  template <typename _Graph>
deba@1845
  1135
  class EdgeWriter : public LemonWriter::SectionWriter {
deba@1845
  1136
    typedef LemonWriter::SectionWriter Parent;
deba@1409
  1137
    typedef _Graph Graph;
deba@1429
  1138
    typedef typename Graph::Edge Edge;
deba@1409
  1139
  public:
deba@1409
  1140
    
deba@1409
  1141
    /// \brief Constructor.
deba@1409
  1142
    ///
deba@1409
  1143
    /// Constructor for EdgeWriter. It creates the EdgeWriter and
deba@1901
  1144
    /// attach it into the given LemonWriter. The given \c _LabelWriter
deba@1901
  1145
    /// will write the edges' label what can be a edgeset writer.
deba@1901
  1146
    template <typename _LabelWriter>
deba@1901
  1147
    EdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
deba@1901
  1148
	       const std::string& _name = std::string()) 
deba@1901
  1149
      : Parent(_writer), name(_name) {
deba@1901
  1150
      checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
deba@1901
  1151
      labelWriter.reset(new _writer_bits::LabelWriter<Edge, _LabelWriter>(_labelWriter));
deba@1476
  1152
    }
deba@1409
  1153
deba@1409
  1154
    /// \brief Destructor.
deba@1409
  1155
    ///
deba@1409
  1156
    /// Destructor for EdgeWriter.
deba@1409
  1157
    virtual ~EdgeWriter() {}
deba@1409
  1158
  private:
deba@1409
  1159
    EdgeWriter(const EdgeWriter&);
deba@1409
  1160
    void operator=(const EdgeWriter&);
deba@1409
  1161
deba@1409
  1162
  public:
deba@1409
  1163
deba@1421
  1164
    /// \brief Add an edge writer command for the EdgeWriter.
deba@1409
  1165
    ///
deba@1421
  1166
    /// Add an edge writer command for the EdgeWriter.
deba@1429
  1167
    void writeEdge(const std::string& name, const Edge& item) {
deba@1409
  1168
      writers.push_back(make_pair(name, &item));
deba@1409
  1169
    }
deba@1409
  1170
deba@1409
  1171
  protected:
deba@1409
  1172
deba@1901
  1173
    /// \brief The header of the section.
deba@1409
  1174
    ///
deba@1901
  1175
    /// It gives back the header of the section.
deba@1421
  1176
    virtual std::string header() {
deba@1901
  1177
      return "@edges " + name;
deba@1421
  1178
    }
deba@1421
  1179
deba@1421
  1180
    /// \brief  Writer function of the section.
deba@1421
  1181
    ///
deba@1421
  1182
    /// Write the content of the section.
deba@1421
  1183
    virtual void write(std::ostream& os) {
deba@1901
  1184
      if (!labelWriter->isLabelWriter()) {
deba@1901
  1185
	throw DataFormatError("Cannot find edgeset or label map");
deba@1476
  1186
      }
deba@1421
  1187
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1421
  1188
	os << writers[i].first << ' ';
deba@1901
  1189
	labelWriter->write(os, *(writers[i].second));
deba@1421
  1190
	os << std::endl;
deba@1421
  1191
      }
deba@1421
  1192
    }
deba@2084
  1193
deba@2084
  1194
    /// \brief Gives back true when the section should be written.
deba@2084
  1195
    ///
deba@2084
  1196
    /// Gives back true when the section should be written.
deba@2084
  1197
    virtual bool valid() { return !writers.empty(); }
deba@1421
  1198
    
deba@1421
  1199
  private:
deba@1421
  1200
deba@1901
  1201
    std::string name;
deba@1421
  1202
deba@1429
  1203
    typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
deba@1429
  1204
    EdgeWriters writers;
deba@1421
  1205
deba@1901
  1206
    std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > labelWriter;
deba@1421
  1207
  };
deba@1421
  1208
deba@2016
  1209
  /// \ingroup section_io
deba@1901
  1210
  /// \brief SectionWriter for writing named undirected edges.
deba@1421
  1211
  ///
klao@1909
  1212
  /// The undirected edges section's header line is \c \@uedges 
klao@1909
  1213
  /// \c uedges_name, but the \c uedges_name may be empty.
deba@1421
  1214
  ///
deba@1901
  1215
  /// Each line in the section contains the name of the undirected edge and 
deba@1901
  1216
  /// then the undirected edge label. 
deba@1421
  1217
  ///
deba@1421
  1218
  /// \relates LemonWriter
deba@1421
  1219
  template <typename _Graph>
klao@1909
  1220
  class UEdgeWriter : public LemonWriter::SectionWriter {
deba@1845
  1221
    typedef LemonWriter::SectionWriter Parent;
deba@1421
  1222
    typedef _Graph Graph;
deba@1429
  1223
    typedef typename Graph::Node Node;
deba@1429
  1224
    typedef typename Graph::Edge Edge;
klao@1909
  1225
    typedef typename Graph::UEdge UEdge;
deba@1421
  1226
  public:
deba@1421
  1227
    
deba@1421
  1228
    /// \brief Constructor.
deba@1421
  1229
    ///
klao@1909
  1230
    /// Constructor for UEdgeWriter. It creates the UEdgeWriter and
deba@1901
  1231
    /// attach it into the given LemonWriter. The given \c _LabelWriter
deba@1901
  1232
    /// will write the undirected edges' label what can be an undirected 
deba@1421
  1233
    /// edgeset writer.
deba@1901
  1234
    template <typename _LabelWriter>
klao@1909
  1235
    UEdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
deba@1901
  1236
	       const std::string& _name = std::string()) 
deba@1901
  1237
      : Parent(_writer), name(_name) {
deba@1901
  1238
      checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
klao@1909
  1239
      checkConcept<_writer_bits::ItemLabelWriter<UEdge>, _LabelWriter>();
klao@1909
  1240
      uEdgeLabelWriter.reset(new _writer_bits::
klao@1909
  1241
			      LabelWriter<UEdge, _LabelWriter>(_labelWriter));
deba@1901
  1242
      edgeLabelWriter.reset(new _writer_bits::
deba@1901
  1243
			 LabelWriter<Edge, _LabelWriter>(_labelWriter));
deba@1476
  1244
    }
deba@1421
  1245
deba@1421
  1246
    /// \brief Destructor.
deba@1421
  1247
    ///
klao@1909
  1248
    /// Destructor for UEdgeWriter.
klao@1909
  1249
    virtual ~UEdgeWriter() {}
deba@1421
  1250
  private:
klao@1909
  1251
    UEdgeWriter(const UEdgeWriter&);
klao@1909
  1252
    void operator=(const UEdgeWriter&);
deba@1421
  1253
deba@1421
  1254
  public:
deba@1421
  1255
klao@1909
  1256
    /// \brief Add an edge writer command for the UEdgeWriter.
deba@1429
  1257
    ///
klao@1909
  1258
    /// Add an edge writer command for the UEdgeWriter.
deba@1429
  1259
    void writeEdge(const std::string& name, const Edge& item) {
deba@1429
  1260
      edgeWriters.push_back(make_pair(name, &item));
deba@1429
  1261
    }
deba@1429
  1262
klao@1909
  1263
    /// \brief Add an undirected edge writer command for the UEdgeWriter.
deba@1421
  1264
    ///
klao@1909
  1265
    /// Add an undirected edge writer command for the UEdgeWriter.
klao@1909
  1266
    void writeUEdge(const std::string& name, const UEdge& item) {
klao@1909
  1267
      uEdgeWriters.push_back(make_pair(name, &item));
deba@1421
  1268
    }
deba@1421
  1269
deba@1421
  1270
  protected:
deba@1421
  1271
deba@1901
  1272
    /// \brief The header of the section.
deba@1421
  1273
    ///
deba@1901
  1274
    /// It gives back the header of the section.
deba@1409
  1275
    virtual std::string header() {
klao@1909
  1276
      return "@uedges " + name;
deba@1409
  1277
    }
deba@1409
  1278
deba@1409
  1279
    /// \brief  Writer function of the section.
deba@1409
  1280
    ///
deba@1409
  1281
    /// Write the content of the section.
deba@1409
  1282
    virtual void write(std::ostream& os) {
deba@1901
  1283
      if (!edgeLabelWriter->isLabelWriter()) {
deba@1901
  1284
	throw DataFormatError("Cannot find undirected edgeset or label map");
deba@1476
  1285
      }
klao@1909
  1286
      if (!uEdgeLabelWriter->isLabelWriter()) {
deba@1901
  1287
	throw DataFormatError("Cannot find undirected edgeset or label map");
deba@1476
  1288
      }
klao@1909
  1289
      for (int i = 0; i < (int)uEdgeWriters.size(); ++i) {
klao@1909
  1290
	os << uEdgeWriters[i].first << ' ';
klao@1909
  1291
	uEdgeLabelWriter->write(os, *(uEdgeWriters[i].second));
deba@1429
  1292
	os << std::endl;
deba@1429
  1293
      }
deba@1429
  1294
      for (int i = 0; i < (int)edgeWriters.size(); ++i) {
deba@1429
  1295
	os << edgeWriters[i].first << ' ';
deba@1901
  1296
	edgeLabelWriter->write(os, *(edgeWriters[i].second));
deba@1409
  1297
	os << std::endl;
deba@1409
  1298
      }
deba@1409
  1299
    }
deba@2084
  1300
deba@2084
  1301
    /// \brief Gives back true when the section should be written.
deba@2084
  1302
    ///
deba@2084
  1303
    /// Gives back true when the section should be written.
deba@2084
  1304
    virtual bool valid() { 
deba@2084
  1305
      return !uEdgeWriters.empty() || !edgeWriters.empty(); 
deba@2084
  1306
    }
deba@1409
  1307
    
deba@1409
  1308
  private:
deba@1409
  1309
deba@1901
  1310
    std::string name;
deba@1409
  1311
deba@1429
  1312
    typedef std::vector<std::pair<std::string, 
klao@1909
  1313
				  const UEdge*> > UEdgeWriters;
klao@1909
  1314
    UEdgeWriters uEdgeWriters;
klao@1909
  1315
    std::auto_ptr<_writer_bits::LabelWriterBase<UEdge> > uEdgeLabelWriter;
deba@1409
  1316
deba@1429
  1317
    typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
deba@1429
  1318
    EdgeWriters edgeWriters;
deba@1901
  1319
    std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > edgeLabelWriter;
deba@1429
  1320
deba@1409
  1321
  };
deba@1409
  1322
deba@2016
  1323
  /// \ingroup section_io
deba@1409
  1324
  /// \brief SectionWriter for attributes.
deba@1409
  1325
  ///
deba@1409
  1326
  /// The lemon format can store multiple attribute set. Each set has
deba@1901
  1327
  /// the header line \c \@attributes \c attributes_name, but the 
deba@1901
  1328
  /// attributeset_name may be empty.
deba@1409
  1329
  ///
deba@1409
  1330
  /// The attributeset section contains several lines. Each of them starts
deba@1409
  1331
  /// with the name of attribute and then the value.
deba@1409
  1332
  ///
deba@1409
  1333
  /// \relates LemonWriter
deba@1409
  1334
  template <typename _Traits = DefaultWriterTraits>
deba@1845
  1335
  class AttributeWriter : public LemonWriter::SectionWriter {
deba@1845
  1336
    typedef LemonWriter::SectionWriter Parent;
deba@1409
  1337
    typedef _Traits Traits; 
deba@1409
  1338
  public:
deba@1409
  1339
    /// \brief Constructor.
deba@1409
  1340
    ///
deba@1409
  1341
    /// Constructor for AttributeWriter. It creates the AttributeWriter and
deba@1409
  1342
    /// attach it into the given LemonWriter.
deba@1409
  1343
    AttributeWriter(LemonWriter& _writer, 
deba@1901
  1344
		    const std::string& _name = std::string()) 
deba@1901
  1345
      : Parent(_writer), name(_name) {}
deba@1409
  1346
deba@1409
  1347
    /// \brief Destructor.
deba@1409
  1348
    ///
deba@1409
  1349
    /// Destructor for AttributeWriter.
deba@1409
  1350
    virtual ~AttributeWriter() {
deba@1409
  1351
      typename Writers::iterator it;
deba@1409
  1352
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
  1353
	delete it->second;
deba@1409
  1354
      }
deba@1409
  1355
    }
deba@1409
  1356
deba@1409
  1357
  private:
deba@1409
  1358
    AttributeWriter(const AttributeWriter&);
deba@1409
  1359
    void operator=(AttributeWriter&);
deba@1409
  1360
deba@1409
  1361
  public:
deba@1409
  1362
    /// \brief Add an attribute writer command for the writer.
deba@1409
  1363
    ///
deba@1409
  1364
    /// Add an attribute writer command for the writer.
deba@1409
  1365
    template <typename Value>
deba@1901
  1366
    AttributeWriter& writeAttribute(const std::string& name, 
deba@1409
  1367
				    const Value& value) {
deba@1409
  1368
      return 
deba@1901
  1369
	writeAttribute<typename Traits::template Writer<Value> >(name, value);
deba@1409
  1370
    }
deba@1409
  1371
deba@1409
  1372
    /// \brief Add an attribute writer command for the writer.
deba@1409
  1373
    ///
deba@1409
  1374
    /// Add an attribute writer command for the writer.
deba@1409
  1375
    template <typename Writer, typename Value>
deba@1409
  1376
    AttributeWriter& writeAttribute(const std::string& name, 
deba@1409
  1377
				    const Value& value,
deba@1409
  1378
				    const Writer& writer = Writer()) {
deba@1492
  1379
      checkConcept<_writer_bits::ItemWriter<Value>, Writer>();
deba@1845
  1380
      writers.push_back(make_pair(name, new _writer_bits::
deba@1845
  1381
				  ValueWriter<Value, Writer>(value, writer)));
deba@1409
  1382
      return *this;
deba@1409
  1383
    }
deba@1409
  1384
deba@1409
  1385
  protected:
deba@1409
  1386
deba@1409
  1387
    /// \brief The header of section.
deba@1409
  1388
    ///
deba@1409
  1389
    /// It gives back the header of the section.
deba@1409
  1390
    std::string header() {
deba@1901
  1391
      return "@attributes " + name;
deba@1409
  1392
    }
deba@1409
  1393
deba@1409
  1394
    /// \brief  Writer function of the section.
deba@1409
  1395
    ///
deba@1409
  1396
    /// Write the content of the section.
deba@1409
  1397
    void write(std::ostream& os) {
deba@1409
  1398
      typename Writers::iterator it;
deba@1409
  1399
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
  1400
	os << it->first << ' ';
deba@1409
  1401
	it->second->write(os);
deba@1409
  1402
	os << std::endl;
deba@1409
  1403
      }
deba@1409
  1404
    }    
deba@1409
  1405
deba@2084
  1406
    /// \brief Gives back true when the section should be written.
deba@2084
  1407
    ///
deba@2084
  1408
    /// Gives back true when the section should be written.
deba@2084
  1409
    virtual bool valid() { return !writers.empty(); }
deba@2084
  1410
deba@1409
  1411
  private:
deba@1901
  1412
    std::string name;
deba@1409
  1413
deba@1845
  1414
    typedef std::vector<std::pair<std::string, 
deba@1845
  1415
				  _writer_bits::ValueWriterBase*> > Writers;
deba@1409
  1416
    Writers writers;  
deba@1409
  1417
  };
deba@1409
  1418
deba@1409
  1419
deba@1409
  1420
}
deba@1409
  1421
#endif