util.pluginloader: Return full file path from internal file loader on success, not...
[prosody.git] / util / multitable.lua
1 -- Prosody IM
2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
4 -- 
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
7 --
8
9
10
11 local select = select;
12 local t_insert = table.insert;
13 local pairs = pairs;
14 local next = next;
15
16 module "multitable"
17
18 local function get(self, ...)
19         local t = self.data;
20         for n = 1,select('#', ...) do
21                 t = t[select(n, ...)];
22                 if not t then break; end
23         end
24         return t;
25 end
26
27 local function add(self, ...)
28         local t = self.data;
29         local count = select('#', ...);
30         for n = 1,count-1 do
31                 local key = select(n, ...);
32                 local tab = t[key];
33                 if not tab then tab = {}; t[key] = tab; end
34                 t = tab;
35         end
36         t_insert(t, (select(count, ...)));
37 end
38
39 local function set(self, ...)
40         local t = self.data;
41         local count = select('#', ...);
42         for n = 1,count-2 do
43                 local key = select(n, ...);
44                 local tab = t[key];
45                 if not tab then tab = {}; t[key] = tab; end
46                 t = tab;
47         end
48         t[(select(count-1, ...))] = (select(count, ...));
49 end
50
51 local function r(t, n, _end, ...)
52         if t == nil then return; end
53         local k = select(n, ...);
54         if n == _end then
55                 t[k] = nil;
56                 return;
57         end
58         if k then
59                 local v = t[k];
60                 if v then
61                         r(v, n+1, _end, ...);
62                         if not next(v) then
63                                 t[k] = nil;
64                         end
65                 end
66         else
67                 for _,b in pairs(t) do
68                         r(b, n+1, _end, ...);
69                         if not next(b) then
70                                 t[_] = nil;
71                         end
72                 end
73         end
74 end
75
76 local function remove(self, ...)
77         local _end = select('#', ...);
78         for n = _end,1 do
79                 if select(n, ...) then _end = n; break; end
80         end
81         r(self.data, 1, _end, ...);
82 end
83
84
85 local function s(t, n, results, _end, ...)
86         if t == nil then return; end
87         local k = select(n, ...);
88         if n == _end then
89                 if k == nil then
90                         for _, v in pairs(t) do
91                                 t_insert(results, v);
92                         end
93                 else
94                         t_insert(results, t[k]);
95                 end
96                 return;
97         end
98         if k then
99                 local v = t[k];
100                 if v then
101                         s(v, n+1, results, _end, ...);
102                 end
103         else
104                 for _,b in pairs(t) do
105                         s(b, n+1, results, _end, ...);
106                 end
107         end
108 end
109
110 -- Search for keys, nil == wildcard
111 local function search(self, ...)
112         local _end = select('#', ...);
113         for n = _end,1 do
114                 if select(n, ...) then _end = n; break; end
115         end
116         local results = {};
117         s(self.data, 1, results, _end, ...);
118         return results;
119 end
120
121 -- Append results to an existing list
122 local function search_add(self, results, ...)
123         if not results then results = {}; end
124         local _end = select('#', ...);
125         for n = _end,1 do
126                 if select(n, ...) then _end = n; break; end
127         end
128         s(self.data, 1, results, _end, ...);
129         return results;
130 end
131
132 function new()
133         return {
134                 data = {};
135                 get = get;
136                 add = add;
137                 set = set;
138                 remove = remove;
139                 search = search;
140                 search_add = search_add;
141         };
142 end
143
144 return _M;