LiteLoaderBDS-1.16.40/Tools/ScriptX/backend/Lua/LuaHelper.hpp
2023-03-02 23:06:13 -08:00

150 lines
3.9 KiB
C++

/*
* Tencent is pleased to support the open source community by making ScriptX available.
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cassert>
#include <optional>
#include <string>
#include "../../src/Reference.h"
#include "../../src/Scope.h"
#include "LuaEngine.h"
#include "LuaHelper.h"
namespace script::lua_backend {
inline LuaEngine* currentEngine() { return &EngineScope::currentEngineCheckedAs<LuaEngine>(); }
inline lua_State* currentLua() { return currentEngine()->lua_; }
/**
* run a balanced stack scope
*/
template <typename Block>
inline void luaStackScope(lua_State* lua, Block&& block) {
#ifndef NDEBUG
auto top = lua_gettop(lua);
block();
// assert the stack is balanced
assert(top == lua_gettop(lua));
#else
block();
#endif
}
inline void luaEnsureStack(lua_State* lua, int size) {
if (!lua_checkstack(lua, size)) {
throw Exception("stack overflow");
}
}
/**
* BE VERY CAREFUL with lua_error, it used longjmp to unwind stack, which WON'T CALL c++
* DESTRUCTORS.
*/
inline void luaThrow(lua_State* lua, const char* message) {
lua_pushstring(lua, message);
lua_error(lua);
}
/**
* BE VERY CAREFUL with lua_error, it used longjmp to unwind stack, which WON'T CALL c++
* DESTRUCTORS.
*/
inline void luaThrow(lua_State* lua, std::optional<std::string>& message) {
if (message.has_value()) {
lua_pushstring(lua, message->c_str());
// destruct std::string by hand
message.~optional();
lua_error(lua);
}
}
inline void pushValue(lua_State* lua, const Local<Value>& local) {
luaEnsureStack(lua, 1);
auto val = LuaEngine::localRefIndex(local);
if (val == 0) {
lua_pushnil(lua);
} else {
lua_pushvalue(lua, val);
}
}
template <typename It>
void pushValues(lua_State* lua, size_t count, It begin) {
luaEnsureStack(lua, static_cast<int>(count));
for (size_t i = 0; i < count; ++i) {
auto val = LuaEngine::localRefIndex(*begin);
if (val == 0) {
lua_pushnil(lua);
} else {
lua_pushvalue(lua, val);
}
++begin;
}
}
inline void rethrowException(lua_State* lua) {
Exception exp(LuaEngine::make<Local<Value>>(lua_gettop(lua)));
lua_pop(lua, 1);
throw exp; // NOLINT
}
} // namespace script::lua_backend
namespace script {
struct lua_interop {
/**
* get lua_State* from LuaEngine
*/
static lua_State* getEngineLua(lua_backend::LuaEngine* engine) { return engine->lua_; }
static lua_State* currentEngineLua() { return ::script::lua_backend::currentLua(); }
/**
* convert Local<T> to a lua local reference
* @return the index in stack
*/
template <typename T>
static int toLua(const Local<T>& ref) {
return lua_backend::LuaEngine::localRefIndex(ref);
}
/**
* create Local from lua local reference
* @param index the index in stack
*/
template <typename T>
static Local<T> makeLocal(int index) {
return lua_backend::LuaEngine::make<Local<T>>(index);
}
static Arguments makeArguments(lua_backend::LuaEngine* engine, int stackBase, size_t paramCount,
bool isInstanceFunc) {
return lua_backend::LuaEngine::makeArguments(engine, stackBase, paramCount, isInstanceFunc);
}
using ArgumentsData = lua_backend::ArgumentsData;
static ArgumentsData extractArguments(const Arguments& args) { return args.callbackInfo_; }
};
} // namespace script