COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_writer.h @ 1791:62e7d237e1fb

Last change on this file since 1791:62e7d237e1fb was 1705:3f63d9db307b, checked in by Balazs Dezso, 14 years ago

Removing smart references

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