diff options
Diffstat (limited to 'squirrel_3_0_1_stable/sqplus/SqPlusSmartPointer.h')
-rw-r--r-- | squirrel_3_0_1_stable/sqplus/SqPlusSmartPointer.h | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/squirrel_3_0_1_stable/sqplus/SqPlusSmartPointer.h b/squirrel_3_0_1_stable/sqplus/SqPlusSmartPointer.h new file mode 100644 index 000000000..34996ffd8 --- /dev/null +++ b/squirrel_3_0_1_stable/sqplus/SqPlusSmartPointer.h @@ -0,0 +1,141 @@ +// SqPlusSmartPointer.h +// SqPlus smart pointer member function support created by James Whitworth. +// Modular integration 07/11/07 James Whitworth. +// you must define the function: +// unsigned char* getSmartPointerPointee(unsigned char*) { +// return &(MySmartPointer->pointee); +// } +// somewhere in your program so it can correctly lookup member variables on the class pointed to +// by your smart pointer. + +#ifdef SQPLUS_SMARTPOINTER_ACCESSTYPE +#undef SQPLUS_SMARTPOINTER_ACCESSTYPE +enum VarAccessType {VAR_ACCESS_READ_WRITE=0,VAR_ACCESS_READ_ONLY=1<<0,VAR_ACCESS_CONSTANT=1<<1,VAR_ACCESS_STATIC=1<<2,VAR_ACCESS_SMARTPOINTER=1<<3}; +#endif // #ifdef SQPLUS_SMARTPOINTER_ACCESSTYPE + +#ifdef SQPLUS_SMARTPOINTER_REGISTER_VARIABLE +#undef SQPLUS_SMARTPOINTER_REGISTER_VARIABLE +// classType is the type of the member variable's containing class. +template<typename T> +void +RegisterSmartInstanceVariable(SquirrelObject & so, + ClassTypeBase *classType, + T *var, + const SQChar *scriptVarName, + VarAccessType access = VAR_ACCESS_READ_WRITE) +{ + VarRef *pvr = createVarRef(so,scriptVarName); + + // var must be passed in as &obj->var, where obj = 0 + // (the address is the offset), or as static/global address. + void *offsetOrAddrOrConst = static_cast<void*>(var); + *pvr = VarRef(offsetOrAddrOrConst, + TypeInfo<T>(), + classType, + ClassType<T>::type(), + sizeof(*var), + access); + pvr->m_access |= VAR_ACCESS_SMARTPOINTER; + createInstanceSetGetHandlers(so); +} +#endif // #ifdef SQPLUS_SMARTPOINTER_REGISTER_VARIABLE + +#ifdef SQPLUS_SMARTPOINTER_DISPATCH +#undef SQPLUS_SMARTPOINTER_DISPATCH +template<typename Callee,typename Pointee,typename Func> +class DirectCallSmartInstanceMemberFunction { +public: + static inline int Dispatch(HSQUIRRELVM v) { + DirectCallInstanceFuncPicker<Callee, Func> p(v); + if (!p.instance || !p.func) { + sq_throwerror(v, _SC("Invalid Instance Type")); + } + Pointee *pointeeInstance = static_cast<Pointee*>(p.instance->get()); + return + !pointeeInstance ? sq_throwerror(v, _SC("SmartPointer Pointee NULL")) : + Call(*pointeeInstance, *(p.func), v, 2); + } +}; +#endif // #ifdef SQPLUS_SMARTPOINTER_DISPATCH + +#ifdef SQPLUS_SMARTPOINTER_DIRECT_CLOSURE +#undef SQPLUS_SMARTPOINTER_DIRECT_CLOSURE + +template<typename Callee,typename Pointee,typename Func> +inline void sq_pushdirectsmartinstanceclosure(HSQUIRRELVM v,const Callee & callee,const Pointee & pointee,Func func,SQUnsignedInteger nupvalues) { + unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func)); // Also pushed on stack. + memcpy(up,&func,sizeof(func)); + sq_newclosure(v,DirectCallSmartInstanceMemberFunction<Callee,Pointee,Func>::Dispatch,nupvalues+1); +} // sq_pushdirectinstanceclosure + +#endif // #ifdef SQPLUS_SMARTPOINTER_DIRECT_CLOSURE + +#ifdef SQPLUS_SMARTPOINTER_REGISTER_INSTANCE +#undef SQPLUS_SMARTPOINTER_REGISTER_INSTANCE + +template<typename Callee, typename Pointee, typename Func> +inline void RegisterSmartInstance(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,Pointee & pointee,Func func,const SQChar * name) { + sq_pushobject(v,hclass); + sq_pushstring(v,name,-1); + sq_pushdirectsmartinstanceclosure(v,callee,pointee,func,0); + sq_createslot(v,-3); + sq_poptop(v); // Remove hclass. +} // RegisterInstance + +#endif // #ifdef SQPLUS_SMARTPOINTER_REGISTER_INSTANCE + +#ifdef SQPLUS_SMARTPOINTER_CLASS_DEF_FUNC +#undef SQPLUS_SMARTPOINTER_CLASS_DEF_FUNC + + // Register a smartpointer member function. + template<typename Pointee, typename Func> + SQClassDefBase & smartFunc(Func pfunc,const SQChar * name) { + RegisterSmartInstance(v,newClass.GetObjectHandle(),*(TClassType *)0,*(Pointee *)0,pfunc,name); + return *this; + } // func + +#endif // #ifdef SQPLUS_SMARTPOINTER_CLASS_DEF_FUNC + +#ifdef SQPLUS_SMARTPOINTER_CLASS_DEF_VAR +#undef SQPLUS_SMARTPOINTER_CLASS_DEF_VAR + + // Register a member variable. + template<typename Pointee, typename VarType> + SQClassDefBase & smartVar(VarType Pointee::* pvar,const SQChar * name,VarAccessType access=VAR_ACCESS_READ_WRITE) { + struct CV { + VarType Pointee::* var; + } cv; // Cast Variable helper. + cv.var = pvar; + RegisterSmartInstanceVariable(newClass,ClassType<TClassType>::type(),*(VarType **)&cv,name,access); + return *this; + } // var + + // Register a member variable as a UserPointer (read only). + template<typename Pointee, typename VarType> + SQClassDefBase & smartVarAsUserPointer(VarType Pointee::* pvar,const SQChar * name) { + struct CV { + VarType Pointee::* var; + } cv; // Cast Variable helper. + cv.var = pvar; + RegisterSmartInstanceVariable(newClass,ClassType<TClassType>::type(),*(SQAnything **)&cv,name,VAR_ACCESS_READ_ONLY); + return *this; + } // varAsUserPointer + +#endif // #ifdef SQPLUS_SMARTPOINTER_CLASS_DEF_VAR + + +#ifdef SQPLUS_SMARTPOINTER_CPP_DECLARATION +#undef SQPLUS_SMARTPOINTER_CPP_DECLARATION +extern unsigned char* getSmartPointerPointee(unsigned char*); +#endif + +#ifdef SQPLUS_SMARTPOINTER_INSTANCE_VARINFO +#undef SQPLUS_SMARTPOINTER_INSTANCE_VARINFO + if(vr->m_access & VAR_ACCESS_SMARTPOINTER) { + up = reinterpret_cast<char*>( + getSmartPointerPointee(reinterpret_cast<unsigned char*>(up)) + ); + } +#endif // #ifdef SQPLUS_SMARTPOINTER_CPP_DECLARATION + +// SqPlusSmartPointer.h |