COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/lemon_writer.h @ 1427:14c75970840e

Last change on this file since 1427:14c75970840e was 1421:7a21e1414c38, checked in by Balazs Dezso, 19 years ago

IO with undirected edgesets and undirected graphs.
Missing features:

InfoReader?,
aliased edges in undir edgesets

File size: 32.7 KB
Line 
1/* -*- C++ -*-
2 * src/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        return 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 Item;
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<Item, 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 Item& 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<Item>*> > MapWriters;
393    MapWriters writers;
394
395    WriterBase<Item>* 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::Edge Item;
434
435    /// \brief Constructor.
436    ///
437    /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
438    /// attach it into the given LemonWriter. It will write node ids by
439    /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
440    /// then the writer will write own id map if the user does not give
441    /// "id" named map.
442    template <typename NodeIdWriter>
443    EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
444                  const NodeIdWriter& _nodeIdWriter,
445                  const std::string& _id = std::string(),
446                  bool _forceIdMap = true)
447      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
448        graph(_graph), id(_id),
449        nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
450                     (_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<Item, 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 Item& 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<Item>*> > MapWriters;
560    MapWriters writers;
561
562    WriterBase<Item>* idMap;
563    bool forceIdMap;
564   
565    typename SmartConstReference<Graph>::Type graph;   
566    std::string id;
567
568    std::auto_ptr<IdWriterBase<typename Graph::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::UndirEdge Item;
608
609    /// \brief Constructor.
610    ///
611    /// Constructor for UndirEdgeSetWriter. It creates the UndirEdgeSetWriter
612    /// and attach it into the given LemonWriter. It will write node ids by
613    /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
614    /// then the writer will write own id map if the user does not give
615    /// "id" named map.
616    template <typename NodeIdWriter>
617    UndirEdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
618                       const NodeIdWriter& _nodeIdWriter,
619                       const std::string& _id = std::string(),
620                       bool _forceIdMap = true)
621      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
622        graph(_graph), id(_id),
623        nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
624                     (_nodeIdWriter)) {}
625
626    /// \brief Destructor.
627    ///
628    /// Destructor for UndirEdgeSetWriter.
629    virtual ~UndirEdgeSetWriter() {
630      typename MapWriters::iterator it;
631      for (it = writers.begin(); it != writers.end(); ++it) {
632        delete it->second;
633      }
634    }
635
636  private:
637    UndirEdgeSetWriter(const UndirEdgeSetWriter&);
638    void operator=(const UndirEdgeSetWriter&);
639
640  public:
641
642    /// \brief Add a new undirected edge map writer command for the writer.
643    ///
644    /// Add a new undirected map writer command for the writer.
645    template <typename Map>
646    UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map) {
647      return writeUndirEdgeMap<typename Traits::
648        template Writer<typename Map::Value>, Map>(name, map);
649    }
650
651    /// \brief Add a new undirected map writer command for the writer.
652    ///
653    /// Add a new undirected map writer command for the writer.
654    template <typename Writer, typename Map>
655    UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map,
656                                          const Writer& writer = Writer()) {
657      writers.push_back(
658        make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
659      return *this;
660    }
661
662    /// \brief Add a new directed edge map writer command for the writer.
663    ///
664    /// Add a new directed map writer command for the writer.
665    template <typename Map>
666    UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
667      writeUndirEdgeMap("+" + name, composeMap(forwardMap(graph), map));
668      writeUndirEdgeMap("-" + name, composeMap(backwardMap(graph), map));
669      return *this;
670    }
671
672    /// \brief Add a new directed map writer command for the writer.
673    ///
674    /// Add a new directed map writer command for the writer.
675    template <typename Writer, typename Map>
676    UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
677                                     const Writer& writer = Writer()) {
678      writeUndirEdge("+" + name, composeMap(forwardMap(graph), map), writer);
679      writeUndirEdge("-" + name, composeMap(forwardMap(graph), map), writer);
680      return *this;
681    }
682
683  protected:
684
685    /// \brief The header of the section.
686    ///
687    /// It gives back the header of the section.
688    virtual std::string header() {
689      return "@undiredgeset " + id;
690    }
691
692    /// \brief  Writer function of the section.
693    ///
694    /// Write the content of the section.
695    virtual void write(std::ostream& os) {
696      for (int i = 0; i < (int)writers.size(); ++i) {
697        if (writers[i].first == "id") {
698          idMap = writers[i].second;
699          forceIdMap = false;
700          break;
701        }
702      }
703      os << "\t\t";
704      if (forceIdMap) {
705        os << "id\t";
706      }
707      for (int i = 0; i < (int)writers.size(); ++i) {
708        os << writers[i].first << '\t';
709      }
710      os << std::endl;
711      for (typename Graph::UndirEdgeIt it(graph); it != INVALID; ++it) {
712        nodeIdWriter->write(os, graph.source(it));
713        os << '\t';
714        nodeIdWriter->write(os, graph.target(it));
715        os << '\t';
716        if (forceIdMap) {
717          os << graph.id(it) << '\t';
718        }
719        for (int i = 0; i < (int)writers.size(); ++i) {
720          writers[i].second->write(os, it);
721          os << '\t';
722        }
723        os << std::endl;
724      }
725    }
726
727  public:
728
729    /// \brief Returns true if the undirected edgeset can write the ids of
730    /// the edges.
731    ///
732    /// Returns true if the undirected edgeset can write the ids of the
733    /// undirected edges. It is possible only if an "id" named map was
734    /// written or the \c _forceIdMap constructor parameter was true.
735    bool isIdWriter() const {
736      return forceIdMap || idMap != 0;
737    }
738
739    /// \brief Write the id of the given undirected edge.
740    ///
741    /// It writes the id of the given undirected edge. If there was written
742    /// an "id" named map then it will write the map value belongs to the
743    /// undirected edge. Otherwise if the \c forceId parameter was true it
744    /// will write its id in the graph.
745    void writeId(std::ostream& os, const Item& item) const {
746      if (forceIdMap) {
747        os << graph.id(item);
748      } else {
749        idMap->write(os, item);
750      }
751    }
752
753  private:
754
755    typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
756    MapWriters writers;
757
758    WriterBase<Item>* idMap;
759    bool forceIdMap;
760   
761    typename SmartConstReference<Graph>::Type graph;   
762    std::string id;
763
764    std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
765  };
766
767  /// \ingroup io_group
768  /// \brief SectionWriter for writing labeled nodes.
769  ///
770  /// The nodes section's header line is \c \@nodes \c nodes_id, but the
771  /// \c nodes_id may be empty.
772  ///
773  /// Each line in the section contains the label of the node and
774  /// then the node id.
775  ///
776  /// \relates LemonWriter
777  template <typename _Graph>
778  class NodeWriter : public CommonSectionWriterBase {
779    typedef CommonSectionWriterBase Parent;
780    typedef _Graph Graph;
781    typedef typename Graph::Node Item;
782  public:
783   
784    /// \brief Constructor.
785    ///
786    /// Constructor for NodeWriter. It creates the NodeWriter and
787    /// attach it into the given LemonWriter. The given \c _IdWriter
788    /// will write the nodes' id what can be a nodeset writer.
789    template <typename _IdWriter>
790    NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
791               const std::string& _id = std::string())
792      : Parent(_writer), id(_id),
793        idWriter(new IdWriter<typename Graph::Node, _IdWriter>(_idWriter)) {}
794
795    /// \brief Destructor.
796    ///
797    /// Destructor for NodeWriter.
798    virtual ~NodeWriter() {}
799
800  private:
801    NodeWriter(const NodeWriter&);
802    void operator=(const NodeWriter&);
803
804  public:
805
806    /// \brief Add a node writer command for the NodeWriter.
807    ///
808    /// Add a node writer command for the NodeWriter.
809    void writeNode(const std::string& name, const Item& item) {
810      writers.push_back(make_pair(name, &item));
811    }
812
813  protected:
814
815    /// \brief Header checking function.
816    ///
817    /// It gives back true when the header line start with \c \@nodes,
818    /// and the header line's id and the writer's id are the same.
819    virtual std::string header() {
820      return "@nodes " + id;
821    }
822
823    /// \brief  Writer function of the section.
824    ///
825    /// Write the content of the section.
826    virtual void write(std::ostream& os) {
827      for (int i = 0; i < (int)writers.size(); ++i) {
828        os << writers[i].first << ' ';
829        idWriter->write(os, *(writers[i].second));
830        os << std::endl;
831      }
832    }
833   
834  private:
835
836    std::string id;
837
838    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
839    ItemWriters writers;
840    std::auto_ptr<IdWriterBase<Item> > idWriter;
841  };
842
843  /// \ingroup io_group
844  /// \brief SectionWriter for writing labeled edges.
845  ///
846  /// The edges section's header line is \c \@edges \c edges_id, but the
847  /// \c edges_id may be empty.
848  ///
849  /// Each line in the section contains the label of the edge and
850  /// then the edge id.
851  ///
852  /// \relates LemonWriter
853  template <typename _Graph>
854  class EdgeWriter : public CommonSectionWriterBase {
855    typedef CommonSectionWriterBase Parent;
856    typedef _Graph Graph;
857    typedef typename Graph::Edge Item;
858  public:
859   
860    /// \brief Constructor.
861    ///
862    /// Constructor for EdgeWriter. It creates the EdgeWriter and
863    /// attach it into the given LemonWriter. The given \c _IdWriter
864    /// will write the edges' id what can be a edgeset writer.
865    template <typename _IdWriter>
866    EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
867               const std::string& _id = std::string())
868      : Parent(_writer), id(_id),
869        idWriter(new IdWriter<typename Graph::Edge, _IdWriter>(_idWriter)) {}
870
871    /// \brief Destructor.
872    ///
873    /// Destructor for EdgeWriter.
874    virtual ~EdgeWriter() {}
875  private:
876    EdgeWriter(const EdgeWriter&);
877    void operator=(const EdgeWriter&);
878
879  public:
880
881    /// \brief Add an edge writer command for the EdgeWriter.
882    ///
883    /// Add an edge writer command for the EdgeWriter.
884    void writeEdge(const std::string& name, const Item& item) {
885      writers.push_back(make_pair(name, &item));
886    }
887
888  protected:
889
890    /// \brief Header checking function.
891    ///
892    /// It gives back true when the header line start with \c \@edges,
893    /// and the header line's id and the writer's id are the same.
894    virtual std::string header() {
895      return "@edges " + id;
896    }
897
898    /// \brief  Writer function of the section.
899    ///
900    /// Write the content of the section.
901    virtual void write(std::ostream& os) {
902      for (int i = 0; i < (int)writers.size(); ++i) {
903        os << writers[i].first << ' ';
904        idWriter->write(os, *(writers[i].second));
905        os << std::endl;
906      }
907    }
908   
909  private:
910
911    std::string id;
912
913    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
914    ItemWriters writers;
915
916    std::auto_ptr<IdWriterBase<Item> > idWriter;
917  };
918
919  /// \ingroup io_group
920  /// \brief SectionWriter for writing labeled undirected edges.
921  ///
922  /// The undirected edges section's header line is \c \@undiredges
923  /// \c undiredges_id, but the \c undiredges_id may be empty.
924  ///
925  /// Each line in the section contains the label of the undirected edge and
926  /// then the undirected edge id.
927  ///
928  /// \relates LemonWriter
929  template <typename _Graph>
930  class UndirEdgeWriter : public CommonSectionWriterBase {
931    typedef CommonSectionWriterBase Parent;
932    typedef _Graph Graph;
933    typedef typename Graph::UndirEdge Item;
934  public:
935   
936    /// \brief Constructor.
937    ///
938    /// Constructor for UndirEdgeWriter. It creates the UndirEdgeWriter and
939    /// attach it into the given LemonWriter. The given \c _IdWriter
940    /// will write the undirected edges' id what can be an undirected
941    /// edgeset writer.
942    template <typename _IdWriter>
943    UndirEdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
944               const std::string& _id = std::string())
945      : Parent(_writer), id(_id),
946        idWriter(new IdWriter<typename Graph::UndirEdge, _IdWriter>
947                 (_idWriter)) {}
948
949    /// \brief Destructor.
950    ///
951    /// Destructor for UndirEdgeWriter.
952    virtual ~UndirEdgeWriter() {}
953  private:
954    UndirEdgeWriter(const UndirEdgeWriter&);
955    void operator=(const UndirEdgeWriter&);
956
957  public:
958
959    /// \brief Add an undirected edge writer command for the UndirEdgeWriter.
960    ///
961    /// Add an edge writer command for the UndirEdgeWriter.
962    void writeUndirEdge(const std::string& name, const Item& item) {
963      writers.push_back(make_pair(name, &item));
964    }
965
966  protected:
967
968    /// \brief Header checking function.
969    ///
970    /// It gives back true when the header line start with \c \@undiredges,
971    /// and the header line's id and the writer's id are the same.
972    virtual std::string header() {
973      return "@edges " + id;
974    }
975
976    /// \brief  Writer function of the section.
977    ///
978    /// Write the content of the section.
979    virtual void write(std::ostream& os) {
980      for (int i = 0; i < (int)writers.size(); ++i) {
981        os << writers[i].first << ' ';
982        idWriter->write(os, *(writers[i].second));
983        os << std::endl;
984      }
985    }
986   
987  private:
988
989    std::string id;
990
991    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
992    ItemWriters writers;
993
994    std::auto_ptr<IdWriterBase<Item> > idWriter;
995  };
996
997  /// \ingroup io_group
998  /// \brief SectionWriter for attributes.
999  ///
1000  /// The lemon format can store multiple attribute set. Each set has
1001  /// the header line \c \@attributes \c attributeset_id, but the
1002  /// attributeset_id may be empty.
1003  ///
1004  /// The attributeset section contains several lines. Each of them starts
1005  /// with the name of attribute and then the value.
1006  ///
1007  /// \relates LemonWriter
1008  template <typename _Traits = DefaultWriterTraits>
1009  class AttributeWriter : public CommonSectionWriterBase {
1010    typedef CommonSectionWriterBase Parent;
1011    typedef _Traits Traits;
1012  public:
1013    /// \brief Constructor.
1014    ///
1015    /// Constructor for AttributeWriter. It creates the AttributeWriter and
1016    /// attach it into the given LemonWriter.
1017    AttributeWriter(LemonWriter& _writer,
1018                    const std::string& _id = std::string())
1019      : Parent(_writer), id(_id) {}
1020
1021    /// \brief Destructor.
1022    ///
1023    /// Destructor for AttributeWriter.
1024    virtual ~AttributeWriter() {
1025      typename Writers::iterator it;
1026      for (it = writers.begin(); it != writers.end(); ++it) {
1027        delete it->second;
1028      }
1029    }
1030
1031  private:
1032    AttributeWriter(const AttributeWriter&);
1033    void operator=(AttributeWriter&);
1034
1035  public:
1036    /// \brief Add an attribute writer command for the writer.
1037    ///
1038    /// Add an attribute writer command for the writer.
1039    template <typename Value>
1040    AttributeWriter& writeAttribute(const std::string& id,
1041                                    const Value& value) {
1042      return
1043        writeAttribute<typename Traits::template Writer<Value> >(id, value);
1044    }
1045
1046    /// \brief Add an attribute writer command for the writer.
1047    ///
1048    /// Add an attribute writer command for the writer.
1049    template <typename Writer, typename Value>
1050    AttributeWriter& writeAttribute(const std::string& name,
1051                                    const Value& value,
1052                                    const Writer& writer = Writer()) {
1053      writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
1054                               (value, writer)));
1055      return *this;
1056    }
1057
1058  protected:
1059
1060    /// \brief The header of section.
1061    ///
1062    /// It gives back the header of the section.
1063    std::string header() {
1064      return "@attributes " + id;
1065    }
1066
1067    /// \brief  Writer function of the section.
1068    ///
1069    /// Write the content of the section.
1070    void write(std::ostream& os) {
1071      typename Writers::iterator it;
1072      for (it = writers.begin(); it != writers.end(); ++it) {
1073        os << it->first << ' ';
1074        it->second->write(os);
1075        os << std::endl;
1076      }
1077    }   
1078
1079  private:
1080    std::string id;
1081
1082    typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;
1083    Writers writers; 
1084  };
1085
1086
1087}
1088#endif
Note: See TracBrowser for help on using the repository browser.