mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-11-26 00:53:00 +00:00
Add deep copy table function
This commit is contained in:
parent
35970b31b3
commit
e82440a096
2 changed files with 41 additions and 0 deletions
40
worldeditadditions/utils/tables/deepcopy.lua
Normal file
40
worldeditadditions/utils/tables/deepcopy.lua
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
|
||||||
|
|
||||||
|
-- 4. Supporting recursive structures.
|
||||||
|
--
|
||||||
|
-- The issue here is that the following code will call itself
|
||||||
|
-- indefinitely and ultimately cause a stack overflow:
|
||||||
|
--
|
||||||
|
-- local my_t = {}
|
||||||
|
-- my_t.a = my_t
|
||||||
|
-- local t_copy = copy2(my_t)
|
||||||
|
--
|
||||||
|
-- This happens to both copy1 and copy2, which each try to make
|
||||||
|
-- a copy of my_t.a, which involves making a copy of my_t.a.a,
|
||||||
|
-- which involves making a copy of my_t.a.a.a, etc. The
|
||||||
|
-- recursive table my_t is perfectly legal, and it's possible to
|
||||||
|
-- make a deep_copy function that can handle this by tracking
|
||||||
|
-- which tables it has already started to copy.
|
||||||
|
--
|
||||||
|
-- Thanks to @mnemnion for pointing out that we should not call
|
||||||
|
-- setmetatable() until we're doing copying values; otherwise we
|
||||||
|
-- may accidentally trigger a custom __index() or __newindex()!
|
||||||
|
|
||||||
|
--- Deep clones a given table.
|
||||||
|
-- @source https://gist.github.com/tylerneylon/81333721109155b2d244
|
||||||
|
-- @param obj table The table to clone.
|
||||||
|
-- @returns table A deep copy of the given table.
|
||||||
|
local function deepcopy(obj, seen)
|
||||||
|
-- Handle non-tables and previously-seen tables.
|
||||||
|
if type(obj) ~= 'table' then return obj end
|
||||||
|
if seen and seen[obj] then return seen[obj] end
|
||||||
|
|
||||||
|
-- New table; mark it as seen and copy recursively.
|
||||||
|
local s = seen or {}
|
||||||
|
local res = {}
|
||||||
|
s[obj] = res
|
||||||
|
for k, v in pairs(obj) do res[deepcopy(k, s)] = deepcopy(v, s) end
|
||||||
|
return setmetatable(res, getmetatable(obj))
|
||||||
|
end
|
||||||
|
|
||||||
|
return deepcopy
|
|
@ -13,6 +13,7 @@ local wea = worldeditadditions
|
||||||
wea.table = {
|
wea.table = {
|
||||||
apply = dofile(wea.modpath.."/utils/tables/table_apply.lua"),
|
apply = dofile(wea.modpath.."/utils/tables/table_apply.lua"),
|
||||||
contains = dofile(wea.modpath.."/utils/tables/table_contains.lua"),
|
contains = dofile(wea.modpath.."/utils/tables/table_contains.lua"),
|
||||||
|
deepcopy = dofile(wea.modpath.."/utils/tables/deepcopy.lua"),
|
||||||
filter = dofile(wea.modpath.."/utils/tables/table_filter.lua"),
|
filter = dofile(wea.modpath.."/utils/tables/table_filter.lua"),
|
||||||
get_last = dofile(wea.modpath.."/utils/tables/table_get_last.lua"),
|
get_last = dofile(wea.modpath.."/utils/tables/table_get_last.lua"),
|
||||||
makeset = dofile(wea.modpath.."/utils/tables/makeset.lua"),
|
makeset = dofile(wea.modpath.."/utils/tables/makeset.lua"),
|
||||||
|
|
Loading…
Reference in a new issue