Created
January 15, 2016 04:38
-
-
Save xaxxon/4d78a903d0327932d713 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Responsible for calling the actual method and populating the return type for non-void return type methods | |
template<typename METHOD_TYPE> | |
struct RunMethod {}; | |
/** | |
* Specialization for methods that don't return void. Sets v8::FunctionCallbackInfo::GetReturnValue to value returned by the method | |
*/ | |
template<typename RETURN_TYPE, typename CLASS_TYPE, typename ... PARAMETERS> | |
struct RunMethod<RETURN_TYPE(CLASS_TYPE::*)(PARAMETERS...)>{ | |
typedef RETURN_TYPE(CLASS_TYPE::*METHOD_TYPE)(PARAMETERS...); | |
void operator()(CLASS_TYPE & object, METHOD_TYPE method, const v8::FunctionCallbackInfo<v8::Value> & info, PARAMETERS... parameters) { | |
RETURN_TYPE return_value = (object.*method)(parameters...); | |
auto casted_result = CastToJS<RETURN_TYPE>()(info.GetIsolate(), return_value); | |
info.GetReturnValue().Set(casted_result); | |
} | |
}; | |
/** | |
* Specialization for methods that return void. No value set for v8::FunctionCallbackInfo::GetReturnValue | |
* The javascript call will return the javascript "undefined" value | |
*/ | |
template<typename CLASS_TYPE, typename ... PARAMETERS> | |
struct RunMethod<void(CLASS_TYPE::*)(PARAMETERS...)> { | |
typedef void(CLASS_TYPE::*METHOD_TYPE)(PARAMETERS...); | |
void operator()(CLASS_TYPE & object, METHOD_TYPE method, const v8::FunctionCallbackInfo<v8::Value> &, PARAMETERS... parameters) { | |
(object.*method)(parameters...); | |
} | |
}; | |
/** | |
* Class for turning a function parameter list into a parameter pack useful for actually calling the function | |
*/ | |
template<int depth, typename T, typename U> | |
struct Caller {}; | |
/** | |
* Specialization for when there are no parameters left to process, so it is time to actually | |
* call the function | |
*/ | |
template<int depth, typename METHOD_TYPE, typename RET, typename CLASS_TYPE> | |
struct Caller<depth, METHOD_TYPE, RET(CLASS_TYPE::*)()> { | |
public: | |
// the final class in the call chain stores the actual method to be called | |
enum {DEPTH=depth, ARITY=0}; | |
// This call method actually calls the method with the specified object and the | |
// parameter pack that was built up via the chain of calls between templated types | |
template<typename ... Ts> | |
void operator()(METHOD_TYPE method, CLASS_TYPE & object, const v8::FunctionCallbackInfo<v8::Value> & info, Ts... ts) { | |
RunMethod<METHOD_TYPE>()(object, method, info, ts...); | |
} | |
}; | |
template<int depth, typename METHOD_TYPE, typename RET, typename CLASS_TYPE> | |
struct Caller<depth, METHOD_TYPE, RET(CLASS_TYPE::*)() const> { | |
public: | |
// the final class in the call chain stores the actual method to be called | |
enum {DEPTH=depth, ARITY=0}; | |
// This call method actually calls the method with the specified object and the | |
// parameter pack that was built up via the chain of calls between templated types | |
template<typename ... Ts> | |
void operator()(METHOD_TYPE method, CLASS_TYPE & object, const v8::FunctionCallbackInfo<v8::Value> & info, Ts... ts) { | |
RunMethod<METHOD_TYPE>()(object, method, info, ts...); | |
} | |
}; | |
/** END TEST CODE ****/ | |
/** | |
* specialization that strips off the first remaining parameter off the method type, stores that and then | |
* inherits from another instance that either strips the next one off, or if none remaining, actually calls | |
* the method | |
* The method type is specified twice because the first is actually used by the final specialization to hold the | |
* method type while the second one has its input parameter list stripped off one at a time to determine when | |
* the inheritance chain ends | |
*/ | |
template<int depth, typename METHOD_TYPE, typename CLASS_TYPE, typename RET, typename HEAD, typename...TAIL> | |
struct Caller<depth, METHOD_TYPE, RET(CLASS_TYPE::*)(HEAD,TAIL...)> : public Caller<depth+1, METHOD_TYPE, RET(CLASS_TYPE::*)(TAIL...)> { | |
public: | |
typedef Caller<depth+1, METHOD_TYPE, RET(CLASS_TYPE::*)(TAIL...)> super; | |
enum {DEPTH = depth, ARITY=super::ARITY + 1}; | |
template<typename ... Ts> | |
void operator()(METHOD_TYPE method, CLASS_TYPE & object, const v8::FunctionCallbackInfo<v8::Value> & info, Ts... ts) { | |
CastToNative<HEAD> cast; | |
this->super::operator()(method, object, info, ts..., cast(info[depth])); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment