1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
/*
* Copyright (c) 2001 James E. Wilson, Robert A. Koeneke, DarkGod
*
* This software may be copied and distributed for educational, research, and
* not for profit purposes provided that this copyright and statement are
* included in all such copies.
*/
#include "hooks.h"
#include "angband.h"
#include <algorithm>
#include <assert.h>
#include <unordered_map>
#include <vector>
/******** Hooks stuff *********/
struct hook_data
{
private:
hook_func_t m_hook_func;
void *m_hook_data;
public:
hook_data(hook_func_t hook_func, void *hook_data)
: m_hook_func(hook_func)
, m_hook_data(hook_data) {
}
hook_data() = delete;
/**
* Check if the given hook points to the given function.
*/
bool is(hook_func_t hook_func) const {
return m_hook_func == hook_func;
}
/**
* Invoke the hook with the given input and output pointers.
*/
bool_ invoke(void *in, void *out) const {
return m_hook_func(m_hook_data, in, out);
}
};
std::unordered_map<size_t, std::vector<hook_data>> &hooks_instance()
{
static auto instance = new std::unordered_map<size_t, std::vector<hook_data>>();
return *instance;
}
int process_hooks_restart = FALSE;
static std::vector<hook_data>::iterator find_hook(std::vector<hook_data> &hooks, hook_func_t hook_func)
{
return std::find_if(hooks.begin(),
hooks.end(),
[&](const hook_data &hook_data) {
return hook_data.is(hook_func);
});
}
void add_hook_new(int h_idx, hook_func_t hook_func, cptr name, void *data)
{
auto &hooks = hooks_instance()[h_idx];
// Only insert if not already present.
if (find_hook(hooks, hook_func) == hooks.end()) {
hooks.emplace_back(hook_func, data);
}
}
void del_hook_new(int h_idx, hook_func_t hook_func)
{
auto &hooks = hooks_instance()[h_idx];
/* Find it */
auto found_it = find_hook(hooks, hook_func);
if (found_it != hooks.end())
{
hooks.erase(found_it);
}
}
bool_ process_hooks_new(int h_idx, void *in, void *out)
{
auto const &hooks = hooks_instance()[h_idx];
auto hooks_it = hooks.begin();
while (hooks_it != hooks.end())
{
auto &hook_data = *hooks_it;
/* Invoke hook function; stop processing if the hook
returns TRUE */
if (hook_data.invoke(in, out))
{
return TRUE;
}
/* Should we restart processing at the beginning? */
if (process_hooks_restart)
{
hooks_it = hooks.begin();
process_hooks_restart = FALSE;
}
else
{
hooks_it++;
}
}
return FALSE;
}
|