[Lemon-commits] [lemon_svn] deba: r1891 - hugo/trunk/src/lemon
Lemon SVN
svn at lemon.cs.elte.hu
Mon Nov 6 20:48:30 CET 2006
Author: deba
Date: Sat May 14 19:39:37 2005
New Revision: 1891
Modified:
hugo/trunk/src/lemon/graph_reader.h
hugo/trunk/src/lemon/graph_writer.h
hugo/trunk/src/lemon/lemon_reader.h
hugo/trunk/src/lemon/lemon_writer.h
Log:
IO with undirected edgesets and undirected graphs.
Missing features:
InfoReader,
aliased edges in undir edgesets
Modified: hugo/trunk/src/lemon/graph_reader.h
==============================================================================
--- hugo/trunk/src/lemon/graph_reader.h (original)
+++ hugo/trunk/src/lemon/graph_reader.h Sat May 14 19:39:37 2005
@@ -56,8 +56,7 @@
/// parameters.
///
/// \code
- /// reader.readNodeMap("x-coord", xCoordMap);
- /// reader.readNodeMap("y-coord", yCoordMap);
+ /// reader.readNodeMap("coords", coords);
///
/// reader.readNodeMap<QuotedStringReader>("label", labelMap);
/// reader.skipNodeMap<QuotedStringReader>("description");
@@ -114,12 +113,13 @@
///
/// Construct a new GraphReader. It reads into the given graph
/// and it use the given reader as the default skipper.
- GraphReader(std::istream& _is, Graph& _graph,
+ GraphReader(std::istream& _is,
+ typename SmartParameter<Graph>::Type _graph,
const DefaultSkipper& _skipper = DefaultSkipper())
- : reader(new LemonReader(_is)), own_reader(true),
- graph(_graph), skipper(_skipper),
- nodeset_reader(*reader, graph, std::string(), skipper),
- edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
+ : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper),
+ nodeset_reader(*reader, _graph, std::string(), skipper),
+ edgeset_reader(*reader, _graph, nodeset_reader,
+ std::string(), skipper),
node_reader(*reader, nodeset_reader, std::string()),
edge_reader(*reader, edgeset_reader, std::string()),
attribute_reader(*reader, std::string()) {}
@@ -128,12 +128,14 @@
///
/// Construct a new GraphReader. It reads into the given graph
/// and it use the given reader as the default skipper.
- GraphReader(const std::string& _filename, Graph& _graph,
+ GraphReader(const std::string& _filename,
+ typename SmartParameter<Graph>::Type _graph,
const DefaultSkipper& _skipper = DefaultSkipper())
: reader(new LemonReader(_filename)), own_reader(true),
- graph(_graph), skipper(_skipper),
- nodeset_reader(*reader, graph, std::string(), skipper),
- edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
+ skipper(_skipper),
+ nodeset_reader(*reader, _graph, std::string(), skipper),
+ edgeset_reader(*reader, _graph, nodeset_reader,
+ std::string(), skipper),
node_reader(*reader, nodeset_reader, std::string()),
edge_reader(*reader, edgeset_reader, std::string()),
attribute_reader(*reader, std::string()) {}
@@ -142,12 +144,13 @@
///
/// Construct a new GraphReader. It reads into the given graph
/// and it use the given reader as the default skipper.
- GraphReader(LemonReader& _reader, Graph& _graph,
+ GraphReader(LemonReader& _reader,
+ typename SmartParameter<Graph>::Type _graph,
const DefaultSkipper& _skipper = DefaultSkipper())
- : reader(_reader), own_reader(false),
- graph(_graph), skipper(_skipper),
- nodeset_reader(*reader, graph, std::string(), skipper),
- edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
+ : reader(_reader), own_reader(false), skipper(_skipper),
+ nodeset_reader(*reader, _graph, std::string(), skipper),
+ edgeset_reader(*reader, _graph, nodeset_reader,
+ std::string(), skipper),
node_reader(*reader, nodeset_reader, std::string()),
edge_reader(*reader, edgeset_reader, std::string()),
attribute_reader(*reader, std::string()) {}
@@ -165,7 +168,13 @@
/// Add a new node map reader command for the reader.
template <typename Map>
GraphReader& readNodeMap(std::string name, Map& map) {
- nodeset_reader.readMap(name, map);
+ nodeset_reader.readNodeMap(name, map);
+ return *this;
+ }
+
+ template <typename Map>
+ GraphReader& readNodeMap(std::string name, const Map& map) {
+ nodeset_reader.readNodeMap(name, map);
return *this;
}
@@ -175,7 +184,14 @@
template <typename Reader, typename Map>
GraphReader& readNodeMap(std::string name, Map& map,
const Reader& reader = Reader()) {
- nodeset_reader.readMap(name, map, reader);
+ nodeset_reader.readNodeMap(name, map, reader);
+ return *this;
+ }
+
+ template <typename Reader, typename Map>
+ GraphReader& readNodeMap(std::string name, const Map& map,
+ const Reader& reader = Reader()) {
+ nodeset_reader.readNodeMap(name, map, reader);
return *this;
}
@@ -185,7 +201,7 @@
template <typename Reader>
GraphReader& skipNodeMap(std::string name,
const Reader& reader = Reader()) {
- nodeset_reader.skipMap(name, reader);
+ nodeset_reader.skipNodeMap(name, reader);
return *this;
}
@@ -194,7 +210,13 @@
/// Add a new edge map reader command for the reader.
template <typename Map>
GraphReader& readEdgeMap(std::string name, Map& map) {
- edgeset_reader.readMap(name, map);
+ edgeset_reader.readEdgeMap(name, map);
+ return *this;
+ }
+
+ template <typename Map>
+ GraphReader& readEdgeMap(std::string name, const Map& map) {
+ edgeset_reader.readEdgeMap(name, map);
return *this;
}
@@ -205,7 +227,14 @@
template <typename Reader, typename Map>
GraphReader& readEdgeMap(std::string name, Map& map,
const Reader& reader = Reader()) {
- edgeset_reader.readMap(name, map, reader);
+ edgeset_reader.readEdgeMap(name, map, reader);
+ return *this;
+ }
+
+ template <typename Reader, typename Map>
+ GraphReader& readEdgeMap(std::string name, const Map& map,
+ const Reader& reader = Reader()) {
+ edgeset_reader.readEdgeMap(name, map, reader);
return *this;
}
@@ -213,10 +242,9 @@
///
/// Add a new edge map skipper command for the reader.
template <typename Reader>
- GraphReader& skipEdgeMap(std::string name,
+ GraphReader& skipEdgeMap(std::string name,
const Reader& reader = Reader()) {
-
- edgeset_reader.skipMap(name, reader);
+ edgeset_reader.skipEdgeMap(name, reader);
return *this;
}
@@ -276,8 +304,6 @@
LemonReader* reader;
bool own_reader;
- Graph& graph;
-
DefaultSkipper skipper;
NodeSetReader<Graph, ReaderTraits> nodeset_reader;
@@ -368,6 +394,365 @@
reader.run();
}
+ /// \brief The undir graph reader class.
+ ///
+ /// The given file format may contain several maps and labeled nodes or
+ /// edges.
+ ///
+ /// If you read a graph you need not read all the maps and items just those
+ /// that you need. The interface of the \c GraphReader is very similar to
+ /// the GraphWriter but the reading method does not depend on the order the
+ /// given commands.
+ ///
+ /// The reader object suppose that each not readed value does not contain
+ /// whitespaces, therefore it has some extra possibilities to control how
+ /// it should skip the values when the string representation contains spaces.
+ ///
+ /// \code
+ /// UndirGraphReader<UndirListGraph> reader(std::cin, graph);
+ /// \endcode
+ ///
+ /// The \c readNodeMap() function reads a map from the \c \@nodeset section.
+ /// If there is a map that you do not want to read from the file and there is
+ /// whitespace in the string represenation of the values then you should
+ /// call the \c skipNodeMap() template member function with proper
+ /// parameters.
+ ///
+ /// \code
+ /// reader.readNodeMap("coords", coords);
+ ///
+ /// reader.readNodeMap<QuotedStringReader>("label", labelMap);
+ /// reader.skipNodeMap<QuotedStringReader>("description");
+ ///
+ /// reader.readNodeMap("color", colorMap);
+ /// \endcode
+ ///
+ /// With the \c readUndirEdgeMap() member function you can give an
+ /// undir edge map reading command similar to the NodeMaps.
+ ///
+ /// \code
+ /// reader.readUndirEdgeMap("capacity", capacityMap);
+ /// \endcode
+ ///
+ /// The reading of the directed edge maps is just a syntactical sugar.
+ /// It reads two undirected edgemaps into a directed edge map. The
+ /// undirected edge maps' name should be start with the \c '+' and the
+ /// \c '-' character and the same.
+ ///
+ /// \code
+ /// reader.readEdgeMap("flow", flowMap);
+ /// \endcode
+ ///
+ /// With \c readNode() and \c readUndirEdge() functions you can read
+ /// labeled Nodes and UndirEdges.
+ ///
+ /// \code
+ /// reader.readNode("source", sourceNode);
+ /// reader.readNode("target", targetNode);
+ ///
+ /// reader.readUndirEdge("observed", undirEdge);
+ /// \endcode
+ ///
+ /// With the \c readAttribute() functions you can read an attribute
+ /// in a variable. You can specify the reader for the attribute as
+ /// the nodemaps.
+ ///
+ /// After you give all read commands you must call the \c run() member
+ /// function, which execute all the commands.
+ ///
+ /// \code
+ /// reader.run();
+ /// \endcode
+ ///
+ /// \see GraphReader
+ /// \see DefaultReaderTraits
+ /// \see \ref UndirGraphWriter
+ /// \see \ref graph-io-page
+ ///
+ /// \author Balazs Dezso
+ template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits>
+ class UndirGraphReader {
+ public:
+
+ typedef _Graph Graph;
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::UndirEdge UndirEdge;
+
+ typedef _ReaderTraits ReaderTraits;
+ typedef typename ReaderTraits::Skipper DefaultSkipper;
+
+ /// \brief Construct a new UndirGraphReader.
+ ///
+ /// Construct a new UndirGraphReader. It reads into the given graph
+ /// and it use the given reader as the default skipper.
+ UndirGraphReader(std::istream& _is, Graph& _graph,
+ const DefaultSkipper& _skipper = DefaultSkipper())
+ : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper),
+ nodeset_reader(*reader, _graph, std::string(), skipper),
+ undir_edgeset_reader(*reader, _graph, nodeset_reader,
+ std::string(), skipper),
+ node_reader(*reader, nodeset_reader, std::string()),
+ undir_edge_reader(*reader, undir_edgeset_reader, std::string()),
+ attribute_reader(*reader, std::string()) {}
+
+ /// \brief Construct a new UndirGraphReader.
+ ///
+ /// Construct a new UndirGraphReader. It reads into the given graph
+ /// and it use the given reader as the default skipper.
+ UndirGraphReader(const std::string& _filename, Graph& _graph,
+ const DefaultSkipper& _skipper = DefaultSkipper())
+ : reader(new LemonReader(_filename)), own_reader(true),
+ skipper(_skipper),
+ nodeset_reader(*reader, _graph, std::string(), skipper),
+ undir_edgeset_reader(*reader, _graph, nodeset_reader,
+ std::string(), skipper),
+ node_reader(*reader, nodeset_reader, std::string()),
+ undir_edge_reader(*reader, undir_edgeset_reader, std::string()),
+ attribute_reader(*reader, std::string()) {}
+
+ /// \brief Construct a new UndirGraphReader.
+ ///
+ /// Construct a new UndirGraphReader. It reads into the given graph
+ /// and it use the given reader as the default skipper.
+ UndirGraphReader(LemonReader& _reader, Graph& _graph,
+ const DefaultSkipper& _skipper = DefaultSkipper())
+ : reader(_reader), own_reader(false), skipper(_skipper),
+ nodeset_reader(*reader, _graph, std::string(), skipper),
+ undir_edgeset_reader(*reader, _graph, nodeset_reader,
+ std::string(), skipper),
+ node_reader(*reader, nodeset_reader, std::string()),
+ undir_edge_reader(*reader, undir_edgeset_reader, std::string()),
+ attribute_reader(*reader, std::string()) {}
+
+ /// \brief Destruct the graph reader.
+ ///
+ /// Destruct the graph reader.
+ ~UndirGraphReader() {
+ if (own_reader)
+ delete reader;
+ }
+
+ /// \brief Add a new node map reader command for the reader.
+ ///
+ /// Add a new node map reader command for the reader.
+ template <typename Map>
+ UndirGraphReader& readNodeMap(std::string name, Map& map) {
+ nodeset_reader.readNodeMap(name, map);
+ return *this;
+ }
+
+ template <typename Map>
+ UndirGraphReader& readNodeMap(std::string name, const Map& map) {
+ nodeset_reader.readNodeMap(name, map);
+ return *this;
+ }
+
+ /// \brief Add a new node map reader command for the reader.
+ ///
+ /// Add a new node map reader command for the reader.
+ template <typename Reader, typename Map>
+ UndirGraphReader& readNodeMap(std::string name, Map& map,
+ const Reader& reader = Reader()) {
+ nodeset_reader.readNodeMap(name, map, reader);
+ return *this;
+ }
+
+ template <typename Reader, typename Map>
+ UndirGraphReader& readNodeMap(std::string name, const Map& map,
+ const Reader& reader = Reader()) {
+ nodeset_reader.readNodeMap(name, map, reader);
+ return *this;
+ }
+
+ /// \brief Add a new node map skipper command for the reader.
+ ///
+ /// Add a new node map skipper command for the reader.
+ template <typename Reader>
+ UndirGraphReader& skipNodeMap(std::string name,
+ const Reader& reader = Reader()) {
+ nodeset_reader.skipNodeMap(name, reader);
+ return *this;
+ }
+
+ /// \brief Add a new undirected edge map reader command for the reader.
+ ///
+ /// Add a new undirected edge map reader command for the reader.
+ template <typename Map>
+ UndirGraphReader& readUndirEdgeMap(std::string name, Map& map) {
+ undir_edgeset_reader.readUndirEdgeMap(name, map);
+ return *this;
+ }
+
+ template <typename Map>
+ UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map) {
+ undir_edgeset_reader.readUndirEdgeMap(name, map);
+ return *this;
+ }
+
+
+ /// \brief Add a new undirected edge map reader command for the reader.
+ ///
+ /// Add a new undirected edge map reader command for the reader.
+ template <typename Reader, typename Map>
+ UndirGraphReader& readUndirEdgeMap(std::string name, Map& map,
+ const Reader& reader = Reader()) {
+ undir_edgeset_reader.readUndirEdgeMap(name, map, reader);
+ return *this;
+ }
+
+ template <typename Reader, typename Map>
+ UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map,
+ const Reader& reader = Reader()) {
+ undir_edgeset_reader.readUndirEdgeMap(name, map, reader);
+ return *this;
+ }
+
+ /// \brief Add a new undirected edge map skipper command for the reader.
+ ///
+ /// Add a new undirected edge map skipper command for the reader.
+ template <typename Reader>
+ UndirGraphReader& skipUndirEdgeMap(std::string name,
+ const Reader& reader = Reader()) {
+ undir_edgeset_reader.skipUndirMap(name, reader);
+ return *this;
+ }
+
+
+ /// \brief Add a new edge map reader command for the reader.
+ ///
+ /// Add a new edge map reader command for the reader.
+ template <typename Map>
+ UndirGraphReader& readEdgeMap(std::string name, Map& map) {
+ undir_edgeset_reader.readEdgeMap(name, map);
+ return *this;
+ }
+
+ template <typename Map>
+ UndirGraphReader& readEdgeMap(std::string name, const Map& map) {
+ undir_edgeset_reader.readEdgeMap(name, map);
+ return *this;
+ }
+
+
+ /// \brief Add a new edge map reader command for the reader.
+ ///
+ /// Add a new edge map reader command for the reader.
+ template <typename Reader, typename Map>
+ UndirGraphReader& readEdgeMap(std::string name, Map& map,
+ const Reader& reader = Reader()) {
+ undir_edgeset_reader.readEdgeMap(name, map, reader);
+ return *this;
+ }
+
+ template <typename Reader, typename Map>
+ UndirGraphReader& readEdgeMap(std::string name, const Map& map,
+ const Reader& reader = Reader()) {
+ undir_edgeset_reader.readEdgeMap(name, map, reader);
+ return *this;
+ }
+
+ /// \brief Add a new edge map skipper command for the reader.
+ ///
+ /// Add a new edge map skipper command for the reader.
+ template <typename Reader>
+ UndirGraphReader& skipEdgeMap(std::string name,
+ const Reader& reader = Reader()) {
+ undir_edgeset_reader.skipEdgeMap(name, reader);
+ return *this;
+ }
+
+ /// \brief Add a new labeled node reader for the reader.
+ ///
+ /// Add a new labeled node reader for the reader.
+ UndirGraphReader& readNode(std::string name, Node& node) {
+ node_reader.readNode(name, node);
+ return *this;
+ }
+
+ /// \brief Add a new labeled edge reader for the reader.
+ ///
+ /// Add a new labeled edge reader for the reader.
+ UndirGraphReader& readUndirEdge(std::string name, UndirEdge& edge) {
+ undir_edge_reader.readUndirEdge(name, edge);
+ }
+
+ /// \brief Add a new attribute reader command.
+ ///
+ /// Add a new attribute reader command.
+ template <typename Value>
+ UndirGraphReader& readAttribute(std::string name, Value& value) {
+ attribute_reader.readAttribute(name, value);
+ return *this;
+ }
+
+ /// \brief Add a new attribute reader command.
+ ///
+ /// Add a new attribute reader command.
+ template <typename Reader, typename Value>
+ UndirGraphReader& readAttribute(std::string name, Value& value,
+ const Reader& reader) {
+ attribute_reader.readAttribute<Reader>(name, value, reader);
+ return *this;
+ }
+
+ /// \brief Conversion operator to LemonReader.
+ ///
+ /// Conversion operator to LemonReader. It make possible
+ /// to access the encapsulated \e LemonReader, this way
+ /// you can attach to this reader new instances of
+ /// \e LemonReader::SectionReader.
+ operator LemonReader&() {
+ return *reader;
+ }
+
+ /// \brief Executes the reader commands.
+ ///
+ /// Executes the reader commands.
+ void run() {
+ reader->run();
+ }
+
+ private:
+
+ LemonReader* reader;
+ bool own_reader;
+
+ DefaultSkipper skipper;
+
+ NodeSetReader<Graph, ReaderTraits> nodeset_reader;
+ UndirEdgeSetReader<Graph, ReaderTraits> undir_edgeset_reader;
+
+ NodeReader<Graph> node_reader;
+ UndirEdgeReader<Graph> undir_edge_reader;
+
+ AttributeReader<ReaderTraits> attribute_reader;
+ };
+
+ /// \brief Read an undir graph from the input.
+ ///
+ /// Read an undir graph from the input.
+ /// \param is The input stream.
+ /// \param g The graph.
+ /// \param capacity The capacity map.
+ template<typename Graph, typename CapacityMap>
+ void readUndirGraph(std::istream& is, Graph &g, CapacityMap& capacity) {
+ UndirGraphReader<Graph> reader(is, g);
+ reader.readUndirEdgeMap("capacity", capacity);
+ reader.run();
+ }
+
+ /// \brief Read an undir graph from the input.
+ ///
+ /// Read an undir graph from the input.
+ /// \param is The input stream.
+ /// \param g The graph.
+ template<typename Graph>
+ void readUndirGraph(std::istream& is, Graph &g) {
+ UndirGraphReader<Graph> reader(is, g);
+ reader.run();
+ }
+
/// @}
}
Modified: hugo/trunk/src/lemon/graph_writer.h
==============================================================================
--- hugo/trunk/src/lemon/graph_writer.h (original)
+++ hugo/trunk/src/lemon/graph_writer.h Sat May 14 19:39:37 2005
@@ -52,8 +52,7 @@
/// IdMap<ListGraph, Node> nodeIdMap;
/// writer.writeNodeMap("id", nodeIdMap);
///
- /// writer.writeNodeMap("x-coord", xCoordMap);
- /// writer.writeNodeMap("y-coord", yCoordMap);
+ /// writer.writeNodeMap("coords", coords);
/// writer.writeNodeMap("color", colorMap);
/// \endcode
///
@@ -91,7 +90,7 @@
/// \see QuotedStringWriter
/// \see IdMap
/// \see DescriptorMap
- /// \see \ref GraphWriter
+ /// \see \ref GraphReader
/// \see \ref graph-io-page
/// \author Balazs Dezso
template <typename _Graph, typename _WriterTraits = DefaultWriterTraits>
@@ -110,9 +109,8 @@
/// to the given stream.
GraphWriter(std::ostream& _os, const Graph& _graph)
: writer(new LemonWriter(_os)), own_writer(true),
- graph(_graph),
- nodeset_writer(*writer, graph, std::string()),
- edgeset_writer(*writer, graph, nodeset_writer, std::string()),
+ nodeset_writer(*writer, _graph, std::string()),
+ edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
node_writer(*writer, nodeset_writer, std::string()),
edge_writer(*writer, edgeset_writer, std::string()),
attribute_writer(*writer, std::string()) {}
@@ -123,9 +121,8 @@
/// to the given file.
GraphWriter(const std::string& _filename, const Graph& _graph)
: writer(new LemonWriter(_filename)), own_writer(true),
- graph(_graph),
- nodeset_writer(*writer, graph, std::string()),
- edgeset_writer(*writer, graph, nodeset_writer, std::string()),
+ nodeset_writer(*writer, _graph, std::string()),
+ edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
node_writer(*writer, nodeset_writer, std::string()),
edge_writer(*writer, edgeset_writer, std::string()),
attribute_writer(*writer, std::string()) {}
@@ -136,9 +133,8 @@
/// to given LemonReader.
GraphWriter(LemonWriter& _writer, const Graph& _graph)
: writer(_writer), own_writer(false),
- graph(_graph),
- nodeset_writer(*writer, graph, std::string()),
- edgeset_writer(*writer, graph, nodeset_writer, std::string()),
+ nodeset_writer(*writer, _graph, std::string()),
+ edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
node_writer(*writer, nodeset_writer, std::string()),
edge_writer(*writer, edgeset_writer, std::string()),
attribute_writer(*writer, std::string()) {}
@@ -156,7 +152,7 @@
/// Add a new node map writer command for the writer.
template <typename Map>
GraphWriter& writeNodeMap(std::string name, const Map& map) {
- nodeset_writer.writeMap(name, map);
+ nodeset_writer.writeNodeMap(name, map);
return *this;
}
@@ -165,8 +161,8 @@
/// Add a new node map writer command for the writer.
template <typename Writer, typename Map>
GraphWriter& writeNodeMap(std::string name, const Map& map,
- const Writer& writer = Writer()) {
- nodeset_writer.writeMap(name, map, writer);
+ const Writer& writer = Writer()) {
+ nodeset_writer.writeNodeMap(name, map, writer);
return *this;
}
@@ -176,7 +172,7 @@
/// Add a new edge map writer command for the writer.
template <typename Map>
GraphWriter& writeEdgeMap(std::string name, const Map& map) {
- edgeset_writer.writeMap(name, map);
+ edgeset_writer.writeEdgeMap(name, map);
return *this;
}
@@ -186,8 +182,8 @@
/// Add a new edge map writer command for the writer.
template <typename Writer, typename Map>
GraphWriter& writeEdgeMap(std::string name, const Map& map,
- const Writer& writer = Writer()) {
- edgeset_writer.writeMap(name, map, writer);
+ const Writer& writer = Writer()) {
+ edgeset_writer.writeEdgeMap(name, map, writer);
return *this;
}
@@ -247,8 +243,6 @@
LemonWriter* writer;
bool own_writer;
- const Graph& graph;
-
NodeSetWriter<Graph, WriterTraits> nodeset_writer;
EdgeSetWriter<Graph, WriterTraits> edgeset_writer;
@@ -360,6 +354,279 @@
writer.run();
}
+ /// \brief The undirected graph writer class.
+ ///
+ /// The \c UndirGraphWriter class provides the undir graph output. To write
+ /// a graph you should first give writing commands for the writer. You can
+ /// declare write command as \c NodeMap, \c EdgeMap or \c UndirEdgeMap
+ /// writing and labeled Node, Edge or UndirEdge writing.
+ ///
+ /// \code
+ /// UndirGraphWriter<UndirListGraph> writer(std::cout, graph);
+ /// \endcode
+ ///
+ /// The \c writeNodeMap() function declares a \c NodeMap writing
+ /// command in the \c UndirGraphWriter. You should give as parameter
+ /// the name of the map and the map object. The NodeMap writing
+ /// command with name "id" should write a unique map because it
+ /// is regarded as ID map.
+ ///
+ /// \code
+ /// IdMap<UndirListGraph, Node> nodeIdMap;
+ /// writer.writeNodeMap("id", nodeIdMap);
+ ///
+ /// writer.writeNodeMap("coords", coords);
+ /// writer.writeNodeMap("color", colorMap);
+ /// \endcode
+ ///
+ /// With the \c writeUndirEdgeMap() member function you can give an
+ /// undirected edge map writing command similar to the NodeMaps.
+ ///
+ /// \code
+ /// DescriptorMap<ListGraph, Edge, ListGraph::EdgeMap<int> >
+ /// edgeDescMap(graph);
+ /// writer.writeUndirEdgeMap("descriptor", edgeDescMap);
+ ///
+ /// writer.writeUndirEdgeMap("weight", weightMap);
+ /// writer.writeUndirEdgeMap("label", labelMap);
+ /// \endcode
+ ///
+ /// The EdgeMap handling is just a syntactical sugar. It writes
+ /// two undirected edge map with '+' and '-' prefix in the name.
+ ///
+ /// \code
+ /// writer.writeEdgeMap("capacity", capacityMap);
+ /// \endcode
+ ///
+ ///
+ /// With \c writeNode() and \c writeUndirEdge() functions you can
+ /// point out nodes and undirected edges in the graph. By example, you can
+ /// write out the source and target of the graph.
+ ///
+ /// \code
+ /// writer.writeNode("source", sourceNode);
+ /// writer.writeNode("target", targetNode);
+ ///
+ /// writer.writeUndirEdge("observed", undirEdge);
+ /// \endcode
+ ///
+ /// After you give all write commands you must call the \c run() member
+ /// function, which execute all the writer commands.
+ ///
+ /// \code
+ /// writer.run();
+ /// \endcode
+ ///
+ /// \see DefaultWriterTraits
+ /// \see QuotedStringWriter
+ /// \see IdMap
+ /// \see DescriptorMap
+ /// \see \ref GraphWriter
+ /// \see \ref graph-io-page
+ /// \author Balazs Dezso
+ template <typename _Graph, typename _WriterTraits = DefaultWriterTraits>
+ class UndirGraphWriter {
+ public:
+
+ typedef _Graph Graph;
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::UndirEdge UndirEdge;
+
+ typedef _WriterTraits WriterTraits;
+
+ /// \brief Construct a new UndirGraphWriter.
+ ///
+ /// Construct a new UndirGraphWriter. It writes the given graph
+ /// to the given stream.
+ UndirGraphWriter(std::ostream& _os, const Graph& _graph)
+ : writer(new LemonWriter(_os)), own_writer(true),
+ nodeset_writer(*writer, _graph, std::string()),
+ undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
+ node_writer(*writer, nodeset_writer, std::string()),
+ undir_edge_writer(*writer, undir_edgeset_writer, std::string()),
+ attribute_writer(*writer, std::string()) {}
+
+ /// \brief Construct a new UndirGraphWriter.
+ ///
+ /// Construct a new UndirGraphWriter. It writes into the given graph
+ /// to the given file.
+ UndirGraphWriter(const std::string& _filename, const Graph& _graph)
+ : writer(new LemonWriter(_filename)), own_writer(true),
+ nodeset_writer(*writer, _graph, std::string()),
+ undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
+ node_writer(*writer, nodeset_writer, std::string()),
+ undir_edge_writer(*writer, undir_edgeset_writer, std::string()),
+ attribute_writer(*writer, std::string()) {}
+
+ /// \brief Construct a new UndirGraphWriter.
+ ///
+ /// Construct a new UndirGraphWriter. It writes into the given graph
+ /// to given LemonReader.
+ UndirGraphWriter(LemonWriter& _writer, const Graph& _graph)
+ : writer(_writer), own_writer(false),
+ nodeset_writer(*writer, _graph, std::string()),
+ undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
+ node_writer(*writer, nodeset_writer, std::string()),
+ undir_edge_writer(*writer, undir_edgeset_writer, std::string()),
+ attribute_writer(*writer, std::string()) {}
+
+ /// \brief Destruct the graph writer.
+ ///
+ /// Destruct the graph writer.
+ ~UndirGraphWriter() {
+ if (own_writer)
+ delete writer;
+ }
+
+ /// \brief Add a new node map writer command for the writer.
+ ///
+ /// Add a new node map writer command for the writer.
+ template <typename Map>
+ UndirGraphWriter& writeNodeMap(std::string name, const Map& map) {
+ nodeset_writer.writeNodeMap(name, map);
+ return *this;
+ }
+
+ /// \brief Add a new node map writer command for the writer.
+ ///
+ /// Add a new node map writer command for the writer.
+ template <typename Writer, typename Map>
+ UndirGraphWriter& writeNodeMap(std::string name, const Map& map,
+ const Writer& writer = Writer()) {
+ nodeset_writer.writeNodeMap(name, map, writer);
+ return *this;
+ }
+
+ /// \brief Add a new edge map writer command for the writer.
+ ///
+ /// Add a new edge map writer command for the writer.
+ template <typename Map>
+ UndirGraphWriter& writeEdgeMap(std::string name, const Map& map) {
+ undir_edgeset_writer.writeEdgeMap(name, map);
+ return *this;
+ }
+
+ /// \brief Add a new edge map writer command for the writer.
+ ///
+ /// Add a new edge map writer command for the writer.
+ template <typename Writer, typename Map>
+ UndirGraphWriter& writeEdgeMap(std::string name, const Map& map,
+ const Writer& writer = Writer()) {
+ undir_edgeset_writer.writeEdgeMap(name, map, writer);
+ return *this;
+ }
+
+ /// \brief Add a new undirected edge map writer command for the writer.
+ ///
+ /// Add a new undirected edge map writer command for the writer.
+ template <typename Map>
+ UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map) {
+ undir_edgeset_writer.writeUndirEdgeMap(name, map);
+ return *this;
+ }
+
+ /// \brief Add a new undirected edge map writer command for the writer.
+ ///
+ /// Add a new edge undirected map writer command for the writer.
+ template <typename Writer, typename Map>
+ UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map,
+ const Writer& writer = Writer()) {
+ undir_edgeset_writer.writeUndirEdgeMap(name, map, writer);
+ return *this;
+ }
+
+ /// \brief Add a new labeled node writer for the writer.
+ ///
+ /// Add a new labeled node writer for the writer.
+ UndirGraphWriter& writeNode(std::string name, const Node& node) {
+ node_writer.writeNode(name, node);
+ return *this;
+ }
+
+ /// \brief Add a new labeled edge writer for the writer.
+ ///
+ /// Add a new labeled edge writer for the writer.
+ UndirGraphWriter& writeUndirEdge(std::string name, const UndirEdge& edge) {
+ undir_edge_writer.writeUndirEdge(name, edge);
+ }
+
+ /// \brief Add a new attribute writer command.
+ ///
+ /// Add a new attribute writer command.
+ template <typename Value>
+ UndirGraphWriter& writeAttribute(std::string name, const Value& value) {
+ attribute_writer.writeAttribute(name, value);
+ return *this;
+ }
+
+ /// \brief Add a new attribute writer command.
+ ///
+ /// Add a new attribute writer command.
+ template <typename Writer, typename Value>
+ UndirGraphWriter& writeAttribute(std::string name, const Value& value,
+ const Writer& writer) {
+ attribute_writer.writeAttribute<Writer>(name, value, writer);
+ return *this;
+ }
+
+ /// \brief Conversion operator to LemonWriter.
+ ///
+ /// Conversion operator to LemonWriter. It make possible
+ /// to access the encapsulated \e LemonWriter, this way
+ /// you can attach to this writer new instances of
+ /// \e LemonWriter::SectionWriter.
+ operator LemonWriter&() {
+ return *writer;
+ }
+
+ /// \brief Executes the writer commands.
+ ///
+ /// Executes the writer commands.
+ void run() {
+ writer->run();
+ }
+
+ private:
+
+ LemonWriter* writer;
+ bool own_writer;
+
+ NodeSetWriter<Graph, WriterTraits> nodeset_writer;
+ UndirEdgeSetWriter<Graph, WriterTraits> undir_edgeset_writer;
+
+ NodeWriter<Graph> node_writer;
+ UndirEdgeWriter<Graph> undir_edge_writer;
+
+ AttributeWriter<WriterTraits> attribute_writer;
+ };
+
+
+ /// \brief Write an undirected graph to the output.
+ ///
+ /// Write an undirected graph to the output.
+ /// \param os The output stream.
+ /// \param g The graph.
+ /// \param capacity The capacity undirected map.
+ template<typename Graph, typename CapacityMap>
+ void writeUndirGraph(std::ostream& os, const Graph &g,
+ const CapacityMap& capacity) {
+ UndirGraphWriter<Graph> writer(os, g);
+ writer.writeUndirEdgeMap("capacity", capacity);
+ writer.run();
+ }
+
+ /// \brief Write an undirected graph to the output.
+ ///
+ /// Write an undirected graph to the output.
+ /// \param os The output stream.
+ /// \param g The graph.
+ template<typename Graph>
+ void writeUndirGraph(std::ostream& os, const Graph &g) {
+ UndirGraphWriter<Graph> writer(os, g);
+ writer.run();
+ }
+
/// @}
}
Modified: hugo/trunk/src/lemon/lemon_reader.h
==============================================================================
--- hugo/trunk/src/lemon/lemon_reader.h (original)
+++ hugo/trunk/src/lemon/lemon_reader.h Sat May 14 19:39:37 2005
@@ -18,9 +18,11 @@
///\file
///\brief Lemon Format reader.
+
#ifndef LEMON_LEMON_READER_H
#define LEMON_LEMON_READER_H
+
#include <iostream>
#include <fstream>
#include <string>
@@ -30,11 +32,61 @@
#include <memory>
#include <lemon/error.h>
+#include <lemon/graph_utils.h>
+#include <lemon/utility.h>
#include <lemon/bits/item_reader.h>
namespace lemon {
+ namespace _reader_bits {
+
+ template <typename T>
+ bool operator<(T, T) {
+ throw DataFormatError("Id is not comparable");
+ }
+
+ template <typename T>
+ struct Less {
+ bool operator()(const T& p, const T& q) const {
+ return p < q;
+ }
+ };
+
+ template <typename M1, typename M2>
+ class WriteComposeMap {
+ public:
+ typedef True NeedCopy;
+
+ typedef typename M2::Key Key;
+ typedef typename M1::Value Value;
+
+ WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2)
+ : m1(_m1), m2(_m2) {}
+
+ void set(const Key& key, const Value& value) {
+ m1.set(m2[key], value);
+ }
+
+ private:
+
+ typename SmartReference<M1>::Type m1;
+ typename SmartConstReference<M2>::Type m2;
+
+ };
+
+ template <typename M1, typename M2>
+ WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) {
+ return WriteComposeMap<M1, M2>(m1, m2);
+ }
+
+ template <typename M1, typename M2>
+ WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) {
+ return WriteComposeMap<M1, M2>(m1, m2);
+ }
+
+ }
+
/// \ingroup io_group
/// \brief Lemon Format reader class.
///
@@ -338,8 +390,6 @@
virtual InverterBase<_Item>* getInverter() {
return this;
}
-
-
};
template <typename _Item, typename _Map, typename _Reader>
@@ -349,13 +399,15 @@
typedef _Reader Reader;
typedef typename Reader::Value Value;
typedef _Map Map;
- typedef std::map<Value, Item> Inverse;
+ typedef std::map<Value, Item,
+ typename _reader_bits::template Less<Value> > Inverse;
- Map& map;
+ typename SmartReference<Map>::Type map;
Reader reader;
Inverse inverse;
- MapReaderInverter(Map& _map, const Reader& _reader)
+ MapReaderInverter(typename SmartParameter<Map>::Type _map,
+ const Reader& _reader)
: map(_map), reader(_reader) {}
virtual ~MapReaderInverter() {}
@@ -382,7 +434,6 @@
throw DataFormatError("Invalid ID error");
}
}
-
};
template <typename _Item, typename _Reader>
@@ -391,7 +442,8 @@
typedef _Item Item;
typedef _Reader Reader;
typedef typename Reader::Value Value;
- typedef std::map<Value, Item> Inverse;
+ typedef std::map<Value, Item,
+ typename _reader_bits::template Less<Value> > Inverse;
Reader reader;
@@ -426,8 +478,6 @@
Inverse inverse;
};
- // Readers
-
template <typename _Item>
class ReaderBase {
public:
@@ -447,10 +497,11 @@
typedef typename Reader::Value Value;
typedef _Item Item;
- Map& map;
+ typename SmartReference<Map>::Type map;
Reader reader;
- MapReader(Map& _map, const Reader& _reader)
+ MapReader(typename SmartParameter<Map>::Type _map,
+ const Reader& _reader)
: map(_map), reader(_reader) {}
virtual ~MapReader() {}
@@ -569,7 +620,8 @@
/// attach it into the given LemonReader. The nodeset reader will
/// add the readed nodes to the given Graph. The reader will read
/// the section when the \c section_id and the \c _id are the same.
- NodeSetReader(LemonReader& _reader, Graph& _graph,
+ NodeSetReader(LemonReader& _reader,
+ typename SmartParameter<Graph>::Type _graph,
const std::string& _id = std::string(),
const DefaultSkipper& _skipper = DefaultSkipper())
: Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {}
@@ -595,17 +647,43 @@
///
/// Add a new node map reader command for the reader.
template <typename Map>
- NodeSetReader& readMap(std::string name, Map& map) {
- return readMap<typename Traits::
- template Reader<typename Map::Value>, Map>(name, map);
+ NodeSetReader& readNodeMap(std::string name, Map& map) {
+ return _readMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename SmartParameter<Map>::Type>(name, map);
+ }
+
+ template <typename Map>
+ NodeSetReader& readNodeMap(std::string name, const Map& map) {
+ return _readMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename SmartParameter<Map>::Type>(name, map);
}
/// \brief Add a new node map reader command for the reader.
///
/// Add a new node map reader command for the reader.
template <typename Reader, typename Map>
- NodeSetReader& readMap(std::string name, Map& map,
- const Reader& reader = Reader()) {
+ NodeSetReader& readNodeMap(std::string name, Map& map,
+ const Reader& reader = Reader()) {
+ return _readMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename SmartParameter<Map>::Type>(name, map, reader);
+ }
+
+ template <typename Reader, typename Map>
+ NodeSetReader& readNodeMap(std::string name, const Map& map,
+ const Reader& reader = Reader()) {
+ return _readMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename SmartParameter<Map>::Type>(name, map, reader);
+ }
+
+ private:
+
+ template <typename Reader, typename Map, typename MapParameter>
+ NodeSetReader& _readMap(std::string name, MapParameter map,
+ const Reader& reader = Reader()) {
if (readers.find(name) != readers.end()) {
ErrorMessage msg;
msg << "Multiple read rule for node map: " << name;
@@ -616,11 +694,13 @@
return *this;
}
+ public:
+
/// \brief Add a new node map skipper command for the reader.
///
/// Add a new node map skipper command for the reader.
template <typename Reader>
- NodeSetReader& skipMap(std::string name,
+ NodeSetReader& skipNodeMap(std::string name,
const Reader& reader = Reader()) {
if (readers.find(name) != readers.end()) {
ErrorMessage msg;
@@ -636,7 +716,7 @@
/// \brief Gives back true when the SectionReader can process
/// the section with the given header line.
///
- /// It gives back true when the header line starts with \c @nodeset,
+ /// It gives back true when the header line starts with \c \@nodeset,
/// and the header line's id and the nodeset's id are the same.
virtual bool header(const std::string& line) {
std::istringstream ls(line);
@@ -690,7 +770,7 @@
///
/// It reads an id from the stream and gives back which node belongs to
/// it. It is possible only if there was read an "id" named map.
- typename Graph::Node readId(std::istream& is) const {
+ Item readId(std::istream& is) const {
return inverter->read(is);
}
@@ -699,7 +779,7 @@
typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
MapReaders readers;
- Graph& graph;
+ typename SmartReference<Graph>::Type graph;
std::string id;
SkipReader<Item, DefaultSkipper> skipper;
@@ -714,8 +794,9 @@
/// \c edgeset_id may be empty.
///
/// The first line of the section contains the names of the maps separated
- /// with white spaces. Each next lines describes a node in the nodeset. The
- /// line contains the two nodes' id and the mapped values for each map.
+ /// with white spaces. Each next lines describes an edge in the edgeset. The
+ /// line contains the source and the target nodes' id and the mapped
+ /// values for each map.
///
/// If the edgeset contains an \c "id" named map then it will be regarded
/// as id map. This map should contain only unique values and when the
@@ -746,7 +827,8 @@
/// The reader will read the section only if the \c _id and the
/// \c edgset_id are the same.
template <typename NodeIdReader>
- EdgeSetReader(LemonReader& _reader, Graph& _graph,
+ EdgeSetReader(LemonReader& _reader,
+ typename SmartParameter<Graph>::Type _graph,
const NodeIdReader& _nodeIdReader,
const std::string& _id = std::string(),
const DefaultSkipper& _skipper = DefaultSkipper())
@@ -774,17 +856,43 @@
///
/// Add a new edge map reader command for the reader.
template <typename Map>
- EdgeSetReader& readMap(std::string name, Map& map) {
- return readMap<typename Traits::
- template Reader<typename Map::Value>, Map>(name, map);
+ EdgeSetReader& readEdgeMap(std::string name, Map& map) {
+ return _readMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename SmartParameter<Map>::Type>(name, map);
+ }
+
+ template <typename Map>
+ EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
+ return _readMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename SmartParameter<Map>::Type>(name, map);
}
/// \brief Add a new edge map reader command for the reader.
///
/// Add a new edge map reader command for the reader.
template <typename Reader, typename Map>
- EdgeSetReader& readMap(std::string name, Map& map,
- const Reader& reader = Reader()) {
+ EdgeSetReader& readEdgeMap(std::string name, Map& map,
+ const Reader& reader = Reader()) {
+ return _readMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename SmartParameter<Map>::Type>(name, map, reader);
+ }
+
+ template <typename Reader, typename Map>
+ EdgeSetReader& readEdgeMap(std::string name, const Map& map,
+ const Reader& reader = Reader()) {
+ return _readMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename SmartParameter<Map>::Type>(name, map, reader);
+ }
+
+ private:
+
+ template <typename Reader, typename Map, typename MapParameter>
+ EdgeSetReader& _readMap(std::string name, MapParameter map,
+ const Reader& reader = Reader()) {
if (readers.find(name) != readers.end()) {
ErrorMessage msg;
msg << "Multiple read rule for edge map: " << name;
@@ -795,15 +903,17 @@
return *this;
}
+ public:
+
/// \brief Add a new edge map skipper command for the reader.
///
/// Add a new edge map skipper command for the reader.
template <typename Reader>
- EdgeSetReader& skipMap(std::string name,
- const Reader& reader = Reader()) {
+ EdgeSetReader& skipEdgeMap(std::string name,
+ const Reader& reader = Reader()) {
if (readers.find(name) != readers.end()) {
ErrorMessage msg;
- msg << "Multiple read rule for node map: " << name;
+ msg << "Multiple read rule for edge map: " << name;
throw IOParameterError(msg.message());
}
readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
@@ -815,7 +925,7 @@
/// \brief Gives back true when the SectionReader can process
/// the section with the given header line.
///
- /// It gives back true when the header line starts with \c @edgeset,
+ /// It gives back true when the header line starts with \c \@edgeset,
/// and the header line's id and the edgeset's id are the same.
virtual bool header(const std::string& line) {
std::istringstream ls(line);
@@ -871,7 +981,7 @@
///
/// It reads an id from the stream and gives back which edge belongs to
/// it. It is possible only if there was read an "id" named map.
- typename Graph::Edge readId(std::istream& is) const {
+ Item readId(std::istream& is) const {
return inverter->read(is);
}
@@ -880,7 +990,281 @@
typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
MapReaders readers;
- Graph& graph;
+ typename SmartReference<Graph>::Type graph;
+ std::string id;
+ SkipReader<Item, DefaultSkipper> skipper;
+
+ std::auto_ptr<InverterBase<Item> > inverter;
+ std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
+ };
+
+ /// \ingroup io_group
+ /// \brief SectionReader for reading a undirected graph's edgeset.
+ ///
+ /// The lemon format can store multiple undirected edgesets with several
+ /// maps. The undirected edgeset section's header line is \c \@undiredgeset
+ /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
+ ///
+ /// The first line of the section contains the names of the maps separated
+ /// with white spaces. Each next lines describes an edge in the edgeset. The
+ /// line contains the connected nodes' id and the mapped values for each map.
+ ///
+ /// The section can handle the directed as a syntactical sugar. Two
+ /// undirected edge map describes one directed edge map. This two maps
+ /// are the forward map and the backward map and the names of this map
+ /// is near the same just with a prefix \c '+' or \c '-' character
+ /// difference.
+ ///
+ /// If the edgeset contains an \c "id" named map then it will be regarded
+ /// as id map. This map should contain only unique values and when the
+ /// \c readId() member will read a value from the given stream it will
+ /// give back that undiricted edge which is mapped to this value.
+ ///
+ /// The undirected edgeset reader needs a node id reader to identify which
+ /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
+ /// it will be able to resolve the nodes by ids.
+ ///
+ /// \relates LemonReader
+ template <typename _Graph, typename _Traits = DefaultReaderTraits>
+ class UndirEdgeSetReader : public CommonSectionReaderBase {
+ typedef CommonSectionReaderBase Parent;
+ public:
+
+ typedef _Graph Graph;
+ typedef _Traits Traits;
+ typedef typename Graph::UndirEdge Item;
+ typedef typename Traits::Skipper DefaultSkipper;
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
+ /// and attach it into the given LemonReader. The undirected edgeset
+ /// reader will add the readed undirected edges to the given Graph. It
+ /// will use the given node id reader to read the source and target
+ /// nodes of the edges. The reader will read the section only if the
+ /// \c _id and the \c undiredgset_id are the same.
+ template <typename NodeIdReader>
+ UndirEdgeSetReader(LemonReader& _reader,
+ typename SmartParameter<Graph>::Type _graph,
+ const NodeIdReader& _nodeIdReader,
+ const std::string& _id = std::string(),
+ const DefaultSkipper& _skipper = DefaultSkipper())
+ : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
+ nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
+ (_nodeIdReader)) {}
+
+ /// \brief Destructor.
+ ///
+ /// Destructor for UndirEdgeSetReader.
+ virtual ~UndirEdgeSetReader() {
+ for (typename MapReaders::iterator it = readers.begin();
+ it != readers.end(); ++it) {
+ delete it->second;
+ }
+ }
+
+ private:
+ UndirEdgeSetReader(const UndirEdgeSetReader&);
+ void operator=(const UndirEdgeSetReader&);
+
+ public:
+
+ /// \brief Add a new undirected edge map reader command for the reader.
+ ///
+ /// Add a new edge undirected map reader command for the reader.
+ template <typename Map>
+ UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
+ return _readMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename SmartParameter<Map>::Type>(name, map);
+ }
+
+ template <typename Map>
+ UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
+ return _readMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename SmartParameter<Map>::Type>(name, map);
+ }
+
+ /// \brief Add a new undirected edge map reader command for the reader.
+ ///
+ /// Add a new edge undirected map reader command for the reader.
+ template <typename Reader, typename Map>
+ UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
+ const Reader& reader = Reader()) {
+ return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
+ (name, map, reader);
+ }
+
+ template <typename Reader, typename Map>
+ UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
+ const Reader& reader = Reader()) {
+ return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
+ (name, map, reader);
+ }
+
+ private:
+
+ template <typename Reader, typename Map, typename MapParameter>
+ UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
+ const Reader& reader = Reader()) {
+ if (readers.find(name) != readers.end()) {
+ ErrorMessage msg;
+ msg << "Multiple read rule for edge map: " << name;
+ throw IOParameterError(msg.message());
+ }
+ readers.insert(
+ make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
+ return *this;
+ }
+
+ public:
+
+ /// \brief Add a new undirected edge map skipper command for the reader.
+ ///
+ /// Add a new undirected edge map skipper command for the reader.
+ template <typename Reader>
+ UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
+ const Reader& reader = Reader()) {
+ if (readers.find(name) != readers.end()) {
+ ErrorMessage msg;
+ msg << "Multiple read rule for node map: " << name;
+ throw IOParameterError(msg.message());
+ }
+ readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
+ return *this;
+ }
+
+ /// \brief Add a new directed edge map reader command for the reader.
+ ///
+ /// Add a new directed edge map reader command for the reader.
+ template <typename Map>
+ UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
+ return _readDirMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename SmartParameter<Map>::Type>(name, map);
+ }
+
+ template <typename Map>
+ UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
+ return _readDirMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename SmartParameter<Map>::Type>(name, map);
+ }
+
+ /// \brief Add a new directed edge map reader command for the reader.
+ ///
+ /// Add a new directed edge map reader command for the reader.
+ template <typename Reader, typename Map>
+ UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
+ const Reader& reader = Reader()) {
+ return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
+ (name, map, reader);
+ }
+
+ template <typename Reader, typename Map>
+ UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
+ const Reader& reader = Reader()) {
+ return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
+ (name, map, reader);
+ }
+
+ private:
+
+ template <typename Reader, typename Map, typename MapParameter>
+ UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
+ const Reader& reader = Reader()) {
+ readMap("+" + name,
+ _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
+ readMap("-" + name,
+ _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
+ return *this;
+ }
+
+ public:
+
+ /// \brief Add a new directed edge map skipper command for the reader.
+ ///
+ /// Add a new directed edge map skipper command for the reader.
+ template <typename Reader>
+ UndirEdgeSetReader& skipEdgeMap(std::string name,
+ const Reader& reader = Reader()) {
+ skipMap("+" + name, reader);
+ skipMap("-" + name, reader);
+ return *this;
+ }
+
+ protected:
+
+ /// \brief Gives back true when the SectionReader can process
+ /// the section with the given header line.
+ ///
+ /// It gives back true when the header line starts with \c \@undiredgeset,
+ /// and the header line's id and the edgeset's id are the same.
+ virtual bool header(const std::string& line) {
+ std::istringstream ls(line);
+ std::string command;
+ std::string name;
+ ls >> command >> name;
+ return command == "@undiredgeset" && name == id;
+ }
+
+ /// \brief Reader function of the section.
+ ///
+ /// It reads the content of the section.
+ virtual void read(std::istream& is) {
+ std::vector<ReaderBase<Item>* > index;
+ std::string line;
+
+ getline(is, line);
+ std::istringstream ls(line);
+ while (ls >> id) {
+ typename MapReaders::iterator it = readers.find(id);
+ if (it != readers.end()) {
+ index.push_back(it->second);
+ } else {
+ index.push_back(&skipper);
+ }
+ if (id == "id" && inverter.get() == 0) {
+ inverter.reset(index.back()->getInverter());
+ index.back() = inverter.get();
+ }
+ }
+ while (getline(is, line)) {
+ std::istringstream ls(line);
+ typename Graph::Node from = nodeIdReader->read(ls);
+ typename Graph::Node to = nodeIdReader->read(ls);
+ typename Graph::UndirEdge edge = graph.addEdge(from, to);
+ for (int i = 0; i < (int)index.size(); ++i) {
+ index[i]->read(ls, edge);
+ }
+ }
+ }
+
+ public:
+
+ /// \brief Returns true if the edgeset can give back the edge by its id.
+ ///
+ /// Returns true if the edgeset can give back the undirected edge by its
+ /// id. It is possible only if an "id" named map was read.
+ bool isIdReader() const {
+ return inverter.get() != 0;
+ }
+
+ /// \brief Gives back the undirected edge by its id.
+ ///
+ /// It reads an id from the stream and gives back which undirected edge
+ /// belongs to it. It is possible only if there was read an "id" named map.
+ Item readId(std::istream& is) const {
+ return inverter->read(is);
+ }
+
+ private:
+
+ typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
+ MapReaders readers;
+
+ typename SmartReference<Graph>::Type graph;
std::string id;
SkipReader<Item, DefaultSkipper> skipper;
@@ -945,7 +1329,7 @@
/// \brief Gives back true when the SectionReader can process
/// the section with the given header line.
///
- /// It gives back true when the header line start with \c @nodes,
+ /// It gives back true when the header line start with \c \@nodes,
/// and the header line's id and the reader's id are the same.
virtual bool header(const std::string& line) {
std::istringstream ls(line);
@@ -1002,7 +1386,7 @@
/// Constructor for EdgeReader. It creates the EdgeReader and
/// attach it into the given LemonReader. It will use the given
/// edge id reader to give back the edges. The reader will read the
- /// section only if the \c _id and the \c nodes_id are the same.
+ /// section only if the \c _id and the \c edges_id are the same.
template <typename _IdReader>
EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
const std::string& _id = std::string())
@@ -1036,7 +1420,100 @@
/// \brief Gives back true when the SectionReader can process
/// the section with the given header line.
///
- /// It gives back true when the header line start with \c @edges,
+ /// It gives back true when the header line start with \c \@edges,
+ /// and the header line's id and the reader's id are the same.
+ virtual bool header(const std::string& line) {
+ std::istringstream ls(line);
+ std::string command;
+ std::string name;
+ ls >> command >> name;
+ return command == "@edges" && name == id;
+ }
+
+ /// \brief Reader function of the section.
+ ///
+ /// It reads the content of the section.
+ virtual void read(std::istream& is) {
+ std::string line;
+ while (getline(is, line)) {
+ std::istringstream ls(line);
+ std::string id;
+ ls >> id;
+ typename ItemReaders::iterator it = readers.find(id);
+ if (it != readers.end()) {
+ *(it->second) = idReader->read(ls);
+ }
+ }
+ }
+
+ private:
+
+ std::string id;
+
+ typedef std::map<std::string, Item*> ItemReaders;
+ ItemReaders readers;
+ std::auto_ptr<IdReaderBase<Item> > idReader;
+ };
+
+ /// \ingroup io_group
+ /// \brief SectionReader for reading labeled undirected edges.
+ ///
+ /// The undirected edges section's header line is \c \@undiredges
+ /// \c undiredges_id, but the \c undiredges_id may be empty.
+ ///
+ /// Each line in the section contains the name of the undirected edge
+ /// and then the undirected edge id.
+ ///
+ /// \relates LemonReader
+ template <typename _Graph>
+ class UndirEdgeReader : public CommonSectionReaderBase {
+ typedef CommonSectionReaderBase Parent;
+ typedef _Graph Graph;
+ typedef typename Graph::UndirEdge Item;
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
+ /// attach it into the given LemonReader. It will use the given
+ /// undirected edge id reader to give back the edges. The reader will
+ /// read the section only if the \c _id and the \c undiredges_id are
+ /// the same.
+ template <typename _IdReader>
+ UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
+ const std::string& _id = std::string())
+ : Parent(_reader), id(_id),
+ idReader(new IdReader<typename Graph::UndirEdge, _IdReader>(_idReader))
+ {}
+
+ /// \brief Destructor.
+ ///
+ /// Destructor for UndirEdgeReader.
+ virtual ~UndirEdgeReader() {}
+ private:
+ UndirEdgeReader(const UndirEdgeReader&);
+ void operator=(const UndirEdgeReader&);
+
+ public:
+
+ /// \brief Add an undirected edge reader command for the UndirEdgeReader.
+ ///
+ /// Add an undirected edge reader command for the UndirEdgeReader.
+ void readUndirEdge(const std::string& name, Item& item) {
+ if (readers.find(name) != readers.end()) {
+ ErrorMessage msg;
+ msg << "Multiple read rule for edge: " << name;
+ throw IOParameterError(msg.message());
+ }
+ readers.insert(make_pair(name, &item));
+ }
+
+ protected:
+
+ /// \brief Gives back true when the SectionReader can process
+ /// the section with the given header line.
+ ///
+ /// It gives back true when the header line start with \c \@edges,
/// and the header line's id and the reader's id are the same.
virtual bool header(const std::string& line) {
std::istringstream ls(line);
@@ -1141,7 +1618,7 @@
/// \brief Gives back true when the SectionReader can process
/// the section with the given header line.
///
- /// It gives back true when the header line start with \c @attributes,
+ /// It gives back true when the header line start with \c \@attributes,
/// and the header line's id and the attributeset's id are the same.
bool header(const std::string& line) {
std::istringstream ls(line);
@@ -1174,6 +1651,5 @@
Readers readers;
};
-
}
#endif
Modified: hugo/trunk/src/lemon/lemon_writer.h
==============================================================================
--- hugo/trunk/src/lemon/lemon_writer.h (original)
+++ hugo/trunk/src/lemon/lemon_writer.h Sat May 14 19:39:37 2005
@@ -31,7 +31,10 @@
#include <lemon/error.h>
#include <lemon/invalid.h>
+#include <lemon/graph_utils.h>
#include <lemon/bits/item_writer.h>
+#include <lemon/utility.h>
+#include <lemon/maps.h>
namespace lemon {
@@ -163,8 +166,6 @@
CommonSectionWriterBase(LemonWriter& _writer)
: Parent(_writer) {}
- // Writers
-
template <typename _Item>
class WriterBase {
public:
@@ -184,7 +185,7 @@
typedef typename Writer::Value Value;
typedef _Item Item;
- const Map& map;
+ typename SmartConstReference<Map>::Type map;
Writer writer;
MapWriter(const Map& _map, const Writer& _writer)
@@ -306,8 +307,8 @@
///
/// Add a new node map writer command for the writer.
template <typename Map>
- NodeSetWriter& writeMap(std::string name, const Map& map) {
- return writeMap<typename Traits::
+ NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
+ return writeNodeMap<typename Traits::
template Writer<typename Map::Value>, Map>(name, map);
}
@@ -315,8 +316,8 @@
///
/// Add a new node map writer command for the writer.
template <typename Writer, typename Map>
- NodeSetWriter& writeMap(std::string name, const Map& map,
- const Writer& writer = Writer()) {
+ NodeSetWriter& writeNodeMap(std::string name, const Map& map,
+ const Writer& writer = Writer()) {
writers.push_back(
make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
return *this;
@@ -394,15 +395,15 @@
WriterBase<Item>* idMap;
bool forceIdMap;
- const Graph& graph;
+ typename SmartConstReference<Graph>::Type graph;
std::string id;
};
/// \ingroup io_group
- /// \brief SectionWriter for writing a graph's edgeset.
+ /// \brief SectionWriter for writing a graph's edgesets.
///
- /// The lemon format can store multiple graph edgesets with several maps.
+ /// The lemon format can store multiple graph edgesets with several maps.
/// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
/// \c edgeset_id may be empty.
///
@@ -413,7 +414,7 @@
///
/// If the edgeset contains an \c "id" named map then it will be regarded
/// as id map. This map should contain only unique values and when the
- /// \c writeId() member will be called with a edge it will write it's id.
+ /// \c writeId() member will be called with an edge it will write it's id.
/// Otherwise if the \c _forceIdMap constructor parameter is true then
/// the id map will be the id in the graph.
///
@@ -436,7 +437,7 @@
/// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
/// attach it into the given LemonWriter. It will write node ids by
/// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
- /// then the writer will write own id map when the user does not give
+ /// then the writer will write own id map if the user does not give
/// "id" named map.
template <typename NodeIdWriter>
EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
@@ -464,21 +465,21 @@
public:
- /// \brief Add a new node map writer command for the writer.
+ /// \brief Add a new edge map writer command for the writer.
///
- /// Add a new node map writer command for the writer.
+ /// Add a new edge map writer command for the writer.
template <typename Map>
- EdgeSetWriter& writeMap(std::string name, const Map& map) {
- return writeMap<typename Traits::
+ EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
+ return writeEdgeMap<typename Traits::
template Writer<typename Map::Value>, Map>(name, map);
}
- /// \brief Add a new node map writer command for the writer.
+ /// \brief Add a new edge map writer command for the writer.
///
- /// Add a new node map writer command for the writer.
+ /// Add a new edge map writer command for the writer.
template <typename Writer, typename Map>
- EdgeSetWriter& writeMap(std::string name, const Map& map,
- const Writer& writer = Writer()) {
+ EdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
+ const Writer& writer = Writer()) {
writers.push_back(
make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
return *this;
@@ -561,7 +562,203 @@
WriterBase<Item>* idMap;
bool forceIdMap;
- const Graph& graph;
+ typename SmartConstReference<Graph>::Type graph;
+ std::string id;
+
+ std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
+ };
+
+ /// \ingroup io_group
+ /// \brief SectionWriter for writing a undirected edgeset.
+ ///
+ /// The lemon format can store multiple undirected edgesets with several
+ /// maps. The undirected edgeset section's header line is \c \@undiredgeset
+ /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
+ ///
+ /// The first line of the section contains the names of the maps separated
+ /// with white spaces. Each next lines describes an undirected edge in the
+ /// edgeset. The line contains the two connected nodes' id and the mapped
+ /// values for each undirected map.
+ ///
+ /// The section can handle the directed as a syntactical sugar. Two
+ /// undirected edge map describes one directed edge map. This two maps
+ /// are the forward map and the backward map and the names of this map
+ /// is near the same just with a prefix \c '+' or \c '-' character
+ /// difference.
+ ///
+ /// If the edgeset contains an \c "id" named map then it will be regarded
+ /// as id map. This map should contain only unique values and when the
+ /// \c writeId() member will be called with an undirected edge it will
+ /// write it's id. Otherwise if the \c _forceIdMap constructor parameter
+ /// is true then the id map will be the id in the graph.
+ ///
+ /// The undirected edgeset writer needs a node id writer to identify
+ /// which nodes have to be connected. If a NodeSetWriter can write the
+ /// nodes' id, it will be able to use with this class.
+ ///
+ /// \relates LemonWriter
+ template <typename _Graph, typename _Traits = DefaultWriterTraits>
+ class UndirEdgeSetWriter : public CommonSectionWriterBase {
+ typedef CommonSectionWriterBase Parent;
+ public:
+
+ typedef _Graph Graph;
+ typedef _Traits Traits;
+ typedef typename Graph::UndirEdge Item;
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for UndirEdgeSetWriter. It creates the UndirEdgeSetWriter
+ /// and attach it into the given LemonWriter. It will write node ids by
+ /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
+ /// then the writer will write own id map if the user does not give
+ /// "id" named map.
+ template <typename NodeIdWriter>
+ UndirEdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
+ const NodeIdWriter& _nodeIdWriter,
+ const std::string& _id = std::string(),
+ bool _forceIdMap = true)
+ : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
+ graph(_graph), id(_id),
+ nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
+ (_nodeIdWriter)) {}
+
+ /// \brief Destructor.
+ ///
+ /// Destructor for UndirEdgeSetWriter.
+ virtual ~UndirEdgeSetWriter() {
+ typename MapWriters::iterator it;
+ for (it = writers.begin(); it != writers.end(); ++it) {
+ delete it->second;
+ }
+ }
+
+ private:
+ UndirEdgeSetWriter(const UndirEdgeSetWriter&);
+ void operator=(const UndirEdgeSetWriter&);
+
+ public:
+
+ /// \brief Add a new undirected edge map writer command for the writer.
+ ///
+ /// Add a new undirected map writer command for the writer.
+ template <typename Map>
+ UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map) {
+ return writeUndirEdgeMap<typename Traits::
+ template Writer<typename Map::Value>, Map>(name, map);
+ }
+
+ /// \brief Add a new undirected map writer command for the writer.
+ ///
+ /// Add a new undirected map writer command for the writer.
+ template <typename Writer, typename Map>
+ UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map,
+ const Writer& writer = Writer()) {
+ writers.push_back(
+ make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
+ return *this;
+ }
+
+ /// \brief Add a new directed edge map writer command for the writer.
+ ///
+ /// Add a new directed map writer command for the writer.
+ template <typename Map>
+ UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
+ writeUndirEdgeMap("+" + name, composeMap(forwardMap(graph), map));
+ writeUndirEdgeMap("-" + name, composeMap(backwardMap(graph), map));
+ return *this;
+ }
+
+ /// \brief Add a new directed map writer command for the writer.
+ ///
+ /// Add a new directed map writer command for the writer.
+ template <typename Writer, typename Map>
+ UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
+ const Writer& writer = Writer()) {
+ writeUndirEdge("+" + name, composeMap(forwardMap(graph), map), writer);
+ writeUndirEdge("-" + name, composeMap(forwardMap(graph), map), writer);
+ return *this;
+ }
+
+ protected:
+
+ /// \brief The header of the section.
+ ///
+ /// It gives back the header of the section.
+ virtual std::string header() {
+ return "@undiredgeset " + id;
+ }
+
+ /// \brief Writer function of the section.
+ ///
+ /// Write the content of the section.
+ virtual void write(std::ostream& os) {
+ for (int i = 0; i < (int)writers.size(); ++i) {
+ if (writers[i].first == "id") {
+ idMap = writers[i].second;
+ forceIdMap = false;
+ break;
+ }
+ }
+ os << "\t\t";
+ if (forceIdMap) {
+ os << "id\t";
+ }
+ for (int i = 0; i < (int)writers.size(); ++i) {
+ os << writers[i].first << '\t';
+ }
+ os << std::endl;
+ for (typename Graph::UndirEdgeIt it(graph); it != INVALID; ++it) {
+ nodeIdWriter->write(os, graph.source(it));
+ os << '\t';
+ nodeIdWriter->write(os, graph.target(it));
+ os << '\t';
+ if (forceIdMap) {
+ os << graph.id(it) << '\t';
+ }
+ for (int i = 0; i < (int)writers.size(); ++i) {
+ writers[i].second->write(os, it);
+ os << '\t';
+ }
+ os << std::endl;
+ }
+ }
+
+ public:
+
+ /// \brief Returns true if the undirected edgeset can write the ids of
+ /// the edges.
+ ///
+ /// Returns true if the undirected edgeset can write the ids of the
+ /// undirected edges. It is possible only if an "id" named map was
+ /// written or the \c _forceIdMap constructor parameter was true.
+ bool isIdWriter() const {
+ return forceIdMap || idMap != 0;
+ }
+
+ /// \brief Write the id of the given undirected edge.
+ ///
+ /// It writes the id of the given undirected edge. If there was written
+ /// an "id" named map then it will write the map value belongs to the
+ /// undirected edge. Otherwise if the \c forceId parameter was true it
+ /// will write its id in the graph.
+ void writeId(std::ostream& os, const Item& item) const {
+ if (forceIdMap) {
+ os << graph.id(item);
+ } else {
+ idMap->write(os, item);
+ }
+ }
+
+ private:
+
+ typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
+ MapWriters writers;
+
+ WriterBase<Item>* idMap;
+ bool forceIdMap;
+
+ typename SmartConstReference<Graph>::Type graph;
std::string id;
std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
@@ -617,7 +814,7 @@
/// \brief Header checking function.
///
- /// It gives back true when the header line start with \c @nodes,
+ /// It gives back true when the header line start with \c \@nodes,
/// and the header line's id and the writer's id are the same.
virtual std::string header() {
return "@nodes " + id;
@@ -644,7 +841,7 @@
};
/// \ingroup io_group
- /// \brief SectionWriter for writeing labeled edges.
+ /// \brief SectionWriter for writing labeled edges.
///
/// The edges section's header line is \c \@edges \c edges_id, but the
/// \c edges_id may be empty.
@@ -681,9 +878,9 @@
public:
- /// \brief Add an edge writer command for the NodeWriter.
+ /// \brief Add an edge writer command for the EdgeWriter.
///
- /// Add an edge writer command for the NodeWriter.
+ /// Add an edge writer command for the EdgeWriter.
void writeEdge(const std::string& name, const Item& item) {
writers.push_back(make_pair(name, &item));
}
@@ -692,7 +889,85 @@
/// \brief Header checking function.
///
- /// It gives back true when the header line start with \c @nodes,
+ /// It gives back true when the header line start with \c \@edges,
+ /// and the header line's id and the writer's id are the same.
+ virtual std::string header() {
+ return "@edges " + id;
+ }
+
+ /// \brief Writer function of the section.
+ ///
+ /// Write the content of the section.
+ virtual void write(std::ostream& os) {
+ for (int i = 0; i < (int)writers.size(); ++i) {
+ os << writers[i].first << ' ';
+ idWriter->write(os, *(writers[i].second));
+ os << std::endl;
+ }
+ }
+
+ private:
+
+ std::string id;
+
+ typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
+ ItemWriters writers;
+
+ std::auto_ptr<IdWriterBase<Item> > idWriter;
+ };
+
+ /// \ingroup io_group
+ /// \brief SectionWriter for writing labeled undirected edges.
+ ///
+ /// The undirected edges section's header line is \c \@undiredges
+ /// \c undiredges_id, but the \c undiredges_id may be empty.
+ ///
+ /// Each line in the section contains the label of the undirected edge and
+ /// then the undirected edge id.
+ ///
+ /// \relates LemonWriter
+ template <typename _Graph>
+ class UndirEdgeWriter : public CommonSectionWriterBase {
+ typedef CommonSectionWriterBase Parent;
+ typedef _Graph Graph;
+ typedef typename Graph::UndirEdge Item;
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for UndirEdgeWriter. It creates the UndirEdgeWriter and
+ /// attach it into the given LemonWriter. The given \c _IdWriter
+ /// will write the undirected edges' id what can be an undirected
+ /// edgeset writer.
+ template <typename _IdWriter>
+ UndirEdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
+ const std::string& _id = std::string())
+ : Parent(_writer), id(_id),
+ idWriter(new IdWriter<typename Graph::UndirEdge, _IdWriter>
+ (_idWriter)) {}
+
+ /// \brief Destructor.
+ ///
+ /// Destructor for UndirEdgeWriter.
+ virtual ~UndirEdgeWriter() {}
+ private:
+ UndirEdgeWriter(const UndirEdgeWriter&);
+ void operator=(const UndirEdgeWriter&);
+
+ public:
+
+ /// \brief Add an undirected edge writer command for the UndirEdgeWriter.
+ ///
+ /// Add an edge writer command for the UndirEdgeWriter.
+ void writeUndirEdge(const std::string& name, const Item& item) {
+ writers.push_back(make_pair(name, &item));
+ }
+
+ protected:
+
+ /// \brief Header checking function.
+ ///
+ /// It gives back true when the header line start with \c \@undiredges,
/// and the header line's id and the writer's id are the same.
virtual std::string header() {
return "@edges " + id;
More information about the Lemon-commits
mailing list