COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_writer.h @ 1622:9c98841eda96

Last change on this file since 1622:9c98841eda96 was 1494:ae55ba000ebb, checked in by Alpar Juttner, 14 years ago

gcc-4.0 compatibility changes
coloring.cc still generates warnings. Don't know why.

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