forked from osandov/drgn
-
Notifications
You must be signed in to change notification settings - Fork 6
/
handler.h
80 lines (67 loc) · 2.37 KB
/
handler.h
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
// Copyright (c) Meta Platforms, Inc. and affiliates.
// SPDX-License-Identifier: LGPL-2.1-or-later
/**
* @file
*
* Chains of named handlers.
*/
#ifndef DRGN_HANDLER_H
#define DRGN_HANDLER_H
#include <stdbool.h>
#include <stdlib.h>
// This should be embedded as the first member in a structure containing the
// handler implementation.
struct drgn_handler {
const char *name;
struct drgn_handler *next;
bool enabled;
// Whether this structure and name need to be freed.
bool free;
};
// This is optimized for frequent drgn_handler_list_for_each_enabled()
// operations; everything else is expected to be rare, so we keep this as small
// as possible.
struct drgn_handler_list {
// All enabled handlers are first, in order, followed by disabled
// handlers in no particular order.
struct drgn_handler *head;
};
// handler->name and handler->free must be initialized.
struct drgn_error *drgn_handler_list_register(struct drgn_handler_list *list,
struct drgn_handler *handler,
size_t enable_index,
const char *what);
struct drgn_error *drgn_handler_list_registered(struct drgn_handler_list *list,
const char ***names_ret,
size_t *count_ret);
struct drgn_error *drgn_handler_list_set_enabled(struct drgn_handler_list *list,
const char * const *names,
size_t count,
const char *what);
struct drgn_error *drgn_handler_list_enabled(struct drgn_handler_list *list,
const char ***names_ret,
size_t *count_ret);
// Helper to simplify the casting and naming in drgn_handler_list_deinit().
static inline struct drgn_handler *
drgn_handler_free_and_next(struct drgn_handler *handler)
{
struct drgn_handler *next = handler->next;
if (handler->free) {
free((char *)handler->name);
free(handler);
}
return next;
}
// Free all registered handlers, optionally executing a statement for each one.
#define drgn_handler_list_deinit(type, handler, list, ...) do { \
type *handler = (type *)(list)->head; \
while (handler) { \
__VA_ARGS__ \
handler = (type *)drgn_handler_free_and_next((struct drgn_handler *)handler);\
} \
} while (0)
#define drgn_handler_list_for_each_enabled(type, handler, list) \
for (type *handler = (type *)(list)->head; \
handler && ((struct drgn_handler *)handler)->enabled; \
handler = (type *)((struct drgn_handler *)handler)->next)
#endif /* DRGN_HANDLER_H */