annotate DEPENDENCIES/generic/include/boost/graph/graphml.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // Copyright (C) 2006 Tiago de Paula Peixoto <tiago@forked.de>
Chris@16 2 // Copyright (C) 2004 The Trustees of Indiana University.
Chris@16 3 //
Chris@16 4 // Use, modification and distribution is subject to the Boost Software
Chris@16 5 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 7 //
Chris@16 8 // Authors: Douglas Gregor
Chris@16 9 // Andrew Lumsdaine
Chris@16 10 // Tiago de Paula Peixoto
Chris@16 11
Chris@16 12 #ifndef BOOST_GRAPH_GRAPHML_HPP
Chris@16 13 #define BOOST_GRAPH_GRAPHML_HPP
Chris@16 14
Chris@16 15 #include <boost/config.hpp>
Chris@16 16 #include <boost/lexical_cast.hpp>
Chris@16 17 #include <boost/any.hpp>
Chris@16 18 #include <boost/type_traits/is_convertible.hpp>
Chris@16 19 #include <boost/graph/dll_import_export.hpp>
Chris@16 20 #include <boost/graph/graphviz.hpp> // for exceptions
Chris@16 21 #include <typeinfo>
Chris@16 22 #include <boost/mpl/bool.hpp>
Chris@16 23 #include <boost/mpl/vector.hpp>
Chris@16 24 #include <boost/mpl/find.hpp>
Chris@16 25 #include <boost/mpl/for_each.hpp>
Chris@16 26 #include <boost/property_tree/detail/xml_parser_utils.hpp>
Chris@16 27 #include <boost/throw_exception.hpp>
Chris@16 28 #include <exception>
Chris@16 29 #include <sstream>
Chris@16 30
Chris@16 31 namespace boost
Chris@16 32 {
Chris@16 33
Chris@16 34 /////////////////////////////////////////////////////////////////////////////
Chris@16 35 // Graph reader exceptions
Chris@16 36 /////////////////////////////////////////////////////////////////////////////
Chris@16 37 struct parse_error: public graph_exception
Chris@16 38 {
Chris@16 39 parse_error(const std::string& err) {error = err; statement = "parse error: " + error;}
Chris@16 40 virtual ~parse_error() throw() {}
Chris@16 41 virtual const char* what() const throw() {return statement.c_str();}
Chris@16 42 std::string statement;
Chris@16 43 std::string error;
Chris@16 44 };
Chris@16 45
Chris@16 46
Chris@16 47 class mutate_graph
Chris@16 48 {
Chris@16 49 public:
Chris@16 50 virtual ~mutate_graph() {}
Chris@16 51 virtual bool is_directed() const = 0;
Chris@16 52
Chris@16 53 virtual boost::any do_add_vertex() = 0;
Chris@16 54 virtual std::pair<boost::any,bool> do_add_edge(boost::any source, boost::any target) = 0;
Chris@16 55
Chris@16 56 virtual void
Chris@16 57 set_graph_property(const std::string& name, const std::string& value, const std::string& value_type) = 0;
Chris@16 58
Chris@16 59 virtual void
Chris@16 60 set_vertex_property(const std::string& name, boost::any vertex, const std::string& value, const std::string& value_type) = 0;
Chris@16 61
Chris@16 62 virtual void
Chris@16 63 set_edge_property(const std::string& name, boost::any edge, const std::string& value, const std::string& value_type) = 0;
Chris@16 64 };
Chris@16 65
Chris@16 66 template<typename MutableGraph>
Chris@16 67 class mutate_graph_impl : public mutate_graph
Chris@16 68 {
Chris@16 69 typedef typename graph_traits<MutableGraph>::vertex_descriptor vertex_descriptor;
Chris@16 70 typedef typename graph_traits<MutableGraph>::edge_descriptor edge_descriptor;
Chris@16 71
Chris@16 72 public:
Chris@16 73 mutate_graph_impl(MutableGraph& g, dynamic_properties& dp)
Chris@16 74 : m_g(g), m_dp(dp) { }
Chris@16 75
Chris@16 76 bool is_directed() const
Chris@16 77 {
Chris@16 78 return is_convertible<typename graph_traits<MutableGraph>::directed_category,
Chris@16 79 directed_tag>::value;
Chris@16 80 }
Chris@16 81
Chris@16 82 virtual any do_add_vertex()
Chris@16 83 {
Chris@16 84 return any(add_vertex(m_g));
Chris@16 85 }
Chris@16 86
Chris@16 87 virtual std::pair<any,bool> do_add_edge(any source, any target)
Chris@16 88 {
Chris@16 89 std::pair<edge_descriptor,bool> retval = add_edge(any_cast<vertex_descriptor>(source),
Chris@16 90 any_cast<vertex_descriptor>(target), m_g);
Chris@16 91 return std::make_pair(any(retval.first), retval.second);
Chris@16 92 }
Chris@16 93
Chris@16 94 virtual void
Chris@16 95 set_graph_property(const std::string& name, const std::string& value, const std::string& value_type)
Chris@16 96 {
Chris@16 97 bool type_found = false;
Chris@16 98 try
Chris@16 99 {
Chris@16 100 mpl::for_each<value_types>(put_property<MutableGraph,value_types>
Chris@16 101 (name, m_dp, m_g, value, value_type, m_type_names, type_found));
Chris@16 102 }
Chris@16 103 catch (bad_lexical_cast)
Chris@16 104 {
Chris@16 105 BOOST_THROW_EXCEPTION(
Chris@16 106 parse_error("invalid value \"" + value + "\" for key " +
Chris@16 107 name + " of type " + value_type));
Chris@16 108 }
Chris@16 109 if (!type_found)
Chris@16 110 {
Chris@16 111 BOOST_THROW_EXCEPTION(
Chris@16 112 parse_error("unrecognized type \"" + value_type +
Chris@16 113 "\" for key " + name));
Chris@16 114 }
Chris@16 115
Chris@16 116 }
Chris@16 117
Chris@16 118 virtual void
Chris@16 119 set_vertex_property(const std::string& name, any vertex, const std::string& value, const std::string& value_type)
Chris@16 120 {
Chris@16 121 bool type_found = false;
Chris@16 122 try
Chris@16 123 {
Chris@16 124 mpl::for_each<value_types>(put_property<vertex_descriptor,value_types>
Chris@16 125 (name, m_dp, any_cast<vertex_descriptor>(vertex),
Chris@16 126 value, value_type, m_type_names, type_found));
Chris@16 127 }
Chris@16 128 catch (bad_lexical_cast)
Chris@16 129 {
Chris@16 130 BOOST_THROW_EXCEPTION(
Chris@16 131 parse_error("invalid value \"" + value + "\" for key " +
Chris@16 132 name + " of type " + value_type));
Chris@16 133 }
Chris@16 134 if (!type_found)
Chris@16 135 {
Chris@16 136 BOOST_THROW_EXCEPTION(
Chris@16 137 parse_error("unrecognized type \"" + value_type +
Chris@16 138 "\" for key " + name));
Chris@16 139 }
Chris@16 140
Chris@16 141 }
Chris@16 142
Chris@16 143 virtual void
Chris@16 144 set_edge_property(const std::string& name, any edge, const std::string& value, const std::string& value_type)
Chris@16 145 {
Chris@16 146 bool type_found = false;
Chris@16 147 try
Chris@16 148 {
Chris@16 149 mpl::for_each<value_types>(put_property<edge_descriptor,value_types>
Chris@16 150 (name, m_dp, any_cast<edge_descriptor>(edge),
Chris@16 151 value, value_type, m_type_names, type_found));
Chris@16 152 }
Chris@16 153 catch (bad_lexical_cast)
Chris@16 154 {
Chris@16 155 BOOST_THROW_EXCEPTION(
Chris@16 156 parse_error("invalid value \"" + value + "\" for key " +
Chris@16 157 name + " of type " + value_type));
Chris@16 158 }
Chris@16 159 if (!type_found)
Chris@16 160 {
Chris@16 161 BOOST_THROW_EXCEPTION(
Chris@16 162 parse_error("unrecognized type \"" + value_type +
Chris@16 163 "\" for key " + name));
Chris@16 164 }
Chris@16 165 }
Chris@16 166
Chris@16 167 template <typename Key, typename ValueVector>
Chris@16 168 class put_property
Chris@16 169 {
Chris@16 170 public:
Chris@16 171 put_property(const std::string& name, dynamic_properties& dp, const Key& key,
Chris@16 172 const std::string& value, const std::string& value_type,
Chris@16 173 const char** type_names, bool& type_found)
Chris@16 174 : m_name(name), m_dp(dp), m_key(key), m_value(value),
Chris@16 175 m_value_type(value_type), m_type_names(type_names),
Chris@16 176 m_type_found(type_found) {}
Chris@16 177 template <class Value>
Chris@16 178 void operator()(Value)
Chris@16 179 {
Chris@16 180 if (m_value_type == m_type_names[mpl::find<ValueVector,Value>::type::pos::value])
Chris@16 181 {
Chris@16 182 put(m_name, m_dp, m_key, lexical_cast<Value>(m_value));
Chris@16 183 m_type_found = true;
Chris@16 184 }
Chris@16 185 }
Chris@16 186 private:
Chris@16 187 const std::string& m_name;
Chris@16 188 dynamic_properties& m_dp;
Chris@16 189 const Key& m_key;
Chris@16 190 const std::string& m_value;
Chris@16 191 const std::string& m_value_type;
Chris@16 192 const char** m_type_names;
Chris@16 193 bool& m_type_found;
Chris@16 194 };
Chris@16 195
Chris@16 196 protected:
Chris@16 197 MutableGraph& m_g;
Chris@16 198 dynamic_properties& m_dp;
Chris@16 199 typedef mpl::vector<bool, int, long, float, double, std::string> value_types;
Chris@16 200 static const char* m_type_names[];
Chris@16 201 };
Chris@16 202
Chris@16 203 template<typename MutableGraph>
Chris@16 204 const char* mutate_graph_impl<MutableGraph>::m_type_names[] = {"boolean", "int", "long", "float", "double", "string"};
Chris@16 205
Chris@16 206 void BOOST_GRAPH_DECL
Chris@16 207 read_graphml(std::istream& in, mutate_graph& g, size_t desired_idx);
Chris@16 208
Chris@16 209 template<typename MutableGraph>
Chris@16 210 void
Chris@16 211 read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp, size_t desired_idx = 0)
Chris@16 212 {
Chris@16 213 mutate_graph_impl<MutableGraph> mg(g,dp);
Chris@16 214 read_graphml(in, mg, desired_idx);
Chris@16 215 }
Chris@16 216
Chris@16 217 template <typename Types>
Chris@16 218 class get_type_name
Chris@16 219 {
Chris@16 220 public:
Chris@16 221 get_type_name(const std::type_info& type, const char** type_names, std::string& type_name)
Chris@16 222 : m_type(type), m_type_names(type_names), m_type_name(type_name) {}
Chris@16 223 template <typename Type>
Chris@16 224 void operator()(Type)
Chris@16 225 {
Chris@16 226 if (typeid(Type) == m_type)
Chris@16 227 m_type_name = m_type_names[mpl::find<Types,Type>::type::pos::value];
Chris@16 228 }
Chris@16 229 private:
Chris@16 230 const std::type_info &m_type;
Chris@16 231 const char** m_type_names;
Chris@16 232 std::string &m_type_name;
Chris@16 233 };
Chris@16 234
Chris@16 235
Chris@16 236 template <typename Graph, typename VertexIndexMap>
Chris@16 237 void
Chris@16 238 write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index,
Chris@16 239 const dynamic_properties& dp, bool ordered_vertices=false)
Chris@16 240 {
Chris@16 241 typedef typename graph_traits<Graph>::directed_category directed_category;
Chris@16 242 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
Chris@16 243 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
Chris@16 244
Chris@16 245 using boost::property_tree::xml_parser::encode_char_entities;
Chris@16 246
Chris@16 247 BOOST_STATIC_CONSTANT(bool,
Chris@16 248 graph_is_directed =
Chris@16 249 (is_convertible<directed_category*, directed_tag*>::value));
Chris@16 250
Chris@16 251 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
Chris@16 252 << "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n";
Chris@16 253
Chris@16 254 typedef mpl::vector<bool, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long, float, double, long double, std::string> value_types;
Chris@16 255 const char* type_names[] = {"boolean", "int", "int", "int", "int", "long", "long", "long", "long", "float", "double", "double", "string"};
Chris@16 256 std::map<std::string, std::string> graph_key_ids;
Chris@16 257 std::map<std::string, std::string> vertex_key_ids;
Chris@16 258 std::map<std::string, std::string> edge_key_ids;
Chris@16 259 int key_count = 0;
Chris@16 260
Chris@16 261 // Output keys
Chris@16 262 for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
Chris@16 263 {
Chris@16 264 std::string key_id = "key" + lexical_cast<std::string>(key_count++);
Chris@16 265 if (i->second->key() == typeid(Graph*))
Chris@16 266 graph_key_ids[i->first] = key_id;
Chris@16 267 else if (i->second->key() == typeid(vertex_descriptor))
Chris@16 268 vertex_key_ids[i->first] = key_id;
Chris@16 269 else if (i->second->key() == typeid(edge_descriptor))
Chris@16 270 edge_key_ids[i->first] = key_id;
Chris@16 271 else
Chris@16 272 continue;
Chris@16 273 std::string type_name = "string";
Chris@16 274 mpl::for_each<value_types>(get_type_name<value_types>(i->second->value(), type_names, type_name));
Chris@16 275 out << " <key id=\"" << encode_char_entities(key_id) << "\" for=\""
Chris@16 276 << (i->second->key() == typeid(Graph*) ? "graph" : (i->second->key() == typeid(vertex_descriptor) ? "node" : "edge")) << "\""
Chris@16 277 << " attr.name=\"" << i->first << "\""
Chris@16 278 << " attr.type=\"" << type_name << "\""
Chris@16 279 << " />\n";
Chris@16 280 }
Chris@16 281
Chris@16 282 out << " <graph id=\"G\" edgedefault=\""
Chris@16 283 << (graph_is_directed ? "directed" : "undirected") << "\""
Chris@16 284 << " parse.nodeids=\"" << (ordered_vertices ? "canonical" : "free") << "\""
Chris@16 285 << " parse.edgeids=\"canonical\" parse.order=\"nodesfirst\">\n";
Chris@16 286
Chris@16 287 // Output graph data
Chris@16 288 for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
Chris@16 289 {
Chris@16 290 if (i->second->key() == typeid(Graph*))
Chris@16 291 {
Chris@16 292 // The const_cast here is just to get typeid correct for property
Chris@16 293 // map key; the graph should not be mutated using it.
Chris@16 294 out << " <data key=\"" << graph_key_ids[i->first] << "\">"
Chris@16 295 << encode_char_entities(i->second->get_string(const_cast<Graph*>(&g))) << "</data>\n";
Chris@16 296 }
Chris@16 297 }
Chris@16 298
Chris@16 299 typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
Chris@16 300 vertex_iterator v, v_end;
Chris@16 301 for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v)
Chris@16 302 {
Chris@16 303 out << " <node id=\"n" << get(vertex_index, *v) << "\">\n";
Chris@16 304 // Output data
Chris@16 305 for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
Chris@16 306 {
Chris@16 307 if (i->second->key() == typeid(vertex_descriptor))
Chris@16 308 {
Chris@16 309 out << " <data key=\"" << vertex_key_ids[i->first] << "\">"
Chris@16 310 << encode_char_entities(i->second->get_string(*v)) << "</data>\n";
Chris@16 311 }
Chris@16 312 }
Chris@16 313 out << " </node>\n";
Chris@16 314 }
Chris@16 315
Chris@16 316 typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
Chris@16 317 edge_iterator e, e_end;
Chris@16 318 typename graph_traits<Graph>::edges_size_type edge_count = 0;
Chris@16 319 for (boost::tie(e, e_end) = edges(g); e != e_end; ++e)
Chris@16 320 {
Chris@16 321 out << " <edge id=\"e" << edge_count++ << "\" source=\"n"
Chris@16 322 << get(vertex_index, source(*e, g)) << "\" target=\"n"
Chris@16 323 << get(vertex_index, target(*e, g)) << "\">\n";
Chris@16 324
Chris@16 325 // Output data
Chris@16 326 for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
Chris@16 327 {
Chris@16 328 if (i->second->key() == typeid(edge_descriptor))
Chris@16 329 {
Chris@16 330 out << " <data key=\"" << edge_key_ids[i->first] << "\">"
Chris@16 331 << encode_char_entities(i->second->get_string(*e)) << "</data>\n";
Chris@16 332 }
Chris@16 333 }
Chris@16 334 out << " </edge>\n";
Chris@16 335 }
Chris@16 336
Chris@16 337 out << " </graph>\n"
Chris@16 338 << "</graphml>\n";
Chris@16 339 }
Chris@16 340
Chris@16 341
Chris@16 342 template <typename Graph>
Chris@16 343 void
Chris@16 344 write_graphml(std::ostream& out, const Graph& g, const dynamic_properties& dp,
Chris@16 345 bool ordered_vertices=false)
Chris@16 346 {
Chris@16 347 write_graphml(out, g, get(vertex_index, g), dp, ordered_vertices);
Chris@16 348 }
Chris@16 349
Chris@16 350 } // boost namespace
Chris@16 351
Chris@16 352 #endif // BOOST_GRAPH_GRAPHML_HPP