Skip to content

Instantly share code, notes, and snippets.

@meepen
Last active January 11, 2016 00:27
Show Gist options
  • Save meepen/910c9b7b2bdaf0fe5a32 to your computer and use it in GitHub Desktop.
Save meepen/910c9b7b2bdaf0fe5a32 to your computer and use it in GitHub Desktop.
table.StructuralEquals
local TableEqualsIntrnl
local NaN = {};
local function NaNSafe(n) return n ~= n and NaN or n; end
local EqualOps = {
["function"] = function(f1, f2)
local s, dump = pcall(string.dump, f1)
local s2, dump2 = pcall(string.dump, f2)
-- test for lua function bytecode first, then c function
return s and s2 and dump == dump2 or f1 == f2
end,
table = function(t1, t2, cache)
return TableEqualsIntrnl(t1, t2, cache)
end
}
function TableEqualsIntrnl(t1, t2, cache)
cache[t2] = cache[t2] or {}
if (cache[t2][t1]) then return true end
cache[t2][t1] = {}
for k,v in next, t1, nil do
local isnew = false
if (not cache[t2][t1][k]) then
cache[t2][t1][k] = true
isnew = true
local ktype = type(k)
if (ktype ~= "number" and ktype ~= "string" and ktype ~= "boolean") then
for k2 in next, t2, nil do
if (type(k2) == ktype and EqualOps[ktype](k, k2, cache)) then
k = k2
break
end
end
end
end
if (isnew or not cache[t2][t1][k]) then
cache[t2][t1][k] = true
local v2 = t2[k]
if (type(v) == "table" and type(v2) == "table") then
if (not TableEqualsIntrnl(v, v2, cache)) then
return false
end
elseif (type(v) == "function" and type(v2) == "function") then
if(string.dump(v) ~= string.dump(v2)) then
return false
end
elseif (NaNSafe(v) ~= NaNSafe(v2)) then
return false
end
end
end
for k,v in next, t2, nil do
if (not cache[t2][t1][k]) then
return false
end
end
return true
end
function table.StructuralEquals(t1, t2) return TableEqualsIntrnl(t1, t2, {}) end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment