summaryrefslogtreecommitdiff
path: root/source/3rd-party/Luax
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-03-19 23:06:27 +0800
committerchai <chaifix@163.com>2019-03-19 23:06:27 +0800
commit1497dccd63a84b7ee2b229b1ad9c5c02718f2a78 (patch)
treef8d1bff50da13e126d08c7345653e002e293202d /source/3rd-party/Luax
parent5e2a973516e0729b225da9de0b03015dc5854ac4 (diff)
*rename
Diffstat (limited to 'source/3rd-party/Luax')
-rw-r--r--source/3rd-party/Luax/luax.h14
-rw-r--r--source/3rd-party/Luax/luax_cfunctions.cpp19
-rw-r--r--source/3rd-party/Luax/luax_cfunctions.h25
-rw-r--r--source/3rd-party/Luax/luax_class.cpp243
-rw-r--r--source/3rd-party/Luax/luax_class.hpp176
-rw-r--r--source/3rd-party/Luax/luax_class.inl550
-rw-r--r--source/3rd-party/Luax/luax_config.h60
-rw-r--r--source/3rd-party/Luax/luax_context.cpp29
-rw-r--r--source/3rd-party/Luax/luax_context.h36
-rw-r--r--source/3rd-party/Luax/luax_enum.cpp67
-rw-r--r--source/3rd-party/Luax/luax_enum.h38
-rw-r--r--source/3rd-party/Luax/luax_memberref.cpp16
-rw-r--r--source/3rd-party/Luax/luax_memberref.h27
-rw-r--r--source/3rd-party/Luax/luax_ref.cpp69
-rw-r--r--source/3rd-party/Luax/luax_ref.h62
-rw-r--r--source/3rd-party/Luax/luax_reftable.cpp120
-rw-r--r--source/3rd-party/Luax/luax_reftable.h67
-rw-r--r--source/3rd-party/Luax/luax_runtime.cpp89
-rw-r--r--source/3rd-party/Luax/luax_runtime.h59
-rw-r--r--source/3rd-party/Luax/luax_state.cpp737
-rw-r--r--source/3rd-party/Luax/luax_state.h238
-rw-r--r--source/3rd-party/Luax/luax_state.inl140
22 files changed, 2881 insertions, 0 deletions
diff --git a/source/3rd-party/Luax/luax.h b/source/3rd-party/Luax/luax.h
new file mode 100644
index 0000000..d05c258
--- /dev/null
+++ b/source/3rd-party/Luax/luax.h
@@ -0,0 +1,14 @@
+#ifndef __LUAX_H__
+#define __LUAX_H__
+
+#include "luax_state.h"
+#include "luax_runtime.h"
+#include "luax_ref.h"
+#include "luax_reftable.h"
+#include "luax_enum.h"
+#include "luax_class.hpp"
+#include "luax_memberref.h"
+#include "luax_class.inl"
+#include "luax_state.inl"
+
+#endif \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_cfunctions.cpp b/source/3rd-party/Luax/luax_cfunctions.cpp
new file mode 100644
index 0000000..d93a0ee
--- /dev/null
+++ b/source/3rd-party/Luax/luax_cfunctions.cpp
@@ -0,0 +1,19 @@
+#include "luax_cfunctions.h"
+#include "luax_config.h"
+
+namespace Luax
+{
+
+ int luax_c_getupvalue(lua_State* L)
+ {
+ lua_pushvalue(L, lua_upvalueindex(1));
+ return 1;
+ }
+
+ int luax_c_errfunc(lua_State* L)
+ {
+ cc8* msg = luaL_optstring(L, lua_upvalueindex(1), "");
+ return luaL_error(L, msg);
+ }
+
+} \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_cfunctions.h b/source/3rd-party/Luax/luax_cfunctions.h
new file mode 100644
index 0000000..2570bb9
--- /dev/null
+++ b/source/3rd-party/Luax/luax_cfunctions.h
@@ -0,0 +1,25 @@
+#ifndef __LUAX_CFUNCTIONS_H__
+#define __LUAX_CFUNCTIONS_H__
+
+#include "luax_config.h"
+
+/**
+ * luax_cfunctionĺעluaһЩ⹦ܵͨú
+*/
+
+namespace Luax
+{
+
+ ///
+ /// õһupvalue
+ ///
+ extern int luax_c_getupvalue(lua_State* L);
+
+ ///
+ /// ô˺ʱᱨupvalue(1)ǴϢ
+ ///
+ extern int luax_c_errfunc(lua_State* L);
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_class.cpp b/source/3rd-party/Luax/luax_class.cpp
new file mode 100644
index 0000000..e2019d4
--- /dev/null
+++ b/source/3rd-party/Luax/luax_class.cpp
@@ -0,0 +1,243 @@
+#include "luax_class.hpp"
+#include "luax_runtime.h"
+#include "luax_cfunctions.h"
+
+namespace Luax
+{
+
+#if LUAX_ENABLE_PLAIN_CLASS
+
+ int LuaxPlainClass::registry(lua_State* L)
+ {
+ LUAX_STATE(L);
+
+ // params:
+ // 1: class name
+
+ cc8* type = state.GetValue<cc8*>(1, "");
+
+ lua_newtable(L); // class table
+
+ // GetClassName()
+ lua_pushstring(L, type);
+ lua_pushcclosure(L, luax_c_getupvalue, 1);
+ lua_setfield(L, -2, "GetClassName");
+
+ // GetClass()
+ lua_pushvalue(L, -1); // class table
+ lua_pushcclosure(L, luax_c_getupvalue, 1);
+ lua_setfield(L, -2, "GetClass");
+
+ // TypeOf()
+ lua_pushcfunction(L, l_TypeOf);
+ lua_setfield(L, -2, "TypeOf");
+
+ // New()
+ lua_pushvalue(L, -1); // class table
+ lua_pushcclosure(L, l_New, 1);
+ lua_setfield(L, -2, "New");
+
+ // Extend()
+ lua_pushvalue(L, -1); // class table
+ lua_pushcclosure(L, l_Extend, 1);
+ lua_setfield(L, -2, "Extend");
+
+ lua_pushvalue(L, -1); // class table
+ lua_setfield(L, -2, "__index");
+
+ lua_pushstring(L, type);
+ lua_pushcclosure(L, l___tostring, 1);
+ lua_setfield(L, -2, "__tostring");
+
+ return 1;
+ }
+
+ int LuaxPlainClass::l___tostring(lua_State* L)
+ {
+ // upvalues:
+ // 1: class name
+
+ // params:
+ // 1: instance
+
+ if (!lua_istable(L, 1))
+ {
+ return luaL_typerror(L, 1, lua_typename(L, LUA_TTABLE));
+ }
+
+ cc8* type = lua_tostring(L, lua_upvalueindex(1));
+
+ lua_pushfstring(L, "%s: %p", type, lua_topointer(L, 1));
+
+ return 1;
+ }
+
+ ///
+ /// NewnԻȡCtorCtorʼʵ
+ ///
+ int LuaxPlainClass::l_New(lua_State* L)
+ {
+ LUAX_STATE(L);
+
+ // upvalues:
+ // 1: class table
+
+ // params:
+ // n: params
+ int n = lua_gettop(L);
+
+ int classTable = lua_upvalueindex(1);
+
+ lua_newtable(L); // instance table
+
+ // instance metatable Ϊ class
+ lua_pushvalue(L, classTable);
+ lua_setmetatable(L, -2);
+
+ // ҵ캯ᴥmetatable.__index,ݼ̳ҡ
+ lua_getfield(L, classTable, "Ctor");
+ if (state.IsType(-1, LUA_TFUNCTION))
+ {
+ // stack:
+ // -1: Ctor()
+ // -2: instance
+ // -3~-n-2: params
+
+ lua_insert(L, -2 - n);
+ // stack:
+ // -1: instance
+ // -2~-n-1: params
+ // -n-2: Ctor()
+
+ lua_pushvalue(L, -1);
+ // stack:
+ // -1: instance
+ // -2: instance
+ // -3~-n-2: params
+ // -n-3: Ctor
+
+ lua_insert(L, -3 - n);
+ // stack:
+ // -1: instance
+ // -2~-n-1: params
+ // -n-2: Ctor()
+ // -n-3: instance
+
+ lua_insert(L, -1 - n);
+ // stack:
+ // -1~-n: params
+ // -n-1: instance
+ // -n-2: Ctor()
+ // -n-3: instance
+
+ lua_pcall(L, n + 1, 0, 0);
+ }
+ else
+ {
+ state.Pop();
+ }
+
+ return 1;
+ }
+
+ int LuaxPlainClass::l_Extend(lua_State* L)
+ {
+ LUAX_STATE(L);
+
+ // upvalues:
+ // 1: base class
+
+ // params:
+ // 1: class name
+
+ cc8* type = state.GetValue<cc8*>(1, "");
+
+ int baseClass = lua_upvalueindex(1);
+
+ lua_newtable(L); // class table
+
+ // GetClassName()
+ lua_pushstring(L, type);
+ lua_pushcclosure(L, luax_c_getupvalue, 1);
+ lua_setfield(L, -2, "GetClassName");
+
+ // GetClass()
+ lua_pushvalue(L, -1); // class table
+ lua_pushcclosure(L, luax_c_getupvalue, 1);
+ lua_setfield(L, -2, "GetClass");
+
+ // New()
+ lua_pushvalue(L, -1); // class table
+ lua_pushcclosure(L, l_New, 1);
+ lua_setfield(L, -2, "New");
+
+ // Extend()
+ lua_pushvalue(L, -1); // class table
+ lua_pushcclosure(L, l_Extend, 1);
+ lua_setfield(L, -2, "Extend");
+
+ // .__base
+ lua_pushvalue(L, baseClass); // base class
+ lua_setfield(L, -2, "__base");
+
+ lua_pushvalue(L, -1); // class table
+ lua_setfield(L, -2, "__index");
+
+ lua_pushstring(L, type);
+ lua_pushcclosure(L, l___tostring, 1);
+ lua_setfield(L, -2, "__tostring");
+
+ // classmetatableΪbaseClass
+ lua_pushvalue(L, baseClass);
+ lua_setmetatable(L, -2);
+
+ return 1;
+ }
+
+ int LuaxPlainClass::l_TypeOf(lua_State* L)
+ {
+ // params:
+ // 1: lua instance
+ // 2: type string
+
+ LUAX_STATE(L);
+
+ cc8* type = state.GetValue<cc8*>(2, "");
+
+ if (!lua_istable(L, 1))
+ {
+ return luaL_typerror(L, 1, "Object");
+ }
+
+ lua_pushvalue(L, 1); // lua instance
+
+ while (lua_getmetatable(L, -1))
+ {
+ lua_getfield(L, -1, "GetClassName");
+ if (lua_isfunction(L, -1))
+ {
+ state.Call(0, 1);
+ cc8* name = state.GetValue<cc8*>(-1, "");
+ if (strcmp(name, type) == 0)
+ {
+ lua_pushboolean(L, true);
+ return 1;
+ }
+ else
+ {
+ state.Pop(); // name
+ }
+ }
+ else
+ {
+ state.Pop();
+ }
+ }
+
+ lua_pushboolean(L, false);
+ return 1;
+ }
+
+#endif /*LUAX_ENABLE_PLAIN_CLASS*/
+
+} \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_class.hpp b/source/3rd-party/Luax/luax_class.hpp
new file mode 100644
index 0000000..ea1fab9
--- /dev/null
+++ b/source/3rd-party/Luax/luax_class.hpp
@@ -0,0 +1,176 @@
+#ifndef __LUAX_CLASS_H__
+#define __LUAX_CLASS_H__
+
+#include <vector>
+
+#include "luax_config.h"
+#include "luax_ref.h"
+#include "luax_memberref.h"
+#include "luax_cfunctions.h"
+
+namespace Luax
+{
+
+#define LUAX_DECL_METHOD(mtd) static int mtd(lua_State* L)
+
+ ///
+ /// RegisterLuaxClass עķͳԱö١ȵclass table
+ /// LuaxGetFactoryName ùͬʱעʱעΪsingletonͨʱ
+ ///
+#define LUAX_DECL_FACTORY(type) \
+ static void RegisterLuaxClass(Luax::LuaxState&);\
+ static void RegisterLuaxPostprocess(Luax::LuaxState&); \
+ static const char* GetLuaxFactoryName() { return #type; };\
+ static const char* GetLuaxClassName() { return #type; };\
+ static bool IsLuaxClassSingleton() { return false; };
+
+ ///
+ /// RegisterLuaxClass עķͳԱö١ȵclass table
+ /// LuaxGetSingletonName õ
+ ///
+#define LUAX_DECL_SINGLETON(type) \
+ static void RegisterLuaxClass(Luax::LuaxState&); \
+ static void RegisterLuaxPostprocess(Luax::LuaxState&); \
+ static const char* GetLuaxSingletonName() { return #type; }; \
+ static const char* GetLuaxClassName() { return #type; }; \
+ static bool IsLuaxClassSingleton() { return true; };
+
+#define LUAX_IMPL_METHOD(type, f) int type::f(lua_State* L)
+
+#define LUAX_REGISTRY(type) void type::RegisterLuaxClass(Luax::LuaxState& state)
+
+#define LUAX_POSTPROCESS(type) void type::RegisterLuaxPostprocess(Luax::LuaxState& state)
+
+#define LUAX_REGISTER_FACTORY(stt, type) stt.RegisterFactory<type>()
+
+#define LUAX_REGISTER_SINGLETON(stt, type) stt.RegisterSingleton<type>()
+
+ ///
+ /// Ҫ¶luanative classҪ̳дࡣͨluaʵҪȷüȷԣڶ߳Ҫȷͷš
+ ///
+ template<class T>
+ class LuaxNativeClass
+ {
+ public:
+
+ ///
+ /// userdataΪkeyref tableuserdataһãάuserdataڡ
+ ///
+ template<class U> void LuaRetain(LuaxState& state, U* userdata);
+
+ ///
+ /// userdataһref tableԳԻuserdata
+ ///
+ template<class U> void LuaRelease(LuaxState& state, U* userdata);
+
+ protected:
+
+ LuaxNativeClass();
+ virtual ~LuaxNativeClass();
+
+ ///
+ /// userdata pushջûгʼmUserdataʼúԪѳʼõuserdataջһá
+ ///
+ bool PushLuaxUserdata(LuaxState& state);
+ bool PushLuaxMemberTable(LuaxState& state);
+ bool PushLuaxRefTable(LuaxState& state);
+
+ ///
+ /// Աùʵref tableáȡ
+ ///
+ void SetMemberRef(LuaxState& state, LuaxMemberRef& memRef, int idx);
+ bool PushMemberRef(LuaxState& state, LuaxMemberRef& memRef);
+ void ClearMemberRef(LuaxState& state, LuaxMemberRef& memRef);
+
+ private:
+
+ friend class LuaxState;
+
+ static void RegisterLuaxClass(LuaxState& state);
+ static void RegisterLuaxFactoryClass(LuaxState& state);
+ static void RegisterLuaxSingletonClass(LuaxState& state);
+
+ static void SetLuaxClassTableRef(LuaxState& state, int idx);
+
+ static void PushLuaxClassTable(LuaxState& state);
+
+ ///
+ /// ȡַҪַֻͨڶϴʵõջϺ;̬ıȡַ֤ü׼ȷ
+ /// ҪãʹôݶǴݵַ
+ ///
+ void* operator &();
+
+ ///
+ /// userdataʵstate
+ ///
+ void BindToLua(LuaxState& state);
+
+ //------------------------------------------------------------------------------------------------------------
+
+ ///
+ /// LuaxNativeClass<T>͵ʵ
+ ///
+ static LuaxStrongRef mClassTable; // class table͵
+ static LuaxStrongRef mSingletonRefTable; // ǵsingletonijԱԱ֤ᱻͨ
+ // ref tableijԱȫڵģֱ_LUAX_STRONGREF_TABLE
+
+ ///
+ /// ͨuserdataõ:
+ /// 1: ref table
+ /// 2: member table
+ /// 3: class table
+ ///
+ LuaxWeakRef mUserdata;
+
+ public:
+
+ //------------------------------------------------------------------------------------------------------------
+ //
+
+ LUAX_DECL_METHOD( l___tostring );
+ LUAX_DECL_METHOD( l_GetClass );
+ LUAX_DECL_METHOD( l_GetClassName );
+
+ //------------------------------------------------------------------------------------------------------------
+ //
+
+ LUAX_DECL_METHOD( l___gc );
+#if LUAX_ENABLE_NATIVE_EXTEND
+ LUAX_DECL_METHOD( l_ExtendFactory );
+#endif
+ LUAX_DECL_METHOD( l_GetRefTable );
+ LUAX_DECL_METHOD( l_New );
+
+ //------------------------------------------------------------------------------------------------------------
+ //
+#if LUAX_ENABLE_NATIVE_EXTEND
+ LUAX_DECL_METHOD( l_ExtendSingleton );
+#endif
+ };
+
+ //--------------------------------------------------------------------------------------------------------------
+
+#if LUAX_ENABLE_PLAIN_CLASS
+ ///
+ /// lua
+ ///
+ class LuaxPlainClass
+ {
+ public:
+
+ ///
+ /// עںͨregistry()עࡣ
+ ///
+ static int registry(lua_State* L);
+
+ LUAX_DECL_METHOD( l___tostring );
+ LUAX_DECL_METHOD( l_Extend );
+ LUAX_DECL_METHOD( l_New );
+ LUAX_DECL_METHOD( l_TypeOf );
+
+ };
+#endif
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_class.inl b/source/3rd-party/Luax/luax_class.inl
new file mode 100644
index 0000000..028d4f9
--- /dev/null
+++ b/source/3rd-party/Luax/luax_class.inl
@@ -0,0 +1,550 @@
+namespace Luax
+{
+
+ //----------------------------------------------------------------------------------------------------------------
+ // ӿ
+
+ ///
+ /// ԲͬͣͨGetLuaClassName࣬GetClassNameᱻǣָluax_c_getupvalue
+ ///
+ template<typename T>
+ int LuaxNativeClass<T>::l_GetClassName(lua_State* L)
+ {
+ LUAX_SETUP(L, "*");
+
+ cc8* type = T::GetLuaxClassName();
+ state.Push(type);
+ return 1;
+ }
+
+ //----------------------------------------------------------------------------------------------------------------
+
+ ///
+ /// עṤ͵еԱ
+ ///
+ template<typename T>
+ void LuaxNativeClass<T>::RegisterLuaxClass(LuaxState& state)
+ {
+ luaL_Reg regTable[] = {
+ { "GetClass", l_GetClass },
+ { "GetClassName", l_GetClassName },
+ { NULL, NULL }
+ };
+
+ state.RegisterMethods(regTable);
+ }
+
+ ///
+ /// ijԱעclass table
+ ///
+ template<typename T>
+ void LuaxNativeClass<T>::RegisterLuaxFactoryClass(LuaxState& state)
+ {
+ luaL_Reg regTable[] = {
+ { "GetRefTable", l_GetRefTable },
+ { NULL, NULL }
+ };
+
+ state.RegisterMethods(regTable);
+ }
+
+ ///
+ /// ijԱעclass table
+ ///
+ template<typename T>
+ void LuaxNativeClass<T>::RegisterLuaxSingletonClass(LuaxState& state)
+ {
+ luaL_Reg regTable[] = {
+ { NULL, NULL }
+ };
+
+ state.RegisterMethods(regTable);
+ }
+
+ template<typename T>
+ void LuaxNativeClass<T>::PushLuaxClassTable(LuaxState& state)
+ {
+ assert(mClassTable);
+
+ mClassTable.PushRef(state);
+ }
+
+ template<typename T>
+ void LuaxNativeClass<T>::SetLuaxClassTableRef(LuaxState& state, int idx)
+ {
+ mClassTable.SetRef(state, idx);
+ }
+
+ template<typename T>
+ LuaxNativeClass<T>::LuaxNativeClass()
+ {
+ }
+
+ template<typename T>
+ LuaxNativeClass<T>::~LuaxNativeClass()
+ {
+ }
+
+ template<typename T>
+ template<typename U>
+ void LuaxNativeClass<T>::LuaRetain(LuaxState& state, U* userdata)
+ {
+ if (PushLuaxRefTable(state))
+ {
+ if (userdata->PushLuaxUserdata(state))
+ {
+ lua_pushvalue(state, -1); // copy the userdata
+ lua_gettable(state, -3); // get the count (or nil)
+ u32 count = state.GetValue<u32>(-1, 0); // get the count (or 0)
+ lua_pop(state, 1); // pop the old count
+ lua_pushnumber(state, count + 1); // push the new count
+ lua_settable(state, -3); // save it in the table: reftable[userdata] = count
+ }
+ }
+ }
+
+ template<typename T>
+ template<typename U>
+ void LuaxNativeClass<T>::LuaRelease(LuaxState& state, U* userdata)
+ {
+ if (PushLuaxRefTable(state))
+ {
+ if (userdata->PushLuaxUserdata(state))
+ {
+ lua_pushvalue(state, -1); // copy the userdata
+ lua_gettable(state, -3); // get the count (or nil)
+ u32 count = state.GetValue<u32>(-1, 0); // get the count (or 0)
+ lua_pop(state, 1); // pop the old count
+
+ if (count == 0) return; // nothing to do
+
+ if (count > 1) {
+ lua_pushnumber(state, count - 1); // push the new count
+ }
+ else {
+ lua_pushnil(state); // maybe cause gc
+ }
+ lua_settable(state, -3); // save it in the table
+ }
+ }
+ }
+
+ template<typename T>
+ bool LuaxNativeClass<T>::PushLuaxUserdata(LuaxState& state)
+ {
+ assert(!T::IsLuaxClassSingleton());
+ if (!mUserdata)
+ {
+ BindToLua(state);
+ return true;
+ }
+ return mUserdata.PushRef(state);
+ }
+
+ template<typename T>
+ bool LuaxNativeClass<T>::PushLuaxMemberTable(LuaxState& state)
+ {
+ int top = state.GetTop();
+ if (this->PushLuaxUserdata(state))
+ {
+ if (lua_getmetatable(state, -1)) // ref table
+ {
+ lua_replace(state, -2);
+ if (lua_getmetatable(state, -1)) // member table
+ {
+ lua_replace(state, -2);
+ return true;
+ }
+ }
+ }
+ state.SetTop(top);
+ lua_pushnil(state);
+ return false;
+ }
+
+ template<typename T>
+ bool LuaxNativeClass<T>::PushLuaxRefTable(LuaxState& state)
+ {
+ // Singleton
+ if (T::IsLuaxClassSingleton())
+ {
+ if (!this->mSingletonRefTable) {
+ lua_newtable(state);
+ this->mSingletonRefTable.SetRef(state, -1); // strong ref to member table won't be garbage collected
+ }
+ else {
+ this->mSingletonRefTable.PushRef(state);
+ }
+ return true;
+ }
+ // Factory
+ else
+ {
+ if (this->PushLuaxUserdata(state))
+ {
+ if (lua_getmetatable(state, -1))
+ {
+ lua_replace(state, -2);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// userdataԴref tablemember tableclass table
+ /// ref table kvǿtableuserdataüͨuserdataΪkeyΪvalueԼԱ
+ /// member table luaʵijԱ
+ /// class table б͵ʵеĺ
+ ///
+ template<typename T>
+ void LuaxNativeClass<T>::BindToLua(LuaxState& state)
+ {
+ // ܰuserdata
+ assert(!T::IsLuaxClassSingleton());
+ assert(!mUserdata);
+
+ // userdataջ
+ state.PushPtrUserData(this);
+
+ lua_newtable(state); // ref table޷luaʣC
+ lua_newtable(state); // member tableluaдĶԱ
+ PushLuaxClassTable(state); // class table
+
+ // stack:
+ // -1: class table
+ // -2: member table
+ // -3: ref table
+ // -4: userdata
+
+ int top = state.GetTop();
+ int memberTable = top - 1;
+ int refTable = top - 2;
+
+ // ref table ע __tostring
+ lua_pushcfunction(state, l___tostring);
+ lua_setfield(state, refTable, "__tostring");
+
+ // ref table __index __newindex Ϊ member table
+ lua_pushvalue(state, memberTable);
+ lua_setfield(state, refTable, "__index");
+
+ lua_pushvalue(state, memberTable);
+ lua_setfield(state, refTable, "__newindex");
+
+ lua_pushcfunction(state, l___gc);
+ lua_setfield(state, refTable, "__gc");
+
+ // Ԫ
+ lua_setmetatable(state, -2); // class is meta of member
+ lua_setmetatable(state, -2); // member is meta of ref
+ lua_setmetatable(state, -2); // ref is meta of userdata
+
+ // һuserdataãͨPushLuaUserdatalua
+ mUserdata.SetRef(state, -1);
+ assert(mUserdata);
+ }
+
+ ///
+ /// Աù
+ ///
+ template<typename T>
+ void LuaxNativeClass<T>::SetMemberRef(LuaxState& state, LuaxMemberRef& memRef, int idx)
+ {
+ ClearMemberRef(state, memRef);
+ if (!lua_isnil(state, idx))
+ {
+ idx = state.AbsIndex(idx);
+ if (PushLuaxRefTable(state))
+ {
+ lua_pushvalue(state, idx);
+ memRef.refID = luaL_ref(state, -2);
+ state.Pop(); // ref table
+ }
+ }
+ }
+
+ template<typename T>
+ bool LuaxNativeClass<T>::PushMemberRef(LuaxState& state, LuaxMemberRef& memRef)
+ {
+ if (memRef)
+ {
+ if (PushLuaxRefTable(state))
+ {
+ lua_rawgeti(state, -1, memRef.refID);
+ lua_replace(state, -2); // ref table
+ if (lua_isnil(state, -1))
+ goto failed;
+ return true;
+ }
+ }
+ lua_pushnil(state);
+ failed:
+ memRef.refID = LUA_NOREF;
+ return false;
+ }
+
+ template<typename T>
+ void LuaxNativeClass<T>::ClearMemberRef(LuaxState& state, LuaxMemberRef& memRef)
+ {
+ if (memRef)
+ {
+ if (PushLuaxRefTable(state))
+ {
+ luaL_unref(state, -1, memRef.refID);
+ state.Pop(); // ref table
+ }
+ memRef.refID = LUA_NOREF;
+ }
+ }
+
+ //--------------------------------------------------------------------------------------------------------------
+
+ ///
+ /// ͷŹʵ
+ ///
+ template<typename T>
+ int LuaxNativeClass<T>::l___gc(lua_State* L)
+ {
+ LUAX_SETUP(L, "U");
+ T* self = state.GetLuaUserdata<T>(1);
+ delete self;
+ return 0;
+ }
+
+ ///
+ /// ʽ:
+ /// ַ
+ ///
+ template<typename T>
+ int LuaxNativeClass<T>::l___tostring(lua_State* L)
+ {
+ // params:
+ // 1: userdata
+
+ LUAX_STATE(L);
+ T* self = state.GetLuaUserdata<T>(1);
+ if (self)
+ {
+ cc8* classname = "";
+ lua_getfield(state, 1, "GetClassName");
+ if (state.IsType(-1, LUA_TFUNCTION))
+ {
+ lua_pushvalue(L, 1); // userdata
+ state.Call(1, 1); // GetClassName
+ classname = state.GetValue<cc8*>(-1, "");
+ }
+ else
+ {
+ classname = T::GetLuaxClassName();
+ }
+ lua_pushfstring(L, "%s: %p", classname, self);
+ return 1;
+ }
+ return 0;
+ }
+
+#if LUAX_ENABLE_NATIVE_EXTEND
+ ///
+ /// ࣬luaijԱΪƣDZ֤userdataͳһNative classṩCtor֧֣
+ /// nativeʵ崴ʹCtorгʼӵкͻһNewбnativeһ͡
+ ///
+ template<typename T>
+ int LuaxNativeClass<T>::l_ExtendFactory(lua_State* L)
+ {
+ // upvalues:
+ // 1: base class
+
+ // params:
+ // 1: class name
+
+ int baseClass = lua_upvalueindex(1);
+
+ lua_newtable(L); // class table
+
+ int inheritClass = lua_gettop(L);
+
+ // .GetClassName()
+ cc8* type = lua_tostring(L, 1);
+ lua_pushstring(L, type);
+ lua_pushcclosure(L, luax_c_getupvalue, 1);
+ lua_setfield(L, -2, "GetClassName");
+
+ // .GetClass()
+ lua_pushvalue(L, inheritClass);
+ lua_pushcclosure(L, luax_c_getupvalue, 1);
+ lua_setfield(L, -2, "GetClass");
+
+ // .Extend()
+ lua_pushvalue(L, inheritClass);
+ lua_pushcclosure(L, l_ExtendFactory, 1);
+ lua_setfield(L, -2, "Extend");
+
+ // .New()
+ lua_pushvalue(L, inheritClass);
+ lua_getfield(L, baseClass, "New");
+ lua_pushcclosure(L, l_New, 2);
+ lua_setfield(L, -2, "New");
+
+ // __base = baseClass
+ lua_pushvalue(L, baseClass);
+ lua_setfield(L, -2, "__base");
+
+ // __index = inheritClass
+ lua_pushvalue(L, inheritClass);
+ lua_setfield(L, -2, "__index");
+
+ // metatable is baseClass
+ lua_pushvalue(L, baseClass);
+ lua_setmetatable(L, inheritClass);
+
+ return 1;
+ }
+
+ template<typename T>
+ int LuaxNativeClass<T>::l_ExtendSingleton(lua_State* L)
+ {
+ // upvalues:
+ // 1: base class
+
+ // params:
+ // 1: class name
+
+ int baseClass = lua_upvalueindex(1);
+
+ lua_newtable(L); // class name
+
+ int inheritClass = lua_gettop(L);
+
+ // .GetClassName()
+ cc8* type = lua_tostring(L, 1);
+ lua_pushstring(L, type);
+ lua_pushcclosure(L, luax_c_getupvalue, 1);
+ lua_setfield(L, -2, "GetClassName");
+
+ // .GetClass()
+ lua_pushvalue(L, inheritClass);
+ lua_pushcclosure(L, luax_c_getupvalue, 1);
+ lua_setfield(L, -2, "GetClass");
+
+ // .Extend()
+ lua_pushvalue(L, inheritClass);
+ lua_pushcclosure(L, l_ExtendFactory, 1);
+ lua_setfield(L, -2, "Extend");
+
+ // __base = baseClass
+ lua_pushvalue(L, baseClass);
+ lua_setfield(L, -2, "__base");
+
+ // __index = inheritClass
+ lua_pushvalue(L, inheritClass);
+ lua_setfield(L, -2, "__index");
+
+ // metatable is baseClass
+ lua_pushvalue(L, baseClass);
+ lua_setmetatable(L, inheritClass);
+
+ return 1;
+ }
+#endif /*LUAX_ENABLE_NATIVE_EXTEND*/
+
+ template<typename T>
+ int LuaxNativeClass<T>::l_GetClass(lua_State* L)
+ {
+ LUAX_STATE(L);
+ if (!mClassTable)
+ lua_pushnil(L);
+ else
+ mClassTable.PushRef(state);
+ return 1;
+ }
+
+ template<typename T>
+ int LuaxNativeClass<T>::l_GetRefTable(lua_State* L)
+ {
+ LUAX_STATE(L);
+ T* self = state.GetLuaUserdata<T>(1);
+ bool success = self->PushLuaxRefTable(state);
+ if (!success)
+ lua_pushnil(L);
+ return 1;
+ }
+
+ template<typename T>
+ int LuaxNativeClass<T>::l_New(lua_State* L)
+ {
+ LUAX_STATE(L);
+
+ // upvalues:
+ // 1: class table
+ // 2: original New()
+
+ // stack:
+ // -1~-n: args
+
+ int n = lua_gettop(L); // n args
+
+ lua_pushvalue(L, lua_upvalueindex(2));
+ if (state.IsType(-1, LUA_TFUNCTION))
+ {
+ // stack:
+ // -1: New
+ // -2~-1-n: args
+
+ state.PushValues(-1 - n, n);
+
+ // stack:
+ // -1~-n: args
+ // -n-1: New
+ // -n-2~-1-2n: args
+
+ state.Call(n, 1);
+
+ // stack:
+ // -1: userdata
+ // -2~-1-n: args
+
+ // reset member table's metatable to class table
+ if (state.IsType(-1, LUA_TUSERDATA))
+ {
+ if (lua_getmetatable(L, -1)) // ref table
+ {
+ if (lua_getmetatable(L, -1)) // member table
+ {
+ lua_pushvalue(L, lua_upvalueindex(1)); // class table
+ lua_setmetatable(L, -2);
+ state.Pop(); // member table
+ }
+ state.Pop(); // ref table
+ }
+
+ // stack:
+ // -1: userdata
+ // -2~-1-n: args
+
+ int args = state.AbsIndex(-1 - n);
+
+ // ԵCtor
+ lua_getfield(L, lua_upvalueindex(1), "Ctor");
+
+ if (state.IsType(-1, LUA_TFUNCTION))
+ {
+ lua_pushvalue(L, -2); // userdata
+ state.PushValues(args, n);
+ state.Call(n + 1, 0);
+ }
+ else
+ state.Pop();
+
+ }
+
+ return 1;
+ }
+ return 0;
+ }
+
+ template<typename T> LuaxStrongRef LuaxNativeClass<T>::mClassTable; // class table
+ template<typename T> LuaxStrongRef LuaxNativeClass<T>::mSingletonRefTable; //
+
+} \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_config.h b/source/3rd-party/Luax/luax_config.h
new file mode 100644
index 0000000..c6562cc
--- /dev/null
+++ b/source/3rd-party/Luax/luax_config.h
@@ -0,0 +1,60 @@
+#ifndef __LUAX_TYPE_H__
+#define __LUAX_TYPE_H__
+
+#include <iostream>
+
+extern "C" {
+#include "lua51/lua.h"
+#include "lua51/lualib.h"
+#include "lua51/lauxlib.h"
+}
+
+#include <assert.h>
+
+namespace Luax
+{
+
+ typedef unsigned int uint;
+ typedef unsigned long uintptr;
+ typedef long sintptr;
+
+ typedef const char cc8;
+
+ typedef unsigned char u8;
+ typedef unsigned short u16;
+ typedef unsigned int u32;
+ typedef unsigned long long u64;
+
+ typedef signed char s8;
+ typedef signed short s16;
+ typedef signed int s32;
+ typedef signed long long s64;
+
+#ifdef _WIN32
+ #define LUAX_FINAL final
+ #define LUAX_LIBRARY_EXPORT __declspec(dllexport)
+ #define LUAX_LIBRARY_IMPORT __declspec(dllimport)
+ #define LUAX_FORCE_INLINE __forceinline
+ #define LUAX_RESTRICT __restrict
+ #define LUAX_ATTRIBUTE_USED
+ #define LUAX_ABSTRACT
+ #define LUAX_API LUAX_LIBRARY_EXPORT
+#else
+ #define LUAX_FINAL final
+ #define LUAX_LIBRARY_EXPORT __attribute__((visibility("default")))
+ #define LUAX_LIBRARY_IMPORT
+ #define LUAX_FORCE_INLINE __attribute__((always_inline)) inline
+ #define LUAX_RESTRICT __restrict__
+ #define LUAX_ATTRIBUTE_USED __attribute__((used))
+ #define LUAX_ABSTRACT
+ #define LUAX_API LUAX_LIBRARY_EXPORT
+#endif
+
+#define LUAX_ENABLE_NATIVE_EXTEND 0
+
+#define LUAX_ENABLE_PLAIN_CLASS 1
+#define LUAX_ENABLE_PLAIN_ENABLE 1
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_context.cpp b/source/3rd-party/Luax/luax_context.cpp
new file mode 100644
index 0000000..d41c24f
--- /dev/null
+++ b/source/3rd-party/Luax/luax_context.cpp
@@ -0,0 +1,29 @@
+#include "luax_context.h"
+
+namespace Luax
+{
+
+ LuaxContext::LuaxContext(lua_State* L)
+ : state(L)
+ {
+ assert(state);
+ }
+
+ LuaxContext::~LuaxContext()
+ {
+ }
+
+ // ʼcontext
+ void LuaxContext::Setup()
+ {
+ SetupRefTables();
+ }
+
+ void LuaxContext::SetupRefTables()
+ {
+ // strong ref weak ref
+ strongRefTable.Init(state, "_LUAX_STRONGREF_TABLE");
+ weakRefTable.Init(state, "_LUAX_WEAKREF_TABLE", "v");
+ }
+
+} \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_context.h b/source/3rd-party/Luax/luax_context.h
new file mode 100644
index 0000000..01c5937
--- /dev/null
+++ b/source/3rd-party/Luax/luax_context.h
@@ -0,0 +1,36 @@
+#ifndef __LUAX_CONTEXT_H__
+#define __LUAX_CONTEXT_H__
+
+#include "luax_ref.h"
+#include "luax_config.h"
+#include "luax_state.h"
+
+namespace Luax
+{
+
+ ///
+ /// lua_stateصcontextһϵдļϣҲûϵҪΪ˽Լڴ档
+ ///
+ class LuaxContext
+ {
+ public:
+ LuaxContext(lua_State* L);
+ ~LuaxContext();
+
+ void Setup();
+
+ LuaxState state; // lua state
+ LuaxRefTable strongRefTable; // strong ref table
+ LuaxRefTable weakRefTable; // weak ref table
+
+ size_t objectCount; // ͳڴstateдʵ
+
+ private:
+
+ void SetupRefTables();
+
+ };
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_enum.cpp b/source/3rd-party/Luax/luax_enum.cpp
new file mode 100644
index 0000000..88bbab4
--- /dev/null
+++ b/source/3rd-party/Luax/luax_enum.cpp
@@ -0,0 +1,67 @@
+#include "luax_enum.h"
+#include "luax_state.h"
+#include "luax_runtime.h"
+
+namespace Luax
+{
+
+ ///
+ /// ֻmetatable__index
+ ///
+ int l_rmt__index(lua_State* L)
+ {
+ // params:
+ // 1: enum table
+ // 2: key
+
+ // upvalues:
+ // 1: metatable
+
+ int mt = lua_upvalueindex(1);
+ lua_pushvalue(L, 2);
+ lua_rawget(L, mt);
+
+ return 1;
+ }
+
+ int l_rmt__newindex(lua_State* L)
+ {
+ // upvalue:
+ // 1: enum table name
+
+ cc8* name = lua_tostring(L, lua_upvalueindex(1));
+
+ return luaL_error(L, "Enum called \"%s\" is readonly.", name);
+ }
+
+ //--------------------------------------------------------------------------------------------------------------
+#if LUAX_ENABLE_PLAIN_ENABLE
+ int LuaxPlainEnum::registry(lua_State* L)
+ {
+ // params:
+ // 1: enum name
+ // 2: metatable
+
+ cc8* name = luaL_checkstring(L, 1);
+
+ if (!lua_istable(L, 2))
+ {
+ return luaL_error(L, "Create plain enum failed. Require table, but get %s", luaL_typename(L, 2));
+ }
+
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "__index");
+
+ lua_pushstring(L, name);
+ lua_pushcclosure(L, l_rmt__newindex, 1);
+ lua_setfield(L, -2, "__newindex");
+
+ lua_newtable(L); // enum table
+
+ lua_pushvalue(L, -2); // metatable
+ lua_setmetatable(L, -2);
+
+ return 1;
+ }
+#endif
+} \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_enum.h b/source/3rd-party/Luax/luax_enum.h
new file mode 100644
index 0000000..36f6bab
--- /dev/null
+++ b/source/3rd-party/Luax/luax_enum.h
@@ -0,0 +1,38 @@
+#ifndef __LUAX_ENUM_H__
+#define __LUAX_ENUM_H__
+
+#include "luax_config.h"
+
+namespace Luax
+{
+
+ ///
+ /// ö٣öһ಻޸ͼϣöٵֵ
+ ///
+ struct LuaxEnum
+ {
+ cc8* name;
+ int value;
+ };
+
+ extern int l_rmt__index(lua_State* L);
+
+ extern int l_rmt__newindex(lua_State* L);
+
+ //--------------------------------------------------------------------------------------------------------------
+#if LUAX_ENABLE_PLAIN_ENABLE
+ ///
+ /// luaö٣޸ĵtable
+ ///
+ class LuaxPlainEnum
+ {
+ public:
+
+ static int registry(lua_State* L);
+
+ };
+#endif
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_memberref.cpp b/source/3rd-party/Luax/luax_memberref.cpp
new file mode 100644
index 0000000..a8a09ba
--- /dev/null
+++ b/source/3rd-party/Luax/luax_memberref.cpp
@@ -0,0 +1,16 @@
+#include "luax_memberref.h"
+
+namespace Luax
+{
+
+ LuaxMemberRef::LuaxMemberRef()
+ : refID(LUA_NOREF)
+ {
+ }
+
+ LuaxMemberRef::~LuaxMemberRef()
+ {
+
+ }
+
+} \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_memberref.h b/source/3rd-party/Luax/luax_memberref.h
new file mode 100644
index 0000000..cda7946
--- /dev/null
+++ b/source/3rd-party/Luax/luax_memberref.h
@@ -0,0 +1,27 @@
+#ifndef __LUAX_MEMBER_REF_H__
+#define __LUAX_MEMBER_REF_H__
+
+#include "luax_config.h"
+
+namespace Luax
+{
+
+ ///
+ /// ʵref tablemember refluax classĹʵref tableǿãmemberڡ
+ /// luanative֮ݹͨ
+ ///
+ class LuaxMemberRef
+ {
+ public:
+ LuaxMemberRef();
+ ~LuaxMemberRef();
+
+ inline operator bool() { return refID != LUA_NOREF; };
+
+ int refID;
+
+ };
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_ref.cpp b/source/3rd-party/Luax/luax_ref.cpp
new file mode 100644
index 0000000..544861d
--- /dev/null
+++ b/source/3rd-party/Luax/luax_ref.cpp
@@ -0,0 +1,69 @@
+#include "luax_runtime.h"
+#include "luax_ref.h"
+
+namespace Luax
+{
+
+ LuaxRef::LuaxRef(int mode)
+ : mRefID(LUA_NOREF)
+ , mMode(mode)
+ {
+ }
+
+ LuaxRef::~LuaxRef()
+ {
+ }
+
+ LuaxRef::operator bool()
+ {
+ return (mRefID != LUA_NOREF);
+ }
+
+ bool LuaxRef::PushRef(LuaxState& state)
+ {
+ assert(mRefID != LUA_NOREF);
+
+ LuaxRuntime& runtime = LuaxRuntime::Get();
+
+ if (mMode == STRONG_REF)
+ {
+ LuaxRefTable& table = runtime[state.GetHandle()].strongRefTable;
+ table.PushRef(state, mRefID);
+ }
+ else if (mMode == WEAK_REF)
+ {
+ LuaxRefTable& table = runtime[state.GetHandle()].weakRefTable;
+ table.PushRef(state, mRefID);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ void LuaxRef::SetRef(LuaxState& state, int idx)
+ {
+ LuaxRuntime& runtime = LuaxRuntime::Get();
+ if (mMode == STRONG_REF)
+ {
+ LuaxRefTable& table = runtime[state.GetHandle()].strongRefTable;
+ mRefID = table.Ref(state, idx);
+ }
+ else if (mMode == WEAK_REF)
+ {
+ LuaxRefTable& table = runtime[state.GetHandle()].weakRefTable;
+ mRefID = table.Ref(state, idx);
+ }
+ }
+
+ LuaxStrongRef::LuaxStrongRef()
+ : LuaxRef(STRONG_REF)
+ {
+ }
+
+ LuaxWeakRef::LuaxWeakRef()
+ : LuaxRef(WEAK_REF)
+ {
+ }
+
+}
diff --git a/source/3rd-party/Luax/luax_ref.h b/source/3rd-party/Luax/luax_ref.h
new file mode 100644
index 0000000..b7aabe5
--- /dev/null
+++ b/source/3rd-party/Luax/luax_ref.h
@@ -0,0 +1,62 @@
+#ifndef __LUAX_REF_H__
+#define __LUAX_REF_H__
+
+#include "luax_config.h"
+#include "luax_state.h"
+
+namespace Luax
+{
+
+ ///
+ /// ãLUA_REGISTRYINDEX
+ ///
+ class LuaxRef
+ {
+ public:
+
+ enum
+ {
+ STRONG_REF,
+ WEAK_REF
+ };
+
+ LuaxRef(int mode = STRONG_REF);
+ virtual ~LuaxRef();
+
+ operator bool();
+
+ void SetRef(LuaxState& state, int idx);
+ bool PushRef(LuaxState& state);
+
+ int GetRefID();
+
+ private:
+
+ int mRefID; // luaL_ref
+ int mMode; // strong or weak
+
+ };
+
+ ///
+ /// ǿãLUA_REGISTRYINDEX["_LUAX_STRONGREF_TABLE"]֤lua objectᱻա
+ ///
+ class LuaxStrongRef: public LuaxRef
+ {
+ public:
+ LuaxStrongRef();
+
+ };
+
+ ///
+ /// ãLUA_REGISTRYINDEX["_LUAX_WEAKREF_TABLE"]Ӱlua objectĻգֻΪһȡlua objectӳ䡣
+ ///
+ class LuaxWeakRef : public LuaxRef
+ {
+ public:
+ LuaxWeakRef();
+
+ };
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_reftable.cpp b/source/3rd-party/Luax/luax_reftable.cpp
new file mode 100644
index 0000000..602c9eb
--- /dev/null
+++ b/source/3rd-party/Luax/luax_reftable.cpp
@@ -0,0 +1,120 @@
+#include "luax_reftable.h"
+#include "luax_state.h"
+
+namespace Luax
+{
+
+ LuaxRefTable::LuaxRefTable()
+ : mState(nullptr)
+ {
+ }
+
+ LuaxRefTable::~LuaxRefTable()
+ {
+ }
+
+ void LuaxRefTable::Init(LuaxState& state, cc8* name, cc8* mode)
+ {
+ assert(!mState);
+ assert(name);
+
+ mName = name;
+ mMode = 0;
+ for (int i = 0; mode && mode[i]; ++i)
+ {
+ if (mode[i] == 'k') mMode |= WEAK_KEY;
+ else if (mode[i] == 'v') mMode |= WEAK_VALUE;
+ }
+ mState = state.GetHandle();
+
+ state.GetField(LUA_REGISTRYINDEX, name); // register[mName]
+ if (state.IsNil(-1))
+ {
+ state.Pop();
+
+ lua_newtable(state); // ref table
+ int ridx = state.AbsIndex(-1);
+ lua_newtable(state); // metatable of ref table
+ int idx = state.AbsIndex(-1);
+
+ // __mode
+ if (mode)
+ {
+ state.Push(mode);
+ state.SetField(idx, "__mode");
+ }
+
+ state.Settop(idx);
+ lua_setmetatable(state, ridx);
+
+ state.Settop(ridx);
+ state.SetField(LUA_REGISTRYINDEX, name);
+ }
+ else
+ {
+ state.Pop();
+ }
+ }
+
+ bool LuaxRefTable::IsKeyWeak()
+ {
+ assert(mState);
+
+ return mMode & WEAK_KEY;
+ }
+
+ bool LuaxRefTable::IsValueWeak()
+ {
+ assert(mState);
+
+ return mMode & WEAK_VALUE;
+ }
+
+ int LuaxRefTable::Ref(LuaxState& state, int idx)
+ {
+ assert(mState && mState == state.GetHandle());
+
+ idx = state.AbsIndex(idx);
+ state.GetField(LUA_REGISTRYINDEX, mName); // ref table
+ lua_pushvalue(state, idx); // stuff
+ int refID = luaL_ref(state, -2);
+ assert(refID != LUA_NOREF);
+ state.Pop();
+ return refID;
+ }
+
+ void LuaxRefTable::Unref(LuaxState& state, int refID)
+ {
+ assert(mState && mState == state.GetHandle());
+
+ state.GetField(LUA_REGISTRYINDEX, mName); // ref table
+ luaL_unref(state, -1, refID);
+ state.Pop();
+ return;
+ }
+
+ void LuaxRefTable::PushRefTable(LuaxState& state)
+ {
+ assert(mState && mState == state.GetHandle());
+
+ lua_getfield(state, LUA_REGISTRYINDEX, mName);
+ }
+
+ void LuaxRefTable::PushRef(LuaxState& state, int refID)
+ {
+ assert(mState && mState == state.GetHandle());
+
+ lua_getfield(state, LUA_REGISTRYINDEX, mName);
+ lua_rawgeti(state, -1, refID);
+ lua_replace(state, -2);
+ }
+
+ void LuaxRefTable::Clear(LuaxState& state)
+ {
+ assert(mState && mState == state.GetHandle());
+
+ lua_newtable(state);
+ state.SetField(LUA_REGISTRYINDEX, mName);
+ }
+
+} \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_reftable.h b/source/3rd-party/Luax/luax_reftable.h
new file mode 100644
index 0000000..58e4b9c
--- /dev/null
+++ b/source/3rd-party/Luax/luax_reftable.h
@@ -0,0 +1,67 @@
+#ifndef __LUAX_REFTABLE_H__
+#define __LUAX_REFTABLE_H__
+
+#include "luax_config.h"
+
+namespace Luax
+{
+
+ class LuaxState;
+
+ ///
+ /// ref table strong ref tableweak ref tabletableĴ
+ ///
+ class LuaxRefTable
+ {
+ public:
+
+ enum
+ {
+ WEAK_KEY = 1,
+ WEAK_VALUE = 1 << 1
+ };
+
+ LuaxRefTable();
+ ~LuaxRefTable();
+
+ inline operator bool() { return mState; };
+
+ void Init(LuaxState& state, cc8* name, cc8* mode = nullptr);
+
+ bool IsKeyWeak();
+ bool IsValueWeak();
+
+ ///
+ /// stack[idx]ʵڴref tableһãrefID
+ ///
+ int Ref(LuaxState& state, int idx);
+ void Unref(LuaxState& state, int refID);
+
+ ///
+ /// ref table ջ
+ ///
+ void PushRefTable(LuaxState& state);
+
+ ///
+ /// reftable[refID] ջ
+ ///
+ void PushRef(LuaxState& state, int refID);
+
+ ///
+ /// ref tableLUA_REGISTRYINDEX[mName]
+ ///
+ void Clear(LuaxState& state);
+
+ private:
+
+ friend class LuaxState;
+
+ lua_State* mState; // һЩȷϹ
+ cc8* mName; // ref table
+ int mMode; // ref table
+
+ };
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_runtime.cpp b/source/3rd-party/Luax/luax_runtime.cpp
new file mode 100644
index 0000000..b45d36a
--- /dev/null
+++ b/source/3rd-party/Luax/luax_runtime.cpp
@@ -0,0 +1,89 @@
+#ifndef __LUAX_RUNTIME_H_
+#define __LUAX_RUNTIME_H_
+
+#include "luax_runtime.h"
+
+using namespace std;
+
+namespace Luax
+{
+
+ LuaxRuntime* LuaxRuntime::mRuntime = nullptr;
+
+ LuaxRuntime::LuaxRuntime() {};
+ LuaxRuntime::~LuaxRuntime() {};
+
+ LuaxRuntime& LuaxRuntime::Get()
+ {
+ if (mRuntime == nullptr)
+ mRuntime = new LuaxRuntime();
+
+ return *mRuntime;
+ }
+
+ lua_State* LuaxRuntime::Open()
+ {
+ lua_State* L = lua_open();
+ assert(L);
+
+ // 1)
+ mContexts.insert(pair<lua_State*, LuaxContext>(L, LuaxContext(L)));
+ // 2) ʼcontext
+ (*this)[L].Setup();
+
+ return L;
+ }
+
+ void LuaxRuntime::Close(lua_State* L)
+ {
+ map<lua_State*, LuaxContext>::iterator it = mContexts.find(L);
+ if (it != mContexts.end())
+ {
+ lua_close(it->second.state);
+ mContexts.erase(it);
+ }
+ }
+
+ bool LuaxRuntime::HasLuaxState(lua_State* L)
+ {
+ map<lua_State*, LuaxContext>::iterator it = mContexts.find(L);
+ return it != mContexts.end();
+ }
+
+ LuaxState& LuaxRuntime::GetLuaxState(lua_State* L)
+ {
+ map<lua_State*, LuaxContext>::iterator it = mContexts.find(L);
+ if (it != mContexts.end())
+ {
+ return it->second.state;
+ }
+ }
+
+ LuaxRefTable& LuaxRuntime::GetStrongRefTable(lua_State* L)
+ {
+ map<lua_State*, LuaxContext>::iterator it = mContexts.find(L);
+ if (it != mContexts.end())
+ {
+ return it->second.strongRefTable;
+ }
+ }
+
+ LuaxRefTable& LuaxRuntime::GetWeaksRefTable(lua_State* L)
+ {
+ map<lua_State*, LuaxContext>::iterator it = mContexts.find(L);
+ if (it != mContexts.end())
+ {
+ return it->second.weakRefTable;
+ }
+ }
+
+ LuaxContext& LuaxRuntime::operator[](lua_State* L)
+ {
+ map<lua_State*, LuaxContext>::iterator it = mContexts.find(L);
+ assert(it != mContexts.end());
+ return it->second;
+ }
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_runtime.h b/source/3rd-party/Luax/luax_runtime.h
new file mode 100644
index 0000000..1234627
--- /dev/null
+++ b/source/3rd-party/Luax/luax_runtime.h
@@ -0,0 +1,59 @@
+#ifndef __LUAX_RUNTIME_H__
+#define __LUAX_RUNTIME_H__
+
+#include <map>
+
+#include "luax_ref.h"
+#include "luax_config.h"
+#include "luax_state.h"
+#include "luax_context.h"
+
+namespace Luax
+{
+
+ ///
+ /// ͳһеlua states
+ ///
+ class LuaxRuntime
+ {
+ public:
+
+ static LuaxRuntime& Get();
+
+ ///
+ /// һµlua_Stateصlua_State*һ8\4ֽڵkey
+ ///
+ lua_State* Open();
+
+ ///
+ /// رlua_Stateruntimeɾ
+ ///
+ void Close(lua_State* L);
+
+ bool HasLuaxState(lua_State* L);
+ LuaxState& GetLuaxState(lua_State* L);
+ LuaxRefTable& GetStrongRefTable(lua_State* L);
+ LuaxRefTable& GetWeaksRefTable(lua_State* L);
+
+ LuaxContext& operator[](lua_State* L);
+
+ private:
+
+ LuaxRuntime();
+ ~LuaxRuntime();
+
+ static LuaxRuntime* mRuntime;
+
+ ///
+ /// lua_State handlecontextӳ
+ ///
+ std::map<lua_State*, LuaxContext> mContexts;
+
+ };
+
+#define LUAX_RUNTIME() \
+ LuaxRuntime& runtime = LuaxRuntime::Get()
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_state.cpp b/source/3rd-party/Luax/luax_state.cpp
new file mode 100644
index 0000000..881aaea
--- /dev/null
+++ b/source/3rd-party/Luax/luax_state.cpp
@@ -0,0 +1,737 @@
+//#include "luax_class.h"
+#include "luax_enum.h"
+#include "luax_state.h"
+#include "luax_runtime.h"
+#include "luax_class.hpp"
+
+namespace Luax
+{
+
+ LuaxState::LuaxState(lua_State* state)
+ : mState(state)
+ {
+ assert(state);
+ }
+
+ LuaxState::LuaxState(const LuaxState& state)
+ : mState(state.mState)
+ {
+ assert(state.mState);
+ }
+
+ LuaxState::~LuaxState()
+ {
+ }
+
+ void LuaxState::OpenLibs()
+ {
+ luaL_openlibs(mState);
+ }
+
+ void LuaxState::PushGlobalNamespace()
+ {
+ int top = GetTop();
+
+ lua_newtable(mState); // pseudo namespace table
+ int pnt = GetTop();
+
+ lua_newtable(mState); // metatable
+ int mt = GetTop();
+
+ // __index = _G
+ // __newindex = _G
+ lua_pushvalue(mState, LUA_GLOBALSINDEX);
+ lua_pushvalue(mState, LUA_GLOBALSINDEX);
+ lua_setfield(mState, mt, "__index");
+ lua_setfield(mState, mt, "__newindex");
+
+ lua_setmetatable(mState, pnt);
+
+ // stack:
+ // -1 pseudo global namespace
+ }
+
+ void LuaxState::PushNamespace(cc8* name)
+ {
+ assert(IsNamespace(-1));
+
+ int top = GetTop();
+
+ lua_getfield(mState, -1, name);
+ if (lua_isnil(mState, -1))
+ {
+ lua_pop(mState, 1);
+
+ lua_newtable(mState);
+ lua_pushvalue(mState, -1);
+ lua_setfield(mState, top, name);
+ }
+
+ // stack:
+ // -1 namespace
+ }
+
+ void LuaxState::PopNamespace()
+ {
+ assert(lua_istable(mState, -1));
+ lua_pop(mState, 1);
+ }
+
+ bool LuaxState::IsNamespace(int idx)
+ {
+ return lua_istable(mState, idx);
+ }
+
+ void LuaxState::DoString(const std::string& code)
+ {
+ luaL_dostring(mState, code.c_str());
+ }
+
+ int LuaxState::AbsIndex(int idx)
+ {
+/*
+#define abs_index(mState, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
+ lua_gettop(mState) + (i) + 1)
+*/
+ if (idx < 0) {
+ //return lua_gettop(mState) + idx + 1;
+ return ((idx) > 0 || (idx) <= LUA_REGISTRYINDEX ? (idx) : \
+ lua_gettop(mState) + (idx)+1);
+ }
+ return idx;
+ }
+
+ void LuaxState::Call(int nArgs, int nResults)
+ {
+ lua_pcall(mState, nArgs, nResults, 0);
+ }
+
+ void LuaxState::PushNil()
+ {
+ lua_pushnil(mState);
+ }
+
+ void LuaxState::Push(bool value)
+ {
+ lua_pushboolean(mState, value ? 1 : 0);
+ }
+
+ void LuaxState::Push(cc8* value)
+ {
+ lua_pushstring(mState, value);
+ }
+
+ void LuaxState::Push(double value)
+ {
+ lua_pushnumber(mState, value);
+ }
+
+ void LuaxState::Push(float value)
+ {
+ lua_pushnumber(mState, value);
+ }
+
+ void LuaxState::Push(int value)
+ {
+ lua_pushnumber(mState, value);
+ }
+
+ void LuaxState::Push(u16 value)
+ {
+ lua_pushnumber(mState, value);
+ }
+
+ void LuaxState::Push(u32 value)
+ {
+ lua_pushnumber(mState, value);
+ }
+
+ void LuaxState::Push(u64 value)
+ {
+ lua_pushnumber(mState, (double)value);
+ }
+
+ void LuaxState::Push(uintptr value)
+ {
+ lua_pushlightuserdata(mState, (void*)value);
+ }
+
+ void LuaxState::Push(lua_CFunction value)
+ {
+ lua_pushcfunction(mState, value);
+ }
+
+ void LuaxState::Push(void* data, size_t size)
+ {
+ lua_pushlstring(mState, (cc8*)data, size);
+ }
+
+ void LuaxState::Push(const void* value)
+ {
+ lua_pushlightuserdata(mState, (void*)value);
+ }
+
+ void LuaxState::PushValues(int idx, int n)
+ {
+ idx = AbsIndex(idx);
+ for (int i = idx; i < idx + n; ++i)
+ lua_pushvalue(mState, i);
+ }
+
+ void LuaxState::Pop(int n /* = 1 */)
+ {
+ lua_pop(mState, n);
+ }
+
+ bool LuaxState::IsNil(int idx)
+ {
+ return lua_isnil(mState, idx);
+ }
+
+ bool LuaxState::IsNilOrNone(int idx)
+ {
+ int t = lua_type(mState, idx);
+ return ((t == LUA_TNONE) || (t == LUA_TNIL));
+ }
+
+ bool LuaxState::IsTableOrUserdata(int idx)
+ {
+ int check = lua_type(mState, idx);
+ return ((check == LUA_TTABLE) || (check == LUA_TUSERDATA));
+ }
+
+ bool LuaxState::IsTrueOrNotNil(int idx)
+ {
+ if (lua_isboolean(mState, idx)) {
+ return lua_toboolean(mState, idx) ? true : false;
+ }
+ return !lua_isnil(mState, idx);
+ }
+
+ bool LuaxState::IsType(int idx, int type)
+ {
+ return (lua_type(mState, idx) == type);
+ }
+
+ bool LuaxState::IsType(int idx, cc8* name, int type)
+ {
+ return this->HasField(idx, name, type);
+ }
+
+ bool LuaxState::IsValid()
+ {
+ return (mState != 0);
+ }
+
+ void LuaxState::Settop(int idx)
+ {
+ lua_settop(mState, idx);
+ }
+
+ int LuaxState::GetTop()
+ {
+ return lua_gettop(mState);
+ }
+
+ bool LuaxState::HasField(int idx, cc8* name) {
+
+ lua_getfield(mState, idx, name);
+ bool hasField = (lua_isnil(mState, -1) == false);
+ lua_pop(mState, 1);
+
+ return hasField;
+ }
+
+ bool LuaxState::HasField(int idx, int key) {
+
+ this->GetField(idx, key);
+ bool hasField = (lua_isnil(mState, -1) == false);
+ lua_pop(mState, 1);
+
+ return hasField;
+ }
+
+ bool LuaxState::HasField(int idx, cc8* name, int type) {
+
+ lua_getfield(mState, idx, name);
+ bool hasField = (lua_type(mState, -1) == type);
+ lua_pop(mState, 1);
+
+ return hasField;
+ }
+
+ bool LuaxState::HasField(int idx, int key, int type) {
+
+ this->GetField(idx, key);
+ bool hasField = (lua_type(mState, -1) == type);
+ lua_pop(mState, 1);
+
+ return hasField;
+ }
+
+ bool LuaxState::HasKeys(int idx) {
+
+ idx = this->AbsIndex(idx);
+
+ lua_pushnil(mState); /* first key */
+ if (lua_next(mState, idx) != 0) {
+ lua_pop(mState, 2);
+ return true;
+ }
+ return false;
+ }
+
+ void LuaxState::GetField(int idx, cc8* name)
+ {
+ lua_getfield(mState, idx, name);
+ }
+
+ void LuaxState::GetField(int idx, int key)
+ {
+ idx = this->AbsIndex(idx);
+
+ lua_pushinteger(mState, key);
+ lua_gettable(mState, idx);
+ }
+
+ std::string LuaxState::GetField(int idx, cc8* key, cc8* value)
+ {
+ std::string str;
+ if (this->GetFieldWithType(idx, key, LUA_TSTRING)) {
+ str = lua_tostring(mState, -1);
+ lua_pop(mState, 1);
+ }
+ else {
+ str = value;
+ }
+ return str;
+ }
+
+ std::string LuaxState::GetField(int idx, int key, cc8* value)
+ {
+ std::string str;
+ if (this->GetFieldWithType(idx, key, LUA_TSTRING)) {
+ str = lua_tostring(mState, -1);
+ lua_pop(mState, 1);
+ }
+ else {
+ str = value;
+ }
+ return str;
+ }
+
+ std::string LuaxState::GetField(int idx, cc8* key, const std::string& value)
+ {
+ std::string str;
+ if (this->GetFieldWithType(idx, key, LUA_TSTRING)) {
+ str = lua_tostring(mState, -1);
+ lua_pop(mState, 1);
+ }
+ else {
+ str = value;
+ }
+ return str;
+ }
+
+ std::string LuaxState::GetField(int idx, int key, const std::string& value)
+ {
+ std::string str;
+ if (this->GetFieldWithType(idx, key, LUA_TSTRING)) {
+ str = lua_tostring(mState, -1);
+ lua_pop(mState, 1);
+ }
+ else {
+ str = value;
+ }
+ return str;
+ }
+
+ bool LuaxState::GetFieldWithType(int idx, cc8* name, int type)
+ {
+ lua_getfield(mState, idx, name);
+ if (lua_type(mState, -1) != type) {
+ lua_pop(mState, 1);
+ return false;
+ }
+ return true;
+ }
+
+ bool LuaxState::GetFieldWithType(int idx, int key, int type)
+ {
+ this->GetField(idx, key);
+ if (lua_type(mState, -1) != type) {
+ lua_pop(mState, 1);
+ return false;
+ }
+ return true;
+ }
+
+ void LuaxState::SetField(int idx, cc8* key)
+ {
+ if (IsTableOrUserdata(idx))
+ {
+ idx = AbsIndex(idx);
+ lua_setfield(mState, idx, key);
+ }
+ }
+
+ cc8* LuaxState::GetLuaTypeName(int type)
+ {
+ switch (type) {
+ case LUA_TNONE: return "none";
+ case LUA_TNIL: return "nil";
+ case LUA_TBOOLEAN: return "boolean";
+ case LUA_TLIGHTUSERDATA: return "lightuserdata";
+ case LUA_TNUMBER: return "number";
+ case LUA_TSTRING: return "string";
+ case LUA_TTABLE: return "table";
+ case LUA_TFUNCTION: return "function";
+ case LUA_TUSERDATA: return "userdata";
+ case LUA_TTHREAD: return "thread";
+ }
+ return "unknown";
+ }
+
+
+ bool LuaxState::GetSubfieldWithType(int idx, cc8* format, int type, ...)
+ {
+ va_list args;
+ va_start(args, type);
+
+ idx = this->AbsIndex(idx);
+ lua_pushvalue(this->mState, idx);
+
+ for (cc8* c = format; *c; ++c) {
+ switch (*c) {
+ // number
+ case 'N':
+ lua_pushnumber(this->mState, va_arg(args, int));
+ lua_gettable(this->mState, -1);
+ break;
+
+ // string
+ case 'S':
+ lua_getfield(this->mState, -1, va_arg(args, char*));
+ break;
+
+ default:
+ lua_pushnil(this->mState);
+ }
+
+ if (lua_isnil(this->mState, -1)) break;
+ lua_replace(this->mState, -2);
+ }
+ va_end(args);
+ if (lua_type(this->mState, -1) != type) {
+ lua_pop(this->mState, 1);
+ return false;
+ }
+ return true;
+ }
+
+ bool LuaxState::CheckParams(int idx, cc8* format)
+ {
+ idx = AbsIndex(idx);
+
+ for (int i = 0; format[i]; ++i) {
+
+ int pos = idx + i;
+ int type = LUA_TNIL;
+ int expected = LUA_TNONE;
+
+ if (pos <= GetTop()) {
+ type = lua_type(mState, pos);
+ }
+
+ switch (format[i]) {
+
+ // boolean
+ case 'B':
+ if (type != LUA_TBOOLEAN) expected = LUA_TBOOLEAN;
+ break;
+
+ // coroutine
+ case 'C':
+ if (type != LUA_TTHREAD) expected = LUA_TTHREAD;
+ break;
+
+ // function
+ case 'F':
+ if (type != LUA_TFUNCTION) expected = LUA_TFUNCTION;
+ break;
+
+ // light userdata
+ case 'L':
+ if (type != LUA_TLIGHTUSERDATA) expected = LUA_TLIGHTUSERDATA;
+ break;
+
+ // number
+ case 'N':
+ if (type != LUA_TNUMBER) expected = LUA_TNUMBER;
+ break;
+
+ // string
+ case 'S':
+ if (type != LUA_TSTRING) expected = LUA_TSTRING;
+ break;
+
+ // table
+ case 'T':
+ if (type != LUA_TTABLE) expected = LUA_TTABLE;
+ break;
+
+ // userdata
+ case 'U':
+ if (type != LUA_TUSERDATA) expected = LUA_TUSERDATA;
+ break;
+
+ // any type
+ case '*':
+ case '.':
+ break;
+ }
+
+ if (expected != LUA_TNONE) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ template <>
+ bool LuaxState::GetValue < bool >(int idx, const bool value) {
+
+ if (this->IsType(idx, LUA_TBOOLEAN)) {
+ return (lua_toboolean(this->mState, idx) != 0);
+ }
+ return value;
+ }
+
+
+ template <>
+ cc8* LuaxState::GetValue < cc8* >(int idx, const cc8* value) {
+
+ if (this->IsType(idx, LUA_TSTRING)) {
+ return lua_tostring(this->mState, idx);
+ }
+ return value;
+ }
+
+ template <>
+ std::string LuaxState::GetValue<std::string>(int idx, const std::string value)
+ {
+ std::string str;
+ if (lua_type(this->mState, idx) == LUA_TSTRING) {
+ str = lua_tostring(this->mState, idx);
+ }
+ else {
+ str = value;
+ }
+ return str;
+ }
+
+ template <>
+ double LuaxState::GetValue < double >(int idx, const double value)
+ {
+ if (this->IsType(idx, LUA_TNUMBER)) {
+ return lua_tonumber(this->mState, idx);
+ }
+ return value;
+ }
+
+ template <>
+ float LuaxState::GetValue < float >(int idx, const float value)
+ {
+ if (this->IsType(idx, LUA_TNUMBER)) {
+ return (float)lua_tonumber(this->mState, idx);
+ }
+ return value;
+ }
+
+ template <>
+ s8 LuaxState::GetValue < s8 >(int idx, const s8 value)
+ {
+ if (this->IsType(idx, LUA_TNUMBER)) {
+ return (s8)lua_tonumber(this->mState, idx);
+ }
+ return value;
+ }
+
+
+ template <>
+ s16 LuaxState::GetValue < s16 >(int idx, const s16 value)
+ {
+ if (this->IsType(idx, LUA_TNUMBER)) {
+ return (s16)lua_tonumber(this->mState, idx);
+ }
+ return value;
+ }
+
+
+ template <>
+ s32 LuaxState::GetValue < s32 >(int idx, const s32 value)
+ {
+ if (this->IsType(idx, LUA_TNUMBER)) {
+ return (s32)lua_tonumber(this->mState, idx);
+ }
+ return value;
+ }
+
+ template <>
+ s64 LuaxState::GetValue < s64 >(int idx, const s64 value)
+ {
+ if (this->IsType(idx, LUA_TNUMBER)) {
+ return (s64)lua_tonumber(this->mState, idx);
+ }
+ return value;
+ }
+
+ template <>
+ u8 LuaxState::GetValue < u8 >(int idx, const u8 value)
+ {
+ if (this->IsType(idx, LUA_TNUMBER)) {
+ return (u8)lua_tonumber(this->mState, idx);
+ }
+ return value;
+ }
+
+ template<>
+ int LuaxState::GetValue<int>(int idx, int value)
+ {
+ if (this->IsType(idx, LUA_TNUMBER)) {
+ return (int)lua_tointeger(this->mState, idx);
+ }
+ return value;
+ }
+
+ template <>
+ u16 LuaxState::GetValue < u16 >(int idx, const u16 value)
+ {
+ if (this->IsType(idx, LUA_TNUMBER)) {
+ return (u16)lua_tonumber(this->mState, idx);
+ }
+ return value;
+ }
+
+ template <>
+ u32 LuaxState::GetValue < u32 >(int idx, const u32 value)
+ {
+ if (this->IsType(idx, LUA_TNUMBER)) {
+ return (u32)lua_tonumber(this->mState, idx);
+ }
+ return value;
+ }
+
+ template <>
+ u64 LuaxState::GetValue < u64 >(int idx, const u64 value)
+ {
+ if (this->IsType(idx, LUA_TNUMBER)) {
+ return (u64)lua_tonumber(this->mState, idx);
+ }
+ return value;
+ }
+
+ template <>
+ const void* LuaxState::GetValue < const void* >(int idx, const void* value)
+ {
+ if (this->IsType(idx, LUA_TLIGHTUSERDATA)) {
+ return (void*)lua_touserdata(this->mState, idx);
+ }
+ return value;
+ }
+
+ void LuaxState::PushPtrUserData(void* ptr) {
+
+ void** handle = (void**)lua_newuserdata(this->mState, sizeof(void*));
+ assert(handle);
+ (*handle) = ptr;
+ }
+
+ void LuaxState::RegisterEnum(cc8* name, LuaxEnum* en)
+ {
+ assert(name);
+ assert(en);
+
+ // short name
+ lua_State* L = mState;
+
+ int top = GetTop();
+
+ lua_newtable(L); // enum table
+
+ int et = GetTop();
+
+ lua_newtable(L); // matatable
+
+ // öٶmetatable£޸ʱ__newindex
+ for (; en->name; ++en)
+ {
+ lua_pushinteger(L, en->value);
+ lua_setfield(L, -2, en->name);
+ }
+
+ // __index
+ //lua_pushvalue(L, -1); // metatable
+ //lua_pushcclosure(L, l_rmt__index, 1);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "__index");
+
+ // __newinedx
+ lua_pushstring(L, name); // enum name
+ lua_pushcclosure(L, l_rmt__newindex, 1);
+ lua_setfield(L, -2, "__newindex");
+
+ lua_setmetatable(L, et);
+
+ lua_setfield(L, top, name);
+ }
+
+
+ void LuaxState::RegisterMethods(const luaL_Reg *l)
+ {
+ assert(lua_istable(mState, -1));
+ // luaL_registerڶΪգ-1λעluaL_RegЩ
+ luaL_register(mState, 0, l);
+ }
+
+ void LuaxState::RegisterMethod(cc8* fname, lua_CFunction func)
+ {
+ assert(lua_istable(mState, -1));
+ lua_pushcfunction(mState, func);
+ lua_setfield(mState, -1, fname);
+ }
+
+ void LuaxState::RegisterPreloader(cc8* libname, lua_CFunction preloader)
+ {
+ lua_getglobal(mState, "package");
+ lua_getfield(mState, -1, "preload");
+ lua_pushcfunction(mState, preloader);
+ lua_setfield(mState, -2, libname);
+ lua_pop(mState, 2);
+ }
+
+ void LuaxState::RegisterLib(cc8* libname, const luaL_Reg* l)
+ {
+ luaL_register(mState, libname, l);
+ }
+
+#if LUAX_ENABLE_PLAIN_CLASS
+ void LuaxState::RegisterPlainClassRegistry(cc8* name)
+ {
+ assert(lua_istable(mState, -1));
+ lua_pushcfunction(mState, LuaxPlainClass::registry);
+ lua_setfield(mState, -2, name);
+ }
+#endif
+
+#if LUAX_ENABLE_PLAIN_ENABLE
+ void LuaxState::RegisterPlainEnumRegistry(cc8* name)
+ {
+ assert(lua_istable(mState, -1));
+ lua_pushcfunction(mState, LuaxPlainEnum::registry);
+ lua_setfield(mState, -2, name);
+ }
+#endif
+
+} \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_state.h b/source/3rd-party/Luax/luax_state.h
new file mode 100644
index 0000000..fbe424b
--- /dev/null
+++ b/source/3rd-party/Luax/luax_state.h
@@ -0,0 +1,238 @@
+#ifndef __LUAX_STATE_H__
+#define __LUAX_STATE_H__
+
+#include <string>
+
+#include "luax_config.h"
+#include "luax_reftable.h"
+
+namespace Luax
+{
+
+ class LuaxContext;
+ class LuaxEnum;
+ class LuaxStrongRef;
+ class LuaxWeakRef;
+
+ ///
+ /// lua_StateĴ˱һlua_Stateòݡһʵmetatable£
+ /// class table
+ /// member table
+ /// ref table
+ /// userdata
+ /// userdataͨgetmetatableȡϼmetatable֮⻹һclass tableעڶӦƿռ
+ ///
+ LUAX_API class LuaxState
+ {
+ public:
+
+ inline lua_State* operator ->() { return mState; };
+ inline lua_State& operator *() { return *mState; };
+ inline operator lua_State*() { return mState; }
+ inline operator bool() { return mState != nullptr; };
+
+ ///
+ /// ȡ󶨵lua_State
+ ///
+ inline lua_State* GetHandle() { return mState; };
+
+ //------------------------------------------------------------------------------------------------------------
+
+ void OpenLibs();
+
+ //------------------------------------------------------------------------------------------------------------
+ // ƿռƿռһ_Gı
+
+ void PushGlobalNamespace();
+ void PushNamespace(cc8* name);
+ void PopNamespace();
+ bool IsNamespace(int idx);
+
+ //------------------------------------------------------------------------------------------------------------
+
+ void SetTop(int top);
+ int GetTop();
+ bool CheckParams(int idx, cc8* format);
+ int AbsIndex(int idx);
+ void Call(int nArgs, int nResults);
+
+ //------------------------------------------------------------------------------------------------------------
+
+ void GetField(int idx, cc8* name);
+ void GetField(int idx, int key);
+ std::string GetField(int idx, cc8* key, cc8* value);
+ std::string GetField(int idx, int key, cc8* value);
+ std::string GetField(int idx, cc8* key, const std::string& value);
+ std::string GetField(int idx, int key, const std::string& value);
+ bool GetFieldWithType(int idx, cc8* name, int type);
+ bool GetFieldWithType(int idx, int key, int type);
+ bool GetSubfieldWithType(int idx, cc8* format, int type, ...);
+ static cc8* GetLuaTypeName(int type);
+
+ void SetField(int idx, cc8* key);
+
+ bool IsNil(int idx);
+ bool IsNilOrNone(int idx);
+ bool IsTableOrUserdata(int idx);
+ bool IsTrueOrNotNil(int idx);
+ bool IsType(int idx, int type);
+ bool IsType(int idx, cc8* name, int type);
+ bool IsValid();
+
+ bool HasField(int idx, cc8* name);
+ bool HasField(int idx, int key);
+ bool HasField(int idx, cc8* name, int type);
+ bool HasField(int idx, int name, int type);
+ bool HasKeys(int idx);
+
+ void PushNil();
+ void Push(bool value);
+ void Push(cc8* value);
+ void Push(double value);
+ void Push(float value);
+ void Push(int value);
+ void Push(u16 value);
+ void Push(u32 value);
+ void Push(u64 value);
+ void Push(uintptr value);
+ void Push(lua_CFunction value);
+ void Push(void* data, size_t size);
+ void Push(const void* value);
+
+ ///
+ /// idxʼnpushջidxᱻȡn
+ ///
+ void PushValues(int idx, int n);
+
+ ///
+ /// void** ʽuserdataֵΪptr
+ ///
+ void PushPtrUserData(void* ptr);
+
+ void Pop(int n = 1);
+
+ void Settop(int idx);
+
+ template<typename T> T* GetLuaUserdata(int idx = 1);
+
+ //------------------------------------------------------------------------------------------------------------
+
+ template<typename T> T GetValue(int idx, T default_value);
+ template<typename T> T GetField(int idx, int key, T value);
+ template<typename T> T GetField(int idx, cc8* key, T value);
+ template<typename T> void SetField(int idx, cc8* key, T value);
+ template<typename T> void SetFieldByIndex(int idx, int key, T value);
+
+ //------------------------------------------------------------------------------------------------------------
+
+ void DoString(const std::string& code);
+ void DoFile(const std::string& file);
+
+ //------------------------------------------------------------------------------------------------------------
+ // ע᷽
+
+ ///
+ /// עṤͨ࣬New
+ ///
+ template<typename T> void RegisterFactory();
+
+ ///
+ /// עᵥûNew
+ ///
+ template<typename T> void RegisterSingleton();
+
+ ///
+ /// עö
+ ///
+ void RegisterEnum(cc8* name, LuaxEnum* enums);
+
+ ///
+ /// עCעһ{0 0}
+ ///
+ void RegisterMethods(const luaL_Reg *l);
+
+ ///
+ /// עᵥC
+ ///
+ void RegisterMethod(cc8* fname, lua_CFunction func);
+
+ ///
+ /// preloaderӵpackage.preloadrequire"libname"ʱlualoader_preloadlibnameҵpreloaderֱӼء
+ /// ʵҪrequireʱżأҼعһκpackage.loaded¼´βټءͨrequire
+ /// preloader
+ ///
+ void RegisterPreloader(cc8* libname, lua_CFunction preloader);
+
+ ///
+ /// luaL_Reglib table_Gpackage.loadedlibnameָlib table
+ ///
+ void RegisterLib(cc8* libname, const luaL_Reg* l);
+
+#if LUAX_ENABLE_PLAIN_CLASS
+ ///
+ /// עᴿluaעắluaࡣ
+ ///
+ void RegisterPlainClassRegistry(cc8* name);
+#endif
+
+#if LUAX_ENABLE_PLAIN_ENABLE
+ ///
+ /// עᴿluaö٣Էֹ޸öֵ
+ ///
+ void RegisterPlainEnumRegistry(cc8* name);
+#endif
+
+ //------------------------------------------------------------------------------------------------------------
+
+ private:
+
+ friend class LuaxContext;
+
+ LuaxState(lua_State* state);
+ LuaxState(const LuaxState& state);
+ ~LuaxState();
+
+ ///
+ /// ζLuaxStateĵַز
+ ///
+ void* operator &();
+ void* operator new(size_t size);
+
+ lua_State* const mState;
+
+ };
+
+ //--------------------------------------------------------------------------------------------------------------
+ // GetValue()ģػ
+
+ template <> bool LuaxState::GetValue < bool >(int idx, const bool value);
+ template <> cc8* LuaxState::GetValue < cc8* >(int idx, const cc8* value);
+ template <> double LuaxState::GetValue < double >(int idx, const double value);
+ template <> float LuaxState::GetValue < float >(int idx, const float value);
+ template <> s8 LuaxState::GetValue < s8 >(int idx, const s8 value);
+ template <> s16 LuaxState::GetValue < s16 >(int idx, const s16 value);
+ template <> s32 LuaxState::GetValue < s32 >(int idx, const s32 value);
+ template <> s64 LuaxState::GetValue < s64 >(int idx, const s64 value);
+ template <> u8 LuaxState::GetValue < u8 >(int idx, const u8 value);
+ template <> u16 LuaxState::GetValue < u16 >(int idx, const u16 value);
+ template <> u32 LuaxState::GetValue < u32 >(int idx, const u32 value);
+ template <> u64 LuaxState::GetValue < u64 >(int idx, const u64 value);
+ template <> std::string LuaxState::GetValue < std::string >(int idx, const std::string value);
+ template <> const void* LuaxState::GetValue < const void* >(int idx, const void* value);
+ template <> int LuaxState::GetValue < int >(int idx, int value);
+
+
+ ///
+ /// ڳԱﴴLuaxStateԲм顣
+ ///
+#define LUAX_SETUP(L, params) \
+ LuaxRuntime& runtime = LuaxRuntime::Get(); \
+ LuaxState& state = runtime[L].state; \
+ if(!state.CheckParams(1, params)) return 0
+
+#define LUAX_STATE(L) \
+ LuaxState& state = LuaxRuntime::Get().GetLuaxState(L)
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/3rd-party/Luax/luax_state.inl b/source/3rd-party/Luax/luax_state.inl
new file mode 100644
index 0000000..06d9350
--- /dev/null
+++ b/source/3rd-party/Luax/luax_state.inl
@@ -0,0 +1,140 @@
+namespace Luax
+{
+
+ ///
+ /// עṤעclass tabletype nameΪƿռϡע׶βԪȵNewõʱŻᡣ
+ ///
+ template<typename T>
+ void LuaxState::RegisterFactory()
+ {
+ lua_State* L = mState;
+ LuaxState& state = *this;
+
+ int top = lua_gettop(L); // namespace table
+ assert(lua_istable(L, top));
+
+ // class table
+ lua_newtable(L);
+ LuaxNativeClass<T>::RegisterLuaxClass(state);
+ LuaxNativeClass<T>::RegisterLuaxFactoryClass(state);
+ T::RegisterLuaxClass(state);
+
+ // TǷûעķ
+#define _assertmethod(I, NAME) \
+ GetField(I, NAME); \
+ assert(IsType(-1, LUA_TFUNCTION)); \
+ Pop();
+
+ _assertmethod(-1, "New");
+ //_assertmethod(-1, "__gc");
+
+#undef _assertmethod
+
+#if LUAX_ENABLE_NATIVE_EXTEND
+ // .Extend()
+ lua_pushvalue(state, -1); // class table
+ lua_pushcclosure(state, LuaxNativeClass<T>::l_ExtendFactory, 1);
+ lua_setfield(state, -2, "Extend");
+#endif
+
+ // class["__index"] = class
+ lua_pushvalue(state, -1); // class table
+ lua_setfield(state, -2, "__index");
+
+ LuaxNativeClass<T>::SetLuaxClassTableRef(state, -1);
+
+ cc8* type = T::GetLuaxFactoryName();
+ SetField(top, type);
+
+ // reset top
+ lua_settop(L, top);
+
+ //
+ T::RegisterLuaxPostprocess(state);
+ }
+
+ ///
+ /// Singleton
+ ///
+ template<typename T>
+ void LuaxState::RegisterSingleton()
+ {
+ lua_State* L = mState;
+ LuaxState& state = *this;
+
+ int top = lua_gettop(L); // namespace table
+ assert(lua_istable(L, top));
+
+ // class table.
+ lua_newtable(L);
+ LuaxNativeClass<T>::RegisterLuaxClass(state);
+ LuaxNativeClass<T>::RegisterLuaxSingletonClass(state);
+ T::RegisterLuaxClass(state);
+
+ LuaxNativeClass<T>::SetLuaxClassTableRef(state, -1);
+
+ lua_pushvalue(state, -1);
+ lua_setfield(state, -2, "__index");
+
+#if LUAX_ENABLE_NATIVE_EXTEND
+ // .Extend()
+ lua_pushvalue(state, -1); // class table
+ lua_pushcclosure(state, LuaxNativeClass<T>::l_ExtendSingleton, 1);
+ lua_setfield(state, -2, "Extend");
+#endif
+
+ cc8* type = T::GetLuaxSingletonName();
+ SetField(top, type);
+
+ // reset top
+ lua_settop(L, top);
+
+ //
+ T::RegisterLuaxPostprocess(state);
+ }
+
+ template<typename T>
+ void LuaxState::SetField(int idx, cc8* key, T value)
+ {
+ if (IsTableOrUserdata(idx))
+ {
+ idx = AbsIndex(idx);
+ this->Push(value);
+ lua_setfield(mState, idx, key);
+ }
+ }
+
+ template<typename T>
+ T LuaxState::GetField(int idx, cc8* key, T value)
+ {
+ GetField(idx, key);
+ T result = GetValue < T >(-1, value);
+ this->Pop();
+
+ return result;
+ }
+
+ template<typename T>
+ T LuaxState::GetField(int idx, int key, T value)
+ {
+ GetField(idx, key);
+ T result = GetValue < T >(-1, value);
+ Pop();
+
+ return result;
+ }
+
+ template<typename T>
+ T* LuaxState::GetLuaUserdata(int idx)
+ {
+ void* p = nullptr;
+
+ if (IsType(idx, LUA_TUSERDATA))
+ {
+ p = *(void**)lua_touserdata(mState, idx);
+ }
+
+ return static_cast<T*>(p);
+ }
+
+} \ No newline at end of file