COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_writer.h @ 1476:182da222fceb

Last change on this file since 1476:182da222fceb was 1476:182da222fceb, checked in by Balazs Dezso, 15 years ago

Some bug fix.

Added: Concept check for maps and IdReader/Writer? classes

Some runtime check

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