]>
Commit | Line | Data |
---|---|---|
760877e9 LP |
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | #pragma once | |
3 | ||
4 | #include <stdlib.h> | |
5 | ||
6 | #include "macro.h" | |
7 | ||
8 | void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, | |
9 | __compar_d_fn_t compar, void *arg); | |
10 | ||
11 | #define typesafe_bsearch_r(k, b, n, func, userdata) \ | |
12 | ({ \ | |
13 | const typeof(b[0]) *_k = k; \ | |
14 | int (*_func_)(const typeof(b[0])*, const typeof(b[0])*, typeof(userdata)) = func; \ | |
15 | xbsearch_r((const void*) _k, (b), (n), sizeof((b)[0]), (__compar_d_fn_t) _func_, userdata); \ | |
16 | }) | |
17 | ||
18 | /** | |
19 | * Normal bsearch requires base to be nonnull. Here were require | |
20 | * that only if nmemb > 0. | |
21 | */ | |
22 | static inline void* bsearch_safe(const void *key, const void *base, | |
23 | size_t nmemb, size_t size, __compar_fn_t compar) { | |
24 | if (nmemb <= 0) | |
25 | return NULL; | |
26 | ||
27 | assert(base); | |
28 | return bsearch(key, base, nmemb, size, compar); | |
29 | } | |
30 | ||
31 | #define typesafe_bsearch(k, b, n, func) \ | |
32 | ({ \ | |
33 | const typeof(b[0]) *_k = k; \ | |
34 | int (*_func_)(const typeof(b[0])*, const typeof(b[0])*) = func; \ | |
35 | bsearch_safe((const void*) _k, (b), (n), sizeof((b)[0]), (__compar_fn_t) _func_); \ | |
36 | }) | |
37 | ||
38 | /** | |
39 | * Normal qsort requires base to be nonnull. Here were require | |
40 | * that only if nmemb > 0. | |
41 | */ | |
33bece16 | 42 | static inline void _qsort_safe(void *base, size_t nmemb, size_t size, __compar_fn_t compar) { |
760877e9 LP |
43 | if (nmemb <= 1) |
44 | return; | |
45 | ||
46 | assert(base); | |
47 | qsort(base, nmemb, size, compar); | |
48 | } | |
49 | ||
50 | /* A wrapper around the above, but that adds typesafety: the element size is automatically derived from the type and so | |
51 | * is the prototype for the comparison function */ | |
52 | #define typesafe_qsort(p, n, func) \ | |
53 | ({ \ | |
54 | int (*_func_)(const typeof(p[0])*, const typeof(p[0])*) = func; \ | |
33bece16 | 55 | _qsort_safe((p), (n), sizeof((p)[0]), (__compar_fn_t) _func_); \ |
760877e9 LP |
56 | }) |
57 | ||
58 | static inline void qsort_r_safe(void *base, size_t nmemb, size_t size, __compar_d_fn_t compar, void *userdata) { | |
59 | if (nmemb <= 1) | |
60 | return; | |
61 | ||
62 | assert(base); | |
63 | qsort_r(base, nmemb, size, compar, userdata); | |
64 | } | |
65 | ||
66 | #define typesafe_qsort_r(p, n, func, userdata) \ | |
67 | ({ \ | |
68 | int (*_func_)(const typeof(p[0])*, const typeof(p[0])*, typeof(userdata)) = func; \ | |
69 | qsort_r_safe((p), (n), sizeof((p)[0]), (__compar_d_fn_t) _func_, userdata); \ | |
70 | }) |