COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_writer.h @ 1493:94535d1833b5

Last change on this file since 1493:94535d1833b5 was 1492:0d58f0301923, checked in by Balazs Dezso, 19 years ago

Correcting concept checks.

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