COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_writer.h @ 2486:0c498f2239a8

Last change on this file since 2486:0c498f2239a8 was 2467:2025a571895e, checked in by Balazs Dezso, 17 years ago

PathNodeIt?

PathWriter/Reader? structures
Distinict MapSet? readers and writers

File size: 61.5 KB
RevLine 
[1409]1/* -*- C++ -*-
2 *
[1956]3 * This file is a part of LEMON, a generic C++ optimization library
4 *
[2391]5 * Copyright (C) 2003-2007
[1956]6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
[1409]7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 *
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
12 *
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
15 * purpose.
16 *
17 */
18
[2084]19///\ingroup lemon_io
[1409]20///\file
21///\brief Lemon Format writer.
22
23#ifndef LEMON_LEMON_WRITER_H
24#define LEMON_LEMON_WRITER_H
25
26#include <iostream>
27#include <fstream>
28#include <string>
29#include <vector>
30#include <algorithm>
31#include <map>
32#include <memory>
33
34#include <lemon/error.h>
[1993]35#include <lemon/bits/invalid.h>
[1421]36#include <lemon/graph_utils.h>
[1409]37#include <lemon/bits/item_writer.h>
[1993]38#include <lemon/bits/utility.h>
[1421]39#include <lemon/maps.h>
[2207]40#include <lemon/dim2.h>
[1409]41
[1476]42#include <lemon/concept_check.h>
[2260]43#include <lemon/concepts/maps.h>
[1476]44
[1409]45
46namespace lemon {
47
[1476]48  namespace _writer_bits {
49   
[2101]50    template <typename T>
51    bool operator<(T, T) {
52      throw DataFormatError("Label is not comparable");
53    }
54
55    template <typename T>
56    struct Less {
57      bool operator()(const T& p, const T& q) const {
58        return p < q;
59      }
60    };
61
62    template <typename Map>
63    struct ComposeLess {
64      ComposeLess(const Map& _map) : map(_map), less() {}
65
66      bool operator()(const typename Map::Key& p,
67                      const typename Map::Key& q) const {
68        return less(map[p], map[q]);
69      }
70      const Map& map;
71      Less<typename Map::Value> less;
72    };
73
[2467]74    template <typename UGraph, typename Map>
75    struct UEdgeComposeLess {
76      UEdgeComposeLess(const UGraph& _ugraph, const Map& _map)
77        : ugraph(_ugraph), map(_map), less() {}
78
79      bool operator()(const typename UGraph::Edge& p,
80                      const typename UGraph::Edge& q) const {
81        return p != q ? less(map[p], map[q]) :
82          (!ugraph.direction(p) && ugraph.direction(q));
83      }
84
85      const UGraph& ugraph;
86      const Map& map;
87      Less<typename Map::Value> less;
88    };
89
[1476]90    template <typename Item>
[1901]91    class ItemLabelWriter {
[1476]92    public:
93
[1901]94      bool isLabelWriter() { return true; }
[1476]95
[1901]96      void writeLabel(std::ostream&, const Item&) {}
[1476]97     
[1901]98      template <class _ItemLabelWriter>
[1476]99      struct Constraints {
100        void constraints() {
[1901]101          bool b = writer.isLabelWriter();
[1476]102          ignore_unused_variable_warning(b);
[1901]103          writer.writeLabel(os, item);
[1476]104        }
[1901]105        _ItemLabelWriter& writer;
[1476]106        std::ostream& os;
[1492]107        const Item& item;
108      };
109
110    };
111
112    template <typename Item>
113    class ItemWriter {
114    public:
115
116      void write(std::ostream&, const Item&) {}
117     
118      template <class _ItemWriter>
119      struct Constraints {
120        void constraints() {
121          writer.write(os, item);
122        }
123        _ItemWriter& writer;
124        std::ostream& os;
125        const Item& item;
[1476]126      };
127
128    };
129
[1705]130    template <typename Map>
131    struct Ref { typedef const Map& Type; };
132
133    template <typename Graph, typename Map>
134    class ForwardComposeMap {
135    public:
[1909]136      typedef typename Graph::UEdge Key;
[1705]137      typedef typename Map::Value Value;
138
139      ForwardComposeMap(const Graph& _graph, const Map& _map)
140        : graph(_graph), map(_map) {}
141     
[2467]142      Value operator[](const Key& key) const {
143        return map[graph.direct(key, true)];
[1705]144      }
145
146    private:
147      typename Ref<Map>::Type map;
148      const Graph& graph;
149    };
150
151    template <typename Graph, typename Map>
152    ForwardComposeMap<Graph, Map>
153    forwardComposeMap(const Graph& graph, const Map& map) {
154      return ForwardComposeMap<Graph, Map>(graph, map);
155    }
156
157    template <typename Graph, typename Map>
158    class BackwardComposeMap {
159    public:
[1909]160      typedef typename Graph::UEdge Key;
[1705]161      typedef typename Map::Value Value;
162
163      BackwardComposeMap(const Graph& _graph, const Map& _map)
164        : graph(_graph), map(_map) {}
165     
[2467]166      Value operator[](const Key& key) const {
[1705]167        return map[graph.direct(key, false)];
168      }
169
170    private:
171      typename Ref<Map>::Type map;
172      const Graph& graph;
173    };
174
175    template <typename Graph, typename Map>
176    BackwardComposeMap<Graph, Map>
177    backwardComposeMap(const Graph& graph, const Map& map) {
178      return BackwardComposeMap<Graph, Map>(graph, map);
179    }
180
181    template <typename Graph, typename Map>
182    struct Ref<ForwardComposeMap<Graph, Map> > {
183      typedef ForwardComposeMap<Graph, Map> Type;
184    };
185
186    template <typename Graph, typename Map>
187    struct Ref<BackwardComposeMap<Graph, Map> > {
188      typedef BackwardComposeMap<Graph, Map> Type;
189    };
190
191    template <typename Map>
[2207]192    struct Ref<dim2::XMap<Map> > {
193      typedef dim2::XMap<Map> Type;
[1705]194    };
195    template <typename Map>
[2207]196    struct Ref<dim2::ConstXMap<Map> > {
197      typedef dim2::ConstXMap<Map> Type;
[1705]198    };
199
200    template <typename Map>
[2207]201    struct Ref<dim2::YMap<Map> > {
202      typedef dim2::YMap<Map> Type;
[1705]203    };
204    template <typename Map>
[2207]205    struct Ref<dim2::ConstYMap<Map> > {
206      typedef dim2::ConstYMap<Map> Type;
[1705]207    };
208
[1845]209
210    template <typename _Item>   
211    class MapWriterBase {
212    public:
213      typedef _Item Item;
214
215      virtual ~MapWriterBase() {}
216
[1852]217      virtual void write(std::ostream& os, const Item& item) const = 0;
[2467]218      virtual void sort(std::vector<Item>&) const = 0;
[1845]219    };
220
221
222    template <typename _Item, typename _Map, typename _Writer>
223    class MapWriter : public MapWriterBase<_Item> {
224    public:
225      typedef _Map Map;
226      typedef _Writer Writer;
227      typedef typename Writer::Value Value;
228      typedef _Item Item;
229     
230      typename _writer_bits::Ref<Map>::Type map;
231      Writer writer;
232
233      MapWriter(const Map& _map, const Writer& _writer)
234        : map(_map), writer(_writer) {}
235
236      virtual ~MapWriter() {}
237
[1852]238      virtual void write(std::ostream& os, const Item& item) const {
[1845]239        Value value = map[item];
240        writer.write(os, value);
241      }
242
[2467]243      virtual void sort(std::vector<Item>& items) const {
244        ComposeLess<Map> less(map);
245        std::sort(items.begin(), items.end(), less);
246      }
247
248    };
249
250    template <typename _UGraph>   
251    class UEdgeMapWriterBase {
252    public:
253      typedef typename _UGraph::Edge Edge;
254      typedef typename _UGraph::UEdge UEdge;
255
256      typedef UEdge Item;
257
258      virtual ~UEdgeMapWriterBase() {}
259
260      virtual void write(std::ostream& os, const Item& item) const = 0;
261      virtual void sort(const _UGraph&, std::vector<Edge>&) const = 0;
262      virtual void sort(std::vector<UEdge>&) const = 0;
263    };
264
265
266    template <typename _UGraph, typename _Map, typename _Writer>
267    class UEdgeMapWriter : public UEdgeMapWriterBase<_UGraph> {
268    public:
269      typedef _Map Map;
270      typedef _Writer Writer;
271      typedef typename Writer::Value Value;
272
273      typedef typename _UGraph::Edge Edge;
274      typedef typename _UGraph::UEdge UEdge;
275      typedef UEdge Item;
276     
277      typename _writer_bits::Ref<Map>::Type map;
278      Writer writer;
279
280      UEdgeMapWriter(const Map& _map, const Writer& _writer)
281        : map(_map), writer(_writer) {}
282
283      virtual ~UEdgeMapWriter() {}
284
285      virtual void write(std::ostream& os, const Item& item) const {
286        Value value = map[item];
287        writer.write(os, value);
288      }
289
290      virtual void sort(const _UGraph& ugraph, std::vector<Edge>& items) const {
291        UEdgeComposeLess<_UGraph, Map> less(ugraph, map);
292        std::sort(items.begin(), items.end(), less);
293      }
294
295      virtual void sort(std::vector<UEdge>& items) const {
[2101]296        ComposeLess<Map> less(map);
297        std::sort(items.begin(), items.end(), less);
298      }
299
[1845]300    };
301
302
303    class ValueWriterBase {
304    public:
305      virtual ~ValueWriterBase() {}
306      virtual void write(std::ostream&) = 0;
307    };
308
309    template <typename _Value, typename _Writer>
310    class ValueWriter : public ValueWriterBase {
311    public:
312      typedef _Value Value;
313      typedef _Writer Writer;
314
315      ValueWriter(const Value& _value, const Writer& _writer)
316        : value(_value), writer(_writer) {}
317
318      virtual void write(std::ostream& os) {
319        writer.write(os, value);
320      }
321    private:
322      const Value& value;
323      Writer writer;
324    };
325   
326
327    template <typename _Item>
[1901]328    class LabelWriterBase {
[1845]329    public:
330      typedef _Item Item;
[1901]331      virtual ~LabelWriterBase() {}
[1845]332      virtual void write(std::ostream&, const Item&) const = 0;
[2467]333      virtual void sort(std::vector<Item>&) const = 0;
[1901]334      virtual bool isLabelWriter() const = 0;
[2467]335      virtual LabelWriterBase* clone() const = 0;
[1845]336    };
337
[1901]338    template <typename _Item, typename _BoxedLabelWriter>
339    class LabelWriter : public LabelWriterBase<_Item> {
[1845]340    public:
341      typedef _Item Item;
[1901]342      typedef _BoxedLabelWriter BoxedLabelWriter;
[1845]343
[1901]344      const BoxedLabelWriter& labelWriter;
[1845]345
[1901]346      LabelWriter(const BoxedLabelWriter& _labelWriter)
347        : labelWriter(_labelWriter) {}
[1845]348
349      virtual void write(std::ostream& os, const Item& item) const {
[1901]350        labelWriter.writeLabel(os, item);
[1845]351      }
[2467]352      virtual void sort(std::vector<Item>& items) const {
353        labelWriter.sortByLabel(items);
354      }
[1845]355
[1901]356      virtual bool isLabelWriter() const {
357        return labelWriter.isLabelWriter();
[1845]358      }
[2467]359
360      virtual LabelWriter* clone() const {
361        return new LabelWriter(labelWriter);
362      }
[1845]363    };
364
[1476]365  }
366
[2084]367  /// \ingroup lemon_io
[1409]368  /// \brief Lemon Format writer class.
369  ///
370  /// The Lemon Format contains several sections. We do not want to
371  /// determine what sections are in a lemon file we give only a framework
372  /// to write a section oriented format.
373  ///
374  /// In the Lemon Format each section starts with a line contains a \c \@
375  /// character on the first not white space position. This line is the
376  /// header line of the section. Each next lines belong to this section
377  /// while it does not starts with \c \@ character. This line can start a
378  /// new section or if it can close the file with the \c \@end line.
379  /// The file format ignore the empty lines and it may contain comments
380  /// started with a \c # character to the end of the line.
381  ///
382  /// The framework provides an abstract LemonWriter::SectionWriter class
383  /// what defines the interface of a SectionWriter. The SectionWriter
384  /// has the \c header() member function what gives back the header of the
385  /// section. After that it will be called the \c write() member which
386  /// should write the content of the section.
387  ///
388  /// \relates GraphWriter
389  /// \relates NodeSetWriter
390  /// \relates EdgeSetWriter
391  /// \relates NodesWriter
392  /// \relates EdgesWriter
393  /// \relates AttributeWriter
394  class LemonWriter {
395  public:
396
397    /// \brief Abstract base class for writing a section.
398    ///
399    /// This class has an \c header() member function what gives back
400    /// the header line of the section. The \c write() member should
401    /// write the content of the section to the stream.
402    class SectionWriter {
403      friend class LemonWriter;
404    protected:
405      /// \brief Constructor for SectionWriter.
406      ///
407      /// Constructor for SectionWriter. It attach this writer to
408      /// the given LemonWriter.
409      SectionWriter(LemonWriter& writer) {
410        writer.attach(*this);
411      }
[1494]412     
413      virtual ~SectionWriter() {}
[1409]414
415      /// \brief The header of section.
416      ///
417      /// It gives back the header of the section.
418      virtual std::string header() = 0;
419
[2084]420      /// \brief Writer function of the section.
[1409]421      ///
422      /// Write the content of the section.
423      virtual void write(std::ostream& os) = 0;
[2084]424     
425      /// \brief Gives back true when the section should be written.
426      ///
427      /// Gives back true when the section should be written.
428      virtual bool valid() { return true; }
[1409]429    };
430
431    /// \brief Constructor for LemonWriter.
432    ///
433    /// Constructor for LemonWriter which writes to the given stream.
434    LemonWriter(std::ostream& _os)
435      : os(&_os), own_os(false) {}
436
437    /// \brief Constructor for LemonWriter.
438    ///
439    /// Constructor for LemonWriter which writes to the given file.
440    LemonWriter(const std::string& filename)
441      : os(0), own_os(true) {
442      os = new std::ofstream(filename.c_str());
443    }
444
445    /// \brief Desctructor for LemonWriter.
446    ///
447    /// Desctructor for LemonWriter.
448    ~LemonWriter() {
449      if (own_os) {
450        delete os;
451      }
452    }
453
454  private:
455    LemonWriter(const LemonWriter&);
456    void operator=(const LemonWriter&);
457
458    void attach(SectionWriter& writer) {
459      writers.push_back(&writer);
460    }
461
462  public:
463
464    /// \brief Executes the LemonWriter.
465    ///
466    /// It executes the LemonWriter.
467    void run() {
468      SectionWriters::iterator it;
469      for (it = writers.begin(); it != writers.end(); ++it) {
[2084]470        if ((*it)->valid()) {
471          *os << (*it)->header() << std::endl;
472          (*it)->write(*os);
473        }
[1409]474      }
475      *os << "@end" << std::endl;
476    }
477
478
479  private:
480
481    std::ostream* os;
482    bool own_os;
483
484    typedef std::vector<SectionWriter*> SectionWriters;
485    SectionWriters writers;
486
487  };
488
[2016]489  /// \ingroup section_io
[1409]490  /// \brief SectionWriter for writing a graph's nodeset.
491  ///
492  /// The lemon format can store multiple graph nodesets with several maps.
[1901]493  /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but
494  /// the \c nodeset_name may be empty.
[1409]495  ///
496  /// The first line of the section contains the names of the maps separated
497  /// with white spaces. Each next lines describes a node in the nodeset, and
498  /// contains the mapped values for each map.
499  ///
[1901]500  /// If the nodeset contains an \c "label" named map then it will be regarded
501  /// as label map. This map should contain only unique values and when the
502  /// \c writeLabel() member will be called with a node it will write it's
503  /// label. Otherwise if the \c _forceLabelMap constructor parameter is true
[2101]504  /// then the label map will be the id in the graph. In addition if the
[2467]505  /// the \c _forceSort is true then the writer will write the edges
[2101]506  /// sorted by the labels.
[1409]507  ///
508  /// \relates LemonWriter
509  template <typename _Graph, typename _Traits = DefaultWriterTraits>
[1845]510  class NodeSetWriter : public LemonWriter::SectionWriter {
511    typedef LemonWriter::SectionWriter Parent;
[1409]512  public:
513
514    typedef _Graph Graph;
515    typedef _Traits Traits;
[1429]516    typedef typename Graph::Node Node;
[1409]517
518    /// \brief Constructor.
519    ///
520    /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
[1901]521    /// attach it into the given LemonWriter. If the \c _forceLabelMap
522    /// parameter is true then the writer will write own label map when
[2101]523    /// the user does not give "label" named map. In addition if the
[2467]524    /// the \c _forceSort is true then the writer will write the edges
[2101]525    /// sorted by the labels.
[1409]526    NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
[1901]527                  const std::string& _name = std::string(),
[2467]528                  bool _forceLabelMap = true, bool _forceSort = true)
[1901]529      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
[2467]530        forceSort(_forceSort), graph(_graph), name(_name) {}
[1409]531
532    /// \brief Destructor.
533    ///
534    /// Destructor for NodeSetWriter.
535    virtual ~NodeSetWriter() {
536      typename MapWriters::iterator it;
537      for (it = writers.begin(); it != writers.end(); ++it) {
538        delete it->second;
539      }
540    }
541
542  private:
543    NodeSetWriter(const NodeSetWriter&);
544    void operator=(const NodeSetWriter&);
545 
546  public:
547
548    /// \brief Add a new node map writer command for the writer.
549    ///
550    /// Add a new node map writer command for the writer.
551    template <typename Map>
[2386]552    NodeSetWriter& writeNodeMap(std::string label, const Map& map) {
[1421]553      return writeNodeMap<typename Traits::
[2386]554        template Writer<typename Map::Value>, Map>(label, map);
[1409]555    }
556
557    /// \brief Add a new node map writer command for the writer.
558    ///
559    /// Add a new node map writer command for the writer.
[2386]560    template <typename ItemWriter, typename Map>
561    NodeSetWriter& writeNodeMap(std::string label, const Map& map,
562                            const ItemWriter& iw = ItemWriter()) {
[2260]563      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
[2386]564      checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
[1409]565      writers.push_back(
[2386]566        make_pair(label, new _writer_bits::
567                  MapWriter<Node, Map, ItemWriter>(map, iw)));
[1409]568      return *this;
569    }
570
571  protected:
572
573    /// \brief The header of the section.
574    ///
575    /// It gives back the header of the section.
576    virtual std::string header() {
[1901]577      return "@nodeset " + name;
[1409]578    }
579
580    /// \brief  Writer function of the section.
581    ///
582    /// Write the content of the section.
583    virtual void write(std::ostream& os) {
[2386]584      for (int i = 0; i < int(writers.size()); ++i) {
[2084]585        if (writers[i].first == "label") {
[1901]586          labelMap = writers[i].second;
587          forceLabelMap = false;
[1409]588          break;
589        }
590      }
[2101]591      std::vector<Node> items;
592      for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
593        items.push_back(it);
594      }
[2467]595      if (forceSort) {
[2101]596        if (labelMap) {
[2467]597          labelMap->sort(items);
[2101]598        } else {
599          typedef IdMap<Graph, Node> Map;
600          Map map(graph);
601          _writer_bits::ComposeLess<Map> less(map);
602          std::sort(items.begin(), items.end(), less);
603        }
604      }
[1901]605      if (forceLabelMap) {
606        os << "label\t";
[1409]607      }
[2386]608      for (int i = 0; i < int(writers.size()); ++i) {
[1409]609        os << writers[i].first << '\t';
610      }
611      os << std::endl;
[2101]612      for (typename std::vector<Node>::iterator it = items.begin();
613           it != items.end(); ++it) {
[1901]614        if (forceLabelMap) {
[2101]615          os << graph.id(*it) << '\t';
[1409]616        }
[2386]617        for (int i = 0; i < int(writers.size()); ++i) {
[2101]618          writers[i].second->write(os, *it);
[1409]619          os << '\t';
620        }
621        os << std::endl;
622      }
623    }
624
625  public:
626
[1901]627    /// \brief Returns true if the nodeset can write the labels of the nodes.
[1409]628    ///
[1901]629    /// Returns true if the nodeset can write the labels of the nodes.
[2467]630    /// It is possible only if a "label" named map was written or the
[1901]631    /// \c _forceLabelMap constructor parameter was true.
632    bool isLabelWriter() const {
633      return labelMap != 0 || forceLabelMap;
[1409]634    }
635
[1901]636    /// \brief Write the label of the given node.
[1409]637    ///
[2467]638    /// It writes the label of the given node. If there was written a "label"
[1409]639    /// named map then it will write the map value belongs to the node.
[1901]640    /// Otherwise if the \c forceLabel parameter was true it will write
641    /// its label in the graph.
642    void writeLabel(std::ostream& os, const Node& item) const {
643      if (forceLabelMap) {
[1409]644        os << graph.id(item);
645      } else {
[1901]646        labelMap->write(os, item);
[1409]647      }
648    }
649
[2467]650    /// \brief Sorts the given node vector by label.
651    ///
652    /// Sorts the given node vector by label. If there was written an
653    /// "label" named map then the vector will be sorted by the values
654    /// of this map. Otherwise if the \c forceLabel parameter was true
655    /// it will be sorted by its id in the graph.
656    void sortByLabel(std::vector<Node>& nodes) const {
657      if (labelMap) {
658        labelMap->sort(nodes);
659      } else {
660        typedef IdMap<Graph, Node> Map;
661        Map map(graph);
662        _writer_bits::ComposeLess<Map> less(map);
663        std::sort(nodes.begin(), nodes.end(), less);
664      }
665    }
666
[1409]667  private:
668
[1845]669    typedef std::vector<std::pair<std::string, _writer_bits::
670                                  MapWriterBase<Node>*> > MapWriters;
[1409]671    MapWriters writers;
672
[1901]673    _writer_bits::MapWriterBase<Node>* labelMap;
674    bool forceLabelMap;
[2467]675    bool forceSort;
[1409]676   
[1705]677    const Graph& graph;   
[1901]678    std::string name;
[1409]679
680  };
681
[2016]682  /// \ingroup section_io
[1421]683  /// \brief SectionWriter for writing a graph's edgesets.
[1409]684  ///
[1421]685  /// The lemon format can store multiple graph edgesets with several maps.
[1901]686  /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but
687  /// the \c edgeset_name may be empty.
[1409]688  ///
689  /// The first line of the section contains the names of the maps separated
690  /// with white spaces. Each next lines describes a edge in the edgeset. The
[1901]691  /// line contains the source and the target nodes' label and the mapped
[1409]692  /// values for each map.
693  ///
[1901]694  /// If the edgeset contains an \c "label" named map then it will be regarded
695  /// as label map. This map should contain only unique values and when the
696  /// \c writeLabel() member will be called with an edge it will write it's
697  /// label. Otherwise if the \c _forceLabelMap constructor parameter is true
[2101]698  /// then the label map will be the id in the graph. In addition if the
[2467]699  /// the \c _forceSort is true then the writer will write the edges
[2101]700  /// sorted by the labels.
[1409]701  ///
[1901]702  /// The edgeset writer needs a node label writer to identify which nodes
703  /// have to be connected. If a NodeSetWriter can write the nodes' label,
[1409]704  /// it will be able to use with this class.
705  ///
706  /// \relates LemonWriter
707  template <typename _Graph, typename _Traits = DefaultWriterTraits>
[1845]708  class EdgeSetWriter : public LemonWriter::SectionWriter {
709    typedef LemonWriter::SectionWriter Parent;
[1409]710  public:
711
712    typedef _Graph Graph;
713    typedef _Traits Traits;
[1429]714    typedef typename Graph::Node Node;
715    typedef typename Graph::Edge Edge;
[1409]716
717    /// \brief Constructor.
718    ///
[2101]719    /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter
720    /// and attach it into the given LemonWriter. It will write node
721    /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap
722    /// parameter is true then the writer will write own label map if
723    /// the user does not give "label" named map. In addition if the
[2467]724    /// the \c _forceSort is true then the writer will write the
[2101]725    /// edges sorted by the labels.
[1901]726    template <typename NodeLabelWriter>
[1409]727    EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
[1901]728                  const NodeLabelWriter& _nodeLabelWriter,
729                  const std::string& _name = std::string(),
[2467]730                  bool _forceLabelMap = true, bool _forceSort = true)
[1901]731      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
[2467]732        forceSort(_forceSort), graph(_graph), name(_name) {
[1901]733      checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
734      nodeLabelWriter.reset(new _writer_bits::
735                         LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
[1476]736    }
[1409]737
738    /// \brief Destructor.
739    ///
740    /// Destructor for EdgeSetWriter.
741    virtual ~EdgeSetWriter() {
742      typename MapWriters::iterator it;
743      for (it = writers.begin(); it != writers.end(); ++it) {
744        delete it->second;
745      }
746    }
747
748  private:
749    EdgeSetWriter(const EdgeSetWriter&);
750    void operator=(const EdgeSetWriter&);
751
752  public:
753
[1421]754    /// \brief Add a new edge map writer command for the writer.
[1409]755    ///
[1421]756    /// Add a new edge map writer command for the writer.
[1409]757    template <typename Map>
[2386]758    EdgeSetWriter& writeEdgeMap(std::string label, const Map& map) {
[1421]759      return writeEdgeMap<typename Traits::
[2386]760        template Writer<typename Map::Value>, Map>(label, map);
[1409]761    }
762
[1421]763    /// \brief Add a new edge map writer command for the writer.
[1409]764    ///
[1421]765    /// Add a new edge map writer command for the writer.
[2386]766    template <typename ItemWriter, typename Map>
767    EdgeSetWriter& writeEdgeMap(std::string label, const Map& map,
768                            const ItemWriter& iw = ItemWriter()) {
[2260]769      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
[2386]770      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, ItemWriter>();
[1409]771      writers.push_back(
[2386]772        make_pair(label, new _writer_bits::
773                  MapWriter<Edge, Map, ItemWriter>(map, iw)));
[1409]774      return *this;
775    }
776
777  protected:
778
779    /// \brief The header of the section.
780    ///
781    /// It gives back the header of the section.
782    virtual std::string header() {
[1901]783      return "@edgeset " + name;
[1409]784    }
785
786    /// \brief  Writer function of the section.
787    ///
788    /// Write the content of the section.
789    virtual void write(std::ostream& os) {
[1901]790      if (!nodeLabelWriter->isLabelWriter()) {
791        throw DataFormatError("Cannot find nodeset or label map");
[1476]792      }
[2386]793      for (int i = 0; i < int(writers.size()); ++i) {
[2084]794        if (writers[i].first == "label") {
[1901]795          labelMap = writers[i].second;
796          forceLabelMap = false;
[1409]797          break;
798        }
799      }
[2101]800      std::vector<Edge> items;
801      for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
802        items.push_back(it);
803      }
[2467]804      if (forceSort) {
[2101]805        if (labelMap) {
[2467]806          labelMap->sort(items);
[2101]807        } else {
808          typedef IdMap<Graph, Edge> Map;
809          Map map(graph);
810          _writer_bits::ComposeLess<Map> less(map);
811          std::sort(items.begin(), items.end(), less);
812        }
813      }
[1409]814      os << "\t\t";
[1901]815      if (forceLabelMap) {
816        os << "label\t";
[1409]817      }
[2386]818      for (int i = 0; i < int(writers.size()); ++i) {
[1409]819        os << writers[i].first << '\t';
820      }
821      os << std::endl;
[2101]822      for (typename std::vector<Edge>::iterator it = items.begin();
823           it != items.end(); ++it) {
824        nodeLabelWriter->write(os, graph.source(*it));
[1409]825        os << '\t';
[2101]826        nodeLabelWriter->write(os, graph.target(*it));
[1409]827        os << '\t';
[1901]828        if (forceLabelMap) {
[2101]829          os << graph.id(*it) << '\t';
[1409]830        }
[2386]831        for (int i = 0; i < int(writers.size()); ++i) {
[2101]832          writers[i].second->write(os, *it);
[1409]833          os << '\t';
834        }
835        os << std::endl;
836      }
837    }
838
839  public:
840
[1901]841    /// \brief Returns true if the edgeset can write the labels of the edges.
[1409]842    ///
[1901]843    /// Returns true if the edgeset can write the labels of the edges.
[2467]844    /// It is possible only if a "label" named map was written or the
[1901]845    /// \c _forceLabelMap constructor parameter was true.
846    bool isLabelWriter() const {
847      return forceLabelMap || labelMap != 0;
[1409]848    }
849
[1901]850    /// \brief Write the label of the given edge.
[1409]851    ///
[2467]852    /// It writes the label of the given edge. If there was written a "label"
[1409]853    /// named map then it will write the map value belongs to the edge.
[1901]854    /// Otherwise if the \c forceLabel parameter was true it will write
855    /// its label in the graph.
856    void writeLabel(std::ostream& os, const Edge& item) const {
857      if (forceLabelMap) {
[1409]858        os << graph.id(item);
859      } else {
[1901]860        labelMap->write(os, item);
[1409]861      }
862    }
863
[2467]864    /// \brief Sorts the given edge vector by label.
865    ///
866    /// Sorts the given edge vector by label. If there was written an
867    /// "label" named map then the vector will be sorted by the values
868    /// of this map. Otherwise if the \c forceLabel parameter was true
869    /// it will be sorted by its id in the graph.
870    void sortByLabel(std::vector<Edge>& edges) const {
871      if (labelMap) {
872        labelMap->sort(edges);
873      } else {
874        typedef IdMap<Graph, Edge> Map;
875        Map map(graph);
876        _writer_bits::ComposeLess<Map> less(map);
877        std::sort(edges.begin(), edges.end(), less);
878      }
879    }
880
[1409]881  private:
882
[1845]883    typedef std::vector<std::pair<std::string, _writer_bits::
884                                  MapWriterBase<Edge>*> > MapWriters;
[1409]885    MapWriters writers;
886
[1901]887    _writer_bits::MapWriterBase<Edge>* labelMap;
888    bool forceLabelMap;
[2467]889    bool forceSort;
[1409]890   
[1705]891    const Graph& graph;   
[1901]892    std::string name;
[1421]893
[1901]894    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
[1421]895  };
896
[2016]897  /// \ingroup section_io
[1421]898  /// \brief SectionWriter for writing a undirected edgeset.
899  ///
900  /// The lemon format can store multiple undirected edgesets with several
[1909]901  /// maps. The undirected edgeset section's header line is \c \@uedgeset
902  /// \c uedgeset_name, but the \c uedgeset_name may be empty.
[1421]903  ///
904  /// The first line of the section contains the names of the maps separated
905  /// with white spaces. Each next lines describes an undirected edge in the
[1901]906  /// edgeset. The line contains the two connected nodes' label and the mapped
[1421]907  /// values for each undirected map.
908  ///
909  /// The section can handle the directed as a syntactical sugar. Two
910  /// undirected edge map describes one directed edge map. This two maps
911  /// are the forward map and the backward map and the names of this map
912  /// is near the same just with a prefix \c '+' or \c '-' character
913  /// difference.
914  ///
[2101]915  /// If the edgeset contains an \c "label" named map then it will be
916  /// regarded as label map. This map should contain only unique
917  /// values and when the \c writeLabel() member will be called with
918  /// an undirected edge it will write it's label. Otherwise if the \c
919  /// _forceLabelMap constructor parameter is true then the label map
920  /// will be the id in the graph.  In addition if the the \c
[2467]921  /// _forceSort is true then the writer will write the edges sorted
[2101]922  /// by the labels.
[1421]923  ///
[1901]924  /// The undirected edgeset writer needs a node label writer to identify
[1421]925  /// which nodes have to be connected. If a NodeSetWriter can write the
[1901]926  /// nodes' label, it will be able to use with this class.
[1421]927  ///
928  /// \relates LemonWriter
929  template <typename _Graph, typename _Traits = DefaultWriterTraits>
[1909]930  class UEdgeSetWriter : public LemonWriter::SectionWriter {
[1845]931    typedef LemonWriter::SectionWriter Parent;
[1421]932  public:
933
934    typedef _Graph Graph;
935    typedef _Traits Traits;
[1429]936    typedef typename Graph::Node Node;
937    typedef typename Graph::Edge Edge;
[1909]938    typedef typename Graph::UEdge UEdge;
[1421]939
940    /// \brief Constructor.
941    ///
[1909]942    /// Constructor for UEdgeSetWriter. It creates the UEdgeSetWriter
[2101]943    /// and attach it into the given LemonWriter. It will write node
944    /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap
945    /// parameter is true then the writer will write own label map if
946    /// the user does not give "label" named map. In addition if the
[2467]947    /// the \c _forceSort is true then the writer will write the
[2101]948    /// edges sorted by the labels.
[1901]949    template <typename NodeLabelWriter>
[1909]950    UEdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
[1901]951                       const NodeLabelWriter& _nodeLabelWriter,
952                       const std::string& _name = std::string(),
[2467]953                       bool _forceLabelMap = true, bool _forceSort = true)
[1901]954      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
[2467]955        forceSort(_forceSort), graph(_graph), name(_name) {
[1901]956      checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
957      nodeLabelWriter.reset(new _writer_bits::
[2467]958        LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
[1476]959    }
[1421]960
961    /// \brief Destructor.
962    ///
[1909]963    /// Destructor for UEdgeSetWriter.
964    virtual ~UEdgeSetWriter() {
[1421]965      typename MapWriters::iterator it;
966      for (it = writers.begin(); it != writers.end(); ++it) {
967        delete it->second;
968      }
969    }
970
971  private:
[1909]972    UEdgeSetWriter(const UEdgeSetWriter&);
973    void operator=(const UEdgeSetWriter&);
[1421]974
975  public:
976
977    /// \brief Add a new undirected edge map writer command for the writer.
978    ///
979    /// Add a new undirected map writer command for the writer.
980    template <typename Map>
[2386]981    UEdgeSetWriter& writeUEdgeMap(std::string label, const Map& map) {
[1909]982      return writeUEdgeMap<typename Traits::
[2386]983        template Writer<typename Map::Value>, Map>(label, map);
[1421]984    }
985
986    /// \brief Add a new undirected map writer command for the writer.
987    ///
988    /// Add a new undirected map writer command for the writer.
[2386]989    template <typename ItemWriter, typename Map>
990    UEdgeSetWriter& writeUEdgeMap(std::string label, const Map& map,
991                                  const ItemWriter& iw = ItemWriter()) {
[2260]992      checkConcept<concepts::ReadMap<UEdge, typename Map::Value>, Map>();
[2386]993      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, ItemWriter>();
[1421]994      writers.push_back(
[2386]995        make_pair(label, new _writer_bits::
[2467]996                  UEdgeMapWriter<Graph, Map, ItemWriter>(map, iw)));
[1421]997      return *this;
998    }
999
1000    /// \brief Add a new directed edge map writer command for the writer.
1001    ///
1002    /// Add a new directed map writer command for the writer.
1003    template <typename Map>
[2386]1004    UEdgeSetWriter& writeEdgeMap(std::string label, const Map& map) {
[1492]1005      return writeEdgeMap<typename Traits::
[2386]1006        template Writer<typename Map::Value>, Map>(label, map);
[1421]1007    }
1008
1009    /// \brief Add a new directed map writer command for the writer.
1010    ///
1011    /// Add a new directed map writer command for the writer.
[2386]1012    template <typename ItemWriter, typename Map>
1013    UEdgeSetWriter& writeEdgeMap(std::string label, const Map& map,
1014                                 const ItemWriter& iw = ItemWriter()) {
[2260]1015      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
[2386]1016      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, ItemWriter>();
[2467]1017      writeUEdgeMap("+" + label,
[2386]1018                    _writer_bits::forwardComposeMap(graph, map), iw);
[2467]1019      writeUEdgeMap("-" + label,
[2386]1020                    _writer_bits::backwardComposeMap(graph, map), iw);
[1421]1021      return *this;
1022    }
1023
1024  protected:
1025
1026    /// \brief The header of the section.
1027    ///
1028    /// It gives back the header of the section.
1029    virtual std::string header() {
[1909]1030      return "@uedgeset " + name;
[1421]1031    }
1032
1033    /// \brief  Writer function of the section.
1034    ///
1035    /// Write the content of the section.
1036    virtual void write(std::ostream& os) {
[1901]1037      if (!nodeLabelWriter->isLabelWriter()) {
1038        throw DataFormatError("Cannot find nodeset or label map");
[1476]1039      }
[2386]1040      for (int i = 0; i < int(writers.size()); ++i) {
[1901]1041        if (writers[i].first == "label") {
1042          labelMap = writers[i].second;
1043          forceLabelMap = false;
[1421]1044          break;
1045        }
1046      }
[2101]1047      std::vector<UEdge> items;
1048      for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) {
1049        items.push_back(it);
1050      }
[2467]1051      if (forceSort) {
[2101]1052        if (labelMap) {
[2467]1053          labelMap->sort(items);
[2101]1054        } else {
1055          typedef IdMap<Graph, UEdge> Map;
1056          Map map(graph);
1057          _writer_bits::ComposeLess<Map> less(map);
1058          std::sort(items.begin(), items.end(), less);
1059        }
1060      }
[1421]1061      os << "\t\t";
[1901]1062      if (forceLabelMap) {
1063        os << "label\t";
[1421]1064      }
[2386]1065      for (int i = 0; i < int(writers.size()); ++i) {
[1421]1066        os << writers[i].first << '\t';
1067      }
1068      os << std::endl;
[2282]1069      for (typename std::vector<UEdge>::iterator it = items.begin();
[2101]1070           it != items.end(); ++it) {
1071        nodeLabelWriter->write(os, graph.source(*it));
[1421]1072        os << '\t';
[2101]1073        nodeLabelWriter->write(os, graph.target(*it));
[1421]1074        os << '\t';
[1901]1075        if (forceLabelMap) {
[2101]1076          os << graph.id(*it) << '\t';
[1421]1077        }
[2386]1078        for (int i = 0; i < int(writers.size()); ++i) {
[2101]1079          writers[i].second->write(os, *it);
[1421]1080          os << '\t';
1081        }
1082        os << std::endl;
1083      }
1084    }
1085
1086  public:
1087
[1901]1088    /// \brief Returns true if the undirected edgeset can write the labels of
[1421]1089    /// the edges.
1090    ///
[1901]1091    /// Returns true if the undirected edgeset can write the labels of the
[2467]1092    /// undirected edges. It is possible only if a "label" named map was
[1901]1093    /// written or the \c _forceLabelMap constructor parameter was true.
1094    bool isLabelWriter() const {
1095      return forceLabelMap || labelMap != 0;
[1421]1096    }
1097
[1901]1098    /// \brief Write the label of the given undirected edge.
[1421]1099    ///
[1901]1100    /// It writes the label of the given undirected edge. If there was written
[2467]1101    /// a "label" named map then it will write the map value belongs to the
[1901]1102    /// undirected edge. Otherwise if the \c forceLabel parameter was true it
[1421]1103    /// will write its id in the graph.
[1909]1104    void writeLabel(std::ostream& os, const UEdge& item) const {
[1901]1105      if (forceLabelMap) {
[1429]1106        os << graph.id(item);
1107      } else {
[1901]1108        labelMap->write(os, item);
[1429]1109      }
1110    }
1111
[1901]1112    /// \brief Write the label of the given edge.
[1429]1113    ///
[1901]1114    /// It writes the label of the given edge. If there was written
[2467]1115    /// a "label" named map then it will write the map value belongs to the
[1901]1116    /// edge. Otherwise if the \c forceLabel parameter was true it
[1429]1117    /// will write its id in the graph. If the edge is forward map
1118    /// then its prefix character is \c '+' elsewhere \c '-'.
[1901]1119    void writeLabel(std::ostream& os, const Edge& item) const {
[1690]1120      if (graph.direction(item)) {
[2467]1121        os << "+";
[1429]1122      } else {
[2467]1123        os << "-";
[1429]1124      }
[1901]1125      if (forceLabelMap) {
[2467]1126        os << graph.id(static_cast<const UEdge&>(item));
[1421]1127      } else {
[1901]1128        labelMap->write(os, item);
[1421]1129      }
1130    }
1131
[2467]1132    /// \brief Sorts the given undirected edge vector by label.
1133    ///
1134    /// Sorts the given undirected edge vector by label. If there was
1135    /// written a "label" named map then the vector will be sorted by
1136    /// the values of this map. Otherwise if the \c forceLabel
1137    /// parameter was true it will be sorted by its id in the graph.
1138    void sortByLabel(std::vector<UEdge>& uedges) const {
1139      if (labelMap) {
1140        labelMap->sort(uedges);
1141      } else {
1142        typedef IdMap<Graph, UEdge> Map;
1143        Map map(graph);
1144        _writer_bits::ComposeLess<Map> less(map);
1145        std::sort(uedges.begin(), uedges.end(), less);
1146      }
1147    }
1148
1149    /// \brief Sorts the given edge vector by label.
1150    ///
1151    /// Sorts the given edge vector by label. If there was written a
1152    /// "label" named map then the vector will be sorted by the values
1153    /// of this map. Otherwise if the \c forceLabel parameter was true
1154    /// it will be sorted by its id in the graph.
1155    void sortByLabel(std::vector<Edge>& edges) const {
1156      if (labelMap) {
1157        labelMap->sort(graph, edges);
1158      } else {
1159        typedef IdMap<Graph, Edge> Map;
1160        Map map(graph);
1161        _writer_bits::ComposeLess<Map> less(map);
1162        std::sort(edges.begin(), edges.end(), less);
1163      }
1164    }
1165
[1421]1166  private:
1167
[1845]1168    typedef std::vector<std::pair<std::string, _writer_bits::
[2467]1169                                  UEdgeMapWriterBase<Graph>*> > MapWriters;
[1421]1170    MapWriters writers;
1171
[2467]1172    _writer_bits::UEdgeMapWriterBase<Graph>* labelMap;
[1901]1173    bool forceLabelMap;
[2467]1174    bool forceSort;
[1421]1175   
[1705]1176    const Graph& graph;   
[1901]1177    std::string name;
[1409]1178
[1901]1179    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
[1409]1180  };
1181
[2016]1182  /// \ingroup section_io
[1901]1183  /// \brief SectionWriter for writing named nodes.
[1409]1184  ///
[1901]1185  /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1186  /// \c nodes_name may be empty.
[1409]1187  ///
[1901]1188  /// Each line in the section contains the name of the node and
1189  /// then the node label.
[1409]1190  ///
1191  /// \relates LemonWriter
1192  template <typename _Graph>
[1845]1193  class NodeWriter : public LemonWriter::SectionWriter {
1194    typedef LemonWriter::SectionWriter Parent;
[1409]1195    typedef _Graph Graph;
[1429]1196    typedef typename Graph::Node Node;
[1409]1197  public:
1198   
1199    /// \brief Constructor.
1200    ///
1201    /// Constructor for NodeWriter. It creates the NodeWriter and
[1901]1202    /// attach it into the given LemonWriter. The given \c _LabelWriter
1203    /// will write the nodes' label what can be a nodeset writer.
1204    template <typename _LabelWriter>
1205    NodeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter,
1206               const std::string& _name = std::string())
1207      : Parent(_writer), name(_name) {
1208      checkConcept<_writer_bits::ItemLabelWriter<Node>, _LabelWriter>();
1209      labelWriter.reset(new _writer_bits::LabelWriter<Node, _LabelWriter>
1210                        (_labelWriter));
[1476]1211    }
1212
[1409]1213
1214    /// \brief Destructor.
1215    ///
1216    /// Destructor for NodeWriter.
1217    virtual ~NodeWriter() {}
1218
1219  private:
1220    NodeWriter(const NodeWriter&);
1221    void operator=(const NodeWriter&);
1222
1223  public:
1224
1225    /// \brief Add a node writer command for the NodeWriter.
1226    ///
1227    /// Add a node writer command for the NodeWriter.
[2386]1228    void writeNode(std::string label, const Node& item) {
1229      writers.push_back(make_pair(label, &item));
[1409]1230    }
1231
1232  protected:
1233
[1901]1234    /// \brief The header of the section.
[1409]1235    ///
[1901]1236    /// It gives back the header of the section.
[1409]1237    virtual std::string header() {
[1901]1238      return "@nodes " + name;
[1409]1239    }
1240
1241    /// \brief  Writer function of the section.
1242    ///
1243    /// Write the content of the section.
1244    virtual void write(std::ostream& os) {
[1901]1245      if (!labelWriter->isLabelWriter()) {
1246        throw DataFormatError("Cannot find nodeset or label map");
[1476]1247      }
[2386]1248      for (int i = 0; i < int(writers.size()); ++i) {
[1409]1249        os << writers[i].first << ' ';
[1901]1250        labelWriter->write(os, *(writers[i].second));
[1409]1251        os << std::endl;
1252      }
1253    }
[2084]1254
1255    /// \brief Gives back true when the section should be written.
1256    ///
1257    /// Gives back true when the section should be written.
1258    virtual bool valid() { return !writers.empty(); }
[1409]1259   
1260  private:
1261
[1901]1262    std::string name;
[1409]1263
[1429]1264    typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
1265    NodeWriters writers;
[1901]1266    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > labelWriter;
[1409]1267  };
1268
[2016]1269  /// \ingroup section_io
[1901]1270  /// \brief SectionWriter for writing named edges.
[1409]1271  ///
[1901]1272  /// The edges section's header line is \c \@edges \c edges_name, but the
1273  /// \c edges_name may be empty.
[1409]1274  ///
[1901]1275  /// Each line in the section contains the name of the edge and
1276  /// then the edge label.
[1409]1277  ///
1278  /// \relates LemonWriter
1279  template <typename _Graph>
[1845]1280  class EdgeWriter : public LemonWriter::SectionWriter {
1281    typedef LemonWriter::SectionWriter Parent;
[1409]1282    typedef _Graph Graph;
[1429]1283    typedef typename Graph::Edge Edge;
[1409]1284  public:
1285   
1286    /// \brief Constructor.
1287    ///
1288    /// Constructor for EdgeWriter. It creates the EdgeWriter and
[1901]1289    /// attach it into the given LemonWriter. The given \c _LabelWriter
1290    /// will write the edges' label what can be a edgeset writer.
1291    template <typename _LabelWriter>
1292    EdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter,
1293               const std::string& _name = std::string())
1294      : Parent(_writer), name(_name) {
1295      checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
1296      labelWriter.reset(new _writer_bits::LabelWriter<Edge, _LabelWriter>(_labelWriter));
[1476]1297    }
[1409]1298
1299    /// \brief Destructor.
1300    ///
1301    /// Destructor for EdgeWriter.
1302    virtual ~EdgeWriter() {}
1303  private:
1304    EdgeWriter(const EdgeWriter&);
1305    void operator=(const EdgeWriter&);
1306
1307  public:
1308
[1421]1309    /// \brief Add an edge writer command for the EdgeWriter.
[1409]1310    ///
[1421]1311    /// Add an edge writer command for the EdgeWriter.
[2386]1312    void writeEdge(std::string label, const Edge& item) {
1313      writers.push_back(make_pair(label, &item));
[1409]1314    }
1315
1316  protected:
1317
[1901]1318    /// \brief The header of the section.
[1409]1319    ///
[1901]1320    /// It gives back the header of the section.
[1421]1321    virtual std::string header() {
[1901]1322      return "@edges " + name;
[1421]1323    }
1324
1325    /// \brief  Writer function of the section.
1326    ///
1327    /// Write the content of the section.
1328    virtual void write(std::ostream& os) {
[1901]1329      if (!labelWriter->isLabelWriter()) {
1330        throw DataFormatError("Cannot find edgeset or label map");
[1476]1331      }
[2386]1332      for (int i = 0; i < int(writers.size()); ++i) {
[1421]1333        os << writers[i].first << ' ';
[1901]1334        labelWriter->write(os, *(writers[i].second));
[1421]1335        os << std::endl;
1336      }
1337    }
[2084]1338
1339    /// \brief Gives back true when the section should be written.
1340    ///
1341    /// Gives back true when the section should be written.
1342    virtual bool valid() { return !writers.empty(); }
[1421]1343   
1344  private:
1345
[1901]1346    std::string name;
[1421]1347
[1429]1348    typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1349    EdgeWriters writers;
[1421]1350
[1901]1351    std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > labelWriter;
[1421]1352  };
1353
[2467]1354
[2016]1355  /// \ingroup section_io
[1901]1356  /// \brief SectionWriter for writing named undirected edges.
[1421]1357  ///
[1909]1358  /// The undirected edges section's header line is \c \@uedges
1359  /// \c uedges_name, but the \c uedges_name may be empty.
[1421]1360  ///
[1901]1361  /// Each line in the section contains the name of the undirected edge and
1362  /// then the undirected edge label.
[1421]1363  ///
1364  /// \relates LemonWriter
1365  template <typename _Graph>
[1909]1366  class UEdgeWriter : public LemonWriter::SectionWriter {
[1845]1367    typedef LemonWriter::SectionWriter Parent;
[1421]1368    typedef _Graph Graph;
[1429]1369    typedef typename Graph::Node Node;
1370    typedef typename Graph::Edge Edge;
[1909]1371    typedef typename Graph::UEdge UEdge;
[1421]1372  public:
1373   
1374    /// \brief Constructor.
1375    ///
[1909]1376    /// Constructor for UEdgeWriter. It creates the UEdgeWriter and
[1901]1377    /// attach it into the given LemonWriter. The given \c _LabelWriter
1378    /// will write the undirected edges' label what can be an undirected
[1421]1379    /// edgeset writer.
[1901]1380    template <typename _LabelWriter>
[1909]1381    UEdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter,
[1901]1382               const std::string& _name = std::string())
1383      : Parent(_writer), name(_name) {
1384      checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
[1909]1385      checkConcept<_writer_bits::ItemLabelWriter<UEdge>, _LabelWriter>();
1386      uEdgeLabelWriter.reset(new _writer_bits::
1387                              LabelWriter<UEdge, _LabelWriter>(_labelWriter));
[1901]1388      edgeLabelWriter.reset(new _writer_bits::
1389                         LabelWriter<Edge, _LabelWriter>(_labelWriter));
[1476]1390    }
[1421]1391
1392    /// \brief Destructor.
1393    ///
[1909]1394    /// Destructor for UEdgeWriter.
1395    virtual ~UEdgeWriter() {}
[1421]1396  private:
[1909]1397    UEdgeWriter(const UEdgeWriter&);
1398    void operator=(const UEdgeWriter&);
[1421]1399
1400  public:
1401
[1909]1402    /// \brief Add an edge writer command for the UEdgeWriter.
[1429]1403    ///
[1909]1404    /// Add an edge writer command for the UEdgeWriter.
[2386]1405    void writeEdge(std::string label, const Edge& item) {
1406      edgeWriters.push_back(make_pair(label, &item));
[1429]1407    }
1408
[1909]1409    /// \brief Add an undirected edge writer command for the UEdgeWriter.
[1421]1410    ///
[1909]1411    /// Add an undirected edge writer command for the UEdgeWriter.
[2386]1412    void writeUEdge(std::string label, const UEdge& item) {
1413      uEdgeWriters.push_back(make_pair(label, &item));
[1421]1414    }
1415
1416  protected:
1417
[1901]1418    /// \brief The header of the section.
[1421]1419    ///
[1901]1420    /// It gives back the header of the section.
[1409]1421    virtual std::string header() {
[1909]1422      return "@uedges " + name;
[1409]1423    }
1424
1425    /// \brief  Writer function of the section.
1426    ///
1427    /// Write the content of the section.
1428    virtual void write(std::ostream& os) {
[1901]1429      if (!edgeLabelWriter->isLabelWriter()) {
1430        throw DataFormatError("Cannot find undirected edgeset or label map");
[1476]1431      }
[1909]1432      if (!uEdgeLabelWriter->isLabelWriter()) {
[1901]1433        throw DataFormatError("Cannot find undirected edgeset or label map");
[1476]1434      }
[2386]1435      for (int i = 0; i < int(uEdgeWriters.size()); ++i) {
[1909]1436        os << uEdgeWriters[i].first << ' ';
1437        uEdgeLabelWriter->write(os, *(uEdgeWriters[i].second));
[1429]1438        os << std::endl;
1439      }
[2386]1440      for (int i = 0; i < int(edgeWriters.size()); ++i) {
[1429]1441        os << edgeWriters[i].first << ' ';
[1901]1442        edgeLabelWriter->write(os, *(edgeWriters[i].second));
[1409]1443        os << std::endl;
1444      }
1445    }
[2084]1446
1447    /// \brief Gives back true when the section should be written.
1448    ///
1449    /// Gives back true when the section should be written.
1450    virtual bool valid() {
1451      return !uEdgeWriters.empty() || !edgeWriters.empty();
1452    }
[1409]1453   
1454  private:
1455
[1901]1456    std::string name;
[1409]1457
[1429]1458    typedef std::vector<std::pair<std::string,
[1909]1459                                  const UEdge*> > UEdgeWriters;
1460    UEdgeWriters uEdgeWriters;
1461    std::auto_ptr<_writer_bits::LabelWriterBase<UEdge> > uEdgeLabelWriter;
[1409]1462
[1429]1463    typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1464    EdgeWriters edgeWriters;
[1901]1465    std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > edgeLabelWriter;
[1429]1466
[1409]1467  };
1468
[2016]1469  /// \ingroup section_io
[2467]1470  /// \brief SectionWriter for writing extra node maps.
1471  ///
1472  /// The lemon format can store maps in the nodeset. This class let
1473  /// you make distinict section to store maps. The main purpose of
1474  /// this class is a logical separation of some maps. The other
1475  /// useful application could be to store paths in node maps.
1476  ///
1477  /// The first line of the section contains the names of the maps
1478  /// separated with white spaces. Each next line describes an item
1479  /// in the itemset, and contains in the first column the label of
1480  /// the item and then the mapped values for each map.
1481  ///
1482  /// \relates LemonWriter
1483  template <typename _Graph, typename _Traits = DefaultWriterTraits>
1484  class NodeMapWriter : public LemonWriter::SectionWriter {
1485    typedef LemonWriter::SectionWriter Parent;
1486  public:
1487
1488    typedef _Graph Graph;
1489    typedef _Traits Traits;
1490    typedef typename Graph::Node Node;
1491
1492    /// \brief Constructor.
1493    ///
1494    /// Constructor for NodeMapWriter. It creates the NodeMapWriter and
1495    /// attach it into the given LemonWriter. If the the
1496    /// \c _forceSort is true then the writer will write the edges
1497    /// sorted by the labels.
1498    template <typename _LabelWriter>
1499    NodeMapWriter(LemonWriter& _writer, const Graph& _graph,
1500                 const _LabelWriter& _labelWriter,
1501                 const std::string& _name = std::string(),
1502                 bool _forceSort = true)
1503      : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) {
1504      checkConcept<_writer_bits::ItemLabelWriter<Node>, _LabelWriter>();
1505      labelWriter.reset(new _writer_bits::LabelWriter<Node,
1506                        _LabelWriter>(_labelWriter));
1507    }
1508
1509    /// \brief Destructor.
1510    ///
1511    /// Destructor for NodeMapWriter.
1512    virtual ~NodeMapWriter() {
1513      typename MapWriters::iterator it;
1514      for (it = writers.begin(); it != writers.end(); ++it) {
1515        delete it->second;
1516      }
1517    }
1518
1519  private:
1520    NodeMapWriter(const NodeMapWriter&);
1521    void operator=(const NodeMapWriter&);
1522 
1523  public:
1524
1525    /// \brief Add a new node map writer command for the writer.
1526    ///
1527    /// Add a new node map writer command for the writer.
1528    template <typename Map>
1529    NodeMapWriter& writeNodeMap(std::string label, const Map& map) {
1530      return writeNodeMap<typename Traits::
1531        template Writer<typename Map::Value>, Map>(label, map);
1532    }
1533
1534    /// \brief Add a new node map writer command for the writer.
1535    ///
1536    /// Add a new node map writer command for the writer.
1537    template <typename ItemWriter, typename Map>
1538    NodeMapWriter& writeNodeMap(std::string label, const Map& map,
1539                           const ItemWriter& iw = ItemWriter()) {
1540      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1541      checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
1542      writers.push_back(
1543        make_pair(label, new _writer_bits::
1544                  MapWriter<Node, Map, ItemWriter>(map, iw)));
1545      return *this;
1546    }
1547
1548  protected:
1549
1550    /// \brief The header of the section.
1551    ///
1552    /// It gives back the header of the section.
1553    virtual std::string header() {
1554      return "@nodemaps " + name;
1555    }
1556
1557    /// \brief  Writer function of the section.
1558    ///
1559    /// Write the content of the section.
1560    virtual void write(std::ostream& os) {
1561      std::vector<Node> nodes;
1562      for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
1563        nodes.push_back(it);
1564      }
1565      if (forceSort) {
1566        labelWriter->sort(nodes);
1567      }
1568      os << '\t';
1569      for (int i = 0; i < int(writers.size()); ++i) {
1570        os << writers[i].first << '\t';
1571      }
1572      os << std::endl;
1573      for (typename std::vector<Node>::iterator it = nodes.begin();
1574           it != nodes.end(); ++it) {
1575
1576        labelWriter->write(os, *it); os << '\t';
1577        for (int i = 0; i < int(writers.size()); ++i) {
1578          writers[i].second->write(os, *it);
1579          os << '\t';
1580        }
1581        os << std::endl;
1582      }
1583    }
1584
1585
1586  private:
1587
1588    typedef std::vector<std::pair<std::string, _writer_bits::
1589                                  MapWriterBase<Node>*> > MapWriters;
1590    MapWriters writers;
1591
1592    _writer_bits::MapWriterBase<Node>* labelMap;
1593
1594    const Graph& graph;   
1595    std::string name;
1596    bool forceSort;
1597
1598    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > labelWriter;
1599  };
1600
1601  /// \ingroup section_io
1602  /// \brief SectionWriter for writing extra edge maps.
1603  ///
1604  /// The lemon format can store maps in the edgeset. This class let
1605  /// you make distinict section to store maps. The main purpose of
1606  /// this class is a logical separation of some maps. The other
1607  /// useful application could be to store paths in edge maps.
1608  ///
1609  /// The first line of the section contains the names of the maps
1610  /// separated with white spaces. Each next line describes an item
1611  /// in the itemset, and contains in the first column the label of
1612  /// the item and then the mapped values for each map.
1613  ///
1614  /// \relates LemonWriter
1615  template <typename _Graph, typename _Traits = DefaultWriterTraits>
1616  class EdgeMapWriter : public LemonWriter::SectionWriter {
1617    typedef LemonWriter::SectionWriter Parent;
1618  public:
1619
1620    typedef _Graph Graph;
1621    typedef _Traits Traits;
1622    typedef typename Graph::Edge Edge;
1623
1624    /// \brief Constructor.
1625    ///
1626    /// Constructor for EdgeMapWriter. It creates the EdgeMapWriter and
1627    /// attach it into the given LemonWriter. If the the
1628    /// \c _forceSort is true then the writer will write the edges
1629    /// sorted by the labels.
1630    template <typename _LabelWriter>
1631    EdgeMapWriter(LemonWriter& _writer, const Graph& _graph,
1632                 const _LabelWriter& _labelWriter,
1633                 const std::string& _name = std::string(),
1634                 bool _forceSort = true)
1635      : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) {
1636      checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
1637      labelWriter.reset(new _writer_bits::LabelWriter<Edge,
1638                        _LabelWriter>(_labelWriter));
1639    }
1640
1641    /// \brief Destructor.
1642    ///
1643    /// Destructor for EdgeMapWriter.
1644    virtual ~EdgeMapWriter() {
1645      typename MapWriters::iterator it;
1646      for (it = writers.begin(); it != writers.end(); ++it) {
1647        delete it->second;
1648      }
1649    }
1650
1651  private:
1652    EdgeMapWriter(const EdgeMapWriter&);
1653    void operator=(const EdgeMapWriter&);
1654 
1655  public:
1656
1657    /// \brief Add a new edge map writer command for the writer.
1658    ///
1659    /// Add a new edge map writer command for the writer.
1660    template <typename Map>
1661    EdgeMapWriter& writeEdgeMap(std::string label, const Map& map) {
1662      return writeEdgeMap<typename Traits::
1663        template Writer<typename Map::Value>, Map>(label, map);
1664    }
1665
1666    /// \brief Add a new edge map writer command for the writer.
1667    ///
1668    /// Add a new edge map writer command for the writer.
1669    template <typename ItemWriter, typename Map>
1670    EdgeMapWriter& writeEdgeMap(std::string label, const Map& map,
1671                                const ItemWriter& iw = ItemWriter()) {
1672      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1673      checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
1674      writers.push_back(
1675        make_pair(label, new _writer_bits::
1676                  MapWriter<Edge, Map, ItemWriter>(map, iw)));
1677      return *this;
1678    }
1679
1680  protected:
1681
1682    /// \brief The header of the section.
1683    ///
1684    /// It gives back the header of the section.
1685    virtual std::string header() {
1686      return "@edgemaps " + name;
1687    }
1688
1689    /// \brief  Writer function of the section.
1690    ///
1691    /// Write the content of the section.
1692    virtual void write(std::ostream& os) {
1693      std::vector<Edge> edges;
1694      for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
1695        edges.push_back(it);
1696      }
1697      if (forceSort) {
1698        labelWriter->sort(edges);
1699      }
1700      os << '\t';
1701      for (int i = 0; i < int(writers.size()); ++i) {
1702        os << writers[i].first << '\t';
1703      }
1704      os << std::endl;
1705      for (typename std::vector<Edge>::iterator it = edges.begin();
1706           it != edges.end(); ++it) {
1707
1708        labelWriter->write(os, *it); os << '\t';
1709        for (int i = 0; i < int(writers.size()); ++i) {
1710          writers[i].second->write(os, *it);
1711          os << '\t';
1712        }
1713        os << std::endl;
1714      }
1715    }
1716
1717
1718  private:
1719
1720    typedef std::vector<std::pair<std::string, _writer_bits::
1721                                  MapWriterBase<Edge>*> > MapWriters;
1722    MapWriters writers;
1723
1724    _writer_bits::MapWriterBase<Edge>* labelMap;
1725
1726    const Graph& graph;   
1727    std::string name;
1728    bool forceSort;
1729
1730    std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > labelWriter;
1731  };
1732
1733  /// \ingroup section_io
1734  /// \brief SectionWriter for writing extra undirected edge maps.
1735  ///
1736  /// The lemon format can store maps in the uedgeset. This class let
1737  /// you make distinict section to store maps. The main purpose of
1738  /// this class is a logical separation of some maps. The other
1739  /// useful application could be to store paths in undirected edge
1740  /// maps.
1741  ///
1742  /// The first line of the section contains the names of the maps
1743  /// separated with white spaces. Each next line describes an item
1744  /// in the itemset, and contains in the first column the label of
1745  /// the item and then the mapped values for each map.
1746  ///
1747  /// \relates LemonWriter
1748  template <typename _Graph, typename _Traits = DefaultWriterTraits>
1749  class UEdgeMapWriter : public LemonWriter::SectionWriter {
1750    typedef LemonWriter::SectionWriter Parent;
1751  public:
1752
1753    typedef _Graph Graph;
1754    typedef _Traits Traits;
1755    typedef typename Graph::UEdge UEdge;
1756    typedef typename Graph::Edge Edge;
1757
1758    /// \brief Constructor.
1759    ///
1760    /// Constructor for UEdgeMapWriter. It creates the UEdgeMapWriter and
1761    /// attach it into the given LemonWriter. If the the
1762    /// \c _forceSort is true then the writer will write the uedges
1763    /// sorted by the labels.
1764    template <typename _LabelWriter>
1765    UEdgeMapWriter(LemonWriter& _writer, const Graph& _graph,
1766                 const _LabelWriter& _labelWriter,
1767                 const std::string& _name = std::string(),
1768                 bool _forceSort = true)
1769      : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) {
1770      checkConcept<_writer_bits::ItemLabelWriter<UEdge>, _LabelWriter>();
1771      labelWriter.reset(new _writer_bits::LabelWriter<UEdge,
1772                            _LabelWriter>(_labelWriter));
1773    }
1774
1775    /// \brief Destructor.
1776    ///
1777    /// Destructor for UEdgeMapWriter.
1778    virtual ~UEdgeMapWriter() {
1779      typename MapWriters::iterator it;
1780      for (it = writers.begin(); it != writers.end(); ++it) {
1781        delete it->second;
1782      }
1783    }
1784
1785  private:
1786    UEdgeMapWriter(const UEdgeMapWriter&);
1787    void operator=(const UEdgeMapWriter&);
1788 
1789  public:
1790
1791    /// \brief Add a new undirected edge map writer command for the writer.
1792    ///
1793    /// Add a new undirected edge map writer command for the writer.
1794    template <typename Map>
1795    UEdgeMapWriter& writeUEdgeMap(std::string label, const Map& map) {
1796      return writeUEdgeMap<typename Traits::
1797        template Writer<typename Map::Value>, Map>(label, map);
1798    }
1799
1800    /// \brief Add a new undirected edge map writer command for the writer.
1801    ///
1802    /// Add a new undirected edge map writer command for the writer.
1803    template <typename ItemWriter, typename Map>
1804    UEdgeMapWriter& writeUEdgeMap(std::string label, const Map& map,
1805                           const ItemWriter& iw = ItemWriter()) {
1806      checkConcept<concepts::ReadMap<UEdge, typename Map::Value>, Map>();
1807      checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
1808      writers.push_back(
1809        make_pair(label, new _writer_bits::
1810                  MapWriter<UEdge, Map, ItemWriter>(map, iw)));
1811      return *this;
1812    }
1813
1814    /// \brief Add a new directed edge map writer command for the writer.
1815    ///
1816    /// Add a new directed map writer command for the writer.
1817    template <typename Map>
1818    UEdgeMapWriter& writeEdgeMap(std::string label, const Map& map) {
1819      return writeEdgeMap<typename Traits::
1820        template Writer<typename Map::Value>, Map>(label, map);
1821    }
1822
1823    /// \brief Add a new directed map writer command for the writer.
1824    ///
1825    /// Add a new directed map writer command for the writer.
1826    template <typename ItemWriter, typename Map>
1827    UEdgeMapWriter& writeEdgeMap(std::string label, const Map& map,
1828                                 const ItemWriter& iw = ItemWriter()) {
1829      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1830      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, ItemWriter>();
1831      writeUEdgeMap("+" + label,
1832                    _writer_bits::forwardComposeMap(graph, map), iw);
1833      writeUEdgeMap("-" + label,
1834                    _writer_bits::backwardComposeMap(graph, map), iw);
1835      return *this;
1836    }
1837
1838  protected:
1839
1840    /// \brief The header of the section.
1841    ///
1842    /// It gives back the header of the section.
1843    virtual std::string header() {
1844      return "@uedgemaps " + name;
1845    }
1846
1847    /// \brief  Writer function of the section.
1848    ///
1849    /// Write the content of the section.
1850    virtual void write(std::ostream& os) {
1851      std::vector<UEdge> uedges;
1852      for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) {
1853        uedges.push_back(it);
1854      }
1855      if (forceSort) {
1856        labelWriter->sort(uedges);
1857      }
1858      os << '\t';
1859      for (int i = 0; i < int(writers.size()); ++i) {
1860        os << writers[i].first << '\t';
1861      }
1862      os << std::endl;
1863      for (typename std::vector<UEdge>::iterator it = uedges.begin();
1864           it != uedges.end(); ++it) {
1865
1866        labelWriter->write(os, *it); os << '\t';
1867        for (int i = 0; i < int(writers.size()); ++i) {
1868          writers[i].second->write(os, *it);
1869          os << '\t';
1870        }
1871        os << std::endl;
1872      }
1873    }
1874
1875
1876  private:
1877
1878    typedef std::vector<std::pair<std::string, _writer_bits::
1879                                  MapWriterBase<UEdge>*> > MapWriters;
1880    MapWriters writers;
1881
1882    _writer_bits::MapWriterBase<UEdge>* labelMap;
1883
1884    const Graph& graph;   
1885    std::string name;
1886    bool forceSort;
1887
1888    std::auto_ptr<_writer_bits::LabelWriterBase<UEdge> > labelWriter;
1889  };
1890
1891
1892  /// \ingroup section_io
[1409]1893  /// \brief SectionWriter for attributes.
1894  ///
1895  /// The lemon format can store multiple attribute set. Each set has
[1901]1896  /// the header line \c \@attributes \c attributes_name, but the
1897  /// attributeset_name may be empty.
[1409]1898  ///
1899  /// The attributeset section contains several lines. Each of them starts
1900  /// with the name of attribute and then the value.
1901  ///
1902  /// \relates LemonWriter
1903  template <typename _Traits = DefaultWriterTraits>
[1845]1904  class AttributeWriter : public LemonWriter::SectionWriter {
1905    typedef LemonWriter::SectionWriter Parent;
[1409]1906    typedef _Traits Traits;
1907  public:
1908    /// \brief Constructor.
1909    ///
1910    /// Constructor for AttributeWriter. It creates the AttributeWriter and
1911    /// attach it into the given LemonWriter.
1912    AttributeWriter(LemonWriter& _writer,
[1901]1913                    const std::string& _name = std::string())
1914      : Parent(_writer), name(_name) {}
[1409]1915
1916    /// \brief Destructor.
1917    ///
1918    /// Destructor for AttributeWriter.
1919    virtual ~AttributeWriter() {
1920      typename Writers::iterator it;
1921      for (it = writers.begin(); it != writers.end(); ++it) {
1922        delete it->second;
1923      }
1924    }
1925
1926  private:
1927    AttributeWriter(const AttributeWriter&);
1928    void operator=(AttributeWriter&);
1929
1930  public:
1931    /// \brief Add an attribute writer command for the writer.
1932    ///
1933    /// Add an attribute writer command for the writer.
1934    template <typename Value>
[2386]1935    AttributeWriter& writeAttribute(std::string label,
[1409]1936                                    const Value& value) {
1937      return
[2414]1938        writeAttribute<typename Traits::template Writer<Value> >(label, value);
[1409]1939    }
1940
1941    /// \brief Add an attribute writer command for the writer.
1942    ///
1943    /// Add an attribute writer command for the writer.
[2386]1944    template <typename ItemWriter, typename Value>
1945    AttributeWriter& writeAttribute(std::string label, const Value& value,
1946                                    const ItemWriter& iw = ItemWriter()) {
1947      checkConcept<_writer_bits::ItemWriter<Value>, ItemWriter>();
1948      writers.push_back(make_pair(label, new _writer_bits::
1949                                  ValueWriter<Value, ItemWriter>(value, iw)));
[1409]1950      return *this;
1951    }
1952
1953  protected:
1954
1955    /// \brief The header of section.
1956    ///
1957    /// It gives back the header of the section.
1958    std::string header() {
[1901]1959      return "@attributes " + name;
[1409]1960    }
1961
1962    /// \brief  Writer function of the section.
1963    ///
1964    /// Write the content of the section.
1965    void write(std::ostream& os) {
1966      typename Writers::iterator it;
1967      for (it = writers.begin(); it != writers.end(); ++it) {
1968        os << it->first << ' ';
1969        it->second->write(os);
1970        os << std::endl;
1971      }
1972    }   
1973
[2084]1974    /// \brief Gives back true when the section should be written.
1975    ///
1976    /// Gives back true when the section should be written.
1977    virtual bool valid() { return !writers.empty(); }
1978
[1409]1979  private:
[1901]1980    std::string name;
[1409]1981
[1845]1982    typedef std::vector<std::pair<std::string,
1983                                  _writer_bits::ValueWriterBase*> > Writers;
[1409]1984    Writers writers; 
1985  };
1986
1987
1988}
1989#endif
Note: See TracBrowser for help on using the repository browser.