libsir 2.2.5
Standard Incident Reporter
Loading...
Searching...
No Matches
helpers.h
1/*
2 * helpers.h
3 *
4 * Version: 2.2.5
5 *
6 * -----------------------------------------------------------------------------
7 *
8 * SPDX-License-Identifier: MIT
9 *
10 * Copyright (c) 2018-2024 Ryan M. Lederman <lederman@gmail.com>
11 * Copyright (c) 2018-2024 Jeffrey H. Johnson <trnsz@pobox.com>
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a copy of
14 * this software and associated documentation files (the "Software"), to deal in
15 * the Software without restriction, including without limitation the rights to
16 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
17 * the Software, and to permit persons to whom the Software is furnished to do so,
18 * subject to the following conditions:
19 *
20 * The above copyright notice and this permission notice shall be included in all
21 * copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
25 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
26 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
27 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 *
30 * -----------------------------------------------------------------------------
31 */
32
33#ifndef _SIR_HELPERS_H_INCLUDED
34# define _SIR_HELPERS_H_INCLUDED
35
36# include "sir/types.h"
37# include "sir/errors.h"
38
39# if defined(__cplusplus)
40extern "C" {
41# endif
42
44# define _sir_countof(arr) (sizeof(arr) / sizeof(arr[0]))
45
47# define _SIR_L_START(format) \
48 bool ret = false; \
49 va_list args; \
50 do { \
51 if (!_sir_validptr(format)) \
52 return false; \
53 va_start(args, format); \
54 } while (false)
55
57# define _SIR_L_END() \
58 va_end(args)
59
61# define _SIR_LOCK_SECTION(type, name, mid, ret) \
62 type* name = _sir_locksection(mid); \
63 do { \
64 if (!name) { \
65 (void)_sir_seterror(_SIR_E_INTERNAL); \
66 return ret; \
67 } \
68 } while (false)
69
71# define _SIR_UNLOCK_SECTION(mid) \
72 _sir_unlocksection(mid)
73
75# define SIR_UNUSED(param) (void)param
76
78# define SIR_ASSERT_UNUSED(assertion, var) SIR_ASSERT(assertion); SIR_UNUSED(var)
79
81# define _SIR_PRNSTR(str) (str ? str : "<null>")
82
84# define _SIR_DECLARE_BIN_SEARCH(low, high) \
85 size_t _low = low, _high = high; \
86 size_t _mid = (_low + _high) / 2
87
88# define _SIR_BEGIN_BIN_SEARCH() do {
89
90# define _SIR_ITERATE_BIN_SEARCH(comparison) \
91 if (_low == _high) \
92 break; \
93 if (0 > comparison && (_mid - 1) >= _low) { \
94 _high = _mid - 1; \
95 } else if ((_mid + 1) <= _high) { \
96 _low = _mid + 1; \
97 } else { \
98 break; \
99 } \
100 _mid = (_low + _high) / 2
101
102# define _SIR_END_BIN_SEARCH() \
103 } while (true)
104
105/* Validates a pointer and optionally fails if it's invalid. */
106static inline
107bool __sir_validptr(const void* restrict p, bool fail, const char* func,
108 const char* file, uint32_t line) {
109 bool valid = NULL != p;
110 if (fail && !valid) {
111 (void)__sir_seterror(_SIR_E_NULLPTR, func, file, line);
112 SIR_ASSERT(!valid && fail);
113 }
114 return valid;
115}
116
118static inline
119bool __sir_validptrptr(const void* restrict* pp, bool fail, const char* func,
120 const char* file, uint32_t line) {
121 bool valid = NULL != pp;
122 if (fail && !valid) {
123 (void)__sir_seterror(_SIR_E_NULLPTR, func, file, line);
124 SIR_ASSERT(!valid && fail);
125 }
126 return valid;
127}
128
130# define _sir_validptrnofail(p) \
131 __sir_validptr(p, false, __func__, __file__, __LINE__)
132
134# define _sir_validptr(p) \
135 __sir_validptr((const void* restrict)p, true, __func__, __file__, __LINE__)
136
138# define _sir_validfnptr(fnp) \
139 __sir_validptrptr((const void* restrict*)&fnp, true, __func__, __file__, __LINE__)
140
142# define _sir_validptrptr(pp) \
143 __sir_validptrptr((const void* restrict*)pp, true, __func__, __file__, __LINE__)
144
146static inline
147bool _sir_bittest(uint32_t flags, uint32_t test) {
148 return (flags & test) == test;
149}
150
152static inline
153void _sir_setbitshigh(uint32_t* flags, uint32_t set) {
154 if (NULL != flags)
155 *flags |= set;
156}
157
159static inline
160void _sir_setbitslow(uint32_t* flags, uint32_t set) {
161 if (NULL != flags)
162 *flags &= ~set;
163}
164
167# define _sir_eqland(b, expr) ((b) = (expr) && (b))
168
170void __sir_safefree(void** pp);
171
173# define _sir_safefree(pp) __sir_safefree((void**)pp)
174
176void _sir_safeclose(int* restrict fd);
177
179void _sir_safefclose(FILE* restrict* restrict f);
180
182bool _sir_validfd(int fd);
183
185static inline
186bool _sir_validfileid(sirfileid id) {
187 return 0U != id;
188}
189
191static inline
192bool _sir_validpluginid(sirpluginid id) {
193 return 0U != id;
194}
195
197bool __sir_validupdatedata(const sir_update_config_data* data, const char* func,
198 const char* file, uint32_t line);
199
201# define _sir_validupdatedata(data) \
202 __sir_validupdatedata(data, __func__, __file__, __LINE__)
203
205bool __sir_validlevels(sir_levels levels, const char* func, const char* file,
206 uint32_t line);
207
209# define _sir_validlevels(levels) \
210 __sir_validlevels(levels, __func__, __file__, __LINE__)
211
213bool __sir_validlevel(sir_level level, const char* func, const char* file,
214 uint32_t line);
215
217# define _sir_validlevel(level) \
218 __sir_validlevel(level, __func__, __file__, __LINE__)
219
221static inline
222void _sir_defaultlevels(sir_levels* levels, sir_levels def) {
223 if (levels && SIRL_DEFAULT == *levels)
224 *levels = def;
225}
226
228static inline
229void _sir_defaultopts(sir_options* opts, sir_options def) {
230 if (opts && SIRO_DEFAULT == *opts)
231 *opts = def;
232}
233
235bool __sir_validopts(sir_options opts, const char* func, const char* file,
236 uint32_t line);
237
239# define _sir_validopts(opts) \
240 __sir_validopts(opts, __func__, __file__, __LINE__)
241
243bool __sir_validtextattr(sir_textattr attr, const char* func, const char* file,
244 uint32_t line);
245
247# define _sir_validtextattr(attr) \
248 __sir_validtextattr(attr, __func__, __file__, __LINE__)
249
251bool __sir_validtextcolor(sir_colormode mode, sir_textcolor color, const char* func,
252 const char* file, uint32_t line);
253
255# define _sir_validtextcolor(mode, color) \
256 __sir_validtextcolor(mode, color, __func__, __file__, __LINE__)
257
259bool __sir_validcolormode(sir_colormode mode, const char* func, const char* file,
260 uint32_t line);
261
263# define _sir_validcolormode(mode) \
264 __sir_validcolormode(mode, __func__, __file__, __LINE__)
265
267static inline
268sir_textcolor _sir_mkansifgcolor(sir_textcolor fg) {
269 return SIRTC_DEFAULT == fg ? 39 : fg < 8 ? fg + 30 : fg + 82;
270}
271
273static inline
274sir_textcolor _sir_mkansibgcolor(sir_textcolor bg) {
275 return SIRTC_DEFAULT == bg ? 49 : bg < 8 ? bg + 40 : bg + 92;
276}
277
279static inline
280sir_textcolor _sir_getansifgcmd(sir_textcolor fg) {
281 return SIRTC_DEFAULT == fg ? 39 : 38;
282}
283
285static inline
286sir_textcolor _sir_getansibgcmd(sir_textcolor bg) {
287 return SIRTC_DEFAULT == bg ? 49 : 48;
288}
289
291# define _sir_getredfromcolor(color) (uint8_t)(((color) >> 16) & 0x000000ffU)
292
294# define _sir_setredincolor(color, red) (color |= (((red) << 16) & 0x00ff0000U))
295
297# define _sir_getgreenfromcolor(color) (uint8_t)(((color) >> 8) & 0x000000ffU)
298
300# define _sir_setgreenincolor(color, green) ((color) |= (((green) << 8) & 0x0000ff00U))
301
303# define _sir_getbluefromcolor(color) (uint8_t)((color) & 0x000000ffU)
304
306# define _sir_setblueincolor(color, blue) ((color) |= ((blue) & 0x000000ffU))
307
309static inline
311 sir_textcolor retval = 0;
312 _sir_setredincolor(retval, r);
313 _sir_setgreenincolor(retval, g);
314 _sir_setblueincolor(retval, b);
315 return retval;
316}
317
319static inline
320bool __sir_validstr(const char* restrict str, bool fail, const char* func,
321 const char* file, uint32_t line) {
322 bool valid = str && *str != '\0';
323 if (fail && !valid) {
324 SIR_ASSERT(!valid && fail);
325 (void)__sir_seterror(_SIR_E_STRING, func, file, line);
326 }
327 return valid;
328}
329
331# define _sir_validstr(str) \
332 __sir_validstr(str, true, __func__, __file__, __LINE__)
333
335# define _sir_validstrnofail(str) \
336 __sir_validstr(str, false, __func__, __file__, __LINE__)
337
339static inline
340void _sir_resetstr(char* str) {
341 if (NULL != str)
342 *str = '\0';
343}
344
349static inline
350bool _sir_strsame(const char* lhs, const char* rhs, size_t count) {
351 return 0 == strncmp(lhs, rhs, count);
352}
353
358int _sir_strncpy(char* restrict dest, size_t destsz,
359 const char* restrict src, size_t count);
360
365int _sir_strncat(char* restrict dest, size_t destsz,
366 const char* restrict src, size_t count);
367
372int _sir_fopen(FILE* restrict* restrict streamptr, const char* restrict filename,
373 const char* restrict mode);
374
379static inline
380struct tm* _sir_localtime(const time_t* timer, struct tm* buf) {
381 if (!timer || !buf)
382 return NULL;
383# if defined(__HAVE_STDC_SECURE_OR_EXT1__) && !defined(__EMBARCADEROC__)
384# if !defined(__WIN__)
385 struct tm* ret = localtime_s(timer, buf);
386 if (!ret) {
387 (void)_sir_handleerr(errno);
388 return NULL;
389 }
390# else /* __WIN__ */
391 errno_t ret = localtime_s(buf, timer);
392 if (0 != ret) {
393 (void)_sir_handleerr(ret);
394 return NULL;
395 }
396# endif
397 return buf;
398# else /* !__HAVE_STDC_SECURE_OR_EXT1__ */
399# if !defined(__WIN__) || \
400 (defined(__EMBARCADEROC__) && (__clang_major__ < 15))
401 struct tm* ret = localtime_r(timer, buf);
402# else
403 struct tm* ret = localtime(timer);
404# endif
405 if (!ret)
406 (void)_sir_handleerr(errno);
407 return ret;
408# endif
409}
410
412# if defined(__GNUC__)
413__attribute__ ((format (strftime, 3, 0)))
414# endif
415static inline
416bool _sir_formattime(time_t now, char* buffer, const char* format) {
417 if (!buffer || !format)
418 return false;
419# if defined(__GNUC__) && !defined(__clang__) && \
420 !(defined(__OPEN64__) || defined(__OPENCC__) || defined(__PCC__))
421# pragma GCC diagnostic push
422# pragma GCC diagnostic ignored "-Wformat-nonliteral"
423# endif
424 struct tm timebuf;
425 const struct tm* ptb = _sir_localtime(&now, &timebuf);
426 return NULL != ptb && 0 != strftime(buffer, SIR_MAXTIME, format, ptb);
427# if defined(__GNUC__) && !defined(__clang__) && \
428 !(defined(__OPEN64__) || defined(__OPENCC__) || defined(__PCC__))
429# pragma GCC diagnostic pop
430# endif
431}
432
437bool _sir_getchar(char* input);
438
442# define _sir_snprintf_trunc(dst, size, ...) \
443 do { \
444 volatile size_t _n = size; \
445 if (!snprintf(dst, _n, __VA_ARGS__)) { (void)_n; }; \
446 } while (false)
447
451static inline
452uint32_t FNV32_1a(const uint8_t* data, size_t len) {
453 uint32_t hash = 2166136261U;
454 for (size_t n = 0; n < len; n++) {
455 hash ^= (uint32_t)data[n];
456 hash = (uint32_t)(hash * 16777619ULL);
457 }
458 return hash;
459}
460
465# if defined(__clang__) /* only Clang has unsigned-integer-overflow; GCC BZ#96829 */
466SANITIZE_SUPPRESS("unsigned-integer-overflow")
467# endif
468static inline
469uint64_t FNV64_1a(const char* str) {
470 uint64_t hash = 14695981039346656037ULL;
471 for (const char* c = str; *c; c++) {
472 hash ^= (uint64_t)(unsigned char)(*c);
473 hash *= 1099511628211ULL; /* unsigned-integer-overflow */
474 }
475 return hash;
476}
477
482void* _sir_explicit_memset(void *ptr, int c, size_t len);
483
487char* _sir_strremove(char *str, const char *sub);
488
494char* _sir_strsqueeze(char *str);
495
499char* _sir_strredact(char *str, const char *sub, const char c);
500
504char* _sir_strreplace(char *str, const char c, const char n);
505
510size_t _sir_strcreplace(char *str, const char c, const char n, int32_t max);
511
512# if defined(__cplusplus)
513}
514# endif
515
516#endif /* !_SIR_HELPERS_H_INCLUDED */
#define SIR_MAXTIME
The size, in characters, of the buffer used to hold time format strings.
Definition config.h:347
uint16_t sir_level
The sir_level type.
Definition types.h:71
uint32_t sirfileid
Log file identifier type.
Definition types.h:49
sir_textattr
Attributes for stdio output.
Definition types.h:107
sir_colormode
Color mode selection.
Definition types.h:99
#define SIRO_DEFAULT
Default options for this type of destination.
Definition types.h:90
#define SIRL_DEFAULT
Default levels for this type of destination.
Definition types.h:68
uint16_t sir_levels
sir_level bitmask type.
Definition types.h:74
uint32_t sir_textcolor
stdio text color type.
Definition types.h:141
uint32_t sirpluginid
Plugin module identifier type.
Definition types.h:52
uint32_t sir_options
sir_option bitmask type.
Definition types.h:96
@ SIRTC_DEFAULT
Represents the default color.
Definition types.h:137
Encapsulates dynamic updating of current configuration.
Definition types.h:478