Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 57 additions & 19 deletions include/boost/graph/graphml.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@
#include <boost/graph/exception.hpp>
#include <boost/graph/graph_traits.hpp>

#include <boost/mpl/bool.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/property_tree/detail/xml_parser_utils.hpp>
#include <boost/throw_exception.hpp>
Expand All @@ -35,6 +31,49 @@
namespace boost
{

namespace graphml_detail
{
// The fixed list of value types GraphML understands
template < typename... Ts > struct value_type_list {};

template < typename List > struct for_each_value_type_impl;

template < typename... Ts >
struct for_each_value_type_impl< value_type_list< Ts... > >
{
// f can accumulate state (type_found)
template < typename F > static void apply(F& f)
{
// an array of 0 but with the side effect of calling the functor on each type
const int expand[] = { 0, (f(Ts()), 0)... };
(void)expand;
}
};

// Calls f once for each type in List, in order
template < typename List, typename F >
void for_each_value_type(F f)
{
for_each_value_type_impl< List >::apply(f);
}

// ::value is the position of T in List.
template < typename List, typename T >
struct index_of_value_type;

template < typename T, typename... Rest >
struct index_of_value_type< value_type_list< T, Rest... >, T >
{
static const int value = 0;
};

template < typename T, typename Head, typename... Rest >
struct index_of_value_type< value_type_list< Head, Rest... >, T >
{
static const int value = 1 + index_of_value_type< value_type_list< Rest... >, T >::value;
};
} // namespace graphml_detail

/////////////////////////////////////////////////////////////////////////////
// Graph reader exceptions
/////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -111,7 +150,7 @@ template < typename MutableGraph > class mutate_graph_impl : public mutate_graph
bool type_found = false;
try
{
mpl::for_each< value_types >(
graphml_detail::for_each_value_type< value_types >(
put_property< MutableGraph*, value_types >(name, m_dp, &m_g,
value, value_type, m_type_names, type_found));
}
Expand All @@ -133,7 +172,7 @@ template < typename MutableGraph > class mutate_graph_impl : public mutate_graph
bool type_found = false;
try
{
mpl::for_each< value_types >(
graphml_detail::for_each_value_type< value_types >(
put_property< vertex_descriptor, value_types >(name, m_dp,
any_cast< vertex_descriptor >(vertex), value, value_type,
m_type_names, type_found));
Expand All @@ -156,7 +195,7 @@ template < typename MutableGraph > class mutate_graph_impl : public mutate_graph
bool type_found = false;
try
{
mpl::for_each< value_types >(
graphml_detail::for_each_value_type< value_types >(
put_property< edge_descriptor, value_types >(name, m_dp,
any_cast< edge_descriptor >(edge), value, value_type,
m_type_names, type_found));
Expand Down Expand Up @@ -192,8 +231,8 @@ template < typename MutableGraph > class mutate_graph_impl : public mutate_graph
template < class Value > void operator()(Value)
{
if (m_value_type
== m_type_names[mpl::find< ValueVector,
Value >::type::pos::value])
== m_type_names[graphml_detail::index_of_value_type<
ValueVector, Value >::value])
{
put(m_name, m_dp, m_key, lexical_cast< Value >(m_value));
m_type_found = true;
Expand All @@ -213,8 +252,7 @@ template < typename MutableGraph > class mutate_graph_impl : public mutate_graph
protected:
MutableGraph& m_g;
dynamic_properties& m_dp;
typedef mpl::vector< bool, int, long, float, double, std::string >
value_types;
using value_types = graphml_detail::value_type_list< bool, int, long, float, double, std::string >;
static const char* m_type_names[];
};

Expand Down Expand Up @@ -244,8 +282,8 @@ template < typename Types > class get_type_name
template < typename Type > void operator()(Type)
{
if (typeid(Type) == m_type)
m_type_name
= m_type_names[mpl::find< Types, Type >::type::pos::value];
m_type_name = m_type_names[graphml_detail::index_of_value_type<
Types, Type >::value];
}

private:
Expand Down Expand Up @@ -275,10 +313,9 @@ void write_graphml(std::ostream& out, const Graph& g,
"xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns "
"http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n";

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;
using value_types = graphml_detail::value_type_list< bool, short,
unsigned short, int, unsigned int, long, unsigned long, long long,
unsigned long long, float, double, long double, std::string >;
const char* type_names[] = { "boolean", "int", "int", "int", "int", "long",
"long", "long", "long", "float", "double", "double", "string" };
std::map< std::string, std::string > graph_key_ids;
Expand All @@ -299,8 +336,9 @@ void write_graphml(std::ostream& out, const Graph& g,
else
continue;
std::string type_name = "string";
mpl::for_each< value_types >(get_type_name< value_types >(
i->second->value(), type_names, type_name));
graphml_detail::for_each_value_type< value_types >(
get_type_name< value_types >(
i->second->value(), type_names, type_name));
out << " <key id=\"" << encode_char_entities(key_id) << "\" for=\""
<< (i->second->key() == typeid(Graph*)
? "graph"
Expand Down
Loading