diff --git a/game/engines/default/engine/class.lua b/game/engines/default/engine/class.lua index aecf0a01d176e74a05cf454c6641bb45e6ef5a07..6d301b1dd1177e7fd83e7a7c75353410afc80258 100644 --- a/game/engines/default/engine/class.lua +++ b/game/engines/default/engine/class.lua @@ -118,7 +118,8 @@ local function clonerecursfull(clonetable, d) local n = {} clonetable[d] = n - for k, e in pairs(d) do + local k, e = next(d) + while k do local nk, ne = k, e if clonetable[k] then nk = clonetable[k] elseif type(k) == "table" then nk, add = clonerecursfull(clonetable, k) nb = nb + add @@ -128,6 +129,8 @@ local function clonerecursfull(clonetable, d) elseif type(e) == "table" and (type(k) ~= "string" or k ~= "__threads") then ne, add = clonerecursfull(clonetable, e) nb = nb + add end n[nk] = ne + + k, e = next(d, k) end setmetatable(n, getmetatable(d)) if n.cloned and n.__CLASSNAME then n:cloned(d) end @@ -138,6 +141,15 @@ end --- Clones the object, all subobjects without cloning twice a subobject -- @return the clone and the number of cloned objects function _M:cloneFull() +-- local old = core.game.getTime() +-- core.serial.cloneFull(self) +-- print("CLONE C", core.game.getTime() - old) + +-- old = core.game.getTime() +-- local clonetable = {} +-- clonerecursfull(clonetable, self) +-- print("CLONE LUA", core.game.getTime() - old) + local clonetable = {} return clonerecursfull(clonetable, self) -- return core.serial.cloneFull(self) diff --git a/src/serial.c b/src/serial.c index 0566c42143a0a0750cb82eb49d683b75991d6782..b7fef6435390e97db219f69f12f3a6422aff90b6 100644 --- a/src/serial.c +++ b/src/serial.c @@ -270,17 +270,13 @@ static int serial_tozip(lua_State *L) } #define CLONETABLE 2 +#define CLONETABLE_LIST 3 static int serial_clonefull_recurs(lua_State *L, int idx) { int ktype, etype; int nb = 0; - lua_newtable(L); - - // Store in the clonetable - lua_pushvalue(L, idx - 1); - lua_pushvalue(L, -2); - lua_rawset(L, CLONETABLE); + // We are called with the newtable on top of the stack lua_pushnil(L); /* first key */ while (lua_next(L, idx - 2) != 0) @@ -303,12 +299,20 @@ static int serial_clonefull_recurs(lua_State *L, int idx) { // Check clonetable first lua_pushvalue(L, -2); - lua_gettable(L, CLONETABLE); + lua_rawget(L, CLONETABLE); if (lua_isnil(L, -1)) { // If not found, clone it lua_pop(L, 1); - nb += serial_clonefull_recurs(L, -2); + lua_newtable(L); + + // Store in the clonetable + lua_pushvalue(L, -3); + lua_pushvalue(L, -2); + lua_rawset(L, CLONETABLE); + lua_pushvalue(L, -3); + lua_pushvalue(L, -2); + lua_rawset(L, CLONETABLE_LIST); } } else @@ -320,12 +324,20 @@ static int serial_clonefull_recurs(lua_State *L, int idx) { // Check clonetable first lua_pushvalue(L, -2); - lua_gettable(L, CLONETABLE); + lua_rawget(L, CLONETABLE); if (lua_isnil(L, -1)) { // If not found, clone it lua_pop(L, 1); - nb += serial_clonefull_recurs(L, -2); + lua_newtable(L); + + // Store in the clonetable + lua_pushvalue(L, -3); + lua_pushvalue(L, -2); + lua_rawset(L, CLONETABLE); + lua_pushvalue(L, -3); + lua_pushvalue(L, -2); + lua_rawset(L, CLONETABLE_LIST); } } else @@ -371,15 +383,35 @@ static int serial_clonefull_recurs(lua_State *L, int idx) static int serial_clonefull(lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); - lua_newtable(L); // idx 2 == clonetable - - printf("<TOP %d\n", lua_gettop(L)); + lua_newtable(L); // idx 2 == clonetable_all + lua_newtable(L); // idx 3 == clonetable + // Store in the clonetable + lua_pushvalue(L, 1); + lua_newtable(L); + lua_rawset(L, CLONETABLE); lua_pushvalue(L, 1); - int nb = serial_clonefull_recurs(L, -1); + lua_newtable(L); + lua_rawset(L, CLONETABLE_LIST); + + int nb = 0; + lua_pushnil(L); /* first key */ + while (lua_next(L, CLONETABLE_LIST) != 0) + { +// printf("<TOP %d\n", lua_gettop(L)); + nb += serial_clonefull_recurs(L, -1); +// printf(">TOP %d // %d\n", lua_gettop(L), nb); + + // Remove from list + lua_pop(L, 1); // remove value + lua_pushnil(L); // set to nil + lua_rawset(L, CLONETABLE_LIST); + + // Reset the next() + lua_pushnil(L); + } lua_pushnumber(L, nb); - printf(">TOP %d\n", lua_gettop(L)); return 2; }