|
|
|
@ -2,6 +2,7 @@
|
|
|
|
|
#define FUNCTION_MAP_HH
|
|
|
|
|
|
|
|
|
|
#include "json_spirit/json_spirit_value.h"
|
|
|
|
|
#include "json_spirit/json_spirit_writer.h"
|
|
|
|
|
#include <type_traits>
|
|
|
|
|
|
|
|
|
|
// Just for debugging:
|
|
|
|
@ -22,6 +23,10 @@ T from_json(const js::Value& v);
|
|
|
|
|
template<class T>
|
|
|
|
|
js::Value to_json(const T& t);
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
js::Value to_json(const Out<T>& t);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// helper classes to specify in- and out-parameters
|
|
|
|
@ -29,23 +34,24 @@ template<class T>
|
|
|
|
|
struct In
|
|
|
|
|
{
|
|
|
|
|
typedef T c_type; // the according type in C function parameter
|
|
|
|
|
|
|
|
|
|
template<class... Args>
|
|
|
|
|
using pack = std::tuple<Args...>;
|
|
|
|
|
enum { is_output = false };
|
|
|
|
|
|
|
|
|
|
explicit In(const T& t) : value(t) {}
|
|
|
|
|
~In();
|
|
|
|
|
|
|
|
|
|
In(const In<T>& other);
|
|
|
|
|
In(const In<T>& other) = delete;
|
|
|
|
|
In(In<T>&& victim);
|
|
|
|
|
|
|
|
|
|
In<T>& operator=(const In<T>&) = delete;
|
|
|
|
|
|
|
|
|
|
// default implementation:
|
|
|
|
|
static In<T> from_json(const js::Value& v, const js::Array& params, unsigned position)
|
|
|
|
|
In(const js::Value& v, const js::Array& params, unsigned position)
|
|
|
|
|
: In( from_json<T>(v) )
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
js::Value to_json() const
|
|
|
|
|
{
|
|
|
|
|
T t = ::from_json<T>(v);
|
|
|
|
|
return In<T>{t};
|
|
|
|
|
throw std::logic_error( std::string(typeid(T).name()) + " is not for output!" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
T value;
|
|
|
|
@ -57,22 +63,23 @@ template<class T>
|
|
|
|
|
struct InRaw
|
|
|
|
|
{
|
|
|
|
|
typedef js::Value c_type; // do not unwrap JSON data type
|
|
|
|
|
|
|
|
|
|
template<class... Args>
|
|
|
|
|
using pack = std::tuple<Args...>;
|
|
|
|
|
enum { is_output = false };
|
|
|
|
|
|
|
|
|
|
explicit InRaw(const js::Value& t) : value(t) {}
|
|
|
|
|
~InRaw() = default;
|
|
|
|
|
|
|
|
|
|
InRaw(const InRaw<T>& other) = default;
|
|
|
|
|
InRaw(InRaw<T>&& victim) = default;
|
|
|
|
|
|
|
|
|
|
InRaw(const InRaw<T>& other) = delete;
|
|
|
|
|
InRaw(InRaw<T>&& victim);
|
|
|
|
|
InRaw<T>& operator=(const InRaw<T>&) = delete;
|
|
|
|
|
|
|
|
|
|
// default implementation:
|
|
|
|
|
static InRaw<T> from_json(const js::Value& v, const js::Array& params, unsigned position)
|
|
|
|
|
InRaw(const js::Value& v, const js::Array& params, unsigned position)
|
|
|
|
|
: InRaw(v)
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
js::Value to_json() const
|
|
|
|
|
{
|
|
|
|
|
return InRaw<T>{v};
|
|
|
|
|
throw std::logic_error( std::string(typeid(T).name()) + " is not for output!" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
js::Value value;
|
|
|
|
@ -84,6 +91,7 @@ template<class T>
|
|
|
|
|
struct InOut : public In<T>
|
|
|
|
|
{
|
|
|
|
|
typedef In<T> Base;
|
|
|
|
|
enum { is_output = true };
|
|
|
|
|
|
|
|
|
|
explicit InOut(const T& t) : Base(t) {}
|
|
|
|
|
~InOut() = default;
|
|
|
|
@ -91,11 +99,9 @@ struct InOut : public In<T>
|
|
|
|
|
InOut<T>& operator=(const InOut<T>&) = delete;
|
|
|
|
|
|
|
|
|
|
// default implementation:
|
|
|
|
|
static InOut<T> from_json(const js::Value& v, const js::Array& params, unsigned position)
|
|
|
|
|
{
|
|
|
|
|
T t = ::from_json<T>(v);
|
|
|
|
|
return InOut<T>{t};
|
|
|
|
|
}
|
|
|
|
|
InOut(const js::Value& v, const js::Array& params, unsigned position)
|
|
|
|
|
: Base( from_json<T>(v) )
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
js::Value to_json() const
|
|
|
|
|
{
|
|
|
|
@ -108,9 +114,7 @@ template<class T>
|
|
|
|
|
struct Out
|
|
|
|
|
{
|
|
|
|
|
typedef T* c_type; // the according type in C function parameter
|
|
|
|
|
|
|
|
|
|
template<class... Args>
|
|
|
|
|
using pack = std::tuple<Out<T>, Args...>;
|
|
|
|
|
enum { is_output = true };
|
|
|
|
|
|
|
|
|
|
explicit Out() : value{ new T{} }
|
|
|
|
|
{
|
|
|
|
@ -122,21 +126,16 @@ struct Out
|
|
|
|
|
|
|
|
|
|
~Out();
|
|
|
|
|
|
|
|
|
|
Out(const Out<T>& other);
|
|
|
|
|
Out(Out<T>&& victim)
|
|
|
|
|
: value(victim.value)
|
|
|
|
|
{
|
|
|
|
|
victim.value = nullptr;
|
|
|
|
|
}
|
|
|
|
|
Out(const Out<T>& other) = delete;
|
|
|
|
|
Out(Out<T>&& victim);
|
|
|
|
|
|
|
|
|
|
// just to be sure they are not implicitly defined:
|
|
|
|
|
Out<T>& operator=(const Out<T>& other) = delete;
|
|
|
|
|
Out<T>& operator=(Out<T>&& victim) = delete;
|
|
|
|
|
|
|
|
|
|
static Out<T> from_json(const js::Value& v, const js::Array& params, unsigned position)
|
|
|
|
|
{
|
|
|
|
|
return Out<T>{};
|
|
|
|
|
}
|
|
|
|
|
Out(const js::Value& v, const js::Array& params, unsigned position)
|
|
|
|
|
: Out()
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
js::Value to_json() const
|
|
|
|
|
{
|
|
|
|
@ -178,72 +177,6 @@ js::Value to_json(const InOut<T>& o)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Heloer class to concatenate the "result-relevant" parameters into a tuple<...>: Out<T> and InOut<T>
|
|
|
|
|
// In<T> and InRaw<T> are ignored and _not_ collected into the output tuple<>
|
|
|
|
|
struct Concat
|
|
|
|
|
{
|
|
|
|
|
template<class T, class... Args>
|
|
|
|
|
std::tuple<Args...> operator()(const In<T>& in, const std::tuple<Args...>& rest) const
|
|
|
|
|
{
|
|
|
|
|
return rest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T, class... Args>
|
|
|
|
|
std::tuple<Args...> operator()(const InRaw<T>& in, const std::tuple<Args...>& rest) const
|
|
|
|
|
{
|
|
|
|
|
return rest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T, class... Args>
|
|
|
|
|
std::tuple<Out<T>, Args...> operator()(const Out<T>& out, const std::tuple<Args...>& rest) const
|
|
|
|
|
{
|
|
|
|
|
return std::tuple_cat(std::tuple<Out<T>>{out}, rest);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T, class... Args>
|
|
|
|
|
std::tuple<InOut<T>, Args...> operator()(const InOut<T>& out, const std::tuple<Args...>& rest) const
|
|
|
|
|
{
|
|
|
|
|
return std::tuple_cat(std::tuple<InOut<T>>{out}, rest);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// because operator() needs an object, we create a dummy one:
|
|
|
|
|
extern const Concat concat;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// recursive helper functors for to_json(tuple<...>):
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
// generic implementation, used for U < V
|
|
|
|
|
template<unsigned U, unsigned V, class... Args>
|
|
|
|
|
struct copy_value
|
|
|
|
|
{
|
|
|
|
|
static void to(js::Array& a, const std::tuple<Args...>& t)
|
|
|
|
|
{
|
|
|
|
|
a[U] = to_json(std::get<U>(t));
|
|
|
|
|
copy_value<U+1, sizeof...(Args), Args...>::to(a, t);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// spezialization for U==V
|
|
|
|
|
template<unsigned U, class... Args>
|
|
|
|
|
struct copy_value<U,U,Args...>
|
|
|
|
|
{
|
|
|
|
|
static void to(js::Array& a, const std::tuple<Args...>& t) {}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class... Args>
|
|
|
|
|
js::Value to_json(const std::tuple<Args...>& t)
|
|
|
|
|
{
|
|
|
|
|
js::Array ret; ret.resize(sizeof...(Args));
|
|
|
|
|
copy_value<0, sizeof...(Args), Args...>::to(ret, t);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// heloer class for generic calls:
|
|
|
|
|
// R : return type of the called function
|
|
|
|
|
// U : number of the parameter which is being extracted
|
|
|
|
@ -258,11 +191,9 @@ template<class R, unsigned U, class... Args>
|
|
|
|
|
class helper<R, U, U, Args...>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
typedef std::tuple<R> RetType;
|
|
|
|
|
|
|
|
|
|
static RetType call( const std::function<R(typename Args::c_type...)>& fn, const js::Array& parameters, const Args&... args)
|
|
|
|
|
static js::Value call( const std::function<R(typename Args::c_type...)>& fn, js::Array& out_parameters, const js::Array& parameters, const Args&... args)
|
|
|
|
|
{
|
|
|
|
|
return RetType( fn(args.value...) );
|
|
|
|
|
return to_json( fn(args.value...) );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -272,12 +203,10 @@ template<unsigned U, class... Args>
|
|
|
|
|
class helper<void, U, U, Args...>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
typedef std::tuple<> RetType;
|
|
|
|
|
|
|
|
|
|
static RetType call( const std::function<void(typename Args::c_type...)>& fn, const js::Array& parameters, const Args&... args)
|
|
|
|
|
static js::Value call( const std::function<void(typename Args::c_type...)>& fn, js::Array& out_parameters, const js::Array& parameters, const Args&... args)
|
|
|
|
|
{
|
|
|
|
|
fn(args.value...);
|
|
|
|
|
return RetType{};
|
|
|
|
|
return js::Value{};
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -293,20 +222,25 @@ public:
|
|
|
|
|
typedef typename std::tuple_element<U, Tuple>::type Element; // The type of the U'th parameter
|
|
|
|
|
typedef helper<R, U+1, MAX, Args...> NextHelper;
|
|
|
|
|
|
|
|
|
|
// depending on whether Element is an output parameter or not the returned tuple contains the paremeter or not:
|
|
|
|
|
typedef typename std::result_of<Concat(Element, typename NextHelper::RetType )>::type RetType;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
// A2... a2 are the alredy pealed-off paremeters
|
|
|
|
|
template<class... A2>
|
|
|
|
|
static RetType call( const std::function<R(typename Args::c_type...)>& fn, const js::Array& parameters, const A2&... a2)
|
|
|
|
|
static js::Value call( const std::function<R(typename Args::c_type...)>& fn, js::Array& out_parameters, const js::Array& parameters, const A2&... a2)
|
|
|
|
|
{
|
|
|
|
|
// extract the U'th element of the parameter list
|
|
|
|
|
const Element element{ Element::from_json(parameters[U], parameters, U) };
|
|
|
|
|
const Element element(parameters[U], parameters, U);
|
|
|
|
|
|
|
|
|
|
// concatenate (Out<T>) or ignore (In<T>) this element into the output tuple:
|
|
|
|
|
return concat( element, NextHelper::call(fn, parameters, a2..., element ) );
|
|
|
|
|
const js::Value ret = NextHelper::call(fn, out_parameters, parameters, a2..., element );
|
|
|
|
|
if(Element::is_output)
|
|
|
|
|
{
|
|
|
|
|
js::Value out = element.to_json();
|
|
|
|
|
std::cerr << "|$ Out #" << U << " : " << js::write(out) << "\n";
|
|
|
|
|
out_parameters.push_back( std::move(out) );
|
|
|
|
|
}else{
|
|
|
|
|
std::cerr << "|$ Param #" << U << " is not for output.\n";
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -405,7 +339,12 @@ public:
|
|
|
|
|
// recursive template magic breaks loose:
|
|
|
|
|
// recursively extract the JSON parameters, call 'fn' and collect its return value
|
|
|
|
|
// and all output parameters into a tuple<> and return it as JSON array
|
|
|
|
|
return to_json( helper<R, 0, sizeof...(Args), Args...>::call(fn, parameters) );
|
|
|
|
|
js::Array out_params;
|
|
|
|
|
out_params.reserve( 1 + sizeof...(Args) ); // too big, but who cares?
|
|
|
|
|
|
|
|
|
|
js::Value ret = helper<R, 0, sizeof...(Args), Args...>::call(fn, out_params, parameters);
|
|
|
|
|
out_params.push_back( ret );
|
|
|
|
|
return out_params;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setJavaScriptSignature(js::Object& o) const override
|
|
|
|
|