diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-12-02 11:53:09 +0100 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-12-02 11:53:09 +0100 |
| commit | ca7657e24549acb8a2dd45fa81c309b5bf9f61ee (patch) | |
| tree | 0124afa9a67d5f9d64fdbad4724bc715b7b502fb /src/tools.cpp | |
| parent | 0728e80bc2d3f5609f19b76f2bcf10412ce029b4 (diff) | |
| download | lanes-ca7657e24549acb8a2dd45fa81c309b5bf9f61ee.tar.gz lanes-ca7657e24549acb8a2dd45fa81c309b5bf9f61ee.tar.bz2 lanes-ca7657e24549acb8a2dd45fa81c309b5bf9f61ee.zip | |
Data transfer supports registered non-deep full userdata
Diffstat (limited to 'src/tools.cpp')
| -rw-r--r-- | src/tools.cpp | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/src/tools.cpp b/src/tools.cpp index 827c4a4..cd64d13 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
| @@ -123,7 +123,7 @@ namespace tools { | |||
| 123 | * receives 2 arguments: a name k and an object o | 123 | * receives 2 arguments: a name k and an object o |
| 124 | * add two entries ["fully.qualified.name"] = o | 124 | * add two entries ["fully.qualified.name"] = o |
| 125 | * and [o] = "fully.qualified.name" | 125 | * and [o] = "fully.qualified.name" |
| 126 | * where <o> is either a table or a function | 126 | * where <o> is either a table, a function, or a full userdata |
| 127 | * if we already had an entry of type [o] = ..., replace the name if the new one is shorter | 127 | * if we already had an entry of type [o] = ..., replace the name if the new one is shorter |
| 128 | * pops the processed object from the stack | 128 | * pops the processed object from the stack |
| 129 | */ | 129 | */ |
| @@ -191,7 +191,7 @@ static void update_lookup_entry(lua_State* const L_, StackIndex const ctxBase_, | |||
| 191 | 191 | ||
| 192 | // ################################################################################################# | 192 | // ################################################################################################# |
| 193 | 193 | ||
| 194 | static void populate_func_lookup_table_recur(lua_State* const L_, StackIndex const dbIdx_, StackIndex const i_, int const depth_) | 194 | static void populate_lookup_table_recur(lua_State* const L_, StackIndex const dbIdx_, StackIndex const i_, int const depth_) |
| 195 | { | 195 | { |
| 196 | // slot dbIdx_ contains the lookup database table | 196 | // slot dbIdx_ contains the lookup database table |
| 197 | // slot dbIdx_ + 1 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot i_ | 197 | // slot dbIdx_ + 1 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot i_ |
| @@ -199,7 +199,7 @@ static void populate_func_lookup_table_recur(lua_State* const L_, StackIndex con | |||
| 199 | // slot dbIdx_ + 2 contains a cache that stores all already visited tables to avoid infinite recursion loops | 199 | // slot dbIdx_ + 2 contains a cache that stores all already visited tables to avoid infinite recursion loops |
| 200 | StackIndex const _cache{ dbIdx_ + 2 }; | 200 | StackIndex const _cache{ dbIdx_ + 2 }; |
| 201 | DEBUGSPEW_CODE(Universe* const _U{ Universe::Get(L_) }); | 201 | DEBUGSPEW_CODE(Universe* const _U{ Universe::Get(L_) }); |
| 202 | DEBUGSPEW_CODE(DebugSpew(_U) << "populate_func_lookup_table_recur()" << std::endl); | 202 | DEBUGSPEW_CODE(DebugSpew(_U) << "populate_lookup_table_recur()" << std::endl); |
| 203 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 203 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
| 204 | 204 | ||
| 205 | STACK_GROW(L_, 6); | 205 | STACK_GROW(L_, 6); |
| @@ -231,14 +231,14 @@ static void populate_func_lookup_table_recur(lua_State* const L_, StackIndex con | |||
| 231 | 231 | ||
| 232 | // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) | 232 | // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) |
| 233 | lua_newtable(L_); // L_: ... {i_} {bfc} | 233 | lua_newtable(L_); // L_: ... {i_} {bfc} |
| 234 | int const breadthFirstCache{ lua_gettop(L_) }; | 234 | StackIndex const _breadthFirstCache{ lua_gettop(L_) }; |
| 235 | // iterate over all entries in the processed table | 235 | // iterate over all entries in the processed table |
| 236 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil | 236 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil |
| 237 | while (lua_next(L_, i_) != 0) { // L_: ... {i_} {bfc} k v | 237 | while (lua_next(L_, i_) != 0) { // L_: ... {i_} {bfc} k v |
| 238 | // just for debug, not actually needed | 238 | // just for debug, not actually needed |
| 239 | // std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostring(L_, -2) : "not a string" }; | 239 | // std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostring(L_, -2) : "not a string" }; |
| 240 | // subtable: process it recursively | 240 | // subtable: process it recursively |
| 241 | if (lua_istable(L_, -1)) { // L_: ... {i_} {bfc} k {} | 241 | if (lua_istable(L_, kIdxTop)) { // L_: ... {i_} {bfc} k {} |
| 242 | // increment visit count to make sure we will actually scan it at this recursive level | 242 | // increment visit count to make sure we will actually scan it at this recursive level |
| 243 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} | 243 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} |
| 244 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} {} | 244 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} {} |
| @@ -250,22 +250,26 @@ static void populate_func_lookup_table_recur(lua_State* const L_, StackIndex con | |||
| 250 | // store the table in the breadth-first cache | 250 | // store the table in the breadth-first cache |
| 251 | lua_pushvalue(L_, -2); // L_: ... {i_} {bfc} k {} k | 251 | lua_pushvalue(L_, -2); // L_: ... {i_} {bfc} k {} k |
| 252 | lua_pushvalue(L_, -2); // L_: ... {i_} {bfc} k {} k {} | 252 | lua_pushvalue(L_, -2); // L_: ... {i_} {bfc} k {} k {} |
| 253 | lua_rawset(L_, breadthFirstCache); // L_: ... {i_} {bfc} k {} | 253 | lua_rawset(L_, _breadthFirstCache); // L_: ... {i_} {bfc} k {} |
| 254 | // generate a name, and if we already had one name, keep whichever is the shorter | 254 | // generate a name, and if we already had one name, keep whichever is the shorter |
| 255 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k | 255 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k |
| 256 | } else if (lua_isfunction(L_, -1) && (luaG_getfuncsubtype(L_, kIdxTop) != FuncSubType::Bytecode)) { | 256 | } else if (lua_isfunction(L_, kIdxTop) && (luaG_getfuncsubtype(L_, kIdxTop) != FuncSubType::Bytecode)) { |
| 257 | // generate a name, and if we already had one name, keep whichever is the shorter | 257 | // generate a name, and if we already had one name, keep whichever is the shorter |
| 258 | // this pops the function from the stack | 258 | // this pops the function from the stack |
| 259 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k | 259 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k |
| 260 | } else if (luaG_type(L_, kIdxTop) == LuaType::USERDATA) { | ||
| 261 | // generate a name, and if we already had one name, keep whichever is the shorter | ||
| 262 | // this pops the userdata from the stack | ||
| 263 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k | ||
| 260 | } else { | 264 | } else { |
| 261 | lua_pop(L_, 1); // L_: ... {i_} {bfc} k | 265 | lua_pop(L_, 1); // L_: ... {i_} {bfc} k |
| 262 | } | 266 | } |
| 263 | STACK_CHECK(L_, 2); | 267 | STACK_CHECK(L_, 2); |
| 264 | } | 268 | } |
| 265 | // now process the tables we encountered at that depth | 269 | // now process the tables we encountered at that depth |
| 266 | int const _deeper{ depth_ + 1 }; | 270 | int const _deeper{ depth_ + 1 }; |
| 267 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil | 271 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil |
| 268 | while (lua_next(L_, breadthFirstCache) != 0) { // L_: ... {i_} {bfc} k {} | 272 | while (lua_next(L_, _breadthFirstCache) != 0) { // L_: ... {i_} {bfc} k {} |
| 269 | DEBUGSPEW_CODE(std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostring(L_, -2) : std::string_view{ "<not a string>" } }); | 273 | DEBUGSPEW_CODE(std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostring(L_, -2) : std::string_view{ "<not a string>" } }); |
| 270 | DEBUGSPEW_CODE(DebugSpew(_U) << "table '"<< _key <<"'" << std::endl); | 274 | DEBUGSPEW_CODE(DebugSpew(_U) << "table '"<< _key <<"'" << std::endl); |
| 271 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ _U }); | 275 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ _U }); |
| @@ -285,7 +289,7 @@ static void populate_func_lookup_table_recur(lua_State* const L_, StackIndex con | |||
| 285 | // push table name in fqn stack (note that concatenation will crash if name is a not string!) | 289 | // push table name in fqn stack (note that concatenation will crash if name is a not string!) |
| 286 | lua_pushvalue(L_, -2); // L_: ... {i_} {bfc} k {} k | 290 | lua_pushvalue(L_, -2); // L_: ... {i_} {bfc} k {} k |
| 287 | lua_rawseti(L_, _fqn, _deeper); // L_: ... {i_} {bfc} k {} | 291 | lua_rawseti(L_, _fqn, _deeper); // L_: ... {i_} {bfc} k {} |
| 288 | populate_func_lookup_table_recur(L_, dbIdx_, StackIndex{ lua_gettop(L_) }, _deeper); | 292 | populate_lookup_table_recur(L_, dbIdx_, StackIndex{ lua_gettop(L_) }, _deeper); |
| 289 | lua_pop(L_, 1); // L_: ... {i_} {bfc} k | 293 | lua_pop(L_, 1); // L_: ... {i_} {bfc} k |
| 290 | STACK_CHECK(L_, 2); | 294 | STACK_CHECK(L_, 2); |
| 291 | } | 295 | } |
| @@ -316,7 +320,8 @@ namespace tools { | |||
| 316 | StackIndex const _dbIdx{ lua_gettop(L_) }; | 320 | StackIndex const _dbIdx{ lua_gettop(L_) }; |
| 317 | STACK_CHECK(L_, 1); | 321 | STACK_CHECK(L_, 1); |
| 318 | LUA_ASSERT(L_, lua_istable(L_, -1)); | 322 | LUA_ASSERT(L_, lua_istable(L_, -1)); |
| 319 | if (luaG_type(L_, _in_base) == LuaType::FUNCTION) { // for example when a module is a simple function | 323 | LuaType const _moduleType{ luaG_type(L_, _in_base) }; |
| 324 | if ((_moduleType == LuaType::FUNCTION) || (_moduleType == LuaType::USERDATA)) { // for example when a module is a simple function | ||
| 320 | if (_name.empty()) { | 325 | if (_name.empty()) { |
| 321 | _name = "nullptr"; | 326 | _name = "nullptr"; |
| 322 | } | 327 | } |
| @@ -343,7 +348,7 @@ namespace tools { | |||
| 343 | // retrieve the cache, create it if we haven't done it yet | 348 | // retrieve the cache, create it if we haven't done it yet |
| 344 | std::ignore = kLookupCacheRegKey.getSubTable(L_, NArr{ 0 }, NRec{ 0 }); // L_: {} {fqn} {cache} | 349 | std::ignore = kLookupCacheRegKey.getSubTable(L_, NArr{ 0 }, NRec{ 0 }); // L_: {} {fqn} {cache} |
| 345 | // process everything we find in that table, filling in lookup data for all functions and tables we see there | 350 | // process everything we find in that table, filling in lookup data for all functions and tables we see there |
| 346 | populate_func_lookup_table_recur(L_, _dbIdx, _in_base, _startDepth); | 351 | populate_lookup_table_recur(L_, _dbIdx, _in_base, _startDepth); |
| 347 | lua_pop(L_, 3); // L_: | 352 | lua_pop(L_, 3); // L_: |
| 348 | } else { | 353 | } else { |
| 349 | lua_pop(L_, 1); // L_: | 354 | lua_pop(L_, 1); // L_: |
