util.events: Convert from Windows line endings
[prosody.git] / util / events.lua
1
2 local ipairs = ipairs;
3 local pairs = pairs;
4 local t_insert = table.insert;
5 local t_sort = table.sort;
6 local select = select;
7
8 module "events"
9
10 function new()
11         local dispatchers = {};
12         local handlers = {};
13         local event_map = {};
14         local function _rebuild_index(event) -- TODO optimize index rebuilding
15                 local _handlers = event_map[event];
16                 local index = handlers[event];
17                 if index then
18                         for i=#index,1,-1 do index[i] = nil; end
19                 else index = {}; handlers[event] = index; end
20                 for handler in pairs(_handlers) do
21                         t_insert(index, handler);
22                 end
23                 t_sort(index, function(a, b) return _handlers[a] > _handlers[b]; end);
24         end;
25         local function add_handler(event, handler, priority)
26                 local map = event_map[event];
27                 if map then
28                         map[handler] = priority or 0;
29                 else
30                         map = {[handler] = priority or 0};
31                         event_map[event] = map;
32                 end
33                 _rebuild_index(event);
34         end;
35         local function remove_handler(event, handler)
36                 local map = event_map[event];
37                 if map then
38                         map[handler] = nil;
39                         _rebuild_index(event);
40                 end
41         end;
42         local function add_plugin(plugin)
43                 for event, handler in pairs(plugin) do
44                         add_handler(event, handler);
45                 end
46         end;
47         local function remove_plugin(plugin)
48                 for event, handler in pairs(plugin) do
49                         remove_handler(event, handler);
50                 end
51         end;
52         local function _create_dispatcher(event) -- FIXME duplicate code in fire_event
53                 local h = handlers[event];
54                 if not h then h = {}; handlers[event] = h; end
55                 local dispatcher = function(...)
56                         for i=1,#h do
57                                 local ret = h[i](...);
58                                 if ret ~= nil then return ret; end
59                         end
60                 end;
61                 dispatchers[event] = dispatcher;
62                 return dispatcher;
63         end;
64         local function get_dispatcher(event)
65                 return dispatchers[event] or _create_dispatcher(event);
66         end;
67         local function fire_event(event, ...) -- FIXME duplicates dispatcher code
68                 local h = handlers[event];
69                 if h then
70                         for i=1,#h do
71                                 local ret = h[i](...);
72                                 if ret ~= nil then return ret; end
73                         end
74                 end
75         end;
76         local function get_named_arg_dispatcher(event, ...)
77                 local dispatcher = get_dispatcher(event);
78                 local keys = {...};
79                 local data = {};
80                 return function(...)
81                         for i, key in ipairs(keys) do data[key] = select(i, ...); end
82                         dispatcher(data);
83                 end;
84         end;
85         return {
86                 add_handler = add_handler;
87                 remove_handler = remove_handler;
88                 add_plugin = add_plugin;
89                 remove_plugin = remove_plugin;
90                 get_dispatcher = get_dispatcher;
91                 fire_event = fire_event;
92                 get_named_arg_dispatcher = get_named_arg_dispatcher;
93                 _dispatchers = dispatchers;
94                 _handlers = handlers;
95                 _event_map = event_map;
96         };
97 end
98
99 return _M;