From 7fa061c9410548debe380d92a929082f9b7bade5 Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Tue, 20 Aug 2024 15:09:32 +0300 Subject: [PATCH] lua_extensions: Add debug.print function that can pretty-print tables recursively(with depth limit of 10) --- src/logic/scripting/lua/lua_extensions.cpp | 90 +++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/src/logic/scripting/lua/lua_extensions.cpp b/src/logic/scripting/lua/lua_extensions.cpp index cb095e9f..f3424e93 100644 --- a/src/logic/scripting/lua/lua_extensions.cpp +++ b/src/logic/scripting/lua/lua_extensions.cpp @@ -1,5 +1,7 @@ -#include "debug/Logger.hpp" +#include + #include "api_lua.hpp" +#include "debug/Logger.hpp" static debug::Logger logger("lua-debug"); @@ -21,6 +23,89 @@ static int l_debug_log(lua::State* L) { return 0; } +const int MAX_DEPTH = 10; + +int l_debug_print(lua::State* L) { + auto addIndentation = [](int depth) { + std::cout << std::string(depth * 2, ' '); + }; + + auto pointerToHexString = [](const void* ptr, size_t size) { + std::stringstream ss; + const auto* bytePtr = reinterpret_cast(ptr); + for (size_t i = 0; i < size; ++i) { + ss << std::hex << std::setw(2) << std::setfill('0') << static_cast(bytePtr[i]) + << ((i + 1) % 8 == 0 && i + 1 < size ? "\n" : " "); + } + return ss.str(); + }; + + std::function debugPrint = [&](int index, int depth, bool is_key) { + if (depth > MAX_DEPTH) { + std::cout << "{...}"; + return; + } + switch (lua::type(L, index)) { + case LUA_TSTRING: + std::cout << (is_key ? lua::tostring(L, index) : "\"" + std::string(lua::tostring(L, index)) + "\""); + break; + case LUA_TBOOLEAN: + std::cout << (lua::toboolean(L, index) ? "true" : "false"); + break; + case LUA_TNUMBER: + std::cout << lua::tonumber(L, index); + break; + case LUA_TTABLE: { + bool is_list = lua::objlen(L, index) > 0, hadItems = false; + int absTableIndex = index > 0 ? index : lua::gettop(L) + index + 1; + std::cout << "{"; + lua::pushnil(L); + while (lua::next(L, absTableIndex) != 0) { + if (hadItems) std::cout << "," << std::endl; + else std::cout << std::endl; + addIndentation(depth + 1); + if (!is_list) debugPrint(-2, depth, true), std::cout << " = "; + debugPrint(-1, depth + 1, false); + lua::pop(L, 1); + hadItems = true; + } + if (hadItems) std::cout << std::endl; + addIndentation(depth); + std::cout << "}"; + break; + } + case LUA_TFUNCTION: + std::cout << "function(0x" << std::hex << lua::topointer(L, index) << std::dec << ")"; + break; + case LUA_TUSERDATA: + std::cout << "userdata:\n" << pointerToHexString(lua::topointer(L, index), lua::objlen(L, index)); + break; + case LUA_TLIGHTUSERDATA: + std::cout << "lightuserdata:\n" << pointerToHexString(lua::topointer(L, index), sizeof(void*)); + break; + case LUA_TNIL: + std::cout << "nil"; + break; + default: + std::cout << lua::type_name(L, lua::type(L, index)); + break; + } + }; + + int n = lua::gettop(L); + std::cout << "debug_print(" << std::endl; + for (int i = 1; i <= n; ++i) { + addIndentation(1); + debugPrint(i, 1, false); + if (i < n) std::cout << "," << std::endl; + } + std::cout << std::endl << ")" << std::endl; + lua::pop(L, n); + return 0; +} + + + void initialize_libs_extends(lua::State* L) { if (lua::getglobal(L, "debug")) { lua::pushcfunction(L, lua::wrap); @@ -32,6 +117,9 @@ void initialize_libs_extends(lua::State* L) { lua::pushcfunction(L, lua::wrap); lua::setfield(L, "log"); + lua::pushcfunction(L, lua::wrap); + lua::setfield(L, "print"); + lua::pop(L); } }