deba@1137: /* -*- C++ -*- deba@1137: * src/lemon/graph_writer.h - Part of LEMON, a generic C++ optimization library deba@1137: * alpar@1164: * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport deba@1137: * (Egervary Combinatorial Optimization Research Group, EGRES). deba@1137: * deba@1137: * Permission to use, modify and distribute this software is granted deba@1137: * provided that this copyright notice appears in all copies. For deba@1137: * precise terms see the accompanying LICENSE file. deba@1137: * deba@1137: * This software is provided "AS IS" with no warranty of any kind, deba@1137: * express or implied, and with no claim as to its suitability for any deba@1137: * purpose. deba@1137: * deba@1137: */ deba@1137: deba@1137: ///\ingroup gio deba@1137: ///\file deba@1137: ///\brief Graph writer. deba@1137: deba@1137: deba@1137: #include deba@1137: #include deba@1137: deba@1137: #include deba@1137: #include deba@1137: deba@1137: #include deba@1137: deba@1137: #include deba@1137: #include deba@1137: deba@1137: deba@1137: namespace lemon { deba@1137: deba@1137: /// \brief Standard WriterTraits for the GraphWriter class. deba@1137: /// deba@1137: /// Standard WriterTraits for the GraphWriter class. deba@1137: /// It defines standard writing method for all type of value. deba@1137: struct DefaultWriterTraits { deba@1137: deba@1137: /// \brief Template class for writing an value. deba@1137: /// deba@1137: /// Template class for writing an value. deba@1137: template deba@1137: struct Writer { deba@1137: /// The value type. deba@1137: typedef _Value Value; deba@1137: deba@1188: /// \brief Writes a value to the given stream. deba@1137: /// deba@1188: /// Writes a value to the given stream. deba@1137: void write(std::ostream& os, const Value& value) { deba@1137: os << value << '\t'; deba@1137: } deba@1137: }; deba@1137: deba@1137: }; deba@1137: deba@1137: deba@1137: /// \brief Writer class for quoted strings. deba@1137: /// deba@1137: /// Writer class for quoted strings. It can process the escape deba@1137: /// sequences in the string. deba@1137: class QuotedStringWriter { deba@1137: public: deba@1137: typedef std::string Value; deba@1137: deba@1137: /// \brief Constructor for the writer. deba@1137: /// deba@1137: /// Constructor for the writer. If the given parameter is true deba@1137: /// the writer creates escape sequences from special characters. deba@1137: QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {} deba@1137: deba@1188: /// \brief Writes a quoted string to the given stream. deba@1137: /// deba@1188: /// Writes a quoted string to the given stream. deba@1137: void write(std::ostream& os, const std::string& value) { deba@1137: os << "\""; deba@1137: if (escaped) { deba@1137: ostringstream ls; deba@1137: for (int i = 0; i < (int)value.size(); ++i) { deba@1137: writeEscape(ls, value[i]); deba@1137: } deba@1137: os << ls.str(); deba@1137: } else { deba@1137: os << value; deba@1137: } deba@1137: os << "\""; deba@1137: } deba@1137: deba@1137: private: deba@1137: deba@1137: static void writeEscape(std::ostream& os, char c) { deba@1137: switch (c) { deba@1137: case '\\': deba@1137: os << "\\\\"; deba@1137: return; deba@1137: case '\"': deba@1137: os << "\\\""; deba@1137: return; deba@1137: case '\'': deba@1137: os << "\\\'"; deba@1137: return; deba@1137: case '\?': deba@1137: os << "\\\?"; deba@1137: return; deba@1137: case '\a': deba@1137: os << "\\a"; deba@1137: return; deba@1137: case '\b': deba@1137: os << "\\b"; deba@1137: return; deba@1137: case '\f': deba@1137: os << "\\f"; deba@1137: return; deba@1137: case '\r': deba@1137: os << "\\r"; deba@1137: return; deba@1137: case '\n': deba@1137: os << "\\n"; deba@1137: return; deba@1137: case '\t': deba@1137: os << "\\t"; deba@1137: return; deba@1137: case '\v': deba@1137: os << "\\v"; deba@1137: return; deba@1137: default: deba@1137: if (c < 0x20) { deba@1137: os << '\\' << oct << (int)c; deba@1137: } else { deba@1137: os << c; deba@1137: } deba@1137: return; deba@1137: } deba@1137: } deba@1137: private: deba@1137: bool escaped; deba@1137: }; deba@1137: deba@1137: deba@1137: /// \brief The graph writer class. deba@1137: /// deba@1137: /// The writer class for the graph output. alpar@1138: /// \see \ref GraphReader alpar@1138: /// \see \ref graph-io-page deba@1137: template deba@1137: class GraphWriter { deba@1137: public: deba@1137: deba@1137: typedef _Graph Graph; deba@1137: typedef typename Graph::Node Node; deba@1137: typedef typename Graph::NodeIt NodeIt; deba@1137: typedef typename Graph::Edge Edge; deba@1137: typedef typename Graph::EdgeIt EdgeIt; deba@1137: deba@1137: typedef _WriterTraits WriterTraits; deba@1137: deba@1137: /// \brief Construct a new GraphWriter. deba@1137: /// deba@1137: /// Construct a new GraphWriter. It writes from the given map, deba@1137: /// it constructs the given map and it use the given writer as the deba@1137: /// default skipper. deba@1137: GraphWriter(std::ostream& _os, Graph& _graph) : os(_os), graph(_graph) {} deba@1137: deba@1137: deba@1137: /// \brief Destruct the graph writer. deba@1137: /// deba@1137: /// Destruct the graph writer. deba@1137: ~GraphWriter() { deba@1137: for (typename NodeMapWriters::iterator it = node_map_writers.begin(); deba@1137: it != node_map_writers.end(); ++it) { deba@1137: delete it->second; deba@1137: } deba@1137: deba@1137: for (typename EdgeMapWriters::iterator it = edge_map_writers.begin(); deba@1137: it != edge_map_writers.end(); ++it) { deba@1137: delete it->second; deba@1137: } deba@1137: deba@1137: } deba@1137: deba@1137: // Node map rules deba@1137: deba@1137: /// \brief Add a new node map writer command for the writer. deba@1137: /// deba@1137: /// Add a new node map writer command for the writer. deba@1137: template deba@1137: GraphWriter& addNodeMap(std::string name, const Map& map) { deba@1137: return addNodeMap, Map>(name, map); deba@1137: } deba@1137: deba@1137: /// \brief Add a new node map writer command for the writer. deba@1137: /// deba@1137: /// Add a new node map writer command for the writer. deba@1137: template deba@1137: GraphWriter& addNodeMap(std::string name, const Map& map, deba@1137: const Writer& writer = Writer()) { deba@1137: node_map_writers.push_back( deba@1137: make_pair(name, new MapWriter(map, writer))); deba@1137: return *this; deba@1137: } deba@1137: deba@1137: // Edge map rules deba@1137: deba@1137: /// \brief Add a new edge map writer command for the writer. deba@1137: /// deba@1137: /// Add a new edge map writer command for the writer. deba@1137: template deba@1137: GraphWriter& addEdgeMap(std::string name, const Map& map) { deba@1137: return addEdgeMap, Map>(name, map); deba@1137: } deba@1137: deba@1137: deba@1137: /// \brief Add a new edge map writer command for the writer. deba@1137: /// deba@1137: /// Add a new edge map writer command for the writer. deba@1137: template deba@1137: GraphWriter& addEdgeMap(std::string name, deba@1137: const Map& map, const Writer& writer = Writer()) { deba@1137: edge_map_writers.push_back(make_pair(name, deba@1137: new MapWriter(map, writer))); deba@1137: return *this; deba@1137: } deba@1137: deba@1137: /// \brief Add a new labeled node writer for the writer. deba@1137: /// deba@1137: /// Add a new labeled node writer for the writer. deba@1137: GraphWriter& addNode(std::string name, const Node& node) { deba@1137: node_writers.push_back(make_pair(name, node)); deba@1137: return *this; deba@1137: } deba@1137: deba@1137: /// \brief Add a new labeled edge writer for the writer. deba@1137: /// deba@1137: /// Add a new labeled edge writer for the writer. deba@1137: GraphWriter& addEdge(std::string name, const Edge& edge) { deba@1137: edge_writers.push_back(make_pair(name, edge)); deba@1137: return *this; deba@1137: } deba@1137: deba@1137: /// \brief Executes the writer commands. deba@1137: /// deba@1137: /// Executes the writer commands. deba@1137: void run() { deba@1137: writeNodeSet(); deba@1137: writeEdgeSet(); deba@1137: writeNodes(); deba@1137: writeEdges(); deba@1137: os << "@end" << std::endl; deba@1137: } deba@1137: deba@1137: private: deba@1137: deba@1137: void writeNodeSet() { deba@1137: if (node_map_writers.size() == 0) return; deba@1137: os << "@nodeset" << std::endl; deba@1137: for (int i = 0; i < (int)node_map_writers.size(); ++i) { deba@1137: os << node_map_writers[i].first << '\t'; deba@1137: } deba@1137: os << std::endl; deba@1137: for (NodeIt it(graph); it != INVALID; ++it) { deba@1137: for (int i = 0; i < (int)node_map_writers.size(); ++i) { deba@1137: node_map_writers[i].second->write(os, it); deba@1137: } deba@1137: os << std::endl; deba@1137: } deba@1137: deba@1137: } deba@1137: deba@1137: void writeEdgeSet() { deba@1137: if (edge_map_writers.size() == 0) return; deba@1137: if (node_map_writers.size() == 0) { deba@1188: // ErrorMessage message; deba@1188: // message << "Missing node id map"; deba@1188: // throw IOLogicError(message); deba@1137: } deba@1137: os << "@edgeset" << std::endl; deba@1137: os << "\t\t"; deba@1137: for (int i = 0; i < (int)edge_map_writers.size(); ++i) { deba@1137: os << edge_map_writers[i].first << '\t'; deba@1137: } deba@1137: os << std::endl; deba@1137: for (EdgeIt it(graph); it != INVALID; ++it) { deba@1137: node_map_writers[0].second->write(os, graph.source(it)); deba@1137: node_map_writers[0].second->write(os, graph.target(it)); deba@1137: for (int i = 0; i < (int)edge_map_writers.size(); ++i) { deba@1137: edge_map_writers[i].second->write(os, it); deba@1137: } deba@1137: os << std::endl; deba@1137: } deba@1137: } deba@1137: deba@1137: void writeNodes() { deba@1137: if (node_writers.size() == 0) return; deba@1137: if (node_map_writers.size() == 0) { deba@1188: // throw Exception() << "Missing node id map"; deba@1137: } deba@1137: os << "@nodes" << std::endl; deba@1137: for (int i = 0; i < (int)node_writers.size(); ++i) { deba@1137: os << node_writers[i].first << '\t'; deba@1137: node_map_writers[0].second->write(os, node_writers[i].second); deba@1137: os << std::endl; deba@1137: } deba@1137: } deba@1137: deba@1137: void writeEdges() { deba@1137: if (edge_writers.size() == 0) return; deba@1137: if (edge_map_writers.size() == 0) { deba@1188: // throw Exception() << "Missing edge id map"; deba@1137: } deba@1137: os << "@edges" << std::endl; deba@1137: for (int i = 0; i < (int)edge_writers.size(); ++i) { deba@1137: os << edge_writers[i].first << '\t'; deba@1137: edge_map_writers[0].second->write(os, edge_writers[i].second); deba@1137: os << std::endl; deba@1137: } deba@1137: } deba@1137: deba@1137: // Writers deba@1137: deba@1137: template deba@1137: class WriterBase { deba@1137: public: deba@1137: typedef _Item Item; deba@1137: virtual void write(std::ostream&, const Item&) = 0; deba@1137: }; deba@1137: deba@1137: template deba@1137: class MapWriter : public WriterBase<_Item> { deba@1137: public: deba@1137: typedef _Map Map; deba@1137: typedef _Writer Writer; deba@1137: typedef typename Writer::Value Value; deba@1137: typedef _Item Item; deba@1137: deba@1137: const Map& map; deba@1137: Writer writer; deba@1137: deba@1137: MapWriter(const Map& _map, const Writer& _writer) deba@1137: : map(_map), writer(_writer) {} deba@1137: deba@1137: deba@1137: virtual void write(std::ostream& os, const Item& item) { deba@1137: writer.write(os, map[item]); deba@1137: } deba@1137: deba@1137: }; deba@1137: deba@1137: deba@1137: deba@1137: typedef std::vector< std::pair*> > deba@1137: NodeMapWriters; deba@1137: NodeMapWriters node_map_writers; deba@1137: deba@1137: typedef std::vector< std::pair*> > deba@1137: EdgeMapWriters; deba@1137: EdgeMapWriters edge_map_writers; deba@1137: deba@1137: typedef std::vector > NodeWriters; deba@1137: NodeWriters node_writers; deba@1137: deba@1137: typedef std::vector > EdgeWriters; deba@1137: EdgeWriters edge_writers; deba@1137: deba@1137: std::ostream& os; deba@1137: Graph& graph; deba@1137: deba@1137: }; deba@1137: deba@1137: deba@1137: }