table.copy: Preserve metatables by default

This commit is contained in:
Lars Mueller 2022-09-30 12:55:44 +02:00
parent 49595be3ac
commit 4ded26be2c

@ -1,6 +1,6 @@
-- Localize globals -- Localize globals
local assert, ipairs, math, next, pairs, rawget, rawset, setmetatable, select, string, table, type local assert, ipairs, math, next, pairs, rawget, rawset, getmetatable, setmetatable, select, string, table, type
= assert, ipairs, math, next, pairs, rawget, rawset, setmetatable, select, string, table, type = assert, ipairs, math, next, pairs, rawget, rawset, getmetatable, setmetatable, select, string, table, type
-- Set environment -- Set environment
local _ENV = {} local _ENV = {}
@ -300,16 +300,20 @@ function shallowcopy(table)
return copy return copy
end end
function deepcopy_noncircular(table) function deepcopy_tree(table)
if type(table) ~= "table" then return table end if type(table) ~= "table" then return table end
local copy = {} local copy = {}
for key, value in pairs(table) do for key, value in pairs(table) do
copy[deepcopy_noncircular(key)] = deepcopy_noncircular(value) copy[deepcopy_tree(key)] = deepcopy_tree(value)
end end
return copy return copy
end end
deepcopy_noncircular = deepcopy_tree
function deepcopy(table) function deepcopy(
table -- table to copy; reference equality will be preserved
, strip_metatables -- whether to strip metatables; falsy by default; metatables are not copied
)
local copies = {} local copies = {}
local function _deepcopy(table) local function _deepcopy(table)
local copy = copies[table] local copy = copies[table]
@ -317,6 +321,9 @@ function deepcopy(table)
return copy return copy
end end
copy = {} copy = {}
if not strip_metatables then
setmetatable(copy, getmetatable(table))
end
copies[table] = copy copies[table] = copy
local function _copy(value) local function _copy(value)
if type(value) == "table" then if type(value) == "table" then