Rizin
unix-like reverse engineering framework and cli tools
event.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2018 pancake
2 // SPDX-License-Identifier: MIT
3 
4 #include <rz_util.h>
5 #include <rz_vector.h>
6 
7 typedef struct rz_event_callback_hook_t {
9  void *user;
10  int handle;
12 
13 static void ht_callback_free(HtUPKv *kv) {
14  rz_vector_free((RzVector *)kv->value);
15 }
16 
17 RZ_API RzEvent *rz_event_new(void *user) {
18  RzEvent *ev = RZ_NEW0(RzEvent);
19  if (!ev) {
20  return NULL;
21  }
22 
23  ev->user = user;
24  ev->next_handle = 0;
25  ev->callbacks = ht_up_new(NULL, ht_callback_free, NULL);
26  if (!ev->callbacks) {
27  goto err;
28  }
31  return ev;
32 err:
33  rz_event_free(ev);
34  return NULL;
35 }
36 
38  if (!ev) {
39  return;
40  }
42  ht_up_free(ev->callbacks);
44  free(ev);
45 }
46 
47 static RzVector *get_cbs(RzEvent *ev, int type) {
48  RzVector *cbs = ht_up_find(ev->callbacks, (ut64)type, NULL);
49  if (!cbs) {
50  cbs = rz_vector_new(sizeof(RzEventCallbackHook), NULL, NULL);
51  if (cbs) {
52  ht_up_insert(ev->callbacks, (ut64)type, cbs);
53  }
54  }
55  return cbs;
56 }
57 
61 
63  hook.cb = cb;
64  hook.user = user;
65  hook.handle = ev->next_handle++;
66  if (type == RZ_EVENT_ALL) {
67  rz_vector_push(&ev->all_callbacks, &hook);
68  } else {
69  RzVector *cbs = get_cbs(ev, type);
70  if (!cbs) {
71  return handle;
72  }
73  rz_vector_push(cbs, &hook);
74  }
75  handle.handle = hook.handle;
76  handle.type = type;
77  return handle;
78 }
79 
80 static bool del_hook(void *user, const ut64 k, const void *v) {
81  int handle = *(int *)user;
82  RzVector *cbs = (RzVector *)v;
83  RzEventCallbackHook *hook;
84  size_t i;
85  rz_return_val_if_fail(cbs, false);
86  rz_vector_enumerate(cbs, hook, i) {
87  if (hook->handle == handle) {
88  rz_vector_remove_at(cbs, i, NULL);
89  break;
90  }
91  }
92  return true;
93 }
94 
97  if (ev->incall) {
98  // when inside a call (meaning rz_event_send currently iterates over the callback vectors),
99  // defer the unhook to after the rz_event_send is done.
101  return;
102  }
103  if (handle.type == RZ_EVENT_ALL) {
104  // try to delete it both from each list of callbacks and from
105  // the "all_callbacks" vector
106  ht_up_foreach(ev->callbacks, del_hook, &handle.handle);
107  del_hook(&handle.handle, 0, &ev->all_callbacks);
108  } else {
109  RzVector *cbs = ht_up_find(ev->callbacks, (ut64)handle.type, NULL);
110  rz_return_if_fail(cbs);
111  del_hook(&handle.handle, 0, cbs);
112  }
113 }
114 
115 RZ_API void rz_event_send(RzEvent *ev, int type, void *data) {
116  RzEventCallbackHook *hook;
117  rz_return_if_fail(ev && !ev->incall);
118 
119  // send to both the per-type callbacks and to the all_callbacks
120  ev->incall = true;
121  rz_vector_foreach(&ev->all_callbacks, hook) {
122  hook->cb(ev, type, hook->user, data);
123  }
124  ev->incall = false;
125 
126  RzVector *cbs = ht_up_find(ev->callbacks, (ut64)type, NULL);
127  if (cbs) {
128  ev->incall = true;
129  rz_vector_foreach(cbs, hook) {
130  hook->cb(ev, type, hook->user, data);
131  }
132  ev->incall = false;
133  }
134 
135  RzEventCallbackHandle *unhook_handle;
136  rz_vector_foreach(&ev->pending_unhook, unhook_handle) {
137  rz_event_unhook(ev, *unhook_handle);
138  }
140 }
lzma_index ** i
Definition: index.h:629
static bool err
Definition: armass.c:435
static mcore_handle handle
Definition: asm_mcore.c:8
#define RZ_API
#define NULL
Definition: cris-opc.c:27
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
RZ_API void rz_event_send(RzEvent *ev, int type, void *data)
Definition: event.c:115
RZ_API void rz_event_free(RzEvent *ev)
Definition: event.c:37
static RzVector * get_cbs(RzEvent *ev, int type)
Definition: event.c:47
struct rz_event_callback_hook_t RzEventCallbackHook
RZ_API RzEvent * rz_event_new(void *user)
Definition: event.c:17
static void ht_callback_free(HtUPKv *kv)
Definition: event.c:13
static bool del_hook(void *user, const ut64 k, const void *v)
Definition: event.c:80
RZ_API RzEventCallbackHandle rz_event_hook(RzEvent *ev, int type, RzEventCallback cb, void *user)
Definition: event.c:58
RZ_API void rz_event_unhook(RzEvent *ev, RzEventCallbackHandle handle)
Definition: event.c:95
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
int type
Definition: mipsasm.c:17
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
@ RZ_EVENT_ALL
Definition: rz_event.h:31
void(* RzEventCallback)(RzEvent *ev, int type, void *user, void *data)
Definition: rz_event.h:28
#define RZ_NEW0(x)
Definition: rz_types.h:284
RZ_API void rz_vector_remove_at(RzVector *vec, size_t index, void *into)
Definition: vector.c:127
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
#define rz_vector_foreach(vec, it)
Definition: rz_vector.h:169
RZ_API void rz_vector_fini(RzVector *vec)
Definition: vector.c:61
RZ_API void rz_vector_free(RzVector *vec)
Definition: vector.c:75
RZ_API RzVector * rz_vector_new(size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:42
RZ_API void rz_vector_clear(RzVector *vec)
Definition: vector.c:68
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:33
#define rz_vector_enumerate(vec, it, i)
Definition: rz_vector.h:177
RzEventCallback cb
Definition: event.c:8
RzVector all_callbacks
Definition: rz_event.h:18
int next_handle
Definition: rz_event.h:20
HtUP * callbacks
Definition: rz_event.h:17
void * user
Definition: rz_event.h:15
bool incall
Definition: rz_event.h:16
RzVector pending_unhook
while inside of a call and a handle is unhooked, the unhook is deferred and saved here
Definition: rz_event.h:19
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static const char * cb[]
Definition: z80_tab.h:176