COIN-OR::LEMON - Graph Library

Changeset 1421:7a21e1414c38 in lemon-0.x


Ignore:
Timestamp:
05/14/05 19:39:37 (20 years ago)
Author:
Balazs Dezso
Branch:
default
Phase:
public
Convert:
svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@1891
Message:

IO with undirected edgesets and undirected graphs.
Missing features:

InfoReader?,
aliased edges in undir edgesets

Location:
src/lemon
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/lemon/graph_reader.h

    r1408 r1421  
    5757  ///
    5858  /// \code
    59   /// reader.readNodeMap("x-coord", xCoordMap);
    60   /// reader.readNodeMap("y-coord", yCoordMap);
     59  /// reader.readNodeMap("coords", coords);
    6160  ///
    6261  /// reader.readNodeMap<QuotedStringReader>("label", labelMap);
     
    115114    /// Construct a new GraphReader. It reads into the given graph
    116115    /// and it use the given reader as the default skipper.
    117     GraphReader(std::istream& _is, Graph& _graph,
     116    GraphReader(std::istream& _is,
     117                typename SmartParameter<Graph>::Type _graph,
    118118                const DefaultSkipper& _skipper = DefaultSkipper())
    119       : reader(new LemonReader(_is)), own_reader(true),
    120         graph(_graph), skipper(_skipper),
    121         nodeset_reader(*reader, graph, std::string(), skipper),
    122         edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
     119      : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper),
     120        nodeset_reader(*reader, _graph, std::string(), skipper),
     121        edgeset_reader(*reader, _graph, nodeset_reader,
     122                      std::string(), skipper),
    123123        node_reader(*reader, nodeset_reader, std::string()),
    124124        edge_reader(*reader, edgeset_reader, std::string()),
     
    129129    /// Construct a new GraphReader. It reads into the given graph
    130130    /// and it use the given reader as the default skipper.
    131     GraphReader(const std::string& _filename, Graph& _graph,
     131    GraphReader(const std::string& _filename,
     132                typename SmartParameter<Graph>::Type _graph,
    132133                const DefaultSkipper& _skipper = DefaultSkipper())
    133134      : reader(new LemonReader(_filename)), own_reader(true),
    134         graph(_graph), skipper(_skipper),
    135         nodeset_reader(*reader, graph, std::string(), skipper),
    136         edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
     135        skipper(_skipper),
     136        nodeset_reader(*reader, _graph, std::string(), skipper),
     137        edgeset_reader(*reader, _graph, nodeset_reader,
     138                       std::string(), skipper),
    137139        node_reader(*reader, nodeset_reader, std::string()),
    138140        edge_reader(*reader, edgeset_reader, std::string()),
     
    143145    /// Construct a new GraphReader. It reads into the given graph
    144146    /// and it use the given reader as the default skipper.
    145     GraphReader(LemonReader& _reader, Graph& _graph,
     147    GraphReader(LemonReader& _reader,
     148                typename SmartParameter<Graph>::Type _graph,
    146149                const DefaultSkipper& _skipper = DefaultSkipper())
    147       : reader(_reader), own_reader(false),
    148         graph(_graph), skipper(_skipper),
    149         nodeset_reader(*reader, graph, std::string(), skipper),
    150         edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
     150      : reader(_reader), own_reader(false), skipper(_skipper),
     151        nodeset_reader(*reader, _graph, std::string(), skipper),
     152        edgeset_reader(*reader, _graph, nodeset_reader,
     153                      std::string(), skipper),
    151154        node_reader(*reader, nodeset_reader, std::string()),
    152155        edge_reader(*reader, edgeset_reader, std::string()),
     
    166169    template <typename Map>
    167170    GraphReader& readNodeMap(std::string name, Map& map) {
    168       nodeset_reader.readMap(name, map);
     171      nodeset_reader.readNodeMap(name, map);
     172      return *this;
     173    }
     174
     175    template <typename Map>
     176    GraphReader& readNodeMap(std::string name, const Map& map) {
     177      nodeset_reader.readNodeMap(name, map);
    169178      return *this;
    170179    }
     
    176185    GraphReader& readNodeMap(std::string name, Map& map,
    177186                             const Reader& reader = Reader()) {
    178       nodeset_reader.readMap(name, map, reader);
     187      nodeset_reader.readNodeMap(name, map, reader);
     188      return *this;
     189    }
     190
     191    template <typename Reader, typename Map>
     192    GraphReader& readNodeMap(std::string name, const Map& map,
     193                             const Reader& reader = Reader()) {
     194      nodeset_reader.readNodeMap(name, map, reader);
    179195      return *this;
    180196    }
     
    186202    GraphReader& skipNodeMap(std::string name,
    187203                             const Reader& reader = Reader()) {
    188       nodeset_reader.skipMap(name, reader);
     204      nodeset_reader.skipNodeMap(name, reader);
    189205      return *this;
    190206    }
     
    195211    template <typename Map>
    196212    GraphReader& readEdgeMap(std::string name, Map& map) {
    197       edgeset_reader.readMap(name, map);
     213      edgeset_reader.readEdgeMap(name, map);
     214      return *this;
     215    }
     216
     217    template <typename Map>
     218    GraphReader& readEdgeMap(std::string name, const Map& map) {
     219      edgeset_reader.readEdgeMap(name, map);
    198220      return *this;
    199221    }
     
    206228    GraphReader& readEdgeMap(std::string name, Map& map,
    207229                             const Reader& reader = Reader()) {
    208       edgeset_reader.readMap(name, map, reader);
     230      edgeset_reader.readEdgeMap(name, map, reader);
     231      return *this;
     232    }
     233
     234    template <typename Reader, typename Map>
     235    GraphReader& readEdgeMap(std::string name, const Map& map,
     236                             const Reader& reader = Reader()) {
     237      edgeset_reader.readEdgeMap(name, map, reader);
    209238      return *this;
    210239    }
     
    214243    /// Add a new edge map skipper command for the reader.
    215244    template <typename Reader>
    216     GraphReader& skipEdgeMap(std::string name,
     245    GraphReader& skipEdgeMap(std::string name, 
    217246                             const Reader& reader = Reader()) {
    218 
    219       edgeset_reader.skipMap(name, reader);
     247      edgeset_reader.skipEdgeMap(name, reader);
    220248      return *this;
    221249    }
     
    276304    LemonReader* reader;
    277305    bool own_reader;
    278 
    279     Graph& graph;
    280306
    281307    DefaultSkipper skipper;
     
    369395  }
    370396
     397  /// \brief The undir graph reader class.
     398  ///
     399  /// The given file format may contain several maps and labeled nodes or
     400  /// edges.
     401  ///
     402  /// If you read a graph you need not read all the maps and items just those
     403  /// that you need. The interface of the \c GraphReader is very similar to
     404  /// the GraphWriter but the reading method does not depend on the order the
     405  /// given commands.
     406  ///
     407  /// The reader object suppose that each not readed value does not contain
     408  /// whitespaces, therefore it has some extra possibilities to control how
     409  /// it should skip the values when the string representation contains spaces.
     410  ///
     411  /// \code
     412  /// UndirGraphReader<UndirListGraph> reader(std::cin, graph);
     413  /// \endcode
     414  ///
     415  /// The \c readNodeMap() function reads a map from the \c \@nodeset section.
     416  /// If there is a map that you do not want to read from the file and there is
     417  /// whitespace in the string represenation of the values then you should
     418  /// call the \c skipNodeMap() template member function with proper
     419  /// parameters.
     420  ///
     421  /// \code
     422  /// reader.readNodeMap("coords", coords);
     423  ///
     424  /// reader.readNodeMap<QuotedStringReader>("label", labelMap);
     425  /// reader.skipNodeMap<QuotedStringReader>("description");
     426  ///
     427  /// reader.readNodeMap("color", colorMap);
     428  /// \endcode
     429  ///
     430  /// With the \c readUndirEdgeMap() member function you can give an
     431  /// undir edge map reading command similar to the NodeMaps.
     432  ///
     433  /// \code
     434  /// reader.readUndirEdgeMap("capacity", capacityMap);
     435  /// \endcode
     436  ///
     437  /// The reading of the directed edge maps is just a syntactical sugar.
     438  /// It reads two undirected edgemaps into a directed edge map. The
     439  /// undirected edge maps' name should be start with the \c '+' and the
     440  /// \c '-' character and the same.
     441  ///
     442  /// \code
     443  /// reader.readEdgeMap("flow", flowMap);
     444  /// \endcode
     445  ///
     446  /// With \c readNode() and \c readUndirEdge() functions you can read
     447  /// labeled Nodes and UndirEdges.
     448  ///
     449  /// \code
     450  /// reader.readNode("source", sourceNode);
     451  /// reader.readNode("target", targetNode);
     452  ///
     453  /// reader.readUndirEdge("observed", undirEdge);
     454  /// \endcode
     455  ///
     456  /// With the \c readAttribute() functions you can read an attribute
     457  /// in a variable. You can specify the reader for the attribute as
     458  /// the nodemaps.
     459  ///
     460  /// After you give all read commands you must call the \c run() member
     461  /// function, which execute all the commands.
     462  ///
     463  /// \code
     464  /// reader.run();
     465  /// \endcode
     466  ///
     467  /// \see GraphReader
     468  /// \see DefaultReaderTraits
     469  /// \see \ref UndirGraphWriter
     470  /// \see \ref graph-io-page
     471  ///
     472  /// \author Balazs Dezso
     473  template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits>
     474  class UndirGraphReader {
     475  public:
     476   
     477    typedef _Graph Graph;
     478    typedef typename Graph::Node Node;
     479    typedef typename Graph::Edge Edge;
     480    typedef typename Graph::UndirEdge UndirEdge;
     481
     482    typedef _ReaderTraits ReaderTraits;
     483    typedef typename ReaderTraits::Skipper DefaultSkipper;
     484
     485    /// \brief Construct a new UndirGraphReader.
     486    ///
     487    /// Construct a new UndirGraphReader. It reads into the given graph
     488    /// and it use the given reader as the default skipper.
     489    UndirGraphReader(std::istream& _is, Graph& _graph,
     490                     const DefaultSkipper& _skipper = DefaultSkipper())
     491      : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper),
     492        nodeset_reader(*reader, _graph, std::string(), skipper),
     493        undir_edgeset_reader(*reader, _graph, nodeset_reader,
     494                             std::string(), skipper),
     495        node_reader(*reader, nodeset_reader, std::string()),
     496        undir_edge_reader(*reader, undir_edgeset_reader, std::string()),
     497        attribute_reader(*reader, std::string()) {}
     498
     499    /// \brief Construct a new UndirGraphReader.
     500    ///
     501    /// Construct a new UndirGraphReader. It reads into the given graph
     502    /// and it use the given reader as the default skipper.
     503    UndirGraphReader(const std::string& _filename, Graph& _graph,
     504                     const DefaultSkipper& _skipper = DefaultSkipper())
     505      : reader(new LemonReader(_filename)), own_reader(true),
     506        skipper(_skipper),
     507        nodeset_reader(*reader, _graph, std::string(), skipper),
     508        undir_edgeset_reader(*reader, _graph, nodeset_reader,
     509                             std::string(), skipper),
     510        node_reader(*reader, nodeset_reader, std::string()),
     511        undir_edge_reader(*reader, undir_edgeset_reader, std::string()),
     512        attribute_reader(*reader, std::string()) {}
     513
     514    /// \brief Construct a new UndirGraphReader.
     515    ///
     516    /// Construct a new UndirGraphReader. It reads into the given graph
     517    /// and it use the given reader as the default skipper.
     518    UndirGraphReader(LemonReader& _reader, Graph& _graph,
     519                     const DefaultSkipper& _skipper = DefaultSkipper())
     520      : reader(_reader), own_reader(false), skipper(_skipper),
     521        nodeset_reader(*reader, _graph, std::string(), skipper),
     522        undir_edgeset_reader(*reader, _graph, nodeset_reader,
     523                             std::string(), skipper),
     524        node_reader(*reader, nodeset_reader, std::string()),
     525        undir_edge_reader(*reader, undir_edgeset_reader, std::string()),
     526        attribute_reader(*reader, std::string()) {}
     527
     528    /// \brief Destruct the graph reader.
     529    ///
     530    /// Destruct the graph reader.
     531    ~UndirGraphReader() {
     532      if (own_reader)
     533        delete reader;
     534    }
     535
     536    /// \brief Add a new node map reader command for the reader.
     537    ///
     538    /// Add a new node map reader command for the reader.
     539    template <typename Map>
     540    UndirGraphReader& readNodeMap(std::string name, Map& map) {
     541      nodeset_reader.readNodeMap(name, map);
     542      return *this;
     543    }
     544
     545    template <typename Map>
     546    UndirGraphReader& readNodeMap(std::string name, const Map& map) {
     547      nodeset_reader.readNodeMap(name, map);
     548      return *this;
     549    }
     550
     551    /// \brief Add a new node map reader command for the reader.
     552    ///
     553    /// Add a new node map reader command for the reader.
     554    template <typename Reader, typename Map>
     555    UndirGraphReader& readNodeMap(std::string name, Map& map,
     556                                  const Reader& reader = Reader()) {
     557      nodeset_reader.readNodeMap(name, map, reader);
     558      return *this;
     559    }
     560
     561    template <typename Reader, typename Map>
     562    UndirGraphReader& readNodeMap(std::string name, const Map& map,
     563                                  const Reader& reader = Reader()) {
     564      nodeset_reader.readNodeMap(name, map, reader);
     565      return *this;
     566    }
     567
     568    /// \brief Add a new node map skipper command for the reader.
     569    ///
     570    /// Add a new node map skipper command for the reader.
     571    template <typename Reader>
     572    UndirGraphReader& skipNodeMap(std::string name,
     573                             const Reader& reader = Reader()) {
     574      nodeset_reader.skipNodeMap(name, reader);
     575      return *this;
     576    }
     577
     578    /// \brief Add a new undirected edge map reader command for the reader.
     579    ///
     580    /// Add a new undirected edge map reader command for the reader.
     581    template <typename Map>
     582    UndirGraphReader& readUndirEdgeMap(std::string name, Map& map) {
     583      undir_edgeset_reader.readUndirEdgeMap(name, map);
     584      return *this;
     585    }
     586
     587    template <typename Map>
     588    UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map) {
     589      undir_edgeset_reader.readUndirEdgeMap(name, map);
     590      return *this;
     591    }
     592
     593
     594    /// \brief Add a new undirected edge map reader command for the reader.
     595    ///
     596    /// Add a new undirected edge map reader command for the reader.
     597    template <typename Reader, typename Map>
     598    UndirGraphReader& readUndirEdgeMap(std::string name, Map& map,
     599                                       const Reader& reader = Reader()) {
     600      undir_edgeset_reader.readUndirEdgeMap(name, map, reader);
     601      return *this;
     602    }
     603
     604    template <typename Reader, typename Map>
     605    UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map,
     606                                       const Reader& reader = Reader()) {
     607      undir_edgeset_reader.readUndirEdgeMap(name, map, reader);
     608      return *this;
     609    }
     610
     611    /// \brief Add a new undirected edge map skipper command for the reader.
     612    ///
     613    /// Add a new undirected edge map skipper command for the reader.
     614    template <typename Reader>
     615    UndirGraphReader& skipUndirEdgeMap(std::string name,
     616                                       const Reader& reader = Reader()) {
     617      undir_edgeset_reader.skipUndirMap(name, reader);
     618      return *this;
     619    }
     620
     621
     622    /// \brief Add a new edge map reader command for the reader.
     623    ///
     624    /// Add a new edge map reader command for the reader.
     625    template <typename Map>
     626    UndirGraphReader& readEdgeMap(std::string name, Map& map) {
     627      undir_edgeset_reader.readEdgeMap(name, map);
     628      return *this;
     629    }
     630
     631    template <typename Map>
     632    UndirGraphReader& readEdgeMap(std::string name, const Map& map) {
     633      undir_edgeset_reader.readEdgeMap(name, map);
     634      return *this;
     635    }
     636
     637
     638    /// \brief Add a new edge map reader command for the reader.
     639    ///
     640    /// Add a new edge map reader command for the reader.
     641    template <typename Reader, typename Map>
     642    UndirGraphReader& readEdgeMap(std::string name, Map& map,
     643                                       const Reader& reader = Reader()) {
     644      undir_edgeset_reader.readEdgeMap(name, map, reader);
     645      return *this;
     646    }
     647
     648    template <typename Reader, typename Map>
     649    UndirGraphReader& readEdgeMap(std::string name, const Map& map,
     650                                       const Reader& reader = Reader()) {
     651      undir_edgeset_reader.readEdgeMap(name, map, reader);
     652      return *this;
     653    }
     654
     655    /// \brief Add a new edge map skipper command for the reader.
     656    ///
     657    /// Add a new edge map skipper command for the reader.
     658    template <typename Reader>
     659    UndirGraphReader& skipEdgeMap(std::string name,
     660                                       const Reader& reader = Reader()) {
     661      undir_edgeset_reader.skipEdgeMap(name, reader);
     662      return *this;
     663    }
     664
     665    /// \brief Add a new labeled node reader for the reader.
     666    ///
     667    /// Add a new labeled node reader for the reader.
     668    UndirGraphReader& readNode(std::string name, Node& node) {
     669      node_reader.readNode(name, node);
     670      return *this;
     671    }
     672
     673    /// \brief Add a new labeled edge reader for the reader.
     674    ///
     675    /// Add a new labeled edge reader for the reader.
     676    UndirGraphReader& readUndirEdge(std::string name, UndirEdge& edge) {
     677      undir_edge_reader.readUndirEdge(name, edge);
     678    }
     679
     680    /// \brief Add a new attribute reader command.
     681    ///
     682    ///  Add a new attribute reader command.
     683    template <typename Value>
     684    UndirGraphReader& readAttribute(std::string name, Value& value) {
     685      attribute_reader.readAttribute(name, value);
     686      return *this;
     687    }
     688   
     689    /// \brief Add a new attribute reader command.
     690    ///
     691    ///  Add a new attribute reader command.
     692    template <typename Reader, typename Value>
     693    UndirGraphReader& readAttribute(std::string name, Value& value,
     694                               const Reader& reader) {
     695      attribute_reader.readAttribute<Reader>(name, value, reader);
     696      return *this;
     697    }
     698
     699    /// \brief Conversion operator to LemonReader.
     700    ///
     701    /// Conversion operator to LemonReader. It make possible
     702    /// to access the encapsulated \e LemonReader, this way
     703    /// you can attach to this reader new instances of
     704    /// \e LemonReader::SectionReader.
     705    operator LemonReader&() {
     706      return *reader;
     707    }
     708
     709    /// \brief Executes the reader commands.
     710    ///
     711    /// Executes the reader commands.
     712    void run() {
     713      reader->run();
     714    }
     715
     716  private:
     717
     718    LemonReader* reader;
     719    bool own_reader;
     720
     721    DefaultSkipper skipper;
     722
     723    NodeSetReader<Graph, ReaderTraits> nodeset_reader;
     724    UndirEdgeSetReader<Graph, ReaderTraits> undir_edgeset_reader;
     725
     726    NodeReader<Graph> node_reader;
     727    UndirEdgeReader<Graph> undir_edge_reader;
     728   
     729    AttributeReader<ReaderTraits> attribute_reader;
     730  };
     731
     732  /// \brief Read an undir graph from the input.
     733  ///
     734  /// Read an undir graph from the input.
     735  /// \param is The input stream.
     736  /// \param g The graph.
     737  /// \param capacity The capacity map.
     738  template<typename Graph, typename CapacityMap>
     739  void readUndirGraph(std::istream& is, Graph &g, CapacityMap& capacity) {
     740    UndirGraphReader<Graph> reader(is, g);
     741    reader.readUndirEdgeMap("capacity", capacity);
     742    reader.run();
     743  }
     744
     745  /// \brief Read an undir graph from the input.
     746  ///
     747  /// Read an undir graph from the input.
     748  /// \param is The input stream.
     749  /// \param g The graph.
     750  template<typename Graph>
     751  void readUndirGraph(std::istream& is, Graph &g) {
     752    UndirGraphReader<Graph> reader(is, g);
     753    reader.run();
     754  }
     755
    371756  /// @}
    372757}
  • src/lemon/graph_writer.h

    r1410 r1421  
    5353  /// writer.writeNodeMap("id", nodeIdMap);
    5454  ///
    55   /// writer.writeNodeMap("x-coord", xCoordMap);
    56   /// writer.writeNodeMap("y-coord", yCoordMap);
     55  /// writer.writeNodeMap("coords", coords);
    5756  /// writer.writeNodeMap("color", colorMap);
    5857  /// \endcode
     
    9291  /// \see IdMap
    9392  /// \see DescriptorMap
    94   /// \see \ref GraphWriter
     93  /// \see \ref GraphReader
    9594  /// \see \ref graph-io-page
    9695  /// \author Balazs Dezso
     
    111110    GraphWriter(std::ostream& _os, const Graph& _graph)
    112111      : writer(new LemonWriter(_os)), own_writer(true),
    113         graph(_graph),
    114         nodeset_writer(*writer, graph, std::string()),
    115         edgeset_writer(*writer, graph, nodeset_writer, std::string()),
     112        nodeset_writer(*writer, _graph, std::string()),
     113        edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
    116114        node_writer(*writer, nodeset_writer, std::string()),
    117115        edge_writer(*writer, edgeset_writer, std::string()),
     
    124122    GraphWriter(const std::string& _filename, const Graph& _graph)
    125123      : writer(new LemonWriter(_filename)), own_writer(true),
    126         graph(_graph),
    127         nodeset_writer(*writer, graph, std::string()),
    128         edgeset_writer(*writer, graph, nodeset_writer, std::string()),
     124        nodeset_writer(*writer, _graph, std::string()),
     125        edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
    129126        node_writer(*writer, nodeset_writer, std::string()),
    130127        edge_writer(*writer, edgeset_writer, std::string()),
     
    137134    GraphWriter(LemonWriter& _writer, const Graph& _graph)
    138135      : writer(_writer), own_writer(false),
    139         graph(_graph),
    140         nodeset_writer(*writer, graph, std::string()),
    141         edgeset_writer(*writer, graph, nodeset_writer, std::string()),
     136        nodeset_writer(*writer, _graph, std::string()),
     137        edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
    142138        node_writer(*writer, nodeset_writer, std::string()),
    143139        edge_writer(*writer, edgeset_writer, std::string()),
     
    157153    template <typename Map>
    158154    GraphWriter& writeNodeMap(std::string name, const Map& map) {
    159       nodeset_writer.writeMap(name, map);
     155      nodeset_writer.writeNodeMap(name, map);
    160156      return *this;
    161157    }
     
    166162    template <typename Writer, typename Map>
    167163    GraphWriter& writeNodeMap(std::string name, const Map& map,
    168                              const Writer& writer = Writer()) {
    169       nodeset_writer.writeMap(name, map, writer);
     164                              const Writer& writer = Writer()) {
     165      nodeset_writer.writeNodeMap(name, map, writer);
    170166      return *this;
    171167    }
     
    177173    template <typename Map>
    178174    GraphWriter& writeEdgeMap(std::string name, const Map& map) {
    179       edgeset_writer.writeMap(name, map);
     175      edgeset_writer.writeEdgeMap(name, map);
    180176      return *this;
    181177    }
     
    187183    template <typename Writer, typename Map>
    188184    GraphWriter& writeEdgeMap(std::string name, const Map& map,
    189                              const Writer& writer = Writer()) {
    190       edgeset_writer.writeMap(name, map, writer);
     185                              const Writer& writer = Writer()) {
     186      edgeset_writer.writeEdgeMap(name, map, writer);
    191187      return *this;
    192188    }
     
    247243    LemonWriter* writer;
    248244    bool own_writer;
    249 
    250     const Graph& graph;
    251245
    252246    NodeSetWriter<Graph, WriterTraits> nodeset_writer;
     
    361355  }
    362356
     357  /// \brief The undirected graph writer class.
     358  ///
     359  /// The \c UndirGraphWriter class provides the undir graph output. To write
     360  /// a graph you should first give writing commands for the writer. You can
     361  /// declare write command as \c NodeMap, \c EdgeMap or \c UndirEdgeMap
     362  /// writing and labeled Node, Edge or UndirEdge writing.
     363  ///
     364  /// \code
     365  /// UndirGraphWriter<UndirListGraph> writer(std::cout, graph);
     366  /// \endcode
     367  ///
     368  /// The \c writeNodeMap() function declares a \c NodeMap writing
     369  /// command in the \c UndirGraphWriter. You should give as parameter
     370  /// the name of the map and the map object. The NodeMap writing
     371  /// command with name "id" should write a unique map because it
     372  /// is regarded as ID map.
     373  ///
     374  /// \code
     375  /// IdMap<UndirListGraph, Node> nodeIdMap;
     376  /// writer.writeNodeMap("id", nodeIdMap);
     377  ///
     378  /// writer.writeNodeMap("coords", coords);
     379  /// writer.writeNodeMap("color", colorMap);
     380  /// \endcode
     381  ///
     382  /// With the \c writeUndirEdgeMap() member function you can give an
     383  /// undirected edge map writing command similar to the NodeMaps.
     384  ///
     385  /// \code
     386  /// DescriptorMap<ListGraph, Edge, ListGraph::EdgeMap<int> >
     387  ///   edgeDescMap(graph);
     388  /// writer.writeUndirEdgeMap("descriptor", edgeDescMap);
     389  ///
     390  /// writer.writeUndirEdgeMap("weight", weightMap);
     391  /// writer.writeUndirEdgeMap("label", labelMap);
     392  /// \endcode
     393  ///
     394  /// The EdgeMap handling is just a syntactical sugar. It writes
     395  /// two undirected edge map with '+' and '-' prefix in the name.
     396  ///
     397  /// \code
     398  /// writer.writeEdgeMap("capacity", capacityMap);
     399  /// \endcode
     400  ///
     401  ///
     402  /// With \c writeNode() and \c writeUndirEdge() functions you can
     403  /// point out nodes and undirected edges in the graph. By example, you can
     404  /// write out the source and target of the graph.
     405  ///
     406  /// \code
     407  /// writer.writeNode("source", sourceNode);
     408  /// writer.writeNode("target", targetNode);
     409  ///
     410  /// writer.writeUndirEdge("observed", undirEdge);
     411  /// \endcode
     412  ///
     413  /// After you give all write commands you must call the \c run() member
     414  /// function, which execute all the writer commands.
     415  ///
     416  /// \code
     417  /// writer.run();
     418  /// \endcode
     419  ///
     420  /// \see DefaultWriterTraits
     421  /// \see QuotedStringWriter
     422  /// \see IdMap
     423  /// \see DescriptorMap
     424  /// \see \ref GraphWriter
     425  /// \see \ref graph-io-page
     426  /// \author Balazs Dezso
     427  template <typename _Graph, typename _WriterTraits = DefaultWriterTraits>
     428  class UndirGraphWriter {
     429  public:
     430   
     431    typedef _Graph Graph;
     432    typedef typename Graph::Node Node;
     433    typedef typename Graph::Edge Edge;
     434    typedef typename Graph::UndirEdge UndirEdge;
     435
     436    typedef _WriterTraits WriterTraits;
     437
     438    /// \brief Construct a new UndirGraphWriter.
     439    ///
     440    /// Construct a new UndirGraphWriter. It writes the given graph
     441    /// to the given stream.
     442    UndirGraphWriter(std::ostream& _os, const Graph& _graph)
     443      : writer(new LemonWriter(_os)), own_writer(true),
     444        nodeset_writer(*writer, _graph, std::string()),
     445        undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
     446        node_writer(*writer, nodeset_writer, std::string()),
     447        undir_edge_writer(*writer, undir_edgeset_writer, std::string()),
     448        attribute_writer(*writer, std::string()) {}
     449
     450    /// \brief Construct a new UndirGraphWriter.
     451    ///
     452    /// Construct a new UndirGraphWriter. It writes into the given graph
     453    /// to the given file.
     454    UndirGraphWriter(const std::string& _filename, const Graph& _graph)
     455      : writer(new LemonWriter(_filename)), own_writer(true),
     456        nodeset_writer(*writer, _graph, std::string()),
     457        undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
     458        node_writer(*writer, nodeset_writer, std::string()),
     459        undir_edge_writer(*writer, undir_edgeset_writer, std::string()),
     460        attribute_writer(*writer, std::string()) {}
     461
     462    /// \brief Construct a new UndirGraphWriter.
     463    ///
     464    /// Construct a new UndirGraphWriter. It writes into the given graph
     465    /// to given LemonReader.
     466    UndirGraphWriter(LemonWriter& _writer, const Graph& _graph)
     467      : writer(_writer), own_writer(false),
     468        nodeset_writer(*writer, _graph, std::string()),
     469        undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
     470        node_writer(*writer, nodeset_writer, std::string()),
     471        undir_edge_writer(*writer, undir_edgeset_writer, std::string()),
     472        attribute_writer(*writer, std::string()) {}
     473
     474    /// \brief Destruct the graph writer.
     475    ///
     476    /// Destruct the graph writer.
     477    ~UndirGraphWriter() {
     478      if (own_writer)
     479        delete writer;
     480    }
     481
     482    /// \brief Add a new node map writer command for the writer.
     483    ///
     484    /// Add a new node map writer command for the writer.
     485    template <typename Map>
     486    UndirGraphWriter& writeNodeMap(std::string name, const Map& map) {
     487      nodeset_writer.writeNodeMap(name, map);
     488      return *this;
     489    }
     490
     491    /// \brief Add a new node map writer command for the writer.
     492    ///
     493    /// Add a new node map writer command for the writer.
     494    template <typename Writer, typename Map>
     495    UndirGraphWriter& writeNodeMap(std::string name, const Map& map,
     496                              const Writer& writer = Writer()) {
     497      nodeset_writer.writeNodeMap(name, map, writer);
     498      return *this;
     499    }
     500
     501    /// \brief Add a new edge map writer command for the writer.
     502    ///
     503    /// Add a new edge map writer command for the writer.
     504    template <typename Map>
     505    UndirGraphWriter& writeEdgeMap(std::string name, const Map& map) {
     506      undir_edgeset_writer.writeEdgeMap(name, map);
     507      return *this;
     508    }
     509
     510    /// \brief Add a new edge map writer command for the writer.
     511    ///
     512    /// Add a new edge map writer command for the writer.
     513    template <typename Writer, typename Map>
     514    UndirGraphWriter& writeEdgeMap(std::string name, const Map& map,
     515                                   const Writer& writer = Writer()) {
     516      undir_edgeset_writer.writeEdgeMap(name, map, writer);
     517      return *this;
     518    }
     519
     520    /// \brief Add a new undirected edge map writer command for the writer.
     521    ///
     522    /// Add a new undirected edge map writer command for the writer.
     523    template <typename Map>
     524    UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map) {
     525      undir_edgeset_writer.writeUndirEdgeMap(name, map);
     526      return *this;
     527    }
     528
     529    /// \brief Add a new undirected edge map writer command for the writer.
     530    ///
     531    /// Add a new edge undirected map writer command for the writer.
     532    template <typename Writer, typename Map>
     533    UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map,
     534                                        const Writer& writer = Writer()) {
     535      undir_edgeset_writer.writeUndirEdgeMap(name, map, writer);
     536      return *this;
     537    }
     538
     539    /// \brief Add a new labeled node writer for the writer.
     540    ///
     541    /// Add a new labeled node writer for the writer.
     542    UndirGraphWriter& writeNode(std::string name, const Node& node) {
     543      node_writer.writeNode(name, node);
     544      return *this;
     545    }
     546
     547    /// \brief Add a new labeled edge writer for the writer.
     548    ///
     549    /// Add a new labeled edge writer for the writer.
     550    UndirGraphWriter& writeUndirEdge(std::string name, const UndirEdge& edge) {
     551      undir_edge_writer.writeUndirEdge(name, edge);
     552    }
     553
     554    /// \brief Add a new attribute writer command.
     555    ///
     556    ///  Add a new attribute writer command.
     557    template <typename Value>
     558    UndirGraphWriter& writeAttribute(std::string name, const Value& value) {
     559      attribute_writer.writeAttribute(name, value);
     560      return *this;
     561    }
     562   
     563    /// \brief Add a new attribute writer command.
     564    ///
     565    ///  Add a new attribute writer command.
     566    template <typename Writer, typename Value>
     567    UndirGraphWriter& writeAttribute(std::string name, const Value& value,
     568                               const Writer& writer) {
     569      attribute_writer.writeAttribute<Writer>(name, value, writer);
     570      return *this;
     571    }
     572
     573    /// \brief Conversion operator to LemonWriter.
     574    ///
     575    /// Conversion operator to LemonWriter. It make possible
     576    /// to access the encapsulated \e LemonWriter, this way
     577    /// you can attach to this writer new instances of
     578    /// \e LemonWriter::SectionWriter.
     579    operator LemonWriter&() {
     580      return *writer;
     581    }
     582
     583    /// \brief Executes the writer commands.
     584    ///
     585    /// Executes the writer commands.
     586    void run() {
     587      writer->run();
     588    }
     589
     590  private:
     591
     592    LemonWriter* writer;
     593    bool own_writer;
     594
     595    NodeSetWriter<Graph, WriterTraits> nodeset_writer;
     596    UndirEdgeSetWriter<Graph, WriterTraits> undir_edgeset_writer;
     597
     598    NodeWriter<Graph> node_writer;
     599    UndirEdgeWriter<Graph> undir_edge_writer;
     600   
     601    AttributeWriter<WriterTraits> attribute_writer;
     602  };
     603
     604
     605  /// \brief Write an undirected graph to the output.
     606  ///
     607  /// Write an undirected graph to the output.
     608  /// \param os The output stream.
     609  /// \param g The graph.
     610  /// \param capacity The capacity undirected map.
     611  template<typename Graph, typename CapacityMap>
     612  void writeUndirGraph(std::ostream& os, const Graph &g,
     613                       const CapacityMap& capacity) {
     614    UndirGraphWriter<Graph> writer(os, g);
     615    writer.writeUndirEdgeMap("capacity", capacity);
     616    writer.run();
     617  }
     618
     619  /// \brief Write an undirected graph to the output.
     620  ///
     621  /// Write an undirected graph to the output.
     622  /// \param os The output stream.
     623  /// \param g The graph.
     624  template<typename Graph>
     625  void writeUndirGraph(std::ostream& os, const Graph &g) {
     626    UndirGraphWriter<Graph> writer(os, g);
     627    writer.run();
     628  }
     629
    363630  /// @}
    364631
  • src/lemon/lemon_reader.h

    r1409 r1421  
    1919///\brief Lemon Format reader.
    2020
     21
    2122#ifndef LEMON_LEMON_READER_H
    2223#define LEMON_LEMON_READER_H
     24
    2325
    2426#include <iostream>
     
    3133
    3234#include <lemon/error.h>
     35#include <lemon/graph_utils.h>
     36#include <lemon/utility.h>
    3337#include <lemon/bits/item_reader.h>
    3438
    3539
    3640namespace lemon {
     41
     42  namespace _reader_bits {
     43 
     44    template <typename T>
     45    bool operator<(T, T) {
     46      throw DataFormatError("Id is not comparable");
     47    }
     48
     49    template <typename T>
     50    struct Less {
     51      bool operator()(const T& p, const T& q) const {
     52        return p < q;
     53      }
     54    };
     55
     56    template <typename M1, typename M2>
     57    class WriteComposeMap {
     58    public:
     59      typedef True NeedCopy;
     60     
     61      typedef typename M2::Key Key;
     62      typedef typename M1::Value Value;
     63
     64      WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2)
     65        : m1(_m1), m2(_m2) {}
     66     
     67      void set(const Key& key, const Value& value) {
     68        m1.set(m2[key], value);
     69      }
     70
     71    private:
     72     
     73      typename SmartReference<M1>::Type m1;
     74      typename SmartConstReference<M2>::Type m2;
     75     
     76    };
     77
     78    template <typename M1, typename M2>
     79    WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) {
     80      return WriteComposeMap<M1, M2>(m1, m2);
     81    }
     82
     83    template <typename M1, typename M2>
     84    WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) {
     85      return WriteComposeMap<M1, M2>(m1, m2);
     86    }
     87 
     88  }
    3789
    3890  /// \ingroup io_group
     
    339391        return this;
    340392      }
    341 
    342 
    343393    };
    344394
     
    350400      typedef typename Reader::Value Value;
    351401      typedef _Map Map;
    352       typedef std::map<Value, Item> Inverse;
    353 
    354       Map& map;
     402      typedef std::map<Value, Item,
     403                       typename _reader_bits::template Less<Value> > Inverse;
     404
     405      typename SmartReference<Map>::Type map;
    355406      Reader reader;
    356407      Inverse inverse;
    357408
    358       MapReaderInverter(Map& _map, const Reader& _reader)
     409      MapReaderInverter(typename SmartParameter<Map>::Type _map,
     410                        const Reader& _reader)
    359411        : map(_map), reader(_reader) {}
    360412
     
    383435        }
    384436      }     
    385 
    386437    };
    387438
     
    392443      typedef _Reader Reader;
    393444      typedef typename Reader::Value Value;
    394       typedef std::map<Value, Item> Inverse;
     445      typedef std::map<Value, Item,
     446                       typename _reader_bits::template Less<Value> > Inverse;
    395447
    396448      Reader reader;
     
    427479    };
    428480
    429     // Readers
    430 
    431481    template <typename _Item>   
    432482    class ReaderBase {
     
    448498      typedef _Item Item;
    449499     
    450       Map& map;
     500      typename SmartReference<Map>::Type map;
    451501      Reader reader;
    452502
    453       MapReader(Map& _map, const Reader& _reader)
     503      MapReader(typename SmartParameter<Map>::Type _map,
     504                const Reader& _reader)
    454505        : map(_map), reader(_reader) {}
    455506
     
    570621    /// add the readed nodes to the given Graph. The reader will read
    571622    /// the section when the \c section_id and the \c _id are the same.
    572     NodeSetReader(LemonReader& _reader, Graph& _graph,
     623    NodeSetReader(LemonReader& _reader,
     624                  typename SmartParameter<Graph>::Type _graph,
    573625                  const std::string& _id = std::string(),
    574626                  const DefaultSkipper& _skipper = DefaultSkipper())
     
    596648    /// Add a new node map reader command for the reader.
    597649    template <typename Map>
    598     NodeSetReader& readMap(std::string name, Map& map) {
    599       return readMap<typename Traits::
    600         template Reader<typename Map::Value>, Map>(name, map);
     650    NodeSetReader& readNodeMap(std::string name, Map& map) {
     651      return _readMap<
     652        typename Traits::template Reader<typename Map::Value>, Map,
     653        typename SmartParameter<Map>::Type>(name, map);
     654    }
     655
     656    template <typename Map>
     657    NodeSetReader& readNodeMap(std::string name, const Map& map) {
     658      return _readMap<
     659        typename Traits::template Reader<typename Map::Value>, Map,
     660        typename SmartParameter<Map>::Type>(name, map);
    601661    }
    602662
     
    605665    /// Add a new node map reader command for the reader.
    606666    template <typename Reader, typename Map>
    607     NodeSetReader& readMap(std::string name, Map& map,
    608                              const Reader& reader = Reader()) {
     667    NodeSetReader& readNodeMap(std::string name, Map& map,
     668                               const Reader& reader = Reader()) {
     669      return _readMap<
     670        typename Traits::template Reader<typename Map::Value>, Map,
     671        typename SmartParameter<Map>::Type>(name, map, reader);
     672    }
     673
     674    template <typename Reader, typename Map>
     675    NodeSetReader& readNodeMap(std::string name, const Map& map,
     676                               const Reader& reader = Reader()) {
     677      return _readMap<
     678        typename Traits::template Reader<typename Map::Value>, Map,
     679        typename SmartParameter<Map>::Type>(name, map, reader);
     680    }
     681
     682  private:
     683
     684    template <typename Reader, typename Map, typename MapParameter>
     685    NodeSetReader& _readMap(std::string name, MapParameter map,
     686                            const Reader& reader = Reader()) {
    609687      if (readers.find(name) != readers.end()) {
    610688        ErrorMessage msg;
     
    617695    }
    618696
     697  public:
     698
    619699    /// \brief Add a new node map skipper command for the reader.
    620700    ///
    621701    /// Add a new node map skipper command for the reader.
    622702    template <typename Reader>
    623     NodeSetReader& skipMap(std::string name,
     703    NodeSetReader& skipNodeMap(std::string name,
    624704                           const Reader& reader = Reader()) {
    625705      if (readers.find(name) != readers.end()) {
     
    637717    /// the section with the given header line.
    638718    ///
    639     /// It gives back true when the header line starts with \c @nodeset,
     719    /// It gives back true when the header line starts with \c \@nodeset,
    640720    /// and the header line's id and the nodeset's id are the same.
    641721    virtual bool header(const std::string& line) {
     
    691771    /// It reads an id from the stream and gives back which node belongs to
    692772    /// it. It is possible only if there was read an "id" named map.
    693     typename Graph::Node readId(std::istream& is) const {
     773    Item readId(std::istream& is) const {
    694774      return inverter->read(is);
    695775    }
     
    700780    MapReaders readers;
    701781   
    702     Graph& graph;   
     782    typename SmartReference<Graph>::Type graph;   
    703783    std::string id;
    704784    SkipReader<Item, DefaultSkipper> skipper;
     
    715795  ///
    716796  /// The first line of the section contains the names of the maps separated
    717   /// with white spaces. Each next lines describes a node in the nodeset. The
    718   /// line contains the two nodes' id and the mapped values for each map.
     797  /// with white spaces. Each next lines describes an edge in the edgeset. The
     798  /// line contains the source and the target nodes' id and the mapped
     799  /// values for each map.
    719800  ///
    720801  /// If the edgeset contains an \c "id" named map then it will be regarded
     
    747828    /// \c edgset_id are the same.
    748829    template <typename NodeIdReader>
    749     EdgeSetReader(LemonReader& _reader, Graph& _graph,
     830    EdgeSetReader(LemonReader& _reader,
     831                  typename SmartParameter<Graph>::Type _graph,
    750832                  const NodeIdReader& _nodeIdReader,
    751833                  const std::string& _id = std::string(),
     
    775857    /// Add a new edge map reader command for the reader.
    776858    template <typename Map>
    777     EdgeSetReader& readMap(std::string name, Map& map) {
    778       return readMap<typename Traits::
    779         template Reader<typename Map::Value>, Map>(name, map);
     859    EdgeSetReader& readEdgeMap(std::string name, Map& map) {
     860      return _readMap<
     861        typename Traits::template Reader<typename Map::Value>, Map,
     862        typename SmartParameter<Map>::Type>(name, map);
     863    }
     864
     865    template <typename Map>
     866    EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
     867      return _readMap<
     868        typename Traits::template Reader<typename Map::Value>, Map,
     869        typename SmartParameter<Map>::Type>(name, map);
    780870    }
    781871
     
    784874    /// Add a new edge map reader command for the reader.
    785875    template <typename Reader, typename Map>
    786     EdgeSetReader& readMap(std::string name, Map& map,
    787                              const Reader& reader = Reader()) {
     876    EdgeSetReader& readEdgeMap(std::string name, Map& map,
     877                           const Reader& reader = Reader()) {
     878      return _readMap<
     879        typename Traits::template Reader<typename Map::Value>, Map,
     880        typename SmartParameter<Map>::Type>(name, map, reader);
     881    }
     882
     883    template <typename Reader, typename Map>
     884    EdgeSetReader& readEdgeMap(std::string name, const Map& map,
     885                               const Reader& reader = Reader()) {
     886      return _readMap<
     887        typename Traits::template Reader<typename Map::Value>, Map,
     888        typename SmartParameter<Map>::Type>(name, map, reader);
     889    }
     890
     891  private:
     892
     893    template <typename Reader, typename Map, typename MapParameter>
     894    EdgeSetReader& _readMap(std::string name, MapParameter map,
     895                            const Reader& reader = Reader()) {
    788896      if (readers.find(name) != readers.end()) {
    789897        ErrorMessage msg;
     
    796904    }
    797905
     906  public:
     907
    798908    /// \brief Add a new edge map skipper command for the reader.
    799909    ///
    800910    /// Add a new edge map skipper command for the reader.
    801911    template <typename Reader>
    802     EdgeSetReader& skipMap(std::string name,
    803                            const Reader& reader = Reader()) {
     912    EdgeSetReader& skipEdgeMap(std::string name,
     913                               const Reader& reader = Reader()) {
    804914      if (readers.find(name) != readers.end()) {
    805915        ErrorMessage msg;
    806         msg << "Multiple read rule for node map: " << name;
     916        msg << "Multiple read rule for edge map: " << name;
    807917        throw IOParameterError(msg.message());
    808918      }
     
    816926    /// the section with the given header line.
    817927    ///
    818     /// It gives back true when the header line starts with \c @edgeset,
     928    /// It gives back true when the header line starts with \c \@edgeset,
    819929    /// and the header line's id and the edgeset's id are the same.
    820930    virtual bool header(const std::string& line) {
     
    872982    /// It reads an id from the stream and gives back which edge belongs to
    873983    /// it. It is possible only if there was read an "id" named map.
    874     typename Graph::Edge readId(std::istream& is) const {
     984    Item readId(std::istream& is) const {
    875985      return inverter->read(is);
    876986    }
     
    881991    MapReaders readers;
    882992   
    883     Graph& graph;   
     993    typename SmartReference<Graph>::Type graph;   
     994    std::string id;
     995    SkipReader<Item, DefaultSkipper> skipper;
     996
     997    std::auto_ptr<InverterBase<Item> > inverter;
     998    std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
     999  };
     1000
     1001  /// \ingroup io_group
     1002  /// \brief SectionReader for reading a undirected graph's edgeset.
     1003  ///
     1004  /// The lemon format can store multiple undirected edgesets with several
     1005  /// maps. The undirected edgeset section's header line is \c \@undiredgeset
     1006  /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
     1007  ///
     1008  /// The first line of the section contains the names of the maps separated
     1009  /// with white spaces. Each next lines describes an edge in the edgeset. The
     1010  /// line contains the connected nodes' id and the mapped values for each map.
     1011  ///
     1012  /// The section can handle the directed as a syntactical sugar. Two
     1013  /// undirected edge map describes one directed edge map. This two maps
     1014  /// are the forward map and the backward map and the names of this map
     1015  /// is near the same just with a prefix \c '+' or \c '-' character
     1016  /// difference.
     1017  ///
     1018  /// If the edgeset contains an \c "id" named map then it will be regarded
     1019  /// as id map. This map should contain only unique values and when the
     1020  /// \c readId() member will read a value from the given stream it will
     1021  /// give back that undiricted edge which is mapped to this value.
     1022  ///
     1023  /// The undirected edgeset reader needs a node id reader to identify which
     1024  /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
     1025  /// it will be able to resolve the nodes by ids.
     1026  ///
     1027  /// \relates LemonReader
     1028  template <typename _Graph, typename _Traits = DefaultReaderTraits>
     1029  class UndirEdgeSetReader : public CommonSectionReaderBase {
     1030    typedef CommonSectionReaderBase Parent;
     1031  public:
     1032
     1033    typedef _Graph Graph;
     1034    typedef _Traits Traits;
     1035    typedef typename Graph::UndirEdge Item;
     1036    typedef typename Traits::Skipper DefaultSkipper;
     1037
     1038    /// \brief Constructor.
     1039    ///
     1040    /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
     1041    /// and attach it into the given LemonReader. The undirected edgeset
     1042    /// reader will add the readed undirected edges to the given Graph. It
     1043    /// will use the given node id reader to read the source and target
     1044    /// nodes of the edges. The reader will read the section only if the
     1045    /// \c _id and the \c undiredgset_id are the same.
     1046    template <typename NodeIdReader>
     1047    UndirEdgeSetReader(LemonReader& _reader,
     1048                       typename SmartParameter<Graph>::Type _graph,
     1049                       const NodeIdReader& _nodeIdReader,
     1050                       const std::string& _id = std::string(),
     1051                       const DefaultSkipper& _skipper = DefaultSkipper())
     1052      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
     1053        nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
     1054                     (_nodeIdReader)) {}
     1055
     1056    /// \brief Destructor.
     1057    ///
     1058    /// Destructor for UndirEdgeSetReader.
     1059    virtual ~UndirEdgeSetReader() {
     1060      for (typename MapReaders::iterator it = readers.begin();
     1061           it != readers.end(); ++it) {
     1062        delete it->second;
     1063      }
     1064    }
     1065
     1066  private:
     1067    UndirEdgeSetReader(const UndirEdgeSetReader&);
     1068    void operator=(const UndirEdgeSetReader&);
     1069
     1070  public:
     1071
     1072    /// \brief Add a new undirected edge map reader command for the reader.
     1073    ///
     1074    /// Add a new edge undirected map reader command for the reader.
     1075    template <typename Map>
     1076    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
     1077      return _readMap<
     1078        typename Traits::template Reader<typename Map::Value>, Map,
     1079        typename SmartParameter<Map>::Type>(name, map);
     1080    }
     1081
     1082    template <typename Map>
     1083    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
     1084      return _readMap<
     1085        typename Traits::template Reader<typename Map::Value>, Map,
     1086        typename SmartParameter<Map>::Type>(name, map);
     1087    }
     1088
     1089    /// \brief Add a new undirected edge map reader command for the reader.
     1090    ///
     1091    /// Add a new edge undirected map reader command for the reader.
     1092    template <typename Reader, typename Map>
     1093    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
     1094                                         const Reader& reader = Reader()) {
     1095      return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
     1096        (name, map, reader);
     1097    }
     1098
     1099    template <typename Reader, typename Map>
     1100    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
     1101                                         const Reader& reader = Reader()) {
     1102      return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
     1103        (name, map, reader);
     1104    }
     1105
     1106  private:
     1107
     1108    template <typename Reader, typename Map, typename MapParameter>
     1109    UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
     1110                                 const Reader& reader = Reader()) {
     1111      if (readers.find(name) != readers.end()) {
     1112        ErrorMessage msg;
     1113        msg << "Multiple read rule for edge map: " << name;
     1114        throw IOParameterError(msg.message());
     1115      }
     1116      readers.insert(
     1117        make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
     1118      return *this;
     1119    }
     1120
     1121  public:
     1122
     1123    /// \brief Add a new undirected edge map skipper command for the reader.
     1124    ///
     1125    /// Add a new undirected edge map skipper command for the reader.
     1126    template <typename Reader>
     1127    UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
     1128                                         const Reader& reader = Reader()) {
     1129      if (readers.find(name) != readers.end()) {
     1130        ErrorMessage msg;
     1131        msg << "Multiple read rule for node map: " << name;
     1132        throw IOParameterError(msg.message());
     1133      }
     1134      readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
     1135      return *this;
     1136    }
     1137
     1138    /// \brief Add a new directed edge map reader command for the reader.
     1139    ///
     1140    /// Add a new directed edge map reader command for the reader.
     1141    template <typename Map>
     1142    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
     1143      return _readDirMap<
     1144        typename Traits::template Reader<typename Map::Value>, Map,
     1145        typename SmartParameter<Map>::Type>(name, map);
     1146    }
     1147
     1148    template <typename Map>
     1149    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
     1150      return _readDirMap<
     1151        typename Traits::template Reader<typename Map::Value>, Map,
     1152        typename SmartParameter<Map>::Type>(name, map);
     1153    }
     1154
     1155    /// \brief Add a new directed edge map reader command for the reader.
     1156    ///
     1157    /// Add a new directed edge map reader command for the reader.
     1158    template <typename Reader, typename Map>
     1159    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
     1160                                    const Reader& reader = Reader()) {
     1161      return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
     1162        (name, map, reader);
     1163    }
     1164
     1165    template <typename Reader, typename Map>
     1166    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
     1167                                    const Reader& reader = Reader()) {
     1168      return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
     1169        (name, map, reader);
     1170    }
     1171
     1172  private:
     1173
     1174    template <typename Reader, typename Map, typename MapParameter>
     1175    UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
     1176                                    const Reader& reader = Reader()) {
     1177      readMap("+" + name,
     1178              _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
     1179      readMap("-" + name,
     1180              _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
     1181      return *this;     
     1182    }
     1183
     1184  public:
     1185
     1186    /// \brief Add a new directed edge map skipper command for the reader.
     1187    ///
     1188    /// Add a new directed edge map skipper command for the reader.
     1189    template <typename Reader>
     1190    UndirEdgeSetReader& skipEdgeMap(std::string name,
     1191                                    const Reader& reader = Reader()) {
     1192      skipMap("+" + name, reader);
     1193      skipMap("-" + name, reader);
     1194      return *this;
     1195    }
     1196
     1197  protected:
     1198
     1199    /// \brief Gives back true when the SectionReader can process
     1200    /// the section with the given header line.
     1201    ///
     1202    /// It gives back true when the header line starts with \c \@undiredgeset,
     1203    /// and the header line's id and the edgeset's id are the same.
     1204    virtual bool header(const std::string& line) {
     1205      std::istringstream ls(line);
     1206      std::string command;
     1207      std::string name;
     1208      ls >> command >> name;
     1209      return command == "@undiredgeset" && name == id;
     1210    }
     1211
     1212    /// \brief Reader function of the section.
     1213    ///
     1214    /// It reads the content of the section.
     1215    virtual void read(std::istream& is) {
     1216      std::vector<ReaderBase<Item>* > index;
     1217      std::string line;
     1218
     1219      getline(is, line);
     1220      std::istringstream ls(line);     
     1221      while (ls >> id) {
     1222        typename MapReaders::iterator it = readers.find(id);
     1223        if (it != readers.end()) {
     1224          index.push_back(it->second);
     1225        } else {
     1226          index.push_back(&skipper);
     1227        }
     1228        if (id == "id" && inverter.get() == 0) {
     1229          inverter.reset(index.back()->getInverter());
     1230          index.back() = inverter.get();
     1231        }
     1232      }
     1233      while (getline(is, line)) {       
     1234        std::istringstream ls(line);
     1235        typename Graph::Node from = nodeIdReader->read(ls);
     1236        typename Graph::Node to = nodeIdReader->read(ls);
     1237        typename Graph::UndirEdge edge = graph.addEdge(from, to);
     1238        for (int i = 0; i < (int)index.size(); ++i) {
     1239          index[i]->read(ls, edge);
     1240        }
     1241      }
     1242    }
     1243
     1244  public:
     1245
     1246    /// \brief Returns true if the edgeset can give back the edge by its id.
     1247    ///
     1248    /// Returns true if the edgeset can give back the undirected edge by its
     1249    /// id. It is possible only if an "id" named map was read.
     1250    bool isIdReader() const {
     1251      return inverter.get() != 0;
     1252    }
     1253
     1254    /// \brief Gives back the undirected edge by its id.
     1255    ///
     1256    /// It reads an id from the stream and gives back which undirected edge
     1257    /// belongs to it. It is possible only if there was read an "id" named map.
     1258    Item readId(std::istream& is) const {
     1259      return inverter->read(is);
     1260    }
     1261
     1262  private:
     1263
     1264    typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
     1265    MapReaders readers;
     1266   
     1267    typename SmartReference<Graph>::Type graph;   
    8841268    std::string id;
    8851269    SkipReader<Item, DefaultSkipper> skipper;
     
    9461330    /// the section with the given header line.
    9471331    ///
    948     /// It gives back true when the header line start with \c @nodes,
     1332    /// It gives back true when the header line start with \c \@nodes,
    9491333    /// and the header line's id and the reader's id are the same.
    9501334    virtual bool header(const std::string& line) {
     
    10031387    /// attach it into the given LemonReader. It will use the given
    10041388    /// edge id reader to give back the edges. The reader will read the
    1005     /// section only if the \c _id and the \c nodes_id are the same.
     1389    /// section only if the \c _id and the \c edges_id are the same.
    10061390    template <typename _IdReader>
    10071391    EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
     
    10371421    /// the section with the given header line.
    10381422    ///
    1039     /// It gives back true when the header line start with \c @edges,
     1423    /// It gives back true when the header line start with \c \@edges,
    10401424    /// and the header line's id and the reader's id are the same.
    10411425    virtual bool header(const std::string& line) {
     
    10731457
    10741458  /// \ingroup io_group
     1459  /// \brief SectionReader for reading labeled undirected edges.
     1460  ///
     1461  /// The undirected edges section's header line is \c \@undiredges
     1462  /// \c undiredges_id, but the \c undiredges_id may be empty.
     1463  ///
     1464  /// Each line in the section contains the name of the undirected edge
     1465  /// and then the undirected edge id.
     1466  ///
     1467  /// \relates LemonReader
     1468  template <typename _Graph>
     1469  class UndirEdgeReader : public CommonSectionReaderBase {
     1470    typedef CommonSectionReaderBase Parent;
     1471    typedef _Graph Graph;
     1472    typedef typename Graph::UndirEdge Item;
     1473  public:
     1474   
     1475    /// \brief Constructor.
     1476    ///
     1477    /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
     1478    /// attach it into the given LemonReader. It will use the given
     1479    /// undirected edge id reader to give back the edges. The reader will
     1480    /// read the section only if the \c _id and the \c undiredges_id are
     1481    /// the same.
     1482    template <typename _IdReader>
     1483    UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
     1484               const std::string& _id = std::string())
     1485      : Parent(_reader), id(_id),
     1486        idReader(new IdReader<typename Graph::UndirEdge, _IdReader>(_idReader))
     1487    {}
     1488
     1489    /// \brief Destructor.
     1490    ///
     1491    /// Destructor for UndirEdgeReader.
     1492    virtual ~UndirEdgeReader() {}
     1493  private:
     1494    UndirEdgeReader(const UndirEdgeReader&);
     1495    void operator=(const UndirEdgeReader&);
     1496
     1497  public:
     1498
     1499    /// \brief Add an undirected edge reader command for the UndirEdgeReader.
     1500    ///
     1501    /// Add an undirected edge reader command for the UndirEdgeReader.
     1502    void readUndirEdge(const std::string& name, Item& item) {
     1503      if (readers.find(name) != readers.end()) {
     1504        ErrorMessage msg;
     1505        msg << "Multiple read rule for edge: " << name;
     1506        throw IOParameterError(msg.message());
     1507      }
     1508      readers.insert(make_pair(name, &item));
     1509    }
     1510
     1511  protected:
     1512
     1513    /// \brief Gives back true when the SectionReader can process
     1514    /// the section with the given header line.
     1515    ///
     1516    /// It gives back true when the header line start with \c \@edges,
     1517    /// and the header line's id and the reader's id are the same.
     1518    virtual bool header(const std::string& line) {
     1519      std::istringstream ls(line);
     1520      std::string command;
     1521      std::string name;
     1522      ls >> command >> name;
     1523      return command == "@edges" && name == id;
     1524    }
     1525
     1526    /// \brief Reader function of the section.
     1527    ///
     1528    /// It reads the content of the section.
     1529    virtual void read(std::istream& is) {
     1530      std::string line;
     1531      while (getline(is, line)) {
     1532        std::istringstream ls(line);
     1533        std::string id;
     1534        ls >> id;
     1535        typename ItemReaders::iterator it = readers.find(id);
     1536        if (it != readers.end()) {
     1537          *(it->second) = idReader->read(ls);
     1538        }       
     1539      }
     1540    }
     1541   
     1542  private:
     1543
     1544    std::string id;
     1545
     1546    typedef std::map<std::string, Item*> ItemReaders;
     1547    ItemReaders readers;
     1548    std::auto_ptr<IdReaderBase<Item> > idReader;
     1549  };
     1550
     1551  /// \ingroup io_group
    10751552  /// \brief SectionReader for attributes.
    10761553  ///
     
    11421619    /// the section with the given header line.
    11431620    ///
    1144     /// It gives back true when the header line start with \c @attributes,
     1621    /// It gives back true when the header line start with \c \@attributes,
    11451622    /// and the header line's id and the attributeset's id are the same.
    11461623    bool header(const std::string& line) {
     
    11751652  };
    11761653
    1177 
    11781654}
    11791655#endif
  • src/lemon/lemon_writer.h

    r1411 r1421  
    3232#include <lemon/error.h>
    3333#include <lemon/invalid.h>
     34#include <lemon/graph_utils.h>
    3435#include <lemon/bits/item_writer.h>
     36#include <lemon/utility.h>
     37#include <lemon/maps.h>
    3538
    3639
     
    164167      : Parent(_writer) {}
    165168
    166     // Writers
    167 
    168169    template <typename _Item>   
    169170    class WriterBase {
     
    185186      typedef _Item Item;
    186187     
    187       const Map& map;
     188      typename SmartConstReference<Map>::Type map;
    188189      Writer writer;
    189190
     
    307308    /// Add a new node map writer command for the writer.
    308309    template <typename Map>
    309     NodeSetWriter& writeMap(std::string name, const Map& map) {
    310       return writeMap<typename Traits::
     310    NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
     311      return writeNodeMap<typename Traits::
    311312        template Writer<typename Map::Value>, Map>(name, map);
    312313    }
     
    316317    /// Add a new node map writer command for the writer.
    317318    template <typename Writer, typename Map>
    318     NodeSetWriter& writeMap(std::string name, const Map& map,
    319                              const Writer& writer = Writer()) {
     319    NodeSetWriter& writeNodeMap(std::string name, const Map& map,
     320                            const Writer& writer = Writer()) {
    320321      writers.push_back(
    321322        make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
     
    395396    bool forceIdMap;
    396397   
    397     const Graph& graph;   
     398    typename SmartConstReference<Graph>::Type graph;   
    398399    std::string id;
    399400
     
    401402
    402403  /// \ingroup io_group
    403   /// \brief SectionWriter for writing a graph's edgeset.
    404   ///
    405   /// The lemon format can store multiple graph edgesets with several maps.
     404  /// \brief SectionWriter for writing a graph's edgesets.
     405  ///
     406  /// The lemon format can store multiple graph edgesets with several maps. 
    406407  /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
    407408  /// \c edgeset_id may be empty.
     
    414415  /// If the edgeset contains an \c "id" named map then it will be regarded
    415416  /// as id map. This map should contain only unique values and when the
    416   /// \c writeId() member will be called with a edge it will write it's id.
     417  /// \c writeId() member will be called with an edge it will write it's id.
    417418  /// Otherwise if the \c _forceIdMap constructor parameter is true then
    418419  /// the id map will be the id in the graph.
     
    437438    /// attach it into the given LemonWriter. It will write node ids by
    438439    /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
    439     /// then the writer will write own id map when the user does not give
     440    /// then the writer will write own id map if the user does not give
    440441    /// "id" named map.
    441442    template <typename NodeIdWriter>
     
    465466  public:
    466467
    467     /// \brief Add a new node map writer command for the writer.
    468     ///
    469     /// Add a new node map writer command for the writer.
     468    /// \brief Add a new edge map writer command for the writer.
     469    ///
     470    /// Add a new edge map writer command for the writer.
    470471    template <typename Map>
    471     EdgeSetWriter& writeMap(std::string name, const Map& map) {
    472       return writeMap<typename Traits::
     472    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
     473      return writeEdgeMap<typename Traits::
    473474        template Writer<typename Map::Value>, Map>(name, map);
    474475    }
    475476
    476     /// \brief Add a new node map writer command for the writer.
    477     ///
    478     /// Add a new node map writer command for the writer.
     477    /// \brief Add a new edge map writer command for the writer.
     478    ///
     479    /// Add a new edge map writer command for the writer.
    479480    template <typename Writer, typename Map>
    480     EdgeSetWriter& writeMap(std::string name, const Map& map,
    481                              const Writer& writer = Writer()) {
     481    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
     482                            const Writer& writer = Writer()) {
    482483      writers.push_back(
    483484        make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
     
    562563    bool forceIdMap;
    563564   
    564     const Graph& graph;   
     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;   
    565762    std::string id;
    566763
     
    618815    /// \brief Header checking function.
    619816    ///
    620     /// It gives back true when the header line start with \c @nodes,
     817    /// It gives back true when the header line start with \c \@nodes,
    621818    /// and the header line's id and the writer's id are the same.
    622819    virtual std::string header() {
     
    645842
    646843  /// \ingroup io_group
    647   /// \brief SectionWriter for writeing labeled edges.
     844  /// \brief SectionWriter for writing labeled edges.
    648845  ///
    649846  /// The edges section's header line is \c \@edges \c edges_id, but the
     
    682879  public:
    683880
    684     /// \brief Add an edge writer command for the NodeWriter.
    685     ///
    686     /// Add an edge writer command for the NodeWriter.
     881    /// \brief Add an edge writer command for the EdgeWriter.
     882    ///
     883    /// Add an edge writer command for the EdgeWriter.
    687884    void writeEdge(const std::string& name, const Item& item) {
    688885      writers.push_back(make_pair(name, &item));
     
    693890    /// \brief Header checking function.
    694891    ///
    695     /// It gives back true when the header line start with \c @nodes,
     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,
    696971    /// and the header line's id and the writer's id are the same.
    697972    virtual std::string header() {
Note: See TracChangeset for help on using the changeset viewer.