mirror of
https://gitlab.com/niansa/SomeBot.git
synced 2025-03-06 20:48:26 +01:00
187 lines
4.7 KiB
C++
187 lines
4.7 KiB
C++
// https://github.com/kunitoki/LuaBridge3
|
|
// Copyright 2021, Lucio Asnaghi
|
|
// Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
|
|
// Copyright 2008, Nigel Atkinson <suprapilot+LuaCode@gmail.com>
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#pragma once
|
|
|
|
#include "Config.h"
|
|
|
|
#include "LuaHelpers.h"
|
|
|
|
#include <cassert>
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <exception>
|
|
|
|
namespace luabridge {
|
|
|
|
//================================================================================================
|
|
class LuaException : public std::exception
|
|
{
|
|
public:
|
|
//=============================================================================================
|
|
/**
|
|
* @brief Construct a LuaException after a lua_pcall().
|
|
*
|
|
* Assumes the error string is on top of the stack, but provides a generic error message otherwise.
|
|
*/
|
|
LuaException(lua_State* L, std::error_code code)
|
|
: m_L(L)
|
|
, m_code(code)
|
|
{
|
|
}
|
|
|
|
~LuaException() noexcept override
|
|
{
|
|
}
|
|
|
|
//=============================================================================================
|
|
/**
|
|
* @brief Return the error message.
|
|
*/
|
|
const char* what() const noexcept override
|
|
{
|
|
return m_what.c_str();
|
|
}
|
|
|
|
//=============================================================================================
|
|
/**
|
|
* @brief Throw an exception or raises a luaerror when exceptions are disabled.
|
|
*/
|
|
static void raise(lua_State* L, std::error_code code)
|
|
{
|
|
assert(areExceptionsEnabled());
|
|
|
|
#if LUABRIDGE_HAS_EXCEPTIONS
|
|
throw LuaException(L, code, FromLua{});
|
|
#else
|
|
unused(L, code);
|
|
|
|
std::abort();
|
|
#endif
|
|
}
|
|
|
|
//=============================================================================================
|
|
/**
|
|
* @brief Check if exceptions are enabled.
|
|
*/
|
|
static bool areExceptionsEnabled() noexcept
|
|
{
|
|
return exceptionsEnabled();
|
|
}
|
|
|
|
/**
|
|
* @brief Initializes error handling.
|
|
*
|
|
* Subsequent Lua errors are translated to C++ exceptions, or logging and abort if exceptions are disabled.
|
|
*/
|
|
static void enableExceptions(lua_State* L) noexcept
|
|
{
|
|
exceptionsEnabled() = true;
|
|
|
|
#if LUABRIDGE_HAS_EXCEPTIONS && LUABRIDGE_ON_LUAJIT
|
|
lua_pushlightuserdata(L, (void*)luajitWrapperCallback);
|
|
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
|
|
lua_pop(L, 1);
|
|
#endif
|
|
|
|
#if LUABRIDGE_ON_LUAU
|
|
auto callbacks = lua_callbacks(L);
|
|
callbacks->panic = +[](lua_State* L, int) { panicHandlerCallback(L); };
|
|
#else
|
|
lua_atpanic(L, panicHandlerCallback);
|
|
#endif
|
|
}
|
|
|
|
//=============================================================================================
|
|
/**
|
|
* @brief Retrieve the lua_State associated with the exception.
|
|
*
|
|
* @return A Lua state.
|
|
*/
|
|
lua_State* state() const { return m_L; }
|
|
|
|
private:
|
|
struct FromLua {};
|
|
|
|
LuaException(lua_State* L, std::error_code code, FromLua)
|
|
: m_L(L)
|
|
, m_code(code)
|
|
{
|
|
whatFromStack();
|
|
}
|
|
|
|
void whatFromStack()
|
|
{
|
|
std::stringstream ss;
|
|
|
|
const char* errorText = nullptr;
|
|
|
|
if (lua_gettop(m_L) > 0)
|
|
{
|
|
errorText = lua_tostring(m_L, -1);
|
|
lua_pop(m_L, 1);
|
|
}
|
|
|
|
ss << (errorText ? errorText : "Unknown error") << " (code=" << m_code.message() << ")";
|
|
|
|
m_what = std::move(ss).str();
|
|
}
|
|
|
|
static int panicHandlerCallback(lua_State* L)
|
|
{
|
|
#if LUABRIDGE_HAS_EXCEPTIONS
|
|
throw LuaException(L, makeErrorCode(ErrorCode::LuaFunctionCallFailed), FromLua{});
|
|
#else
|
|
unused(L);
|
|
|
|
std::abort();
|
|
#endif
|
|
}
|
|
|
|
#if LUABRIDGE_HAS_EXCEPTIONS && LUABRIDGE_ON_LUAJIT
|
|
static int luajitWrapperCallback(lua_State* L, lua_CFunction f)
|
|
{
|
|
try
|
|
{
|
|
return f(L);
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
lua_pushstring(L, e.what());
|
|
return lua_error_x(L);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static bool& exceptionsEnabled()
|
|
{
|
|
static bool areExceptionsEnabled = false;
|
|
return areExceptionsEnabled;
|
|
}
|
|
|
|
lua_State* m_L = nullptr;
|
|
std::error_code m_code;
|
|
std::string m_what;
|
|
};
|
|
|
|
//=================================================================================================
|
|
/**
|
|
* @brief Initializes error handling using C++ exceptions.
|
|
*
|
|
* Subsequent Lua errors are translated to C++ exceptions. It aborts the application if called when no exceptions.
|
|
*/
|
|
inline void enableExceptions(lua_State* L) noexcept
|
|
{
|
|
#if LUABRIDGE_HAS_EXCEPTIONS
|
|
LuaException::enableExceptions(L);
|
|
#else
|
|
unused(L);
|
|
|
|
assert(false); // Never call this function when exceptions are not enabled.
|
|
#endif
|
|
}
|
|
|
|
} // namespace luabridge
|