diff options
| author | Albert Cervin <albert@acervin.com> | 2024-09-17 08:47:03 +0200 |
|---|---|---|
| committer | Albert Cervin <albert@acervin.com> | 2025-11-01 22:11:14 +0100 |
| commit | 4459b8b3aa9d73895391785a99dcc87134e80601 (patch) | |
| tree | a5204f447a0b2b05f63504c7fe958ef9bbf1918a /src/dged/hook.h | |
| parent | 4689f3f38277bb64981fc960e8e384e2d065d659 (diff) | |
| download | dged-4459b8b3aa9d73895391785a99dcc87134e80601.tar.gz dged-4459b8b3aa9d73895391785a99dcc87134e80601.tar.xz dged-4459b8b3aa9d73895391785a99dcc87134e80601.zip | |
More lsp support
This makes the LSP support complete for now:
- Completion
- Diagnostics
- Goto implementation/declaration
- Rename
- Documentation
- Find references
Diffstat (limited to 'src/dged/hook.h')
| -rw-r--r-- | src/dged/hook.h | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/dged/hook.h b/src/dged/hook.h new file mode 100644 index 0000000..66e2839 --- /dev/null +++ b/src/dged/hook.h @@ -0,0 +1,84 @@ +#ifndef _HOOK_H +#define _HOOK_H + +#include <stdint.h> + +#include "vec.h" + +/** Callback when removing hooks to clean up userdata */ +typedef void (*remove_hook_cb)(void *userdata); + +#define HOOK_IMPL(name, callback_type) \ + struct name##_hook { \ + uint32_t id; \ + callback_type callback; \ + void *userdata; \ + }; \ + \ + typedef VEC(struct name##_hook) name##_hook_vec; \ + \ + static inline uint32_t insert_##name##_hook( \ + name##_hook_vec *hooks, uint32_t *id, callback_type callback, \ + void *userdata) { \ + uint32_t iid = ++(*id); \ + struct name##_hook hook = (struct name##_hook){ \ + .id = iid, \ + .callback = callback, \ + .userdata = userdata, \ + }; \ + VEC_PUSH(hooks, hook); \ + \ + return iid; \ + } \ + \ + static inline void remove_##name##_hook(name##_hook_vec *hooks, uint32_t id, \ + remove_hook_cb callback) { \ + uint64_t found_at = (uint64_t) - 1; \ + VEC_FOR_EACH_INDEXED(hooks, struct name##_hook *h, idx) { \ + if (h->id == id) { \ + if (callback != NULL) { \ + callback(h->userdata); \ + } \ + found_at = idx; \ + break; \ + } \ + } \ + if (found_at != (uint64_t) - 1) { \ + if (found_at < VEC_SIZE(hooks) - 1) { \ + VEC_SWAP(hooks, found_at, VEC_SIZE(hooks) - 1); \ + } \ + VEC_POP(hooks, struct name##_hook removed); \ + (void)removed; \ + } \ + } + +#define HOOK_IMPL_NO_REMOVE(name, callback_type) \ + struct name##_hook { \ + uint32_t id; \ + callback_type callback; \ + void *userdata; \ + }; \ + \ + typedef VEC(struct name##_hook) name##_hook_vec; \ + \ + static inline uint32_t insert_##name##_hook( \ + name##_hook_vec *hooks, uint32_t *id, callback_type callback, \ + void *userdata) { \ + uint32_t iid = ++(*id); \ + struct name##_hook hook = (struct name##_hook){ \ + .id = iid, \ + .callback = callback, \ + .userdata = userdata, \ + }; \ + VEC_PUSH(hooks, hook); \ + \ + return iid; \ + } + +#define dispatch_hook(hooks, hook_type, ...) \ + VEC_FOR_EACH(hooks, hook_type *h) { h->callback(__VA_ARGS__, h->userdata); } + +#define dispatch_hook_no_args(hooks, hook_type) \ + VEC_FOR_EACH(hooks, hook_type *h) { h->callback(h->userdata); } + +#endif |
