Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- template<typename _classType>
- class Class
- {
- public:
- class ClassInstance
- {
- private:
- std::shared_ptr<_classType> mInstance;
- public:
- ClassInstance(std::shared_ptr<_classType> instance) {
- mInstance = instance;
- }
- std::shared_ptr<_classType> getInstance() const {
- return mInstance;
- }
- };
- private:
- class GenericPropertyInfoHolder
- {
- public:
- virtual ~GenericPropertyInfoHolder() {
- }
- };
- template<typename PT>
- class PropertyInfoHolder : public GenericPropertyInfoHolder
- {
- std::function<PT(_classType*)> getter;
- std::function<void (_classType*, PT)> setter;
- bool mIsReadOnly;
- public:
- PropertyInfoHolder(std::function<PT(_classType*)> getter) {
- this->getter = getter;
- mIsReadOnly = true;
- }
- PropertyInfoHolder(std::function<PT(_classType*)> getter, std::function<void (_classType*, PT)> setter) {
- this->getter = getter;
- this->setter = setter;
- mIsReadOnly = false;
- }
- void setValue(_classType* instance, PT value) {
- if (mIsReadOnly) {
- v8::ThrowException(v8::String::New("Cannot set property, its readonly"));
- return;
- }
- setter(instance, value);
- }
- PT getValue(_classType* instance) {
- return getter(instance);
- }
- };
- private:
- static v8::Handle<v8::Value> __cdecl __defaultConstructorCall(const v8::Arguments& args) {
- if (args.IsConstructCall() == false) {
- v8::ThrowException(v8::Exception::Error(v8::String::New("Constructor cannot be called as function.")));
- }
- auto ext = v8::Handle<v8::External>::Cast(args.Data());
- Class<_classType>* clsInstance = reinterpret_cast<Class<_classType>*>(ext->Value());
- return clsInstance->mFunConstructor->externalInvoke(args);
- }
- template<typename P>
- static v8::Handle<v8::Value> __cdecl custPropertyGetCall(v8::Local<v8::String> key, const v8::AccessorInfo& info) {
- ClassInstance* inst = (ClassInstance*)v8::Local<v8::External>::Cast(info.This()->GetInternalField(0))->Value();
- PropertyInfoHolder<P>* holder = (PropertyInfoHolder<P>*)v8::Local<v8::External>::Cast(info.Data())->Value();
- const P& value = holder->getValue(inst->getInstance().get());
- return ObjectWrap::wrap<P>(value);
- }
- template<typename P>
- static void __cdecl custPropertySetCall(v8::Local<v8::String> key, v8::Local<v8::Value> value, const v8::AccessorInfo& info) {
- ClassInstance* inst = (ClassInstance*)v8::Local<v8::External>::Cast(info.This()->GetInternalField(0))->Value();
- PropertyInfoHolder<P>* holder = (PropertyInfoHolder<P>*)v8::Local<v8::External>::Cast(info.Data())->Value();
- holder->setValue(inst->getInstance().get(), ObjectWrap::unwrap<P>(value));
- }
- private:
- std::string mName;
- bool mIsStatic;
- FunctionPtr mFunConstructor;
- std::map<std::wstring, FunctionPtr> mFunctions;
- std::map<std::wstring, FunctionPtr> mStaticFunctions;
- std::list<std::unique_ptr<GenericPropertyInfoHolder>> mPropertyHolders;
- v8::Handle<v8::ObjectTemplate> mTemplate;
- v8::Handle<v8::FunctionTemplate> mConstructor;
- void initTemplate() {
- mFunConstructor = std::make_shared<Function>("__constructor");
- mConstructor = v8::FunctionTemplate::New(&__defaultConstructorCall, v8::External::New(this));
- mTemplate = mConstructor->PrototypeTemplate();
- mTemplate->SetInternalFieldCount(2);
- }
- static void __cdecl destructorCall(v8::Persistent<v8::Value> obj, void* params) {
- ClassInstance* instance = (ClassInstance*)params;
- delete instance;
- obj.Dispose();
- }
- v8::Handle<v8::Value> wrapInstance(std::shared_ptr<_classType> instance) {
- ClassInstance* clsInst = new ClassInstance(instance);
- auto obj = v8::Persistent<v8::Object>::New(mTemplate->NewInstance());
- obj->SetInternalField(0, v8::External::New(clsInst));
- obj->SetInternalField(1, v8::Integer::NewFromUnsigned('JSCL'));
- obj.MakeWeak(clsInst, &Class<_classType>::destructorCall);
- return obj;
- }
- public:
- Class(const std::string& name) {
- mName = name;
- initTemplate();
- }
- v8::Handle<v8::Object> createInstance(std::shared_ptr<GenericSharedPtrWrap> ptr) {
- auto subClass = std::dynamic_pointer_cast<SharedPtrWrap<_classType>>(ptr);
- ClassInstance* instance = new ClassInstance(subClass->getPtr());
- auto obj = v8::Persistent<v8::Object>::New(mTemplate->NewInstance());
- obj->SetInternalField(0, v8::External::New(instance));
- obj->SetInternalField(1, v8::Integer::NewFromUnsigned('JSCL'));
- obj.MakeWeak(instance, &Class::destructorCall);
- return obj;
- }
- void addToScope(ScopePtr scope) const {
- scope->getTemplate()->Set(v8::String::New(mName.c_str()), mConstructor);
- }
- template<typename... Args>
- void def_constructor() {
- using namespace std; // HACK: Error in visual studio 2012, variadic templates get their namespace removed. So std::shared_ptr will be shared_ptr here
- std::function < v8::Handle<v8::Value> (Args...) > fun = [this](Args... args) { return wrapInstance(std::make_shared<_classType>(args...)); };
- mFunConstructor->addOverload(fun);
- }
- void def_constructor() {
- mFunConstructor->addOverload(std::function<v8::Handle<v8::Value> ()>([this]() { return wrapInstance(std::make_shared<_classType>()); }));
- }
- template<typename Res, typename... Args>
- void def_function(const std::wstring& name, Res(_classType::*func)(Args...)) {
- auto existing = mFunctions.find(name);
- FunctionPtr dstFun = nullptr;
- if (existing == mFunctions.end()) {
- FunctionPtr funPtr = std::make_shared<Function>(String::toAnsi(name));
- funPtr->setMemberFunction(true);
- mTemplate->Set(v8::String::New(String::toAnsi(name).c_str()), funPtr->getTemplate());
- dstFun = funPtr;
- mFunctions.insert(std::make_pair(name, funPtr));
- } else {
- dstFun = existing->second;
- }
- dstFun->addOverload(std::function<Res(std::shared_ptr<_classType>, Args...)>(
- [func](std::shared_ptr<_classType> _this, Args... args) {
- return ((_this.get())->*func)(args...);
- }
- ));
- }
- template<typename Res, typename... Args>
- void def_function(const std::wstring& name, std::function<Res(std::shared_ptr<_classType>, Args...)> fun) {
- auto existing = mFunctions.find(name);
- FunctionPtr dstFun = nullptr;
- if (existing == mFunctions.end()) {
- FunctionPtr funPtr = std::make_shared<Function>(String::toAnsi(name));
- funPtr->setMemberFunction(true);
- mTemplate->Set(v8::String::New(String::toAnsi(name).c_str()), funPtr->getTemplate());
- dstFun = funPtr;
- mFunctions.insert(std::make_pair(name, funPtr));
- } else {
- dstFun = existing->second;
- }
- dstFun->addOverload(fun);
- }
- template<typename Res, typename... Args>
- void def_function(const std::wstring& name, Res(*fun)(std::shared_ptr<_classType>, Args...)) {
- def_function(name, std::function<Res(std::shared_ptr<_classType>, Args...)>(fun));
- }
- template<typename T>
- void def_function_static(const std::wstring& name, T fun) {
- def_function_static(name, std::function<typename std::remove_pointer<T>::type>(fun));
- }
- template<typename Res>
- void def_function_static(const std::wstring& name, Res(*fun)()) {
- def_function_static(name, std::function<Res()>(fun));
- }
- template<typename Res, typename... Args>
- void def_function_static(const std::wstring& name, const std::function<Res(Args...)>& fun) {
- auto existing = mStaticFunctions.find(name);
- FunctionPtr dstFun = nullptr;
- if (existing == mStaticFunctions.end()) {
- FunctionPtr funPtr = std::make_shared<Function>(String::toAnsi(name));
- mConstructor->Set(v8::String::New(String::toAnsi(name).c_str()), funPtr->getTemplate());
- dstFun = funPtr;
- mStaticFunctions.insert(std::make_pair(name, funPtr));
- } else {
- dstFun = existing->second;
- }
- dstFun->addOverload(fun);
- }
- template<typename Res>
- void def_function_static(const std::wstring& name, const std::function<Res()>& fun) {
- auto existing = mStaticFunctions.find(name);
- FunctionPtr dstFun = nullptr;
- if (existing == mStaticFunctions.end()) {
- FunctionPtr funPtr = std::make_shared<Function>(String::toAnsi(name));
- mConstructor->Set(v8::String::New(String::toAnsi(name).c_str()), funPtr->getTemplate());
- dstFun = funPtr;
- mStaticFunctions.insert(std::make_pair(name, funPtr));
- } else {
- dstFun = existing->second;
- }
- dstFun->addOverload(fun);
- }
- template<typename P>
- void def_property(const std::wstring& name, std::function<P(_classType*)> getter, std::function<void (_classType*, P)> setter) {
- PropertyInfoHolder<P>* holder = new PropertyInfoHolder<P>(getter, setter);
- mTemplate->SetAccessor(
- v8::String::New(::String::toAnsi(name).c_str()),
- &Class::custPropertyGetCall<P>,
- &Class::custPropertySetCall<P>,
- v8::External::New(holder));
- mPropertyHolders.push_back(std::unique_ptr<GenericPropertyInfoHolder>(holder));
- }
- template<typename P>
- void def_property(const std::wstring& name, std::function<P(_classType*)> getter) {
- PropertyInfoHolder<P>* holder = new PropertyInfoHolder<P>(getter);
- mTemplate->SetAccessor(
- v8::String::New(::String::toAnsi(name).c_str()),
- &Class::custPropertyGetCall<P>,
- &Class::custPropertySetCall<P>,
- v8::External::New(holder));
- mPropertyHolders.push_back(std::unique_ptr<GenericPropertyInfoHolder>(holder));
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment