summaryrefslogtreecommitdiff
path: root/Source/external/Luax/luax_state.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/external/Luax/luax_state.cpp')
-rw-r--r--Source/external/Luax/luax_state.cpp857
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