// https://github.com/vinniefalco/LuaBridge
// Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
// Copyright 2008, Nigel Atkinson <suprapilot+LuaCode@gmail.com>
// SPDX-License-Identifier: MIT
#pragma once
#include <exception>
#include <string>
namespace luabridge {
class LuaException : public std::exception
{
private:
lua_State* m_L;
std::string m_what;
public:
//----------------------------------------------------------------------------
/**
Construct a LuaException after a lua_pcall().
*/
LuaException(lua_State* L, int /*code*/) : m_L(L) { whatFromStack(); }
//----------------------------------------------------------------------------
LuaException(lua_State* L, char const*, char const*, long) : m_L(L) { whatFromStack(); }
//----------------------------------------------------------------------------
~LuaException() throw() {}
//----------------------------------------------------------------------------
char const* what() const throw() { return m_what.c_str(); }
//============================================================================
/**
Throw an exception.
This centralizes all the exceptions thrown, so that we can set
breakpoints before the stack is unwound, or otherwise customize the
behavior.
*/
template<class Exception>
static void Throw(Exception e)
{
throw e;
}
//----------------------------------------------------------------------------
/**
Wrapper for lua_pcall that throws.
*/
static void pcall(lua_State* L, int nargs = 0, int nresults = 0, int msgh = 0)
{
int code = lua_pcall(L, nargs, nresults, msgh);
if (code != LUABRIDGE_LUA_OK)
Throw(LuaException(L, code));
}
//----------------------------------------------------------------------------
/**
Initializes error handling. Subsequent Lua errors are translated to C++ exceptions.
*/
static void enableExceptions(lua_State* L) { lua_atpanic(L, throwAtPanic); }
/** Retrieve the lua_State associated with the exception.
@returns A Lua state.
*/
lua_State* state() const { return m_L; }
protected:
void whatFromStack()
{
if (lua_gettop(m_L) > 0)
{
char const* s = lua_tostring(m_L, -1);
m_what = s ? s : "";
}
else
{
// stack is empty
m_what = "missing error";
}
}
private:
static int throwAtPanic(lua_State* L) { throw LuaException(L, -1); }
};
//----------------------------------------------------------------------------
/**
Initializes error handling. Subsequent Lua errors are translated to C++ exceptions.
*/
static void enableExceptions(lua_State* L)
{
LuaException::enableExceptions(L);
}
} // namespace luabridge