/* -*- C++ -*- * src/lemon/graph_writer.h - Part of LEMON, a generic C++ optimization library * * Copyright (C) 2004 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. #include #include #include #include #include #include #include namespace lemon { struct DefaultWriterTraits { template struct Writer { typedef _Value Value; void write(std::ostream& os, const Value& value) { os << value << '\t'; } }; }; class QuotedStringWriter { public: typedef std::string Value; QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {} void write(std::ostream& os, const std::string& value) { char c; os << "\""; if (escaped) { ostringstream ls; for (int i = 0; i < 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; }; // Graph writer 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; GraphWriter(std::ostream& _os, Graph& _graph) : os(_os), graph(_graph) {} ~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 template GraphWriter& writeNodeMap(std::string name, const Map& map) { return writeNodeMap, Map>(name, map); } template GraphWriter& writeNodeMap(std::string name, const Map& map, const Writer& writer = Writer()) { // if (node_map_writers.find(name) != node_map_writers.end()) { // throw Exception() << "Multiple write rule for node map: " << name; // } node_map_writers.push_back(make_pair(name, new MapWriter(map, writer))); return *this; } // Edge map rules template GraphWriter& writeEdgeMap(std::string name, const Map& map) { return writeEdgeMap, Map>(name, map); } template GraphWriter& writeEdgeMap(std::string name, const Map& map, const Writer& writer = Writer()) { // if (edge_map_writers.find(name) != edge_map_writers.end()) { // throw Exception() << "Multiple write rule for edge map: " << name; // } edge_map_writers.push_back(make_pair(name, new MapWriter(map, writer))); return *this; } // Node rules GraphWriter& writeNode(std::string name, const Node& node) { // if (node_writers.find(name) != node_writers.end()) { // throw Exception() << "Multiple write rule for node"; // } node_writers.push_back(make_pair(name, node)); } // Edge rules GraphWriter& writeEdge(std::string name, const Edge& edge) { // if (edge_writers.find(name) != edge_writers.end()) { // throw Exception() << "Multiple write rule for edge"; // } edge_writers.push_back(make_pair(name, edge)); } void write() { 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 < 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 < 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) { throw Exception() << "Missing node id map"; } os << "@edgeset" << std::endl; os << "\t\t"; for (int i = 0; i < 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 < 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 < 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 < 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) { Value value; 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; Graph& graph; }; }