added tablex.copy is an alias for tablex.shallow_copy, same for overlay, bunch of whitespace changes, some additional asserts

This commit is contained in:
Max Cahill 2022-03-07 12:00:05 +11:00
parent de5c803389
commit 213ba5df0f

View File

@ -260,7 +260,7 @@ end
-- this call will be slow but then following iterations can use ipairs) -- this call will be slow but then following iterations can use ipairs)
function tablex.keys(t) function tablex.keys(t)
local r = {} local r = {}
for k,v in pairs(t) do for k, v in pairs(t) do
table.insert(r, k) table.insert(r, k)
end end
return r return r
@ -270,7 +270,7 @@ end
--(shallow copy if it's already sequential) --(shallow copy if it's already sequential)
function tablex.values(t) function tablex.values(t)
local r = {} local r = {}
for k,v in pairs(t) do for k, v in pairs(t) do
table.insert(r, v) table.insert(r, v)
end end
return r return r
@ -278,7 +278,7 @@ end
--append sequence t2 into t1, modifying t1 --append sequence t2 into t1, modifying t1
function tablex.append_inplace(t1, t2, ...) function tablex.append_inplace(t1, t2, ...)
for i,v in ipairs(t2) do for i, v in ipairs(t2) do
table.insert(t1, v) table.insert(t1, v)
end end
if ... then if ... then
@ -299,7 +299,7 @@ end
function tablex.dedupe(t) function tablex.dedupe(t)
local seen = {} local seen = {}
local r = {} local r = {}
for i,v in ipairs(t) do for i, v in ipairs(t) do
if not seen[v] then if not seen[v] then
seen[v] = true seen[v] = true
table.insert(r, v) table.insert(r, v)
@ -331,6 +331,7 @@ end
-- Copy a table -- Copy a table
-- See shallow_overlay to shallow copy into an existing table to avoid garbage. -- See shallow_overlay to shallow copy into an existing table to avoid garbage.
function tablex.shallow_copy(t) function tablex.shallow_copy(t)
assert:type(t, "table", "tablex.shallow_copy - t", 1)
if type(t) == "table" then if type(t) == "table" then
local into = {} local into = {}
for k, v in pairs(t) do for k, v in pairs(t) do
@ -341,29 +342,39 @@ function tablex.shallow_copy(t)
return t return t
end end
local function deep_copy(t, copied) --alias
tablex.copy = tablex.shallow_copy
--implementation for deep copy
--traces stuff that has already been copied, to handle circular references
local function _deep_copy_impl(t, already_copied)
local clone = t local clone = t
if type(t) == "table" then if type(t) == "table" then
if copied[t] then if already_copied[t] then
clone = copied[t] --something we've already encountered before
clone = already_copied[t]
elseif type(t.copy) == "function" then elseif type(t.copy) == "function" then
--something that provides its own copy function
clone = t:copy() clone = t:copy()
assert:type(clone, "table", "copy() didn't return a copy") assert:type(clone, "table", "member copy() function didn't return a copy")
else else
--a plain table to clone
clone = {} clone = {}
for k, v in pairs(t) do for k, v in pairs(t) do
clone[k] = deep_copy(v, copied) clone[k] = _deep_copy_impl(v, already_copied)
end end
setmetatable(clone, getmetatable(t)) setmetatable(clone, getmetatable(t))
copied[t] = clone already_copied[t] = clone
end end
end end
return clone return clone
end end
-- Recursively copy values of a table. -- Recursively copy values of a table.
-- Retains the same keys as original table -- they're not cloned. -- Retains the same keys as original table -- they're not cloned.
function tablex.deep_copy(t) function tablex.deep_copy(t)
return deep_copy(t, {}) assert:type(t, "table", "tablex.deep_copy - t", 1)
return _deep_copy_impl(t, {})
end end
-- Overlay tables directly onto one another, merging them together. -- Overlay tables directly onto one another, merging them together.
@ -376,13 +387,15 @@ function tablex.shallow_overlay(dest, ...)
for i = 1, select("#", ...) do for i = 1, select("#", ...) do
local t = select(i, ...) local t = select(i, ...)
assert:type(t, "table", "tablex.shallow_overlay - ...", 1) assert:type(t, "table", "tablex.shallow_overlay - ...", 1)
for k,v in pairs(t) do for k, v in pairs(t) do
dest[k] = v dest[k] = v
end end
end end
return dest return dest
end end
tablex.overlay = tablex.shallow_overlay
-- Overlay tables directly onto one another, merging them together into something like a union. -- Overlay tables directly onto one another, merging them together into something like a union.
-- Also overlays nested tables, but doesn't clone them (so a nested table may be added to dest). -- Also overlays nested tables, but doesn't clone them (so a nested table may be added to dest).
-- Takes as many tables as required, -- Takes as many tables as required,
@ -393,7 +406,7 @@ function tablex.deep_overlay(dest, ...)
for i = 1, select("#", ...) do for i = 1, select("#", ...) do
local t = select(i, ...) local t = select(i, ...)
assert:type(t, "table", "tablex.deep_overlay - ...", 1) assert:type(t, "table", "tablex.deep_overlay - ...", 1)
for k,v in pairs(t) do for k, v in pairs(t) do
if type(v) == "table" and type(dest[k]) == "table" then if type(v) == "table" and type(dest[k]) == "table" then
tablex.deep_overlay(dest[k], v) tablex.deep_overlay(dest[k], v)
else else
@ -437,6 +450,7 @@ function tablex.shallow_equal(a, b)
end end
end end
-- second loop to ensure a isn't missing any keys from b. -- second loop to ensure a isn't missing any keys from b.
-- we don't compare the values - if any are missing we're not equal
for k, v in pairs(b) do for k, v in pairs(b) do
if a[k] == nil then if a[k] == nil then
return false return false
@ -462,8 +476,8 @@ function tablex.deep_equal(a, b)
return false return false
end end
end end
-- second loop to ensure a isn't missing any keys from b, so we can skip -- second loop to ensure a isn't missing any keys from b
-- recursion. -- we don't compare the values - if any are missing we're not equal
for k, v in pairs(b) do for k, v in pairs(b) do
if a[k] == nil then if a[k] == nil then
return false return false