]> source.dussan.org Git - rspamd.git/commitdiff
[Minor] Add table compare utility
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 24 Feb 2018 14:29:29 +0000 (14:29 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 24 Feb 2018 14:29:29 +0000 (14:29 +0000)
lualib/lua_util.lua

index fb9fab0a4b2d6a4df7a30fcf8a28eb6457f33607..a7509665a7986a32f7b1c5165dca01351cf0b540 100644 (file)
@@ -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