mod_adhoc: Add support for commands only executable by global administrators
[prosody.git] / util / multitable.lua
index f586330efebd5ecbe92c3fd8c041b32d007859f2..66b9bd8aba1a90481d80efcaa056773552a61f60 100644 (file)
@@ -1,20 +1,9 @@
--- Prosody IM v0.1
--- Copyright (C) 2008 Matthew Wild
--- Copyright (C) 2008 Waqas Hussain
+-- Prosody IM
+-- Copyright (C) 2008-2010 Matthew Wild
+-- Copyright (C) 2008-2010 Waqas Hussain
 -- 
--- This program is free software; you can redistribute it and/or
--- modify it under the terms of the GNU General Public License
--- as published by the Free Software Foundation; either version 2
--- of the License, or (at your option) any later version.
--- 
--- This program is distributed in the hope that it will be useful,
--- but WITHOUT ANY WARRANTY; without even the implied warranty of
--- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--- GNU General Public License for more details.
--- 
--- You should have received a copy of the GNU General Public License
--- along with this program; if not, write to the Free Software
--- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+-- This project is MIT/X11 licensed. Please see the
+-- COPYING file in the source package for more information.
 --
 
 
@@ -22,6 +11,7 @@
 local select = select;
 local t_insert = table.insert;
 local pairs = pairs;
+local next = next;
 
 module "multitable"
 
@@ -43,22 +33,42 @@ local function add(self, ...)
                if not tab then tab = {}; t[key] = tab; end
                t = tab;
        end
-       t_insert(t, select(count, ...));
+       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
-       if n > _end then
-               for key in pairs(t) do
-                       t[key] = nil;
-               end
-       end
        local k = select(n, ...);
+       if n == _end then
+               t[k] = nil;
+               return;
+       end
        if k then
-               r(t[k], n+1, _end, ...);
+               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
@@ -72,12 +82,62 @@ local function remove(self, ...)
 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
+
 function new()
        return {
                data = {};
                get = get;
                add = add;
+               set = set;
                remove = remove;
+               search = search;
+               search_add = search_add;
        };
 end