diff options
Diffstat (limited to 'Source/external/Luax/luax_state.cpp')
-rw-r--r-- | Source/external/Luax/luax_state.cpp | 857 |
1 files changed, 857 insertions, 0 deletions
diff --git a/Source/external/Luax/luax_state.cpp b/Source/external/Luax/luax_state.cpp new file mode 100644 index 0000000..a2610b4 --- /dev/null +++ b/Source/external/Luax/luax_state.cpp @@ -0,0 +1,857 @@ +#include "luax_enum.h" +#include "luax_state.h" +#include "luax_vm.h" +#include "luax_class.hpp" +#include "luax_internal.h" + +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); + } + + global_State* LuaxState::GetGlobalState() + { + return G(mState); + } + + LuaxVM* LuaxState::GetVM() + { + return LuaxVM::TryGetVM(G(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(s64 value) + { + lua_pushinteger(mState, 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::Push(std::string value) + { + Push(value.c_str()); + } + + 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* default_value) + { + std::string str; + if (this->GetFieldWithType(idx, key, LUA_TSTRING)) { + str = lua_tostring(mState, -1); + lua_pop(mState, 1); + } + else { + str = default_value; + } + return str; + } + + std::string LuaxState::GetField(int idx, int key, cc8* default_value) + { + std::string str; + if (this->GetFieldWithType(idx, key, LUA_TSTRING)) { + str = lua_tostring(mState, -1); + lua_pop(mState, 1); + } + else { + str = default_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 <> + 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, _rmt__index, 1); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + + // __newinedx + lua_pushstring(L, name); // enum name + lua_pushcclosure(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_ENUM + void LuaxState::RegisterPlainEnumRegistry(cc8* name) + { + assert(lua_istable(mState, -1)); + lua_pushcfunction(mState, LuaxPlainEnum::registry); + lua_setfield(mState, -2, name); + } +#endif + + int LuaxState::ErrorType(int idx, cc8* hint) + { + return luaL_typerror(mState, idx, hint); + } + + template <> + bool LuaxState::CheckValue < bool >(int idx) + { + bool b = false; + if (lua_type(mState, idx) == LUA_TBOOLEAN) + { + b = lua_toboolean(mState, idx); + } + else + { + luaL_typerror(mState, idx, lua_typename(mState, LUA_TBOOLEAN)); + } + return b; + } + + template <> + cc8* LuaxState::CheckValue < cc8* >(int idx) + { + return luaL_checkstring(mState, idx); + } + + template <> + double LuaxState::CheckValue < double >(int idx) + { + return luaL_checknumber(mState, idx); + } + + template <> + float LuaxState::CheckValue < float >(int idx) + { + return luaL_checknumber(mState, idx); + } + + template <> + s8 LuaxState::CheckValue < s8 >(int idx) + { + return luaL_checkinteger(mState, idx); + } + + template <> + s16 LuaxState::CheckValue < s16 >(int idx) + { + return luaL_checkinteger(mState, idx); + } + + template <> + s32 LuaxState::CheckValue < s32 >(int idx) + { + return luaL_checkinteger(mState, idx); + } + + template <> + s64 LuaxState::CheckValue < s64 >(int idx) + { + return luaL_checkinteger(mState, idx); + } + + template <> + u8 LuaxState::CheckValue < u8 >(int idx) + { + return luaL_checkinteger(mState, idx); + } + + template <> + u16 LuaxState::CheckValue < u16 >(int idx) + { + return luaL_checkinteger(mState, idx); + } + + template <> + u32 LuaxState::CheckValue < u32 >(int idx) + { + return luaL_checkinteger(mState, idx); + } + + template <> + u64 LuaxState::CheckValue < u64 >(int idx) + { + return luaL_checkinteger(mState, idx); + } + + template <> + std::string LuaxState::CheckValue < std::string >(int idx) + { + return luaL_checkstring(mState, idx); + } + + /// + /// check light userdata + /// + template <> + const void* LuaxState::CheckValue < const void* >(int idx) + { + if (IsType(idx, LUA_TLIGHTUSERDATA)) + { + return GetValue<const void*>(idx, nullptr); + } + else + { + luaL_typerror(mState, idx, "light userdata"); + return nullptr; + } + } + +}
\ No newline at end of file |