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;