debug.print: remove as many allocations as possible, modified string print to escape any special characters

This commit is contained in:
REDxEYE 2024-08-20 18:10:05 +03:00
parent 6ff608c012
commit 408e7fd763

View File

@ -27,27 +27,58 @@ const int MAX_DEPTH = 10;
int l_debug_print(lua::State* L) { int l_debug_print(lua::State* L) {
auto addIndentation = [](int depth) { auto addIndentation = [](int depth) {
std::cout << std::string(depth * 2, ' '); for (int i = 0; i < depth; ++i) std::cout << " ";
}; };
auto pointerToHexString = [](const void* ptr, size_t size) { auto printHexData = [](const void* ptr, size_t size) {
std::stringstream ss;
const auto* bytePtr = reinterpret_cast<const uint8_t*>(ptr); const auto* bytePtr = reinterpret_cast<const uint8_t*>(ptr);
for (size_t i = 0; i < size; ++i) { for (size_t i = 0; i < size; ++i) {
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(bytePtr[i]) std::cout << std::hex << std::setw(2) << std::setfill('0')
<< ((i + 1) % 8 == 0 && i + 1 < size ? "\n" : " "); << static_cast<int>(bytePtr[i])
<< ((i + 1) % 8 == 0 && i + 1 < size ? "\n" : " ");
} }
return ss.str();
}; };
std::function<void(int, int, bool)> debugPrint = [&](int index, int depth, bool is_key) { auto printEscapedString = [](const char* str) {
while (*str) {
switch (*str) {
case '\\': std::cout << "\\\\"; break;
case '\"': std::cout << "\\\""; break;
case '\n': std::cout << "\\n"; break;
case '\t': std::cout << "\\t"; break;
case '\r': std::cout << "\\r"; break;
case '\b': std::cout << "\\b"; break;
case '\f': std::cout << "\\f"; break;
default:
if (iscntrl(static_cast<unsigned char>(*str))) {
// Print other control characters in \xHH format
std::cout << "\\x" << std::hex << std::setw(2) << std::setfill('0')
<< static_cast<int>(static_cast<unsigned char>(*str)) << std::dec;
} else {
std::cout << *str;
}
break;
}
++str;
}
};
std::function<void(int, int, bool)> debugPrint = [&](int index,
int depth,
bool is_key) {
if (depth > MAX_DEPTH) { if (depth > MAX_DEPTH) {
std::cout << "{...}"; std::cout << "{...}";
return; return;
} }
switch (lua::type(L, index)) { switch (lua::type(L, index)) {
case LUA_TSTRING: case LUA_TSTRING:
std::cout << (is_key ? lua::tostring(L, index) : "\"" + std::string(lua::tostring(L, index)) + "\""); if (is_key){
std::cout << lua::tostring(L, index);
}else{
std::cout << "\"";
printEscapedString(lua::tostring(L, index));
std::cout << "\"";
}
break; break;
case LUA_TBOOLEAN: case LUA_TBOOLEAN:
std::cout << (lua::toboolean(L, index) ? "true" : "false"); std::cout << (lua::toboolean(L, index) ? "true" : "false");
@ -57,31 +88,41 @@ int l_debug_print(lua::State* L) {
break; break;
case LUA_TTABLE: { case LUA_TTABLE: {
bool is_list = lua::objlen(L, index) > 0, hadItems = false; bool is_list = lua::objlen(L, index) > 0, hadItems = false;
int absTableIndex = index > 0 ? index : lua::gettop(L) + index + 1; int absTableIndex =
index > 0 ? index : lua::gettop(L) + index + 1;
std::cout << "{"; std::cout << "{";
lua::pushnil(L); lua::pushnil(L);
while (lua::next(L, absTableIndex) != 0) { while (lua::next(L, absTableIndex) != 0) {
if (hadItems) std::cout << "," << std::endl; if (hadItems)
else std::cout << std::endl; std::cout << "," << '\n';
else
std::cout << '\n';
addIndentation(depth + 1); addIndentation(depth + 1);
if (!is_list) debugPrint(-2, depth, true), std::cout << " = "; if (!is_list) {
debugPrint(-2, depth, true);
std::cout << " = ";
}
debugPrint(-1, depth + 1, false); debugPrint(-1, depth + 1, false);
lua::pop(L, 1); lua::pop(L, 1);
hadItems = true; hadItems = true;
} }
if (hadItems) std::cout << std::endl; if (hadItems) std::cout << '\n';
addIndentation(depth); addIndentation(depth);
std::cout << "}"; std::cout << "}";
break; break;
} }
case LUA_TFUNCTION: case LUA_TFUNCTION:
std::cout << "function(0x" << std::hex << lua::topointer(L, index) << std::dec << ")"; std::cout << "function(0x" << std::hex
<< lua::topointer(L, index) << std::dec << ")";
break; break;
case LUA_TUSERDATA: case LUA_TUSERDATA:
std::cout << "userdata:\n" << pointerToHexString(lua::topointer(L, index), lua::objlen(L, index)); std::cout << "userdata:\n";
printHexData(lua::topointer(L, index), lua::objlen(L, index));
break; break;
case LUA_TLIGHTUSERDATA: case LUA_TLIGHTUSERDATA:
std::cout << "lightuserdata:\n" << pointerToHexString(lua::topointer(L, index), sizeof(void*)); std::cout << "lightuserdata:\n";
printHexData(lua::topointer(L, index), sizeof(void*));
break; break;
case LUA_TNIL: case LUA_TNIL:
std::cout << "nil"; std::cout << "nil";
@ -93,19 +134,17 @@ int l_debug_print(lua::State* L) {
}; };
int n = lua::gettop(L); int n = lua::gettop(L);
std::cout << "debug.print(" << std::endl; std::cout << "debug.print(" << '\n';
for (int i = 1; i <= n; ++i) { for (int i = 1; i <= n; ++i) {
addIndentation(1); addIndentation(1);
debugPrint(i, 1, false); debugPrint(i, 1, false);
if (i < n) std::cout << "," << std::endl; if (i < n) std::cout << "," << '\n';
} }
std::cout << std::endl << ")" << std::endl; std::cout << '\n' << ")" << std::endl;
lua::pop(L, n); lua::pop(L, n);
return 0; return 0;
} }
void initialize_libs_extends(lua::State* L) { void initialize_libs_extends(lua::State* L) {
if (lua::getglobal(L, "debug")) { if (lua::getglobal(L, "debug")) {
lua::pushcfunction(L, lua::wrap<l_debug_error>); lua::pushcfunction(L, lua::wrap<l_debug_error>);