Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- class Scope;
- #include "ObjectWrap.h"
- #include "Utils/TypeTraitsExt.h"
- #include "JSFunction.h"
- #include "JSObject.h"
- class Function
- {
- enum class ArgumentMatch
- {
- Exact,
- CanConvertImplicit,
- CanConvertExplicit,
- None
- };
- template<typename T>
- class Argument
- {
- public:
- static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
- return ArgumentMatch::Exact;
- }
- static T convert(const v8::Handle<v8::Value>& value) {
- return ObjectWrap::unwrap<T>(value);
- }
- };
- template<>
- class Argument<int>
- {
- public:
- static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
- if (value->IsInt32()) {
- return ArgumentMatch::Exact;
- }
- if (value->IsNumber()) {
- return ArgumentMatch::CanConvertImplicit;
- }
- return ArgumentMatch::None;
- }
- static int convert(const v8::Handle<v8::Value>& value) {
- return value->Int32Value();
- }
- };
- template<>
- class Argument<short>
- {
- public:
- static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
- if (value->IsInt32()) {
- return ArgumentMatch::Exact;
- }
- if (value->IsNumber()) {
- return ArgumentMatch::CanConvertImplicit;
- }
- return ArgumentMatch::None;
- }
- static short convert(const v8::Handle<v8::Value>& value) {
- return (short) value->Int32Value();
- }
- };
- template<>
- class Argument<char>
- {
- public:
- static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
- if (value->IsInt32()) {
- return ArgumentMatch::Exact;
- }
- if (value->IsNumber()) {
- return ArgumentMatch::CanConvertImplicit;
- }
- return ArgumentMatch::None;
- }
- static char convert(const v8::Handle<v8::Value>& value) {
- return (char) value->Int32Value();
- }
- };
- template<>
- class Argument<unsigned int>
- {
- public:
- static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
- if (value->IsInt32()) {
- return ArgumentMatch::Exact;
- }
- if (value->IsNumber()) {
- return ArgumentMatch::CanConvertImplicit;
- }
- return ArgumentMatch::None;
- }
- static unsigned int convert(const v8::Handle<v8::Value>& value) {
- return value->Uint32Value();
- }
- };
- template<>
- class Argument<unsigned short>
- {
- public:
- static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
- if (value->IsInt32()) {
- return ArgumentMatch::Exact;
- }
- if (value->IsNumber()) {
- return ArgumentMatch::CanConvertImplicit;
- }
- return ArgumentMatch::None;
- }
- static unsigned short convert(const v8::Handle<v8::Value>& value) {
- return (unsigned short) value->Uint32Value();
- }
- };
- template<>
- class Argument<unsigned char>
- {
- public:
- static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
- if (value->IsInt32()) {
- return ArgumentMatch::Exact;
- }
- if (value->IsNumber()) {
- return ArgumentMatch::CanConvertImplicit;
- }
- return ArgumentMatch::None;
- }
- static unsigned char convert(const v8::Handle<v8::Value>& value) {
- return (unsigned char) value->Uint32Value();
- }
- };
- template<>
- class Argument<float>
- {
- public:
- static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
- if (value->IsInt32()) {
- return ArgumentMatch::CanConvertImplicit;
- }
- if (value->IsNumber()) {
- return ArgumentMatch::Exact;
- }
- return ArgumentMatch::None;
- }
- static float convert(const v8::Handle<v8::Value>& value) {
- return (float) value->NumberValue();
- }
- };
- template<>
- class Argument<double>
- {
- public:
- static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
- if (value->IsInt32()) {
- return ArgumentMatch::CanConvertImplicit;
- }
- if (value->IsNumber()) {
- return ArgumentMatch::Exact;
- }
- return ArgumentMatch::None;
- }
- static double convert(const v8::Handle<v8::Value>& value) {
- return (double) value->NumberValue();
- }
- };
- template<>
- class Argument<std::string>
- {
- public:
- static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
- if (value->IsString()) {
- return ArgumentMatch::Exact;
- }
- return ArgumentMatch::CanConvertExplicit;
- }
- static std::string convert(const v8::Handle<v8::Value>& value) {
- return ObjectWrap::unwrap<std::string>(value);
- }
- };
- template<>
- class Argument<std::wstring>
- {
- public:
- static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
- if (value->IsString()) {
- return ArgumentMatch::Exact;
- }
- return ArgumentMatch::CanConvertExplicit;
- }
- static std::wstring convert(const v8::Handle<v8::Value>& value) {
- v8::Local<v8::String> str = value->ToString();
- if (str->Utf8Length() == 0) {
- return L"";
- }
- std::vector<wchar_t> utf16Buffer(str->Utf8Length());
- str->Write(reinterpret_cast<uint16_t*>(utf16Buffer.data()), 0, utf16Buffer.size());
- return std::wstring(utf16Buffer.begin(), utf16Buffer.end());
- }
- };
- class GenericFunctionOverload
- {
- public:
- virtual int getOverloadScore(const v8::Arguments& args, Function* fun) = 0;
- virtual v8::Handle<v8::Value> execute(const v8::Arguments& args, Function* fun) const = 0;
- };
- template<typename T, typename... Args>
- class FunctionOverload : public GenericFunctionOverload
- {
- private:
- std::function < T(Args...) > mCallback;
- template<int numArgs, int curArg>
- void parseArgScore(int& curScore, const v8::Arguments& args) const {
- }
- template<int numArgs, int curArg, typename _Cur, typename... Args>
- void parseArgScore(int& curScore, const v8::Arguments& args) const {
- auto match = Argument<_Cur>::matches(args[curArg]);
- if (match == ArgumentMatch::None) {
- curScore = 0;
- } else if (match == ArgumentMatch::CanConvertImplicit) {
- curScore -= (int) (99.0f / (2 * numArgs));
- } else if (match == ArgumentMatch::CanConvertExplicit) {
- curScore -= (int) (99.0f / numArgs);
- }
- if (curScore <= 0) {
- curScore = 0;
- return;
- }
- parseArgScore<numArgs, curArg + 1, Args...>(curScore, args);
- }
- template<typename Res, int _curArgNum, typename _curArgType, typename... _remArgs, typename... _prevArgs>
- v8::Handle<v8::Value> _expand_invoke(const v8::Arguments& args, const _prevArgs&... curArgs) const {
- _curArgType curArg = Argument<_curArgType>::convert(args[_curArgNum]);
- return _expand_invoke<Res, _curArgNum + 1, _remArgs...>(args, curArgs..., curArg);
- }
- template<typename Res, int _curArgNum, typename... _cArgs>
- typename std::enable_if<!std::is_void<Res>::value, v8::Handle<v8::Value>>::type _expand_invoke(const v8::Arguments& args, const Args&... curArgs) const {
- return ObjectWrap::wrap<T>(mCallback(curArgs...));
- }
- template<typename Res, int _curArgNum, typename... _cArgs>
- typename std::enable_if<std::is_void<Res>::value, v8::Handle<v8::Value>>::type _expand_invoke(const v8::Arguments& args, const Args&... curArgs) const {
- mCallback(curArgs...);
- return v8::Undefined();
- }
- public:
- FunctionOverload(std::function < T(Args...) > callback) {
- mCallback = callback;
- }
- template<typename _thisType, typename... Args>
- int getMemberOverloadScore(const v8::Arguments& args, Function* fun) {
- if (args.This().IsEmpty() == true) {
- return 0;
- }
- if (args.Length() != sizeof...(Args)) {
- return 0;
- }
- int score = 100;
- parseArgScore<sizeof...(Args), 0, Args...>(score, args);
- return score;
- }
- template<typename ...Args>
- int getOverloadScore(const v8::Arguments& args, Function* fun) {
- if (fun->isMemberFunction()) {
- return getMemberOverloadScore<Args...>(args, fun);
- }
- if (args.Length() != sizeof...(Args)) {
- return 0;
- }
- int score = 100;
- parseArgScore < sizeof...(Args), 0, Args...>(score, args);
- return score;
- }
- template<>
- int getOverloadScore<>(const v8::Arguments& args, Function* fun) {
- v8::Handle<v8::External> dataParam = v8::Handle<v8::External>::Cast(args.Data());
- if (fun->isMemberFunction() == true) {
- return 0;
- }
- if (args.Length() != 0) {
- return 0;
- }
- return 100;
- }
- int getOverloadScore(const v8::Arguments& args, Function* fun) {
- return getOverloadScore<Args...>(args, fun);
- }
- template<typename _thisType, typename... Args>
- v8::Handle<v8::Value> execute_member(const v8::Arguments& args, Function* fun) const {
- return _expand_invoke<T, 0, Args...>(args, Argument<_thisType>::convert(args.This()));
- }
- template<typename... Args>
- v8::Handle<v8::Value> _execute(const v8::Arguments& args, Function* fun) const {
- if (fun->isMemberFunction()) {
- return execute_member<Args...>(args, fun);
- }
- return _expand_invoke<T, 0, Args...>(args);
- }
- template<>
- v8::Handle<v8::Value> _execute<>(const v8::Arguments& args, Function* fun) const {
- return ObjectWrap::wrap<T>(mCallback());
- }
- v8::Handle<v8::Value> execute(const v8::Arguments& args, Function* fun) const {
- return _execute<Args...>(args, fun);
- }
- };
- typedef std::shared_ptr<GenericFunctionOverload> GenericFunctionOverloadPtr;
- int mClassMagic;
- std::list<GenericFunctionOverloadPtr> mOverloads;
- mutable v8::Handle<v8::FunctionTemplate> mTemplate;
- std::string mName;
- bool mIsMemberFunction;
- private:
- v8::Handle<v8::Value> __functionCallback(const v8::Arguments& args) {
- GenericFunctionOverloadPtr bestMatch = nullptr;
- int maxScore = 0;
- bool hasDuplicate = false;
- for (auto& overload : mOverloads) {
- int score = overload->getOverloadScore(args, this);
- if (score == 0) {
- continue;
- }
- if (score > maxScore) {
- bestMatch = overload;
- maxScore = score;
- hasDuplicate = false;
- } else if (score == maxScore) {
- hasDuplicate = true;
- }
- }
- if (bestMatch == nullptr) {
- std::stringstream errStrm;
- errStrm << "Unable to match function overload for function '" << mName << "'.";
- v8::ThrowException(v8::Exception::Error(v8::String::New(errStrm.str().c_str())));
- return v8::Undefined();
- }
- if (hasDuplicate == true) {
- std::stringstream errStrm;
- errStrm << "Unable to match function overload for function '" << mName << "'. Ambigous function call.";
- v8::ThrowException(v8::Exception::Error(v8::String::New(errStrm.str().c_str())));
- return v8::Undefined();
- }
- auto res = bestMatch->execute(args, this);
- return res;
- }
- static v8::Handle<v8::Value> __cdecl __staticCallback(const v8::Arguments& args) {
- v8::Handle<v8::External> dataParam = v8::Handle<v8::External>::Cast(args.Data());
- Function* pFunction = reinterpret_cast<Function*>(dataParam->Value());
- if (pFunction->getMagic() != ClassMagic) {
- v8::ThrowException(v8::String::New("Unknown error. Invalid function object."));
- return v8::Undefined();
- }
- return pFunction->__functionCallback(args);
- }
- public:
- Function(const std::string& name) : mName(name) {
- mClassMagic = ClassMagic;
- mIsMemberFunction = false;
- }
- //void addToScope(ScopePtr scope) const;
- template<typename Res, typename... Args>
- void addOverload(const std::function < Res(Args...) >& function) {
- GenericFunctionOverloadPtr overload = std::dynamic_pointer_cast<GenericFunctionOverload>(
- std::make_shared < FunctionOverload<Res, Args...> >(function)
- );
- mOverloads.push_back(overload);
- }
- v8::Handle<v8::Value> externalInvoke(const v8::Arguments& cbInfo) { return __functionCallback(cbInfo); }
- v8::Handle<v8::FunctionTemplate> getTemplate() const {
- if (mTemplate.IsEmpty() == false) {
- return mTemplate;
- }
- mTemplate = v8::FunctionTemplate::New(&Function::__staticCallback, v8::External::New(const_cast<Function*>(this)));
- return mTemplate;
- }
- int getMagic() const { return mClassMagic; }
- void setMemberFunction(bool memberFunction) { mIsMemberFunction = memberFunction; }
- bool isMemberFunction() const { return mIsMemberFunction; }
- static const int ClassMagic = 363078014;
- };
- typedef std::shared_ptr<::Function> FunctionPtr;
Advertisement
Add Comment
Please, Sign In to add comment