Line data Source code
1 : /*
2 : * libpino - handler.c
3 : *
4 : * Copyright (c) 2025 Go Kudo
5 : *
6 : * This library is licensed under the BSD 3-Clause License.
7 : * For license details, please refer to the LICENSE file.
8 : *
9 : * SPDX-FileCopyrightText: Go Kudo <zeriyoshi@gmail.com>
10 : * SPDX-License-Identifier: BSD-3-Clause
11 : */
12 :
13 : #include <pino.h>
14 : #include <pino/handler.h>
15 :
16 : #include <pino_internal.h>
17 :
18 : static struct {
19 : bool initialized;
20 : size_t capacity;
21 : size_t usage;
22 : handler_entry_t **entries;
23 : } g_handlers;
24 :
25 6 : static inline bool glow_handlers(size_t step)
26 : {
27 : handler_entry_t **entries;
28 : size_t i;
29 :
30 6 : entries = (handler_entry_t **)prealloc(g_handlers.entries, (g_handlers.capacity + step) * sizeof(handler_entry_t *));
31 6 : if (!entries) {
32 : return false; /* LCOV_EXCL_LINE */
33 : }
34 :
35 1014 : for (i = g_handlers.capacity; i < g_handlers.capacity + step; i++) {
36 1008 : entries[i] = NULL;
37 : }
38 :
39 6 : g_handlers.entries = entries;
40 6 : g_handlers.capacity += step;
41 :
42 : PINO_SUPRTF("glowed capacity: %zu, usage: %zu", g_handlers.capacity, g_handlers.usage);
43 :
44 6 : return true;
45 : }
46 :
47 18 : extern bool pino_handler_init(size_t initialize_size)
48 : {
49 : handler_entry_t **ents;
50 : size_t i;
51 :
52 18 : if (g_handlers.initialized) {
53 : return true; /* LCOV_EXCL_LINE */
54 : }
55 :
56 18 : g_handlers.initialized = false;
57 18 : g_handlers.capacity = initialize_size;
58 18 : g_handlers.usage = 0;
59 :
60 18 : ents = (handler_entry_t **)pcalloc(initialize_size, sizeof(handler_entry_t *));
61 18 : if (!ents) {
62 : return false; /* LCOV_EXCL_LINE */
63 : }
64 :
65 162 : for (i = 0; i < initialize_size; i++) {
66 144 : ents[i] = NULL;
67 : }
68 :
69 18 : g_handlers.entries = ents;
70 :
71 : PINO_SUPRTF("usage: %zu, capacity: %zu", g_handlers.usage, g_handlers.capacity);
72 :
73 18 : return g_handlers.initialized = true;
74 : }
75 :
76 18 : extern void pino_handler_free(void)
77 : {
78 : size_t i, j;
79 :
80 18 : if (!g_handlers.initialized) {
81 : return; /* LCOV_EXCL_LINE */
82 : }
83 :
84 1170 : for (i = 0; i < g_handlers.capacity; i++) {
85 1152 : if (g_handlers.entries[i]) {
86 1004 : pino_memory_manager_obj_free(&g_handlers.entries[i]->mm);
87 1004 : pfree(g_handlers.entries[i]);
88 1004 : g_handlers.entries[i] = NULL;
89 1004 : --g_handlers.usage;
90 :
91 : PINO_SUPRTF("freeing: %zu, usage: %zu, capacity: %zu", i, g_handlers.usage, g_handlers.capacity);
92 : }
93 : }
94 :
95 18 : pfree(g_handlers.entries);
96 :
97 18 : g_handlers.initialized = false;
98 : }
99 :
100 1034 : extern bool pino_handler_register(pino_magic_safe_t magic, pino_handler_t *handler)
101 : {
102 : handler_entry_t *entry;
103 : size_t i;
104 :
105 1034 : if (!handler) {
106 : PINO_SUPRTF("handler is NULL");
107 1 : return false;
108 : }
109 :
110 1033 : if (!validate_magic(magic)) {
111 : PINO_SUPRTF("magic is invalid");
112 5 : return false;
113 : }
114 :
115 1028 : if (pino_handler_find(magic)) {
116 : PINO_SUPRTF("magic: %.4s already registered", magic);
117 2 : return false;
118 : }
119 :
120 1026 : if (g_handlers.usage >= g_handlers.capacity) {
121 6 : if (!glow_handlers(g_handlers.capacity + HANDLER_STEP)) {
122 : return false; /* LCOV_EXCL_LINE */
123 : }
124 : }
125 :
126 1026 : entry = (handler_entry_t *)pmalloc(sizeof(handler_entry_t));
127 1026 : if (!entry) {
128 : return false; /* LCOV_EXCL_LINE */
129 : }
130 :
131 1026 : if (!pino_memory_manager_obj_init(&entry->mm, MM_STEP)) {
132 : /* LCOV_EXCL_START */
133 : pfree(entry);
134 : PINO_SUPRTF("pino_memory_manager_obj_init failed");
135 : return false;
136 : /* LCOV_EXCL_STOP */
137 : }
138 :
139 1026 : pmemcpy(entry->magic, magic, sizeof(pino_magic_t));
140 1026 : entry->handler = handler;
141 1026 : handler->entry = entry;
142 :
143 501541 : for (i = 0; i < g_handlers.capacity; i++) {
144 501541 : if (!g_handlers.entries[i]) {
145 1026 : g_handlers.entries[i] = entry;
146 1026 : ++g_handlers.usage;
147 :
148 : PINO_SUPRTF("magic: %.4s, using: %zu, usage: %zu, capacity: %zu", magic, i, g_handlers.usage, g_handlers.capacity);
149 :
150 1026 : return true;
151 : }
152 : }
153 :
154 : /* LCOV_EXCL_START */
155 : PINO_SUPUNREACH();
156 : return false;
157 : /* LCOV_EXCL_STOP */
158 : }
159 :
160 23 : extern bool pino_handler_unregister(pino_magic_safe_t magic)
161 : {
162 : size_t i;
163 :
164 23 : if (!g_handlers.initialized) {
165 : return false; /* LCOV_EXCL_LINE */
166 : }
167 :
168 23 : if (!validate_magic(magic)) {
169 : PINO_SUPRTF("magic is invalid");
170 1 : return false;
171 : }
172 :
173 27 : for (i = 0; i < g_handlers.usage; i++) {
174 27 : if (g_handlers.entries[i] && magic_equal(g_handlers.entries[i]->magic, magic)) {
175 22 : pino_memory_manager_obj_free(&g_handlers.entries[i]->mm);
176 22 : pfree(g_handlers.entries[i]);
177 22 : g_handlers.entries[i] = NULL;
178 22 : --g_handlers.usage;
179 :
180 : PINO_SUPRTF("freeing: %zu, usage: %zu, capacity: %zu", i, g_handlers.usage, g_handlers.capacity);
181 :
182 22 : return true;
183 : }
184 : }
185 :
186 : /* LCOV_EXCL_START */
187 : PINO_SUPUNREACH();
188 : return false;
189 : /* LCOV_EXCL_STOP */
190 : }
191 :
192 2039 : extern pino_handler_t *pino_handler_find(pino_magic_safe_t magic)
193 : {
194 : size_t i;
195 :
196 2039 : if (!g_handlers.initialized) {
197 : return NULL; /* LCOV_EXCL_LINE */
198 : }
199 :
200 502561 : for (i = 0; i < g_handlers.usage; i++) {
201 501530 : if (g_handlers.entries[i] && magic_equal(g_handlers.entries[i]->magic, magic)) {
202 1008 : return g_handlers.entries[i]->handler;
203 : }
204 : }
205 :
206 : /* LCOV_EXCL_START */
207 : PINO_SUPRTF("magic: %.4s not found", magic);
208 : return NULL;
209 : /* LCOV_EXCL_STOP */
210 : }
|