#include "luacxx.hpp" extern "C" { #include #include } namespace getsuyomi { using fud::FudStatus; LuaContext::LuaContext() { m_state = luaL_newstate(); if (m_state != nullptr) { luaL_openlibs(m_state); } } LuaContext::~LuaContext() { if (m_state != nullptr) { lua_close(m_state); m_state = nullptr; } } LuaContext::LuaContext(LuaContext&& rhs) : m_state{rhs.m_state} { rhs.m_state = nullptr; } LuaContext& LuaContext::operator=(LuaContext&& rhs) { if (m_state != nullptr) { lua_close(m_state); m_state = nullptr; } m_state = rhs.m_state; rhs.m_state = nullptr; return *this; } FudStatus LuaContext::loadFile(const char* filename) { if (!valid()) { return FudStatus::ObjectInvalid; } if (luaL_loadfile(m_state, filename) || lua_pcall(m_state, 0, 0, 0)) { return FudStatus::Failure; } return FudStatus::Success; } LuaResult LuaContext::getGlobalInteger(const char* name) { if (m_state == nullptr) { return LuaResult::error(FudStatus::ObjectInvalid); } int isNumber{}; int64_t result{}; auto luaType = lua_getglobal(m_state, name); // discard luaType since isNumber will check if variable is integral static_cast(luaType); result = lua_tointegerx(m_state, -1, &isNumber); lua_pop(m_state, 1); if (!static_cast(isNumber)) { return LuaResult::error(FudStatus::Failure); } return LuaResult::okay(result); } LuaResult LuaContext::getGlobalString(const char* name) { if (m_state == nullptr) { return LuaResult::error(FudStatus::ObjectInvalid); } size_t length; const char* result{nullptr}; auto luaType = lua_getglobal(m_state, name); static_cast(luaType); result = lua_tolstring(m_state, -1, &length); lua_pop(m_state, 1); if (result == nullptr) { return LuaResult::error(FudStatus::Failure); } return LuaResult::okay(result); } LuaResult> LuaContext::getGlobalStringArray(const char* name) { using RetType = LuaResult>; if (m_state == nullptr) { return RetType::error(FudStatus::ObjectInvalid); } auto luaType = lua_getglobal(m_state, name); if (luaType == LUA_TNONE || luaType == LUA_TNIL) { lua_pop(m_state, 1); return RetType::error(FudStatus::NotFound); } if (luaType != LUA_TTABLE) { lua_pop(m_state, 1); return RetType::error(FudStatus::InvalidInput); } int64_t length; int isNumber{}; lua_len(m_state, -1); length = lua_tointegerx(m_state, -1, &isNumber); lua_pop(m_state, 1); if (!static_cast(isNumber) || length < 0) { lua_pop(m_state, 1); return RetType::error(FudStatus::Failure); } std::vector output{}; output.reserve(static_cast(length)); lua_pushnil(m_state); auto result = FudStatus::Success; for (int64_t index = 1; index <= length; ++index) { const char* luaResult{nullptr}; auto luaNext = lua_next(m_state, -2); if (luaNext == 0) { lua_pop(m_state, 2); result = FudStatus::Failure; break; } luaResult = lua_tolstring(m_state, -1, nullptr); if (luaResult == nullptr) { lua_pop(m_state, 1); result = FudStatus::Failure; break; } output.emplace_back(luaResult); lua_pop(m_state, 1); } lua_pop(m_state, 1); if (result != FudStatus::Success) { return RetType::error(result); } return RetType::okay(output); } } // namespace getsuyomi