Cromon

Untitled

Aug 25th, 2013
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.11 KB | None | 0 0
  1. template<typename _classType>
  2. class Class
  3. {
  4. public:
  5.     class ClassInstance
  6.     {
  7.     private:
  8.         std::shared_ptr<_classType> mInstance;
  9.  
  10.     public:
  11.         ClassInstance(std::shared_ptr<_classType> instance) {
  12.             mInstance = instance;
  13.         }
  14.  
  15.         std::shared_ptr<_classType> getInstance() const {
  16.             return mInstance;
  17.         }
  18.     };
  19.  
  20. private:
  21.  
  22.     class GenericPropertyInfoHolder
  23.     {
  24.     public:
  25.         virtual ~GenericPropertyInfoHolder() {
  26.         }
  27.     };
  28.  
  29.     template<typename PT>
  30.     class PropertyInfoHolder : public GenericPropertyInfoHolder
  31.     {
  32.         std::function<PT(_classType*)> getter;
  33.         std::function<void (_classType*, PT)> setter;
  34.         bool mIsReadOnly;
  35.  
  36.     public:
  37.         PropertyInfoHolder(std::function<PT(_classType*)> getter) {
  38.             this->getter = getter;
  39.             mIsReadOnly = true;
  40.         }
  41.  
  42.         PropertyInfoHolder(std::function<PT(_classType*)> getter, std::function<void (_classType*, PT)> setter) {
  43.             this->getter = getter;
  44.             this->setter = setter;
  45.  
  46.             mIsReadOnly = false;
  47.         }
  48.  
  49.         void setValue(_classType* instance, PT value) {
  50.             if (mIsReadOnly) {
  51.                 v8::ThrowException(v8::String::New("Cannot set property, its readonly"));
  52.                 return;
  53.             }
  54.  
  55.             setter(instance, value);
  56.         }
  57.  
  58.         PT getValue(_classType* instance) {
  59.             return getter(instance);
  60.         }
  61.     };
  62.  
  63. private:
  64.     static v8::Handle<v8::Value> __cdecl __defaultConstructorCall(const v8::Arguments& args) {
  65.         if (args.IsConstructCall() == false) {
  66.             v8::ThrowException(v8::Exception::Error(v8::String::New("Constructor cannot be called as function.")));
  67.         }
  68.  
  69.         auto ext = v8::Handle<v8::External>::Cast(args.Data());
  70.         Class<_classType>* clsInstance = reinterpret_cast<Class<_classType>*>(ext->Value());
  71.         return clsInstance->mFunConstructor->externalInvoke(args);
  72.     }
  73.  
  74.     template<typename P>
  75.     static v8::Handle<v8::Value> __cdecl custPropertyGetCall(v8::Local<v8::String> key, const v8::AccessorInfo& info) {
  76.         ClassInstance* inst = (ClassInstance*)v8::Local<v8::External>::Cast(info.This()->GetInternalField(0))->Value();
  77.         PropertyInfoHolder<P>* holder = (PropertyInfoHolder<P>*)v8::Local<v8::External>::Cast(info.Data())->Value();
  78.  
  79.         const P& value = holder->getValue(inst->getInstance().get());
  80.         return ObjectWrap::wrap<P>(value);
  81.     }
  82.  
  83.     template<typename P>
  84.     static void __cdecl custPropertySetCall(v8::Local<v8::String> key, v8::Local<v8::Value> value, const v8::AccessorInfo& info) {
  85.         ClassInstance* inst = (ClassInstance*)v8::Local<v8::External>::Cast(info.This()->GetInternalField(0))->Value();
  86.         PropertyInfoHolder<P>* holder = (PropertyInfoHolder<P>*)v8::Local<v8::External>::Cast(info.Data())->Value();
  87.  
  88.         holder->setValue(inst->getInstance().get(), ObjectWrap::unwrap<P>(value));
  89.     }
  90.  
  91. private:
  92.     std::string mName;
  93.     bool mIsStatic;
  94.     FunctionPtr mFunConstructor;
  95.     std::map<std::wstring, FunctionPtr> mFunctions;
  96.     std::map<std::wstring, FunctionPtr> mStaticFunctions;
  97.     std::list<std::unique_ptr<GenericPropertyInfoHolder>> mPropertyHolders;
  98.  
  99.     v8::Handle<v8::ObjectTemplate> mTemplate;
  100.     v8::Handle<v8::FunctionTemplate> mConstructor;
  101.  
  102.     void initTemplate() {
  103.         mFunConstructor = std::make_shared<Function>("__constructor");
  104.         mConstructor = v8::FunctionTemplate::New(&__defaultConstructorCall, v8::External::New(this));
  105.         mTemplate = mConstructor->PrototypeTemplate();
  106.         mTemplate->SetInternalFieldCount(2);
  107.     }
  108.  
  109.     static void __cdecl destructorCall(v8::Persistent<v8::Value> obj, void* params) {
  110.         ClassInstance* instance = (ClassInstance*)params;
  111.         delete instance;
  112.  
  113.         obj.Dispose();
  114.     }
  115.  
  116.     v8::Handle<v8::Value> wrapInstance(std::shared_ptr<_classType> instance) {
  117.         ClassInstance* clsInst = new ClassInstance(instance);
  118.  
  119.         auto obj = v8::Persistent<v8::Object>::New(mTemplate->NewInstance());
  120.         obj->SetInternalField(0, v8::External::New(clsInst));
  121.         obj->SetInternalField(1, v8::Integer::NewFromUnsigned('JSCL'));
  122.  
  123.         obj.MakeWeak(clsInst, &Class<_classType>::destructorCall);
  124.  
  125.         return obj;
  126.     }
  127.  
  128. public:
  129.     Class(const std::string& name) {
  130.         mName = name;
  131.         initTemplate();
  132.     }
  133.  
  134.     v8::Handle<v8::Object> createInstance(std::shared_ptr<GenericSharedPtrWrap> ptr) {
  135.         auto subClass = std::dynamic_pointer_cast<SharedPtrWrap<_classType>>(ptr);
  136.         ClassInstance* instance = new ClassInstance(subClass->getPtr());
  137.         auto obj = v8::Persistent<v8::Object>::New(mTemplate->NewInstance());
  138.         obj->SetInternalField(0, v8::External::New(instance));
  139.         obj->SetInternalField(1, v8::Integer::NewFromUnsigned('JSCL'));
  140.  
  141.         obj.MakeWeak(instance, &Class::destructorCall);
  142.  
  143.         return obj;
  144.     }
  145.  
  146.     void addToScope(ScopePtr scope) const {
  147.         scope->getTemplate()->Set(v8::String::New(mName.c_str()), mConstructor);
  148.     }
  149.  
  150.     template<typename... Args>
  151.     void def_constructor() {
  152.         using namespace std; // HACK: Error in visual studio 2012, variadic templates get their namespace removed. So std::shared_ptr will be shared_ptr here
  153.         std::function < v8::Handle<v8::Value> (Args...) > fun = [this](Args... args) { return wrapInstance(std::make_shared<_classType>(args...)); };
  154.         mFunConstructor->addOverload(fun);
  155.     }
  156.  
  157.     void def_constructor() {
  158.         mFunConstructor->addOverload(std::function<v8::Handle<v8::Value> ()>([this]() { return wrapInstance(std::make_shared<_classType>()); }));
  159.     }
  160.  
  161.     template<typename Res, typename... Args>
  162.     void def_function(const std::wstring& name, Res(_classType::*func)(Args...)) {
  163.         auto existing = mFunctions.find(name);
  164.         FunctionPtr dstFun = nullptr;
  165.         if (existing == mFunctions.end()) {
  166.             FunctionPtr funPtr = std::make_shared<Function>(String::toAnsi(name));
  167.             funPtr->setMemberFunction(true);
  168.  
  169.             mTemplate->Set(v8::String::New(String::toAnsi(name).c_str()), funPtr->getTemplate());
  170.  
  171.             dstFun = funPtr;
  172.  
  173.             mFunctions.insert(std::make_pair(name, funPtr));
  174.         } else {
  175.             dstFun = existing->second;
  176.         }
  177.  
  178.         dstFun->addOverload(std::function<Res(std::shared_ptr<_classType>, Args...)>(
  179.             [func](std::shared_ptr<_classType> _this, Args... args) {
  180.                 return ((_this.get())->*func)(args...);
  181.             }
  182.         ));
  183.     }
  184.  
  185.     template<typename Res, typename... Args>
  186.     void def_function(const std::wstring& name, std::function<Res(std::shared_ptr<_classType>, Args...)> fun) {
  187.         auto existing = mFunctions.find(name);
  188.         FunctionPtr dstFun = nullptr;
  189.         if (existing == mFunctions.end()) {
  190.             FunctionPtr funPtr = std::make_shared<Function>(String::toAnsi(name));
  191.             funPtr->setMemberFunction(true);
  192.            
  193.             mTemplate->Set(v8::String::New(String::toAnsi(name).c_str()), funPtr->getTemplate());
  194.  
  195.             dstFun = funPtr;
  196.  
  197.             mFunctions.insert(std::make_pair(name, funPtr));
  198.         } else {
  199.             dstFun = existing->second;
  200.         }
  201.  
  202.         dstFun->addOverload(fun);
  203.     }
  204.  
  205.     template<typename Res, typename... Args>
  206.     void def_function(const std::wstring& name, Res(*fun)(std::shared_ptr<_classType>, Args...)) {
  207.         def_function(name, std::function<Res(std::shared_ptr<_classType>, Args...)>(fun));
  208.     }
  209.  
  210.     template<typename T>
  211.     void def_function_static(const std::wstring& name, T fun) {
  212.         def_function_static(name, std::function<typename std::remove_pointer<T>::type>(fun));
  213.     }
  214.  
  215.     template<typename Res>
  216.     void def_function_static(const std::wstring& name, Res(*fun)()) {
  217.         def_function_static(name, std::function<Res()>(fun));
  218.     }
  219.  
  220.     template<typename Res, typename... Args>
  221.     void def_function_static(const std::wstring& name, const std::function<Res(Args...)>& fun) {
  222.         auto existing = mStaticFunctions.find(name);
  223.         FunctionPtr dstFun = nullptr;
  224.         if (existing == mStaticFunctions.end()) {
  225.             FunctionPtr funPtr = std::make_shared<Function>(String::toAnsi(name));
  226.  
  227.             mConstructor->Set(v8::String::New(String::toAnsi(name).c_str()), funPtr->getTemplate());
  228.  
  229.             dstFun = funPtr;
  230.  
  231.             mStaticFunctions.insert(std::make_pair(name, funPtr));
  232.         } else {
  233.             dstFun = existing->second;
  234.         }
  235.  
  236.         dstFun->addOverload(fun);
  237.     }
  238.  
  239.     template<typename Res>
  240.     void def_function_static(const std::wstring& name, const std::function<Res()>& fun) {
  241.         auto existing = mStaticFunctions.find(name);
  242.         FunctionPtr dstFun = nullptr;
  243.         if (existing == mStaticFunctions.end()) {
  244.             FunctionPtr funPtr = std::make_shared<Function>(String::toAnsi(name));
  245.  
  246.             mConstructor->Set(v8::String::New(String::toAnsi(name).c_str()), funPtr->getTemplate());
  247.  
  248.             dstFun = funPtr;
  249.  
  250.             mStaticFunctions.insert(std::make_pair(name, funPtr));
  251.         } else {
  252.             dstFun = existing->second;
  253.         }
  254.  
  255.         dstFun->addOverload(fun);
  256.     }
  257.  
  258.     template<typename P>
  259.     void def_property(const std::wstring& name, std::function<P(_classType*)> getter, std::function<void (_classType*, P)> setter) {
  260.         PropertyInfoHolder<P>* holder = new PropertyInfoHolder<P>(getter, setter);
  261.         mTemplate->SetAccessor(
  262.             v8::String::New(::String::toAnsi(name).c_str()),
  263.             &Class::custPropertyGetCall<P>,
  264.             &Class::custPropertySetCall<P>,
  265.             v8::External::New(holder));
  266.  
  267.         mPropertyHolders.push_back(std::unique_ptr<GenericPropertyInfoHolder>(holder));
  268.     }
  269.  
  270.     template<typename P>
  271.     void def_property(const std::wstring& name, std::function<P(_classType*)> getter) {
  272.         PropertyInfoHolder<P>* holder = new PropertyInfoHolder<P>(getter);
  273.         mTemplate->SetAccessor(
  274.             v8::String::New(::String::toAnsi(name).c_str()),
  275.             &Class::custPropertyGetCall<P>,
  276.             &Class::custPropertySetCall<P>,
  277.             v8::External::New(holder));
  278.  
  279.         mPropertyHolders.push_back(std::unique_ptr<GenericPropertyInfoHolder>(holder));
  280.     }
  281. };
Advertisement
Add Comment
Please, Sign In to add comment