* @brief Walks a Lua table at @p idx and returns its JSON object/array equivalent. */
| 264 | * @brief Walks a Lua table at @p idx and returns its JSON object/array equivalent. |
| 265 | */ |
| 266 | static QJsonValue luaTableToJson(lua_State* L, int idx, int depth) |
| 267 | { |
| 268 | if (depth >= kMaxJsonDepth) |
| 269 | return QJsonValue(); |
| 270 | |
| 271 | const int abs = (idx > 0) ? idx : lua_gettop(L) + idx + 1; |
| 272 | |
| 273 | if (luaTableIsArray(L, abs)) { |
| 274 | QJsonArray arr; |
| 275 | const lua_Integer n = static_cast<lua_Integer>(lua_rawlen(L, abs)); |
| 276 | for (lua_Integer i = 1; i <= n; ++i) { |
| 277 | lua_rawgeti(L, abs, i); |
| 278 | arr.append(luaToJson(L, -1, depth + 1)); |
| 279 | lua_pop(L, 1); |
| 280 | } |
| 281 | return arr; |
| 282 | } |
| 283 | |
| 284 | QJsonObject obj; |
| 285 | lua_pushnil(L); |
| 286 | // code-verify off -- canonical lua_next walk, bounded by Lua table size |
| 287 | while (lua_next(L, abs) != 0) { |
| 288 | if (lua_type(L, -2) == LUA_TSTRING) { |
| 289 | size_t klen = 0; |
| 290 | const char* kstr = lua_tolstring(L, -2, &klen); |
| 291 | const QString k = QString::fromUtf8(kstr, static_cast<int>(klen)); |
| 292 | obj.insert(k, luaToJson(L, -1, depth + 1)); |
| 293 | } else if (lua_type(L, -2) == LUA_TNUMBER) { |
| 294 | obj.insert(QString::number(lua_tonumber(L, -2)), luaToJson(L, -1, depth + 1)); |
| 295 | } |
| 296 | lua_pop(L, 1); |
| 297 | } |
| 298 | // code-verify on |
| 299 | return obj; |
| 300 | } |
| 301 | |
| 302 | /** |
| 303 | * @brief Converts the Lua value at @p idx into a QJsonValue; unsupported types become null. |
no test coverage detected