/* -*- C++ -*- * src/lemon/graph_writer.h - Part of LEMON, a generic C++ optimization library * * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Combinatorial Optimization Research Group, 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 gio ///\file ///\brief Graph writer. #ifndef LEMON_GRAPH_WRITER_H #define LEMON_GRAPH_WRITER_H #include #include #include #include #include #include #include #include namespace lemon { /// \brief Standard WriterTraits for the GraphWriter class. /// /// Standard WriterTraits for the GraphWriter class. /// It defines standard writing method for all type of value. struct DefaultWriterTraits { /// \brief Template class for writing an value. /// /// Template class for writing an value. template 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 Writer class for quoted strings. /// /// Writer class for quoted strings. It can process the escape /// sequences in the string. 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) { 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 << '\\' << oct << (int)c; } else { os << c; } return; } } private: bool escaped; }; /// \brief The graph writer class. /// /// The writer class for the graph output. /// \see \ref GraphReader /// \see \ref graph-io-page template class GraphWriter { public: 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. GraphWriter(std::ostream& _os, const Graph& _graph) : os(_os), graph(_graph) {} /// \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; } } // 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 GraphWriter& addNodeMap(std::string name, const Map& map) { return addNodeMap, 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 GraphWriter& addNodeMap(std::string name, const Map& map, const Writer& writer = Writer()) { node_map_writers.push_back( make_pair(name, new MapWriter(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 GraphWriter& addEdgeMap(std::string name, const Map& map) { return addEdgeMap, Map>(name, map); } /// \brief Add a new edge map writer command for the writer. /// /// Add a new edge map writer command for the writer. template GraphWriter& addEdgeMap(std::string name, const Map& map, const Writer& writer = Writer()) { edge_map_writers.push_back(make_pair(name, new MapWriter(map, writer))); return *this; } /// \brief Add a new labeled node writer for the writer. /// /// Add a new labeled node writer for the writer. GraphWriter& addNode(std::string name, const Node& node) { node_writers.push_back(make_pair(name, node)); return *this; } /// \brief Add a new labeled edge writer for the writer. /// /// Add a new labeled edge writer for the writer. GraphWriter& addEdge(std::string name, const Edge& edge) { edge_writers.push_back(make_pair(name, edge)); return *this; } /// \brief Executes the writer commands. /// /// Executes the writer commands. void run() { writeNodeSet(); writeEdgeSet(); writeNodes(); writeEdges(); os << "@end" << std::endl; } private: void writeNodeSet() { if (node_map_writers.size() == 0) return; os << "@nodeset" << std::endl; for (int i = 0; i < (int)node_map_writers.size(); ++i) { os << node_map_writers[i].first << '\t'; } 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() { if (edge_map_writers.size() == 0) return; if (node_map_writers.size() == 0) { // ErrorMessage message; // message << "Missing node id map"; // throw IOLogicError(message); } os << "@edgeset" << std::endl; os << "\t\t"; for (int i = 0; i < (int)edge_map_writers.size(); ++i) { os << edge_map_writers[i].first << '\t'; } os << std::endl; for (EdgeIt it(graph); it != INVALID; ++it) { node_map_writers[0].second->write(os, graph.source(it)); node_map_writers[0].second->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() { if (node_writers.size() == 0) return; if (node_map_writers.size() == 0) { // throw Exception() << "Missing node id map"; } os << "@nodes" << std::endl; for (int i = 0; i < (int)node_writers.size(); ++i) { os << node_writers[i].first << '\t'; node_map_writers[0].second->write(os, node_writers[i].second); os << std::endl; } } void writeEdges() { if (edge_writers.size() == 0) return; if (edge_map_writers.size() == 0) { // throw Exception() << "Missing edge id map"; } os << "@edges" << std::endl; for (int i = 0; i < (int)edge_writers.size(); ++i) { os << edge_writers[i].first << '\t'; edge_map_writers[0].second->write(os, edge_writers[i].second); os << std::endl; } } // Writers template class WriterBase { public: typedef _Item Item; virtual void write(std::ostream&, const Item&) = 0; }; template 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]); } }; typedef std::vector< std::pair*> > NodeMapWriters; NodeMapWriters node_map_writers; typedef std::vector< std::pair*> > EdgeMapWriters; EdgeMapWriters edge_map_writers; typedef std::vector > NodeWriters; NodeWriters node_writers; typedef std::vector > EdgeWriters; EdgeWriters edge_writers; std::ostream& os; const Graph& graph; }; /// Ready to use writer function. template void writeGraph(std::ostream& os, const Graph &g, const CapacityMap& capacity, const typename Graph::Node &s, const typename Graph::Node &t, const CostMap& cost) { GraphWriter reader(os, g); IdMap nodeIdMap(g); reader.addNodeMap("id", nodeIdMap); IdMap edgeIdMap(g); reader.addEdgeMap("id", edgeIdMap); reader.addEdgeMap("capacity", capacity); reader.addEdgeMap("cost", cost); reader.addNode("source", s); reader.addNode("target", t); reader.run(); } /// Ready to use writer function. template void writeGraph(std::ostream& os, const Graph &g, const CapacityMap& capacity, const typename Graph::Node &s, const typename Graph::Node &t) { GraphWriter reader(os, g); IdMap nodeIdMap(g); reader.addNodeMap("id", nodeIdMap); IdMap edgeIdMap(g); reader.addEdgeMap("id", edgeIdMap); reader.addEdgeMap("capacity", capacity); reader.addNode("source", s); reader.addNode("target", t); reader.run(); } /// Ready to use writer function. template void writeGraph(std::ostream& os, const Graph &g, const CapacityMap& capacity, const typename Graph::Node &s) { GraphWriter reader(os, g); IdMap nodeIdMap(g); reader.addNodeMap("id", nodeIdMap); IdMap edgeIdMap(g); reader.addEdgeMap("id", edgeIdMap); reader.addEdgeMap("capacity", capacity); reader.addNode("source", s); reader.run(); } /// Ready to use writer function. template void writeGraph(std::ostream& os, const Graph &g, const CapacityMap& capacity) { GraphWriter reader(os, g); IdMap nodeIdMap(g); reader.addNodeMap("id", nodeIdMap); IdMap edgeIdMap(g); reader.addEdgeMap("id", edgeIdMap); reader.addEdgeMap("capacity", capacity); reader.run(); } /// Ready to use writer function. template void writeGraph(std::ostream& os, const Graph &g) { GraphWriter reader(os, g); IdMap nodeIdMap(g); reader.addNodeMap("id", nodeIdMap); IdMap edgeIdMap(g); reader.addEdgeMap("id", edgeIdMap); reader.run(); } } #endif