summaryrefslogtreecommitdiffstats
path: root/lualib/lua_util.lua
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2018-02-24 14:29:29 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2018-02-24 14:29:29 +0000
commit0ed33d48078e69cff0c01dd99a84f77d9a123a5b (patch)
treef1e66774e6b46488eefb5c292f5f6a152ef191ae /lualib/lua_util.lua
parent67f8d8fccd3403450f6652fdd67a4db37112a592 (diff)
downloadrspamd-0ed33d48078e69cff0c01dd99a84f77d9a123a5b.tar.gz
rspamd-0ed33d48078e69cff0c01dd99a84f77d9a123a5b.zip
[Minor] Add table compare utility
Diffstat (limited to 'lualib/lua_util.lua')
-rw-r--r--lualib/lua_util.lua50
1 files changed, 50 insertions, 0 deletions
diff --git a/lualib/lua_util.lua b/lualib/lua_util.lua
index fb9fab0a4..a7509665a 100644
--- a/lualib/lua_util.lua
+++ b/lualib/lua_util.lua
@@ -321,4 +321,54 @@ end
exports.parse_time_interval = parse_time_interval
+--[[[
+-- @function lua_util.table_cmp(t1, t2)
+-- Compare two tables deeply
+--]]
+local function table_cmp(table1, table2)
+ local avoid_loops = {}
+ local function recurse(t1, t2)
+ if type(t1) ~= type(t2) then return false end
+ if type(t1) ~= "table" then return t1 == t2 end
+
+ if avoid_loops[t1] then return avoid_loops[t1] == t2 end
+ avoid_loops[t1] = t2
+ -- Copy keys from t2
+ local t2keys = {}
+ local t2tablekeys = {}
+ for k, _ in pairs(t2) do
+ if type(k) == "table" then table.insert(t2tablekeys, k) end
+ t2keys[k] = true
+ end
+ -- Let's iterate keys from t1
+ for k1, v1 in pairs(t1) do
+ local v2 = t2[k1]
+ if type(k1) == "table" then
+ -- if key is a table, we need to find an equivalent one.
+ local ok = false
+ for i, tk in ipairs(t2tablekeys) do
+ if table_cmp(k1, tk) and recurse(v1, t2[tk]) then
+ table.remove(t2tablekeys, i)
+ t2keys[tk] = nil
+ ok = true
+ break
+ end
+ end
+ if not ok then return false end
+ else
+ -- t1 has a key which t2 doesn't have, fail.
+ if v2 == nil then return false end
+ t2keys[k1] = nil
+ if not recurse(v1, v2) then return false end
+ end
+ end
+ -- if t2 has a key which t1 doesn't have, fail.
+ if next(t2keys) then return false end
+ return true
+ end
+ return recurse(table1, table2)
+end
+
+exports.table_cmp = table_cmp
+
return exports