mirror of
https://github.com/bjc/prosody.git
synced 2025-04-01 20:27:39 +03:00
182 lines
3.6 KiB
Lua
182 lines
3.6 KiB
Lua
-- Prosody IM
|
|
-- Copyright (C) 2008-2010 Matthew Wild
|
|
-- Copyright (C) 2008-2010 Waqas Hussain
|
|
--
|
|
-- This project is MIT/X11 licensed. Please see the
|
|
-- COPYING file in the source package for more information.
|
|
--
|
|
|
|
local select = select;
|
|
local t_insert = table.insert;
|
|
local pairs, next, type = pairs, next, type;
|
|
local unpack = table.unpack;
|
|
|
|
local _ENV = nil;
|
|
-- luacheck: std none
|
|
|
|
local function get(self, ...)
|
|
local t = self.data;
|
|
for n = 1,select('#', ...) do
|
|
t = t[select(n, ...)];
|
|
if not t then break; end
|
|
end
|
|
return t;
|
|
end
|
|
|
|
local function add(self, ...)
|
|
local t = self.data;
|
|
local count = select('#', ...);
|
|
for n = 1,count-1 do
|
|
local key = select(n, ...);
|
|
local tab = t[key];
|
|
if not tab then tab = {}; t[key] = tab; end
|
|
t = tab;
|
|
end
|
|
t_insert(t, (select(count, ...)));
|
|
end
|
|
|
|
local function set(self, ...)
|
|
local t = self.data;
|
|
local count = select('#', ...);
|
|
for n = 1,count-2 do
|
|
local key = select(n, ...);
|
|
local tab = t[key];
|
|
if not tab then tab = {}; t[key] = tab; end
|
|
t = tab;
|
|
end
|
|
t[(select(count-1, ...))] = (select(count, ...));
|
|
end
|
|
|
|
local function r(t, n, _end, ...)
|
|
if t == nil then return; end
|
|
local k = select(n, ...);
|
|
if n == _end then
|
|
t[k] = nil;
|
|
return;
|
|
end
|
|
if k then
|
|
local v = t[k];
|
|
if v then
|
|
r(v, n+1, _end, ...);
|
|
if not next(v) then
|
|
t[k] = nil;
|
|
end
|
|
end
|
|
else
|
|
for _,b in pairs(t) do
|
|
r(b, n+1, _end, ...);
|
|
if not next(b) then
|
|
t[_] = nil;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function remove(self, ...)
|
|
local _end = select('#', ...);
|
|
for n = _end,1 do
|
|
if select(n, ...) then _end = n; break; end
|
|
end
|
|
r(self.data, 1, _end, ...);
|
|
end
|
|
|
|
|
|
local function s(t, n, results, _end, ...)
|
|
if t == nil then return; end
|
|
local k = select(n, ...);
|
|
if n == _end then
|
|
if k == nil then
|
|
for _, v in pairs(t) do
|
|
t_insert(results, v);
|
|
end
|
|
else
|
|
t_insert(results, t[k]);
|
|
end
|
|
return;
|
|
end
|
|
if k then
|
|
local v = t[k];
|
|
if v then
|
|
s(v, n+1, results, _end, ...);
|
|
end
|
|
else
|
|
for _,b in pairs(t) do
|
|
s(b, n+1, results, _end, ...);
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Search for keys, nil == wildcard
|
|
local function search(self, ...)
|
|
local _end = select('#', ...);
|
|
for n = _end,1 do
|
|
if select(n, ...) then _end = n; break; end
|
|
end
|
|
local results = {};
|
|
s(self.data, 1, results, _end, ...);
|
|
return results;
|
|
end
|
|
|
|
-- Append results to an existing list
|
|
local function search_add(self, results, ...)
|
|
if not results then results = {}; end
|
|
local _end = select('#', ...);
|
|
for n = _end,1 do
|
|
if select(n, ...) then _end = n; break; end
|
|
end
|
|
s(self.data, 1, results, _end, ...);
|
|
return results;
|
|
end
|
|
|
|
local function iter(self, ...)
|
|
local query = { ... };
|
|
local maxdepth = select("#", ...);
|
|
local stack = { self.data };
|
|
local keys = { };
|
|
local function it(self) -- luacheck: ignore 432/self
|
|
local depth = #stack;
|
|
local key = next(stack[depth], keys[depth]);
|
|
if key == nil then -- Go up the stack
|
|
stack[depth], keys[depth] = nil, nil;
|
|
if depth > 1 then
|
|
return it(self);
|
|
end
|
|
return; -- The end
|
|
else
|
|
keys[depth] = key;
|
|
end
|
|
local value = stack[depth][key];
|
|
if query[depth] == nil or key == query[depth] then
|
|
if depth == maxdepth then -- Result
|
|
local result = {}; -- Collect keys forming path to result
|
|
for i = 1, depth do
|
|
result[i] = keys[i];
|
|
end
|
|
result[depth+1] = value;
|
|
return unpack(result, 1, depth+1);
|
|
elseif type(value) == "table" then
|
|
t_insert(stack, value); -- Descend
|
|
end
|
|
end
|
|
return it(self);
|
|
end;
|
|
return it, self;
|
|
end
|
|
|
|
local function new()
|
|
return {
|
|
data = {};
|
|
get = get;
|
|
add = add;
|
|
set = set;
|
|
remove = remove;
|
|
search = search;
|
|
search_add = search_add;
|
|
iter = iter;
|
|
};
|
|
end
|
|
|
|
return {
|
|
iter = iter;
|
|
new = new;
|
|
};
|