[Lemon-commits] [lemon_svn] deba: r1876 - in hugo/trunk/src/lemon: . bits
Lemon SVN
svn at lemon.cs.elte.hu
Mon Nov 6 20:48:23 CET 2006
Author: deba
Date: Wed May 11 13:50:13 2005
New Revision: 1876
Added:
hugo/trunk/src/lemon/bits/item_writer.h
hugo/trunk/src/lemon/lemon_writer.h
Modified:
hugo/trunk/src/lemon/Makefile.am
hugo/trunk/src/lemon/graph_writer.h
hugo/trunk/src/lemon/lemon_reader.h
Log:
LemonWriter and GraphWriter.
Little bit better documentation.
Modified: hugo/trunk/src/lemon/Makefile.am
==============================================================================
--- hugo/trunk/src/lemon/Makefile.am (original)
+++ hugo/trunk/src/lemon/Makefile.am Wed May 11 13:50:13 2005
@@ -53,6 +53,7 @@
concept_check.h \
utility.h \
lemon_reader.h \
+ lemon_writer.h \
graph_reader.h \
graph_writer.h \
bits/alteration_notifier.h \
@@ -66,7 +67,8 @@
bits/clearable_graph_extender.h \
bits/erasable_graph_extender.h \
bits/undir_graph_extender.h \
- bits/item_reader.h
+ bits/item_reader.h \
+ bits/item_writer.h
noinst_HEADERS = \
concept/graph.h \
Added: hugo/trunk/src/lemon/bits/item_writer.h
==============================================================================
--- (empty file)
+++ hugo/trunk/src/lemon/bits/item_writer.h Wed May 11 13:50:13 2005
@@ -0,0 +1,214 @@
+/* -*- C++ -*-
+ * src/lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+/// \ingroup io_group
+/// \file
+/// \brief Item writer bits for lemon output.
+
+#ifndef LEMON_BITS_ITEM_WRITER_H
+#define LEMON_BITS_ITEM_WRITER_H
+
+#include <iostream>
+#include <string>
+
+#include <vector>
+#include <deque>
+#include <list>
+#include <set>
+
+namespace lemon {
+
+ template <typename Value>
+ class DefaultWriter;
+
+ /// \ingroup io_group
+ /// \brief Writer class for quoted strings.
+ ///
+ /// Writer class for quoted strings. It can process the escape
+ /// sequences in the string.
+ /// \author Balazs Dezso
+ class QuotedStringWriter {
+ public:
+ typedef std::string Value;
+
+ /// \brief Constructor for the writer.
+ ///
+ /// Constructor for the writer. If the given parameter is true
+ /// the writer creates escape sequences from special characters.
+ QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
+
+ /// \brief Writes a quoted string to the given stream.
+ ///
+ /// Writes a quoted string to the given stream.
+ void write(std::ostream& os, const std::string& value) {
+ os << "\"";
+ if (escaped) {
+ std::ostringstream ls;
+ for (int i = 0; i < (int)value.size(); ++i) {
+ writeEscape(ls, value[i]);
+ }
+ os << ls.str();
+ } else {
+ os << value;
+ }
+ os << "\"";
+ }
+
+ private:
+
+ static void writeEscape(std::ostream& os, char c) {
+ switch (c) {
+ case '\\':
+ os << "\\\\";
+ return;
+ case '\"':
+ os << "\\\"";
+ return;
+ case '\'':
+ os << "\\\'";
+ return;
+ case '\?':
+ os << "\\\?";
+ return;
+ case '\a':
+ os << "\\a";
+ return;
+ case '\b':
+ os << "\\b";
+ return;
+ case '\f':
+ os << "\\f";
+ return;
+ case '\r':
+ os << "\\r";
+ return;
+ case '\n':
+ os << "\\n";
+ return;
+ case '\t':
+ os << "\\t";
+ return;
+ case '\v':
+ os << "\\v";
+ return;
+ default:
+ if (c < 0x20) {
+ os << '\\' << std::oct << (int)c;
+ } else {
+ os << c;
+ }
+ return;
+ }
+ }
+ private:
+ bool escaped;
+ };
+
+ /// \ingroup io_group
+ ///
+ /// \brief Writer for standard containers.
+ ///
+ /// Writer for each iterable standard containers. The representation
+ /// of the container is the values enumerated between an open and a
+ /// close parse.
+ ///
+ /// \author Balazs Dezso
+ template <
+ typename _Container,
+ typename _ItemWriter = DefaultWriter<typename _Container::value_type>
+ >
+ class IterableWriter {
+ public:
+ typedef _Container Value;
+ typedef _ItemWriter ItemWriter;
+
+ private:
+
+ ItemWriter item_writer;
+
+ public:
+
+ /// \brief Writes the values of the container to the given stream.
+ ///
+ /// Writes the values of the container to the given stream.
+ void write(std::ostream& os, const Value& value) const {
+ typename Value::const_iterator it;
+ os << '(';
+ for (it = value.begin(); it != value.end(); ++it) {
+ item_writer.write(os, *it);
+ os << ' ';
+ }
+ os << ')';
+ }
+
+ };
+
+ /// \ingroup io_group
+ ///
+ /// \brief The default item writer template class.
+ ///
+ /// The default item writer template class. If some section writer
+ /// needs to write a value to the stream it will give the default way for it.
+ ///
+ /// \author Balazs Dezso
+ template <typename _Value>
+ class DefaultWriter {
+ public:
+ /// The value type.
+ typedef _Value Value;
+ /// \brief Writes the value to the given stream.
+ ///
+ /// Writes the value to the given stream.
+ void write(std::ostream& os, const Value& value) const {
+ os << value;
+ }
+ };
+
+ template <typename Item>
+ class DefaultWriter<std::vector<Item> >
+ : public IterableWriter<std::vector<Item> > {};
+
+ template <typename Item>
+ class DefaultWriter<std::deque<Item> >
+ : public IterableWriter<std::deque<Item> > {};
+
+ template <typename Item>
+ class DefaultWriter<std::list<Item> >
+ : public IterableWriter<std::list<Item> > {};
+
+ template <typename Item>
+ class DefaultWriter<std::set<Item> >
+ : public IterableWriter<std::set<Item> > {};
+
+ template <typename Item>
+ class DefaultWriter<std::multiset<Item> >
+ : public IterableWriter<std::multiset<Item> > {};
+
+ /// \brief Standard WriterTraits for the section writers.
+ ///
+ /// Standard WriterTraits for the section writers.
+ /// It defines standard writing method for all type of value.
+ /// \author Balazs Dezso
+ struct DefaultWriterTraits {
+
+ template <typename _Value>
+ struct Writer : DefaultWriter<_Value> {};
+
+ };
+
+}
+
+#endif
Modified: hugo/trunk/src/lemon/graph_writer.h
==============================================================================
--- hugo/trunk/src/lemon/graph_writer.h (original)
+++ hugo/trunk/src/lemon/graph_writer.h Wed May 11 13:50:13 2005
@@ -22,146 +22,15 @@
#define LEMON_GRAPH_WRITER_H
#include <iostream>
-#include <sstream>
-#include <map>
-#include <vector>
-
-#include <memory>
-
-#include <lemon/graph_utils.h>
-
-#include <lemon/invalid.h>
#include <lemon/error.h>
-
+#include <lemon/lemon_writer.h>
namespace lemon {
/// \addtogroup io_group
/// @{
- /// \brief Standard WriterTraits for the GraphWriter class.
- ///
- /// Standard WriterTraits for the GraphWriter class.
- /// It defines standard writing method for all type of value.
- /// \author Balazs Dezso
- struct DefaultWriterTraits {
-
- /// \brief Template class for writing an value.
- ///
- /// Template class for writing an value.
- /// \author Balazs Dezso
- template <typename _Value>
- struct Writer {
- /// The value type.
- typedef _Value Value;
-
- /// \brief Writes a value to the given stream.
- ///
- /// Writes a value to the given stream.
- void write(std::ostream& os, const Value& value) {
- os << value << '\t';
- }
- };
-
- /// \brief Returns wheter this name is an ID map name.
- ///
- /// Returns wheter this name is an ID map name.
- static bool idMapName(const std::string& name) {
- return name == "id";
- }
-
- };
-
-
- /// \brief Writer class for quoted strings.
- ///
- /// Writer class for quoted strings. It can process the escape
- /// sequences in the string.
- /// \author Balazs Dezso
- class QuotedStringWriter {
- public:
- typedef std::string Value;
-
- /// \brief Constructor for the writer.
- ///
- /// Constructor for the writer. If the given parameter is true
- /// the writer creates escape sequences from special characters.
- QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
-
- /// \brief Writes a quoted string to the given stream.
- ///
- /// Writes a quoted string to the given stream.
- void write(std::ostream& os, const std::string& value) {
- os << "\"";
- if (escaped) {
- std::ostringstream ls;
- for (int i = 0; i < (int)value.size(); ++i) {
- writeEscape(ls, value[i]);
- }
- os << ls.str();
- } else {
- os << value;
- }
- os << "\"";
- }
-
- private:
-
- static void writeEscape(std::ostream& os, char c) {
- switch (c) {
- case '\\':
- os << "\\\\";
- return;
- case '\"':
- os << "\\\"";
- return;
- case '\'':
- os << "\\\'";
- return;
- case '\?':
- os << "\\\?";
- return;
- case '\a':
- os << "\\a";
- return;
- case '\b':
- os << "\\b";
- return;
- case '\f':
- os << "\\f";
- return;
- case '\r':
- os << "\\r";
- return;
- case '\n':
- os << "\\n";
- return;
- case '\t':
- os << "\\t";
- return;
- case '\v':
- os << "\\v";
- return;
- default:
- if (c < 0x20) {
- os << '\\' << std::oct << (int)c;
- } else {
- os << c;
- }
- return;
- }
- }
- private:
- bool escaped;
- };
-
- class GUIWriter {
- public:
- virtual void write(std::ostream& os) = 0;
- };
-
-
/// \brief The graph writer class.
///
/// The \c GraphWriter class provides the graph output. To write a graph
@@ -231,46 +100,64 @@
typedef _Graph Graph;
typedef typename Graph::Node Node;
- typedef typename Graph::NodeIt NodeIt;
typedef typename Graph::Edge Edge;
- typedef typename Graph::EdgeIt EdgeIt;
typedef _WriterTraits WriterTraits;
-
+
/// \brief Construct a new GraphWriter.
///
- /// Construct a new GraphWriter. It writes from the given map,
- /// it constructs the given map and it use the given writer as the
- /// default skipper.
+ /// Construct a new GraphWriter. It writes the given graph
+ /// to the given stream.
GraphWriter(std::ostream& _os, const Graph& _graph)
- : gui_writer(0), os(_os), 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()),
+ node_writer(*writer, nodeset_writer, std::string()),
+ edge_writer(*writer, edgeset_writer, std::string()),
+ attribute_writer(*writer, std::string()) {}
+ /// \brief Construct a new GraphWriter.
+ ///
+ /// Construct a new GraphWriter. It writes into the given graph
+ /// 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(), skipper),
+ edgeset_writer(*writer, graph, nodeset_writer, std::string(), skipper),
+ node_writer(*writer, nodeset_writer, std::string()),
+ edge_writer(*writer, edgeset_writer, std::string()),
+ attribute_writer(*writer, std::string()) {}
+
+ /// \brief Construct a new GraphWriter.
+ ///
+ /// Construct a new GraphWriter. It writes into the given graph
+ /// 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()),
+ node_writer(*writer, nodeset_writer, std::string()),
+ edge_writer(*writer, edgeset_writer, std::string()),
+ attribute_writer(*writer, std::string()) {}
/// \brief Destruct the graph writer.
///
/// Destruct the graph writer.
~GraphWriter() {
- for (typename NodeMapWriters::iterator it = node_map_writers.begin();
- it != node_map_writers.end(); ++it) {
- delete it->second;
- }
-
- for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
- it != edge_map_writers.end(); ++it) {
- delete it->second;
- }
-
+ if (own_writer)
+ delete writer;
}
- // Node map rules
-
/// \brief Add a new node map writer command for the writer.
///
/// Add a new node map writer command for the writer.
template <typename Map>
GraphWriter& writeNodeMap(std::string name, const Map& map) {
- return writeNodeMap<typename WriterTraits::template Writer<
- typename Map::Value>, Map>(name, map);
+ nodeset_writer.writeMap(name, map);
+ return *this;
}
/// \brief Add a new node map writer command for the writer.
@@ -278,21 +165,19 @@
/// 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()) {
- node_map_writers.push_back(
- make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
+ const Writer& writer = Writer()) {
+ nodeset_writer.writeMap(name, map, writer);
return *this;
}
- // Edge map rules
/// \brief Add a new edge map writer command for the writer.
///
/// Add a new edge map writer command for the writer.
template <typename Map>
GraphWriter& writeEdgeMap(std::string name, const Map& map) {
- return writeEdgeMap<typename WriterTraits::template Writer<
- typename Map::Value>, Map>(name, map);
+ edgeset_writer.writeMap(name, map);
+ return *this;
}
@@ -300,10 +185,9 @@
///
/// 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()) {
- edge_map_writers.push_back(make_pair(name,
- new MapWriter<Edge, Map, Writer>(map, writer)));
+ GraphWriter& writeEdgeMap(std::string name, const Map& map,
+ const Writer& writer = Writer()) {
+ edgeset_writer.writeMap(name, map, writer);
return *this;
}
@@ -311,7 +195,7 @@
///
/// Add a new labeled node writer for the writer.
GraphWriter& writeNode(std::string name, const Node& node) {
- node_writers.push_back(make_pair(name, node));
+ node_writer.writeNode(name, node);
return *this;
}
@@ -319,160 +203,62 @@
///
/// Add a new labeled edge writer for the writer.
GraphWriter& writeEdge(std::string name, const Edge& edge) {
- edge_writers.push_back(make_pair(name, edge));
+ edge_writer.writeEdge(name, edge);
+ }
+
+ /// \brief Add a new attribute writer command.
+ ///
+ /// Add a new attribute writer command.
+ template <typename Value>
+ GraphWriter& 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>
+ GraphWriter& writeAttribute(std::string name, const Value& value,
+ const Writer& writer) {
+ attribute_writer.writeAttribute<Writer>(name, value, writer);
return *this;
}
- GraphWriter& writeGUI(const GUIWriter& writer) {
- gui_writer = &writer;
+ /// \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() {
- WriterBase<Node>* nodeWriter = 0;
- WriterBase<Edge>* edgeWriter = 0;
- writeNodeSet(nodeWriter);
- writeEdgeSet(nodeWriter, edgeWriter);
- writeNodes(nodeWriter);
- writeEdges(edgeWriter);
- writeGUI();
- os << "@end" << std::endl;
+ void run() {
+ writer->run();
}
private:
- template <class _Item>
- class WriterBase {
- public:
- typedef _Item Item;
- virtual void write(std::ostream&, const Item&) = 0;
- };
-
- template <class _Item, typename _Map, typename _Writer>
- class MapWriter : public WriterBase<_Item> {
- public:
- typedef _Map Map;
- typedef _Writer Writer;
- typedef typename Writer::Value Value;
- typedef _Item Item;
-
- const Map& map;
- Writer writer;
-
- MapWriter(const Map& _map, const Writer& _writer)
- : map(_map), writer(_writer) {}
-
-
- virtual void write(std::ostream& os, const Item& item) {
- writer.write(os, map[item]);
- }
-
- };
-
- void writeNodeSet(WriterBase<Node>* & nodeWriter) {
- if (node_map_writers.size() == 0) return;
- os << "@nodeset" << std::endl;
- for (int i = 0; i < (int)node_map_writers.size(); ++i) {
- const std::string& id = node_map_writers[i].first;
- os << id << '\t';
- if (WriterTraits::idMapName(id) && nodeWriter == 0) {
- nodeWriter = node_map_writers[i].second;
- }
- }
- os << std::endl;
- for (NodeIt it(graph); it != INVALID; ++it) {
- for (int i = 0; i < (int)node_map_writers.size(); ++i) {
- node_map_writers[i].second->write(os, it);
- }
- os << std::endl;
- }
-
- }
-
- void writeEdgeSet(WriterBase<Node>* nodeWriter,
- WriterBase<Edge>* & edgeWriter) {
- if (edge_map_writers.size() == 0) return;
- if (nodeWriter == 0) {
- throw DataFormatError("Cannot find node id map");
- }
- os << "@edgeset" << std::endl;
- os << "\t\t";
- for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
- const std::string& id = edge_map_writers[i].first;
- os << id << '\t';
- if (WriterTraits::idMapName(id) && edgeWriter == 0) {
- edgeWriter = edge_map_writers[i].second;
- }
- }
- os << std::endl;
- for (EdgeIt it(graph); it != INVALID; ++it) {
- nodeWriter->write(os, graph.source(it));
- nodeWriter->write(os, graph.target(it));
- for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
- edge_map_writers[i].second->write(os, it);
- }
- os << std::endl;
- }
- }
-
- void writeNodes(WriterBase<Node>* nodeWriter) {
- if (node_writers.size() == 0) return;
- if (nodeWriter == 0) {
- throw DataFormatError("Cannot find node id map");
- }
- os << "@nodes" << std::endl;
- for (int i = 0; i < (int)node_writers.size(); ++i) {
- os << node_writers[i].first << '\t';
- nodeWriter->write(os, node_writers[i].second);
- os << std::endl;
- }
- }
-
- void writeEdges(WriterBase<Edge>* edgeWriter) {
- if (edge_writers.size() == 0) return;
- if (edgeWriter == 0) {
- throw DataFormatError("Cannot find node id map");
- }
- os << "@edges" << std::endl;
- for (int i = 0; i < (int)edge_writers.size(); ++i) {
- os << edge_writers[i].first << '\t';
- edgeWriter->write(os, edge_writers[i].second);
- os << std::endl;
- }
- }
-
- void writeGUI() {
- if (gui_writer) {
- os << "@gui" << std::endl;
- gui_writer->write(os);
- }
- }
-
-
-
- typedef std::vector< std::pair<std::string, WriterBase<Node>*> >
- NodeMapWriters;
- NodeMapWriters node_map_writers;
+ LemonWriter* writer;
+ bool own_writer;
- typedef std::vector< std::pair<std::string, WriterBase<Edge>*> >
- EdgeMapWriters;
- EdgeMapWriters edge_map_writers;
-
- typedef std::vector<std::pair<std::string, Node> > NodeWriters;
- NodeWriters node_writers;
-
- typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
- EdgeWriters edge_writers;
-
- GUIWriter* gui_writer;
-
- std::ostream& os;
const Graph& graph;
+ NodeSetWriter<Graph, WriterTraits> nodeset_writer;
+ EdgeSetWriter<Graph, WriterTraits> edgeset_writer;
+
+ NodeWriter<Graph> node_writer;
+ EdgeWriter<Graph> edge_writer;
+
+ AttributeWriter<WriterTraits> attribute_writer;
};
+
/// \brief Write a graph to the output.
///
/// Write a graph to the output.
Modified: hugo/trunk/src/lemon/lemon_reader.h
==============================================================================
--- hugo/trunk/src/lemon/lemon_reader.h (original)
+++ hugo/trunk/src/lemon/lemon_reader.h Wed May 11 13:50:13 2005
@@ -39,7 +39,7 @@
/// \brief Lemon Format reader class.
///
/// The Lemon Format contains several sections. We do not want to
- /// determine what sections are in an lemon file we give only a framework
+ /// determine what sections are in a lemon file we give only a framework
/// to read a section oriented format.
///
/// In the Lemon Format each section starts with a line contains a \c \@
@@ -229,15 +229,16 @@
reader.attach(*this);
}
- /// \brief Header checking function.
+ /// \brief Gives back true when the SectionReader can process
+ /// the section with the given header line.
///
/// It gives back true when the SectionReader can process
/// the section with the given header line.
virtual bool header(const std::string& line) = 0;
- /// \brief Reading function.
+ /// \brief Reader function of the section.
///
- /// It processes the section.
+ /// It reads the content of the section.
virtual void read(std::istream& is) = 0;
};
@@ -489,25 +490,25 @@
};
template <typename _Item>
- class ResolverReaderBase {
+ class IdReaderBase {
public:
typedef _Item Item;
- virtual Item resolve(std::istream& is) const = 0;
+ virtual Item read(std::istream& is) const = 0;
};
- template <typename _Item, typename _Resolver>
- class ResolverReader : public ResolverReaderBase<_Item> {
+ template <typename _Item, typename _BoxedIdReader>
+ class IdReader : public IdReaderBase<_Item> {
public:
typedef _Item Item;
- typedef _Resolver Resolver;
-
- const Resolver& resolver;
+ typedef _BoxedIdReader BoxedIdReader;
+
+ const BoxedIdReader& boxedIdReader;
- ResolverReader(const Resolver& _resolver)
- : resolver(_resolver) {}
+ IdReader(const BoxedIdReader& _boxedIdReader)
+ : boxedIdReader(_boxedIdReader) {}
- virtual Item resolve(std::istream& is) const {
- return resolver.resolve(is);
+ virtual Item read(std::istream& is) const {
+ return boxedIdReader.readId(is);
}
};
@@ -548,8 +549,8 @@
///
/// If the nodeset 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 resolve() member will read a value from the given stream it will
- /// give back that node which is mapped to the value.
+ /// \c readId() member will read a value from the given stream it will
+ /// give back that node which is mapped to this value.
///
/// \relates LemonReader
template <typename _Graph, typename _Traits = DefaultReaderTraits>
@@ -566,8 +567,8 @@
///
/// Constructor for NodeSetReader. It creates the NodeSetReader and
/// attach it into the given LemonReader. The nodeset reader will
- /// be add the readed nodes to the given Graph. The reader will read
- /// the section when the \c section_id and the _id are the same.
+ /// 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,
const std::string& _id = std::string(),
const DefaultSkipper& _skipper = DefaultSkipper())
@@ -632,9 +633,10 @@
protected:
- /// \brief Header checking function.
+ /// \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 @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);
@@ -644,9 +646,9 @@
return command == "@nodeset" && name == id;
}
- /// \brief Reading function.
+ /// \brief Reader function of the section.
///
- /// It processes the section.
+ /// It reads the content of the section.
virtual void read(std::istream& is) {
std::vector<ReaderBase<Item>* > index;
std::string line;
@@ -676,19 +678,19 @@
public:
- /// \brief Decide if it can resolve nodes by ids.
+ /// \brief Returns true if the nodeset can give back the node by its id.
///
- /// Decide if it can resolve nodes by ids. It depends on that the
- /// readed file contains \c "id" named map.
- bool isResolver() const {
+ /// Returns true if the nodeset can give back the node by its id.
+ /// It is possible only if an "id" named map was read.
+ bool isIdReader() const {
return inverter.get() != 0;
}
- /// \brief Node resolver function.
+ /// \brief Gives back the node by its id.
///
- /// It reads from the given stream an id and gives back
- /// the node that the id belongs to.
- typename Graph::Node resolve(std::istream& is) const {
+ /// 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 {
return inverter->read(is);
}
@@ -717,10 +719,10 @@
///
/// 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 resolve() member will read a value from the given stream it will
- /// give back that node which is mapped to the value.
+ /// \c readId() member will read a value from the given stream it will
+ /// give back that edge which is mapped to this value.
///
- /// The edgeset reader needs a node resolver to identify which nodes
+ /// The 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.
///
@@ -739,17 +741,18 @@
///
/// Constructor for EdgeSetReader. It creates the EdgeSetReader and
/// attach it into the given LemonReader. The edgeset reader will
- /// be add the readed edges to the given Graph. It will resolve the nodes
- /// by id with the given Resolver. The reader will read the section
- /// only if the \c _id and the \c edgset_id are the same.
- template <typename Resolver>
+ /// add the readed 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 edgset_id are the same.
+ template <typename NodeIdReader>
EdgeSetReader(LemonReader& _reader, Graph& _graph,
- const Resolver& _nodeResolver,
+ const NodeIdReader& _nodeIdReader,
const std::string& _id = std::string(),
- const DefaultSkipper& _defreader = DefaultSkipper())
- : Parent(_reader), graph(_graph), id(_id), skipper(_defreader),
- nodeResolver(new ResolverReader<typename Graph::Node, Resolver>
- (_nodeResolver)) {}
+ const DefaultSkipper& _skipper = DefaultSkipper())
+ : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
+ nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
+ (_nodeIdReader)) {}
/// \brief Destructor.
///
@@ -767,18 +770,18 @@
public:
- /// \brief Add a new node map reader command for the reader.
+ /// \brief Add a new edge map reader command for the reader.
///
- /// Add a new node map reader command for the reader.
+ /// 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);
}
- /// \brief Add a new node map reader command for the reader.
+ /// \brief Add a new edge map reader command for the reader.
///
- /// Add a new node 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()) {
@@ -792,9 +795,9 @@
return *this;
}
- /// \brief Add a new node map skipper command for the reader.
+ /// \brief Add a new edge map skipper command for the reader.
///
- /// Add a new node 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()) {
@@ -809,9 +812,10 @@
protected:
- /// \brief Header checking function.
+ /// \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 @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);
@@ -821,9 +825,9 @@
return command == "@edgeset" && name == id;
}
- /// \brief Reading function.
+ /// \brief Reader function of the section.
///
- /// It processes the section.
+ /// It reads the content of the section.
virtual void read(std::istream& is) {
std::vector<ReaderBase<Item>* > index;
std::string line;
@@ -844,8 +848,8 @@
}
while (getline(is, line)) {
std::istringstream ls(line);
- typename Graph::Node from = nodeResolver->resolve(ls);
- typename Graph::Node to = nodeResolver->resolve(ls);
+ typename Graph::Node from = nodeIdReader->read(ls);
+ typename Graph::Node to = nodeIdReader->read(ls);
typename Graph::Edge edge = graph.addEdge(from, to);
for (int i = 0; i < (int)index.size(); ++i) {
index[i]->read(ls, edge);
@@ -855,19 +859,19 @@
public:
- /// \brief Decide if it can resolve edges by ids.
+ /// \brief Returns true if the edgeset can give back the edge by its id.
///
- /// Decide if it can resolve edges by ids. It depends on that the
- /// readed file contains \c "id" named map.
- bool isResolver() const {
+ /// Returns true if the edgeset can give back the edge by its id.
+ /// It is possible only if an "id" named map was read.
+ bool isIdReader() const {
return inverter.get() != 0;
}
- /// \brief Edge resolver function.
+ /// \brief Gives back the edge by its id.
///
- /// It reads from the given stream an id and gives back
- /// the edge that the id belongs to.
- typename Graph::Edge resolve(std::istream& is) const {
+ /// 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 {
return inverter->read(is);
}
@@ -881,16 +885,17 @@
SkipReader<Item, DefaultSkipper> skipper;
std::auto_ptr<InverterBase<Item> > inverter;
- std::auto_ptr<ResolverReaderBase<typename Graph::Node> > nodeResolver;
+ std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
};
/// \ingroup io_group
- /// \brief SectionReader for reading labelled nodes.
+ /// \brief SectionReader for reading labeled nodes.
///
/// The nodes section's header line is \c \@nodes \c nodes_id, but the
/// \c nodes_id may be empty.
///
- /// Each line in the section contains a name and then a node id.
+ /// Each line in the section contains the name of the node
+ /// and then the node id.
///
/// \relates LemonReader
template <typename _Graph>
@@ -903,15 +908,14 @@
/// \brief Constructor.
///
/// Constructor for NodeReader. It creates the NodeReader and
- /// attach it into the given LemonReader. It will resolve the nodes
- /// by id with the given Resolver. The reader will read the section
- /// only if the \c _id and the \c nodes_id are the same.
- template <typename Resolver>
- NodeReader(LemonReader& _reader, const Resolver& _resolver,
+ /// attach it into the given LemonReader. It will use the given
+ /// node id reader to give back the nodes. The reader will read the
+ /// section only if the \c _id and the \c nodes_id are the same.
+ template <typename _IdReader>
+ NodeReader(LemonReader& _reader, const _IdReader& _idReader,
const std::string& _id = std::string())
: Parent(_reader), id(_id),
- resolver(new ResolverReader<typename Graph::Node, Resolver>
- (_resolver)) {}
+ idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {}
/// \brief Destructor.
///
@@ -938,7 +942,8 @@
protected:
- /// \brief Header checking function.
+ /// \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,
/// and the header line's id and the reader's id are the same.
@@ -950,9 +955,9 @@
return command == "@nodes" && name == id;
}
- /// \brief Reading function.
+ /// \brief Reader function of the section.
///
- /// It processes the section.
+ /// It reads the content of the section.
virtual void read(std::istream& is) {
std::string line;
while (getline(is, line)) {
@@ -961,7 +966,7 @@
ls >> id;
typename ItemReaders::iterator it = readers.find(id);
if (it != readers.end()) {
- *(it->second) = resolver->resolve(ls);
+ *(it->second) = idReader->read(ls);
}
}
}
@@ -972,16 +977,17 @@
typedef std::map<std::string, Item*> ItemReaders;
ItemReaders readers;
- std::auto_ptr<ResolverReaderBase<Item> > resolver;
+ std::auto_ptr<IdReaderBase<Item> > idReader;
};
/// \ingroup io_group
- /// \brief SectionReader for reading labelled edges.
+ /// \brief SectionReader for reading labeled edges.
///
/// The edges section's header line is \c \@edges \c edges_id, but the
/// \c edges_id may be empty.
///
- /// Each line in the section contains a name and then a edge id.
+ /// Each line in the section contains the name of the edge
+ /// and then the edge id.
///
/// \relates LemonReader
template <typename _Graph>
@@ -994,15 +1000,14 @@
/// \brief Constructor.
///
/// Constructor for EdgeReader. It creates the EdgeReader and
- /// attach it into the given LemonReader. It will resolve the edges
- /// by id with the given Resolver. The reader will read the section
- /// only if the \c _id and the \c edges_id are the same.
- template <typename Resolver>
- EdgeReader(LemonReader& _reader, const Resolver& _resolver,
+ /// 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.
+ template <typename _IdReader>
+ EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
const std::string& _id = std::string())
: Parent(_reader), id(_id),
- resolver(new ResolverReader<typename Graph::Edge, Resolver>
- (_resolver)) {}
+ idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {}
/// \brief Destructor.
///
@@ -1014,9 +1019,9 @@
public:
- /// \brief Add an edge reader command for the NodeReader.
+ /// \brief Add an edge reader command for the EdgeReader.
///
- /// Add an edge reader command for the NodeReader.
+ /// Add an edge reader command for the EdgeReader.
void readEdge(const std::string& name, Item& item) {
if (readers.find(name) != readers.end()) {
ErrorMessage msg;
@@ -1028,9 +1033,10 @@
protected:
- /// \brief Header checking function.
+ /// \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 @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);
@@ -1040,9 +1046,9 @@
return command == "@edges" && name == id;
}
- /// \brief Reading function.
+ /// \brief Reader function of the section.
///
- /// It processes the section.
+ /// It reads the content of the section.
virtual void read(std::istream& is) {
std::string line;
while (getline(is, line)) {
@@ -1051,7 +1057,7 @@
ls >> id;
typename ItemReaders::iterator it = readers.find(id);
if (it != readers.end()) {
- *(it->second) = resolver->resolve(ls);
+ *(it->second) = idReader->read(ls);
}
}
}
@@ -1062,7 +1068,7 @@
typedef std::map<std::string, Item*> ItemReaders;
ItemReaders readers;
- std::auto_ptr<ResolverReaderBase<Item> > resolver;
+ std::auto_ptr<IdReaderBase<Item> > idReader;
};
/// \ingroup io_group
@@ -1073,7 +1079,7 @@
/// attributeset_id may be empty.
///
/// The attributeset section contains several lines. Each of them starts
- /// with an attribute is and then a the value for the id.
+ /// with an attribute and then a the value for the id.
///
/// \relates LemonReader
template <typename _Traits = DefaultReaderTraits>
@@ -1132,7 +1138,8 @@
protected:
- /// \brief Header checking function.
+ /// \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,
/// and the header line's id and the attributeset's id are the same.
@@ -1144,9 +1151,9 @@
return command == "@attributes" && name == id;
}
- /// \brief Reading function.
+ /// \brief Reader function of the section.
///
- /// It processes the section.
+ /// It reads the content of the section.
void read(std::istream& is) {
std::string line;
while (getline(is, line)) {
Added: hugo/trunk/src/lemon/lemon_writer.h
==============================================================================
--- (empty file)
+++ hugo/trunk/src/lemon/lemon_writer.h Wed May 11 13:50:13 2005
@@ -0,0 +1,813 @@
+/* -*- C++ -*-
+ * src/lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup io_group
+///\file
+///\brief Lemon Format writer.
+
+#ifndef LEMON_LEMON_WRITER_H
+#define LEMON_LEMON_WRITER_H
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <map>
+#include <memory>
+
+#include <lemon/error.h>
+#include <lemon/invalid.h>
+#include <lemon/bits/item_writer.h>
+
+
+namespace lemon {
+
+ /// \ingroup io_group
+ /// \brief Lemon Format writer class.
+ ///
+ /// The Lemon Format contains several sections. We do not want to
+ /// determine what sections are in a lemon file we give only a framework
+ /// to write a section oriented format.
+ ///
+ /// In the Lemon Format each section starts with a line contains a \c \@
+ /// character on the first not white space position. This line is the
+ /// header line of the section. Each next lines belong to this section
+ /// while it does not starts with \c \@ character. This line can start a
+ /// new section or if it can close the file with the \c \@end line.
+ /// The file format ignore the empty lines and it may contain comments
+ /// started with a \c # character to the end of the line.
+ ///
+ /// The framework provides an abstract LemonWriter::SectionWriter class
+ /// what defines the interface of a SectionWriter. The SectionWriter
+ /// has the \c header() member function what gives back the header of the
+ /// section. After that it will be called the \c write() member which
+ /// should write the content of the section.
+ ///
+ /// \relates GraphWriter
+ /// \relates NodeSetWriter
+ /// \relates EdgeSetWriter
+ /// \relates NodesWriter
+ /// \relates EdgesWriter
+ /// \relates AttributeWriter
+ class LemonWriter {
+ public:
+
+ /// \brief Abstract base class for writing a section.
+ ///
+ /// This class has an \c header() member function what gives back
+ /// the header line of the section. The \c write() member should
+ /// write the content of the section to the stream.
+ class SectionWriter {
+ friend class LemonWriter;
+ protected:
+ /// \brief Constructor for SectionWriter.
+ ///
+ /// Constructor for SectionWriter. It attach this writer to
+ /// the given LemonWriter.
+ SectionWriter(LemonWriter& writer) {
+ writer.attach(*this);
+ }
+
+ /// \brief The header of section.
+ ///
+ /// It gives back the header of the section.
+ virtual std::string header() = 0;
+
+ /// \brief Writer function of the section.
+ ///
+ /// Write the content of the section.
+ virtual void write(std::ostream& os) = 0;
+ };
+
+ /// \brief Constructor for LemonWriter.
+ ///
+ /// Constructor for LemonWriter which writes to the given stream.
+ LemonWriter(std::ostream& _os)
+ : os(&_os), own_os(false) {}
+
+ /// \brief Constructor for LemonWriter.
+ ///
+ /// Constructor for LemonWriter which writes to the given file.
+ LemonWriter(const std::string& filename)
+ : os(0), own_os(true) {
+ os = new std::ofstream(filename.c_str());
+ }
+
+ /// \brief Desctructor for LemonWriter.
+ ///
+ /// Desctructor for LemonWriter.
+ ~LemonWriter() {
+ if (own_os) {
+ delete os;
+ }
+ }
+
+ private:
+ LemonWriter(const LemonWriter&);
+ void operator=(const LemonWriter&);
+
+ void attach(SectionWriter& writer) {
+ writers.push_back(&writer);
+ }
+
+ public:
+
+ /// \brief Executes the LemonWriter.
+ ///
+ /// It executes the LemonWriter.
+ void run() {
+ SectionWriters::iterator it;
+ for (it = writers.begin(); it != writers.end(); ++it) {
+ *os << (*it)->header() << std::endl;
+ (*it)->write(*os);
+ }
+ *os << "@end" << std::endl;
+ }
+
+
+ private:
+
+ std::ostream* os;
+ bool own_os;
+
+ typedef std::vector<SectionWriter*> SectionWriters;
+ SectionWriters writers;
+
+ };
+
+ /// \brief Helper class for implementing the common SectionWriters.
+ ///
+ /// Helper class for implementing the common SectionWriters.
+ class CommonSectionWriterBase : public LemonWriter::SectionWriter {
+ typedef LemonWriter::SectionWriter Parent;
+ protected:
+
+ /// \brief Constructor for CommonSectionWriterBase.
+ ///
+ /// Constructor for CommonSectionWriterBase. It attach this writer to
+ /// the given LemonWriter.
+ CommonSectionWriterBase(LemonWriter& _writer)
+ : Parent(_writer) {}
+
+ // Writers
+
+ template <typename _Item>
+ class WriterBase {
+ public:
+ typedef _Item Item;
+
+ virtual ~WriterBase() {}
+
+ virtual void write(std::ostream& os, const Item& item) = 0;
+ };
+
+
+ template <typename _Item, typename _Map, typename _Writer>
+ class MapWriter : public WriterBase<_Item> {
+ public:
+ typedef _Map Map;
+ typedef _Writer Writer;
+ typedef typename Writer::Value Value;
+ typedef _Item Item;
+
+ const Map& map;
+ Writer writer;
+
+ MapWriter(const Map& _map, const Writer& _writer)
+ : map(_map), writer(_writer) {}
+
+ virtual ~MapWriter() {}
+
+ virtual void write(std::ostream& os, const Item& item) {
+ Value value = map[item];
+ writer.write(os, value);
+ }
+
+ };
+
+
+ class ValueWriterBase {
+ public:
+ virtual void write(std::ostream&) = 0;
+ };
+
+ template <typename _Value, typename _Writer>
+ class ValueWriter : public ValueWriterBase {
+ public:
+ typedef _Value Value;
+ typedef _Writer Writer;
+
+ ValueWriter(const Value& _value, const Writer& _writer)
+ : value(_value), writer(_writer) {}
+
+ virtual void write(std::ostream& os) {
+ writer.write(is, value);
+ }
+ private:
+ const Value& value;
+ Writer writer;
+ };
+
+
+ template <typename _Item>
+ class IdWriterBase {
+ public:
+ typedef _Item Item;
+ virtual void write(std::ostream&, const Item&) const = 0;
+ };
+
+ template <typename _Item, typename _BoxedIdWriter>
+ class IdWriter : public IdWriterBase<_Item> {
+ public:
+ typedef _Item Item;
+ typedef _BoxedIdWriter BoxedIdWriter;
+
+ const BoxedIdWriter& idWriter;
+
+ IdWriter(const BoxedIdWriter& _idWriter)
+ : idWriter(_idWriter) {}
+
+ virtual void write(std::ostream& os, const Item& item) const {
+ return idWriter.writeId(os, item);
+ }
+ };
+ };
+
+ /// \ingroup io_group
+ /// \brief SectionWriter for writing a graph's nodeset.
+ ///
+ /// The lemon format can store multiple graph nodesets with several maps.
+ /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
+ /// \c nodeset_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, and
+ /// contains the mapped values for each map.
+ ///
+ /// If the nodeset 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 node 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.
+ ///
+ /// \relates LemonWriter
+ template <typename _Graph, typename _Traits = DefaultWriterTraits>
+ class NodeSetWriter : public CommonSectionWriterBase {
+ typedef CommonSectionWriterBase Parent;
+ public:
+
+ typedef _Graph Graph;
+ typedef _Traits Traits;
+ typedef typename Graph::Node Item;
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
+ /// attach it into the given LemonWriter. If the \c _forceIdMap
+ /// parameter is true then the writer will write own id map when
+ /// the user does not give "id" named map.
+ NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
+ const std::string& _id = std::string(),
+ bool _forceIdMap = true)
+ : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
+ graph(_graph), id(_id) {}
+
+ /// \brief Destructor.
+ ///
+ /// Destructor for NodeSetWriter.
+ virtual ~NodeSetWriter() {
+ typename MapWriters::iterator it;
+ for (it = writers.begin(); it != writers.end(); ++it) {
+ delete it->second;
+ }
+ }
+
+ private:
+ NodeSetWriter(const NodeSetWriter&);
+ void operator=(const NodeSetWriter&);
+
+ public:
+
+ /// \brief Add a new node map writer command for the writer.
+ ///
+ /// 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::
+ template Writer<typename Map::Value>, Map>(name, map);
+ }
+
+ /// \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>
+ NodeSetWriter& writeMap(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;
+ }
+
+ protected:
+
+ /// \brief The header of the section.
+ ///
+ /// It gives back the header of the section.
+ virtual std::string header() {
+ return "@nodeset " + 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;
+ }
+ }
+ 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::NodeIt it(graph); it != INVALID; ++it) {
+ 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 nodeset can write the ids of the nodes.
+ ///
+ /// Returns true if the nodeset can write the ids of the nodes.
+ /// It is possible only if an "id" named map was written or the
+ /// \c _forceIdMap constructor parameter was true.
+ bool isIdWriter() const {
+ return idMap != 0 || forceIdMap;
+ }
+
+ /// \brief Write the id of the given node.
+ ///
+ /// It writes the id of the given node. If there was written an "id"
+ /// named map then it will write the map value belongs to the node.
+ /// 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;
+
+ const Graph& graph;
+ std::string id;
+
+ };
+
+ /// \ingroup io_group
+ /// \brief SectionWriter for writing a graph's edgeset.
+ ///
+ /// 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.
+ ///
+ /// The first line of the section contains the names of the maps separated
+ /// with white spaces. Each next lines describes a 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
+ /// \c writeId() member will be called with a 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 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 EdgeSetWriter : public CommonSectionWriterBase {
+ typedef CommonSectionWriterBase Parent;
+ public:
+
+ typedef _Graph Graph;
+ typedef _Traits Traits;
+ typedef typename Graph::Edge Item;
+
+ /// \brief Constructor.
+ ///
+ /// 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
+ /// "id" named map.
+ template <typename NodeIdWriter>
+ EdgeSetWriter(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 EdgeSetWriter.
+ virtual ~EdgeSetWriter() {
+ typename MapWriters::iterator it;
+ for (it = writers.begin(); it != writers.end(); ++it) {
+ delete it->second;
+ }
+ }
+
+ private:
+ EdgeSetWriter(const EdgeSetWriter&);
+ void operator=(const EdgeSetWriter&);
+
+ public:
+
+ /// \brief Add a new node map writer command for the writer.
+ ///
+ /// Add a new node map writer command for the writer.
+ template <typename Map>
+ EdgeSetWriter& writeMap(std::string name, const Map& map) {
+ return writeMap<typename Traits::
+ template Writer<typename Map::Value>, Map>(name, map);
+ }
+
+ /// \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>
+ EdgeSetWriter& writeMap(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;
+ }
+
+ protected:
+
+ /// \brief The header of the section.
+ ///
+ /// It gives back the header of the section.
+ virtual std::string header() {
+ return "@edgeset " + 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::EdgeIt 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 edgeset can write the ids of the edges.
+ ///
+ /// Returns true if the edgeset can write the ids of the 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 edge.
+ ///
+ /// It writes the id of the given edge. If there was written an "id"
+ /// named map then it will write the map value belongs to the 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;
+
+ const Graph& graph;
+ std::string id;
+
+ std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
+ };
+
+ /// \ingroup io_group
+ /// \brief SectionWriter for writing labeled nodes.
+ ///
+ /// The nodes section's header line is \c \@nodes \c nodes_id, but the
+ /// \c nodes_id may be empty.
+ ///
+ /// Each line in the section contains the label of the node and
+ /// then the node id.
+ ///
+ /// \relates LemonWriter
+ template <typename _Graph>
+ class NodeWriter : public CommonSectionWriterBase {
+ typedef CommonSectionWriterBase Parent;
+ typedef _Graph Graph;
+ typedef typename Graph::Node Item;
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for NodeWriter. It creates the NodeWriter and
+ /// attach it into the given LemonWriter. The given \c _IdWriter
+ /// will write the nodes' id what can be a nodeset writer.
+ template <typename _IdWriter>
+ NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
+ const std::string& _id = std::string())
+ : Parent(_writer), id(_id),
+ idWriter(new IdWriter<typename Graph::Node, _IdWriter>(_idWriter)) {}
+
+ /// \brief Destructor.
+ ///
+ /// Destructor for NodeWriter.
+ virtual ~NodeWriter() {}
+
+ private:
+ NodeWriter(const NodeWriter&);
+ void operator=(const NodeWriter&);
+
+ public:
+
+ /// \brief Add a node writer command for the NodeWriter.
+ ///
+ /// Add a node writer command for the NodeWriter.
+ void writeNode(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 @nodes,
+ /// and the header line's id and the writer's id are the same.
+ virtual std::string header() {
+ return "@nodes " + 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 writeing labeled edges.
+ ///
+ /// The edges section's header line is \c \@edges \c edges_id, but the
+ /// \c edges_id may be empty.
+ ///
+ /// Each line in the section contains the label of the edge and
+ /// then the edge id.
+ ///
+ /// \relates LemonWriter
+ template <typename _Graph>
+ class EdgeWriter : public CommonSectionWriterBase {
+ typedef CommonSectionWriterBase Parent;
+ typedef _Graph Graph;
+ typedef typename Graph::Edge Item;
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for EdgeWriter. It creates the EdgeWriter and
+ /// attach it into the given LemonWriter. The given \c _IdWriter
+ /// will write the edges' id what can be a edgeset writer.
+ template <typename _IdWriter>
+ EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
+ const std::string& _id = std::string())
+ : Parent(_writer), id(_id),
+ idWriter(new IdWriter<typename Graph::Edge, _IdWriter>(_idWriter)) {}
+
+ /// \brief Destructor.
+ ///
+ /// Destructor for EdgeWriter.
+ virtual ~EdgeWriter() {}
+ private:
+ EdgeWriter(const EdgeWriter&);
+ void operator=(const EdgeWriter&);
+
+ public:
+
+ /// \brief Add an edge writer command for the NodeWriter.
+ ///
+ /// Add an edge writer command for the NodeWriter.
+ void writeEdge(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 @nodes,
+ /// 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 attributes.
+ ///
+ /// The lemon format can store multiple attribute set. Each set has
+ /// the header line \c \@attributes \c attributeset_id, but the
+ /// attributeset_id may be empty.
+ ///
+ /// The attributeset section contains several lines. Each of them starts
+ /// with the name of attribute and then the value.
+ ///
+ /// \relates LemonWriter
+ template <typename _Traits = DefaultWriterTraits>
+ class AttributeWriter : public CommonSectionWriterBase {
+ typedef CommonSectionWriterBase Parent;
+ typedef _Traits Traits;
+ public:
+ /// \brief Constructor.
+ ///
+ /// Constructor for AttributeWriter. It creates the AttributeWriter and
+ /// attach it into the given LemonWriter.
+ AttributeWriter(LemonWriter& _writer,
+ const std::string& _id = std::string())
+ : Parent(_writer), id(_id) {}
+
+ /// \brief Destructor.
+ ///
+ /// Destructor for AttributeWriter.
+ virtual ~AttributeWriter() {
+ typename Writers::iterator it;
+ for (it = writers.begin(); it != writers.end(); ++it) {
+ delete it->second;
+ }
+ }
+
+ private:
+ AttributeWriter(const AttributeWriter&);
+ void operator=(AttributeWriter&);
+
+ public:
+ /// \brief Add an attribute writer command for the writer.
+ ///
+ /// Add an attribute writer command for the writer.
+ template <typename Value>
+ AttributeWriter& writeAttribute(const std::string& id,
+ const Value& value) {
+ return
+ writeAttribute<typename Traits::template Writer<Value> >(id, value);
+ }
+
+ /// \brief Add an attribute writer command for the writer.
+ ///
+ /// Add an attribute writer command for the writer.
+ template <typename Writer, typename Value>
+ AttributeWriter& writeAttribute(const std::string& name,
+ const Value& value,
+ const Writer& writer = Writer()) {
+ writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
+ (value, writer)));
+ return *this;
+ }
+
+ protected:
+
+ /// \brief The header of section.
+ ///
+ /// It gives back the header of the section.
+ std::string header() {
+ return "@attributes " + id;
+ }
+
+ /// \brief Writer function of the section.
+ ///
+ /// Write the content of the section.
+ void write(std::ostream& os) {
+ typename Writers::iterator it;
+ for (it = writers.begin(); it != writers.end(); ++it) {
+ os << it->first << ' ';
+ it->second->write(os);
+ os << std::endl;
+ }
+ }
+
+ private:
+ std::string id;
+
+ typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;
+ Writers writers;
+ };
+
+
+}
+#endif
More information about the Lemon-commits
mailing list