COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_writer.h @ 1865:dcefd1d1377f

Last change on this file since 1865:dcefd1d1377f was 1852:ffa7c6e96330, checked in by Balazs Dezso, 18 years ago

Some bug fixes and improvments in the io classes

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