root/tyrant_manager/extensions/our.lua

Revision 52, 3.3 kB (checked in by amix, 2 years ago)

Some miniatur optimization of list_add

Line 
1 -- Misc. Extensions
2 --
3 function incr(key, value)
4    value = tonumber(value)
5    if not value then
6       return nil
7    end
8    local old = tonumber(_get(key))
9    if old then
10       value = value + old
11    end
12    if not _put(key, value) then
13       return nil
14    end
15    return value
16 end
17
18
19 -- List functions
20 --
21 --
22 LIST_DELIM = "~"
23
24 function list_add(key, value)
25     --- Determine the limit by inspecting if | is in the key
26     local limit = 200
27
28     if string.find(key, '|') then
29         local key_parts = _tokenize(key, '|')
30         limit = tonumber(key_parts[1])
31         key = key_parts[2]
32     end
33
34     local current_value = _get(key) or ''
35
36     --- Filter out values so we don't insert duplicates
37     local search_val = LIST_DELIM .. current_value
38     local values = _tokenize(value, LIST_DELIM)
39     local filtered = {}
40
41     for i=1, #values do
42         if not string.match(search_val, LIST_DELIM .. values[i] .. LIST_DELIM) then
43             table.insert(filtered, values[i])
44         end
45     end
46
47     --- Check if they are all duplicates
48     if #filtered == 0 then
49         return "ok"
50     end
51
52     values = filtered
53
54     --- Check if we should apply cleanup
55     local list_size = char_count(search_val, LIST_DELIM)
56     list_size = list_size + #values
57
58     if list_size > (limit + 100) then
59         local current_list = _current_list(current_value, nil)
60         _list_cleanup(key, current_list, limit, #values)
61     end
62
63     --- Append values at the end of the list
64     _putcat(key, value)
65     return "ok"
66 end
67
68
69 function list_remove(key, value)
70     local current_list = _get(key)
71
72     if not current_list then
73         return "ok"
74     end
75
76     local tokens = _tokenize(value, LIST_DELIM)
77
78     for i = 1, #tokens do
79         current_list = string.gsub(current_list, tokens[i] .. LIST_DELIM, "")
80     end
81
82     _put(key, current_list)
83
84     return "ok"
85 end
86
87
88
89 --
90 -- Helpers
91 --
92 function _tokenize(text, delims)
93     local tokens = {}
94     for token in string.gmatch(text, "[^" .. delims .. "]+") do
95        if #token > 0 then
96           table.insert(tokens, token)
97        end
98     end
99     return tokens
100 end
101
102 function _current_list(old_list, tokens)
103    if old_list then
104        if tokens then
105            for i = 1, #tokens do
106                 old_list = string.gsub(old_list, "^" .. tokens[i] .. LIST_DELIM, "")
107                 old_list = string.gsub(old_list, LIST_DELIM .. tokens[i] .. LIST_DELIM, LIST_DELIM)
108            end
109        end
110
111        return _tokenize(old_list, LIST_DELIM)
112     else
113         return {}
114    end
115 end
116
117
118 --- Deletes the first entries in the list
119 --- so there's only `limit` entires left in the list
120 function _list_cleanup(key, current_list, limit, new_items_size)
121     local current_size = #current_list + new_items_size
122
123     while current_size > limit do
124         --remove the first item
125         table.remove(current_list, 1)
126         current_size = current_size - 1
127     end
128
129     _list_store(key, current_list)
130
131     return current_size
132 end
133
134 function _list_store(key, list)
135     local result = table.concat(list, LIST_DELIM)  .. LIST_DELIM
136     _put(key, result)
137 end
138
139 function char_count(str, char)
140     if not str then
141         return 0
142     end
143
144     local count = 0
145     local byte_char = string.byte(char)
146     for i = 1, #str do
147         if string.byte(str, i) == byte_char then
148             count = count + 1
149         end
150     end
151     return count
152 end
Note: See TracBrowser for help on using the browser.