COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_writer.h @ 1435:8e85e6bbefdf

Last change on this file since 1435:8e85e6bbefdf was 1435:8e85e6bbefdf, checked in by Akos Ladanyi, 15 years ago

trunk/src/* move to trunk/

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