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