Multi-user gravity beats for Sound of Science 2013 (server)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 

124 lines
3.5 KiB

#pragma once
#include <utility>
#include <type_traits>
#include <stdexcept>
#include <boost/fusion/include/define_struct.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/mpl.hpp>
#include <json_spirit/json_spirit.h>
namespace js = json_spirit;
inline js::Value parse_json(std::string const & in){
js::Value value;
js::read(in, value);
return value;
}
inline std::string write_json(js::Value const & v){
return js::write(v);
}
/*
*** WRITING ***
Note: Does not yet support arrays, only basic types, std::strings and user defined types (with boost::fusion adaption)
*/
// Basic types
template <typename T>
typename std::enable_if<!std::is_class<T>::value && !std::is_pointer<T>::value, js::Value>::type to_json(T const & x){
return x;
}
inline js::Value to_json(std::string const & x){
return x;
}
// Compound types (need recursion)
template <typename T>
typename std::enable_if<std::is_class<T>::value, js::Value>::type to_json(T const & x);
// boost::fusion magics
template<typename T, typename N>
struct write_itr{
typedef typename boost::mpl::next<N>::type next_t;
typedef boost::fusion::extension::struct_member_name<T, N::value> name_t;
static inline void exec(js::Object & obj, const T& x){
obj[name_t::call()] = to_json(boost::fusion::at<N>(x));
write_itr<T, next_t>::exec(obj, x);
}
};
template<typename T>
struct write_itr<T, typename boost::fusion::result_of::size<T>::type>{
static inline void exec(js::Object & obj, const T& x) {}
};
// Compound types (need recursion)
template <typename T>
typename std::enable_if<std::is_class<T>::value, js::Value>::type to_json(T const & x){
js::Object obj;
write_itr<T, boost::mpl::int_<0>>::exec(obj, x);
return obj;
}
/*
*** READING ***
Note: Does not yet support arrays, only basic types, std::strings and user defined types (with boost::fusion adaption)
*/
// Basic types
template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type from_json(js::Value const & x){
return x.getInt64();
}
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type from_json(js::Value const & x){
return x.getReal();
}
template <typename T>
typename std::enable_if<std::is_same<T, std::string>::value, T>::type from_json(js::Value const & x){
return x.getString();
}
// Compound types (need recursion)
template <typename T>
typename std::enable_if<std::is_class<T>::value && !std::is_same<T, std::string>::value, T>::type from_json(js::Value const & x);
// boost::fusion magics
template<typename T, typename N>
struct read_itr{
typedef typename boost::fusion::result_of::value_at<T, N>::type current_t;
typedef typename boost::mpl::next<N>::type next_t;
typedef boost::fusion::extension::struct_member_name<T, N::value> name_t;
static inline void exec(js::Object const & obj, T& x){
try{
boost::fusion::at<N>(x) = from_json<current_t>(obj.at(name_t::call()));
} catch(std::out_of_range& e) {
throw std::out_of_range(e.what() + std::string(": ") + name_t::call());
}
read_itr<T, next_t>::exec(obj, x);
}
};
template<typename T>
struct read_itr<T, typename boost::fusion::result_of::size<T>::type>{
static inline void exec(js::Object const & obj, T& x) {}
};
// Compound types (need recursion)
template <typename T>
typename std::enable_if<std::is_class<T>::value && !std::is_same<T, std::string>::value, T>::type from_json(js::Value const & x){
T ret;
read_itr<T, boost::mpl::int_<0>>::exec(x.getObject(), ret);
return ret;
}