Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-11 08:12:58

0001 // Copyright (C) 2006  Tiago de Paula Peixoto <tiago@forked.de>
0002 // Copyright (C) 2004  The Trustees of Indiana University.
0003 //
0004 // Use, modification and distribution is subject to the Boost Software
0005 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 //  Authors: Douglas Gregor
0009 //           Andrew Lumsdaine
0010 //           Tiago de Paula Peixoto
0011 
0012 #ifndef BOOST_GRAPH_GRAPHML_HPP
0013 #define BOOST_GRAPH_GRAPHML_HPP
0014 
0015 #include <boost/config.hpp>
0016 #include <boost/lexical_cast.hpp>
0017 #include <boost/any.hpp>
0018 #include <boost/type_traits/is_convertible.hpp>
0019 #include <boost/graph/adjacency_list.hpp>
0020 #include <boost/graph/dll_import_export.hpp>
0021 #include <boost/graph/exception.hpp>
0022 #include <boost/graph/graph_traits.hpp>
0023 
0024 #include <boost/mpl/bool.hpp>
0025 #include <boost/mpl/vector.hpp>
0026 #include <boost/mpl/find.hpp>
0027 #include <boost/mpl/for_each.hpp>
0028 #include <boost/property_map/dynamic_property_map.hpp>
0029 #include <boost/property_tree/detail/xml_parser_utils.hpp>
0030 #include <boost/throw_exception.hpp>
0031 #include <exception>
0032 #include <sstream>
0033 #include <typeinfo>
0034 
0035 namespace boost
0036 {
0037 
0038 /////////////////////////////////////////////////////////////////////////////
0039 // Graph reader exceptions
0040 /////////////////////////////////////////////////////////////////////////////
0041 struct BOOST_SYMBOL_VISIBLE parse_error : public graph_exception
0042 {
0043     parse_error(const std::string& err)
0044     {
0045         error = err;
0046         statement = "parse error: " + error;
0047     }
0048     ~parse_error() throw() BOOST_OVERRIDE {}
0049     const char* what() const throw() BOOST_OVERRIDE { return statement.c_str(); }
0050     std::string statement;
0051     std::string error;
0052 };
0053 
0054 class mutate_graph
0055 {
0056 public:
0057     virtual ~mutate_graph() {}
0058     virtual bool is_directed() const = 0;
0059 
0060     virtual boost::any do_add_vertex() = 0;
0061     virtual std::pair< boost::any, bool > do_add_edge(
0062         boost::any source, boost::any target)
0063         = 0;
0064 
0065     virtual void set_graph_property(const std::string& name,
0066         const std::string& value, const std::string& value_type)
0067         = 0;
0068 
0069     virtual void set_vertex_property(const std::string& name, boost::any vertex,
0070         const std::string& value, const std::string& value_type)
0071         = 0;
0072 
0073     virtual void set_edge_property(const std::string& name, boost::any edge,
0074         const std::string& value, const std::string& value_type)
0075         = 0;
0076 };
0077 
0078 template < typename MutableGraph > class mutate_graph_impl : public mutate_graph
0079 {
0080     typedef typename graph_traits< MutableGraph >::vertex_descriptor
0081         vertex_descriptor;
0082     typedef
0083         typename graph_traits< MutableGraph >::edge_descriptor edge_descriptor;
0084 
0085 public:
0086     mutate_graph_impl(MutableGraph& g, dynamic_properties& dp)
0087     : m_g(g), m_dp(dp)
0088     {
0089     }
0090 
0091     bool is_directed() const BOOST_OVERRIDE
0092     {
0093         return is_convertible<
0094             typename graph_traits< MutableGraph >::directed_category,
0095             directed_tag >::value;
0096     }
0097 
0098     any do_add_vertex() BOOST_OVERRIDE { return any(add_vertex(m_g)); }
0099 
0100     std::pair< any, bool > do_add_edge(any source, any target) BOOST_OVERRIDE
0101     {
0102         std::pair< edge_descriptor, bool > retval
0103             = add_edge(any_cast< vertex_descriptor >(source),
0104                 any_cast< vertex_descriptor >(target), m_g);
0105         return std::make_pair(any(retval.first), retval.second);
0106     }
0107 
0108     void set_graph_property(const std::string& name,
0109         const std::string& value, const std::string& value_type) BOOST_OVERRIDE
0110     {
0111         bool type_found = false;
0112         try
0113         {
0114             mpl::for_each< value_types >(
0115                 put_property< MutableGraph*, value_types >(name, m_dp, &m_g,
0116                     value, value_type, m_type_names, type_found));
0117         }
0118         catch (const bad_lexical_cast&)
0119         {
0120             BOOST_THROW_EXCEPTION(parse_error("invalid value \"" + value
0121                 + "\" for key " + name + " of type " + value_type));
0122         }
0123         if (!type_found)
0124         {
0125             BOOST_THROW_EXCEPTION(parse_error(
0126                 "unrecognized type \"" + value_type + "\" for key " + name));
0127         }
0128     }
0129 
0130     void set_vertex_property(const std::string& name, any vertex,
0131         const std::string& value, const std::string& value_type) BOOST_OVERRIDE
0132     {
0133         bool type_found = false;
0134         try
0135         {
0136             mpl::for_each< value_types >(
0137                 put_property< vertex_descriptor, value_types >(name, m_dp,
0138                     any_cast< vertex_descriptor >(vertex), value, value_type,
0139                     m_type_names, type_found));
0140         }
0141         catch (const bad_lexical_cast&)
0142         {
0143             BOOST_THROW_EXCEPTION(parse_error("invalid value \"" + value
0144                 + "\" for key " + name + " of type " + value_type));
0145         }
0146         if (!type_found)
0147         {
0148             BOOST_THROW_EXCEPTION(parse_error(
0149                 "unrecognized type \"" + value_type + "\" for key " + name));
0150         }
0151     }
0152 
0153     void set_edge_property(const std::string& name, any edge,
0154         const std::string& value, const std::string& value_type) BOOST_OVERRIDE
0155     {
0156         bool type_found = false;
0157         try
0158         {
0159             mpl::for_each< value_types >(
0160                 put_property< edge_descriptor, value_types >(name, m_dp,
0161                     any_cast< edge_descriptor >(edge), value, value_type,
0162                     m_type_names, type_found));
0163         }
0164         catch (const bad_lexical_cast&)
0165         {
0166             BOOST_THROW_EXCEPTION(parse_error("invalid value \"" + value
0167                 + "\" for key " + name + " of type " + value_type));
0168         }
0169         if (!type_found)
0170         {
0171             BOOST_THROW_EXCEPTION(parse_error(
0172                 "unrecognized type \"" + value_type + "\" for key " + name));
0173         }
0174     }
0175 
0176     template < typename Key, typename ValueVector > class put_property
0177     {
0178     public:
0179         put_property(const std::string& name, dynamic_properties& dp,
0180             const Key& key, const std::string& value,
0181             const std::string& value_type, const char** type_names,
0182             bool& type_found)
0183         : m_name(name)
0184         , m_dp(dp)
0185         , m_key(key)
0186         , m_value(value)
0187         , m_value_type(value_type)
0188         , m_type_names(type_names)
0189         , m_type_found(type_found)
0190         {
0191         }
0192         template < class Value > void operator()(Value)
0193         {
0194             if (m_value_type
0195                 == m_type_names[mpl::find< ValueVector,
0196                     Value >::type::pos::value])
0197             {
0198                 put(m_name, m_dp, m_key, lexical_cast< Value >(m_value));
0199                 m_type_found = true;
0200             }
0201         }
0202 
0203     private:
0204         const std::string& m_name;
0205         dynamic_properties& m_dp;
0206         const Key& m_key;
0207         const std::string& m_value;
0208         const std::string& m_value_type;
0209         const char** m_type_names;
0210         bool& m_type_found;
0211     };
0212 
0213 protected:
0214     MutableGraph& m_g;
0215     dynamic_properties& m_dp;
0216     typedef mpl::vector< bool, int, long, float, double, std::string >
0217         value_types;
0218     static const char* m_type_names[];
0219 };
0220 
0221 template < typename MutableGraph >
0222 const char* mutate_graph_impl< MutableGraph >::m_type_names[]
0223     = { "boolean", "int", "long", "float", "double", "string" };
0224 
0225 void BOOST_GRAPH_DECL read_graphml(
0226     std::istream& in, mutate_graph& g, size_t desired_idx);
0227 
0228 template < typename MutableGraph >
0229 void read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp,
0230     size_t desired_idx = 0)
0231 {
0232     mutate_graph_impl< MutableGraph > mg(g, dp);
0233     read_graphml(in, mg, desired_idx);
0234 }
0235 
0236 template < typename Types > class get_type_name
0237 {
0238 public:
0239     get_type_name(const std::type_info& type, const char** type_names,
0240         std::string& type_name)
0241     : m_type(type), m_type_names(type_names), m_type_name(type_name)
0242     {
0243     }
0244     template < typename Type > void operator()(Type)
0245     {
0246         if (typeid(Type) == m_type)
0247             m_type_name
0248                 = m_type_names[mpl::find< Types, Type >::type::pos::value];
0249     }
0250 
0251 private:
0252     const std::type_info& m_type;
0253     const char** m_type_names;
0254     std::string& m_type_name;
0255 };
0256 
0257 template < typename Graph, typename VertexIndexMap >
0258 void write_graphml(std::ostream& out, const Graph& g,
0259     VertexIndexMap vertex_index, const dynamic_properties& dp,
0260     bool ordered_vertices = false)
0261 {
0262     typedef typename graph_traits< Graph >::directed_category directed_category;
0263     typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor;
0264     typedef typename graph_traits< Graph >::vertex_descriptor vertex_descriptor;
0265 
0266     using boost::property_tree::xml_parser::encode_char_entities;
0267 
0268     BOOST_STATIC_CONSTANT(bool,
0269         graph_is_directed
0270         = (is_convertible< directed_category*, directed_tag* >::value));
0271 
0272     out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
0273         << "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" "
0274            "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
0275            "xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns "
0276            "http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n";
0277 
0278     typedef mpl::vector< bool, short, unsigned short, int, unsigned int, long,
0279         unsigned long, long long, unsigned long long, float, double,
0280         long double, std::string >
0281         value_types;
0282     const char* type_names[] = { "boolean", "int", "int", "int", "int", "long",
0283         "long", "long", "long", "float", "double", "double", "string" };
0284     std::map< std::string, std::string > graph_key_ids;
0285     std::map< std::string, std::string > vertex_key_ids;
0286     std::map< std::string, std::string > edge_key_ids;
0287     int key_count = 0;
0288 
0289     // Output keys
0290     for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
0291     {
0292         std::string key_id = "key" + lexical_cast< std::string >(key_count++);
0293         if (i->second->key() == typeid(Graph*))
0294             graph_key_ids[i->first] = key_id;
0295         else if (i->second->key() == typeid(vertex_descriptor))
0296             vertex_key_ids[i->first] = key_id;
0297         else if (i->second->key() == typeid(edge_descriptor))
0298             edge_key_ids[i->first] = key_id;
0299         else
0300             continue;
0301         std::string type_name = "string";
0302         mpl::for_each< value_types >(get_type_name< value_types >(
0303             i->second->value(), type_names, type_name));
0304         out << "  <key id=\"" << encode_char_entities(key_id) << "\" for=\""
0305             << (i->second->key() == typeid(Graph*)
0306                        ? "graph"
0307                        : (i->second->key() == typeid(vertex_descriptor)
0308                                ? "node"
0309                                : "edge"))
0310             << "\""
0311             << " attr.name=\"" << i->first << "\""
0312             << " attr.type=\"" << type_name << "\""
0313             << " />\n";
0314     }
0315 
0316     out << "  <graph id=\"G\" edgedefault=\""
0317         << (graph_is_directed ? "directed" : "undirected") << "\""
0318         << " parse.nodeids=\"" << (ordered_vertices ? "canonical" : "free")
0319         << "\""
0320         << " parse.edgeids=\"canonical\" parse.order=\"nodesfirst\">\n";
0321 
0322     // Output graph data
0323     for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
0324     {
0325         if (i->second->key() == typeid(Graph*))
0326         {
0327             // The const_cast here is just to get typeid correct for property
0328             // map key; the graph should not be mutated using it.
0329             out << "   <data key=\"" << graph_key_ids[i->first] << "\">"
0330                 << encode_char_entities(
0331                        i->second->get_string(const_cast< Graph* >(&g)))
0332                 << "</data>\n";
0333         }
0334     }
0335 
0336     typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator;
0337     vertex_iterator v, v_end;
0338     for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v)
0339     {
0340         out << "    <node id=\"n" << get(vertex_index, *v) << "\">\n";
0341         // Output data
0342         for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end();
0343              ++i)
0344         {
0345             if (i->second->key() == typeid(vertex_descriptor))
0346             {
0347                 out << "      <data key=\"" << vertex_key_ids[i->first] << "\">"
0348                     << encode_char_entities(i->second->get_string(*v))
0349                     << "</data>\n";
0350             }
0351         }
0352         out << "    </node>\n";
0353     }
0354 
0355     typedef typename graph_traits< Graph >::edge_iterator edge_iterator;
0356     edge_iterator e, e_end;
0357     typename graph_traits< Graph >::edges_size_type edge_count = 0;
0358     for (boost::tie(e, e_end) = edges(g); e != e_end; ++e)
0359     {
0360         out << "    <edge id=\"e" << edge_count++ << "\" source=\"n"
0361             << get(vertex_index, source(*e, g)) << "\" target=\"n"
0362             << get(vertex_index, target(*e, g)) << "\">\n";
0363 
0364         // Output data
0365         for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end();
0366              ++i)
0367         {
0368             if (i->second->key() == typeid(edge_descriptor))
0369             {
0370                 out << "      <data key=\"" << edge_key_ids[i->first] << "\">"
0371                     << encode_char_entities(i->second->get_string(*e))
0372                     << "</data>\n";
0373             }
0374         }
0375         out << "    </edge>\n";
0376     }
0377 
0378     out << "  </graph>\n"
0379         << "</graphml>\n";
0380 }
0381 
0382 template < typename Graph >
0383 void write_graphml(std::ostream& out, const Graph& g,
0384     const dynamic_properties& dp, bool ordered_vertices = false)
0385 {
0386     write_graphml(out, g, get(vertex_index, g), dp, ordered_vertices);
0387 }
0388 
0389 } // boost namespace
0390 
0391 #endif // BOOST_GRAPH_GRAPHML_HPP