Ben Cheng | 21eab51 | 2012-03-13 23:04:57 -0700 | [diff] [blame] | 1 | /*- |
| 2 | * Written by J.T. Conklin <jtc@netbsd.org> |
| 3 | * Public domain. |
| 4 | * |
| 5 | * $NetBSD: search.h,v 1.12 1999/02/22 10:34:28 christos Exp $ |
| 6 | * $FreeBSD: release/9.0.0/include/search.h 105250 2002-10-16 14:29:23Z robert $ |
| 7 | */ |
| 8 | |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 9 | #pragma once |
| 10 | |
| 11 | /** |
| 12 | * @file search.h |
| 13 | * @brief Queues, hash tables, trees, and linear array searches. |
| 14 | */ |
Ben Cheng | 21eab51 | 2012-03-13 23:04:57 -0700 | [diff] [blame] | 15 | |
| 16 | #include <sys/cdefs.h> |
Elliott Hughes | 7f3a272 | 2014-04-01 12:40:00 -0700 | [diff] [blame] | 17 | #include <sys/types.h> |
Ben Cheng | 21eab51 | 2012-03-13 23:04:57 -0700 | [diff] [blame] | 18 | |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 19 | /** See hsearch()/hsearch_r(). */ |
Elliott Hughes | 7f3a272 | 2014-04-01 12:40:00 -0700 | [diff] [blame] | 20 | typedef enum { |
Elliott Hughes | 5702c6f | 2017-08-31 17:27:05 -0700 | [diff] [blame] | 21 | FIND, |
| 22 | ENTER |
| 23 | } ACTION; |
| 24 | |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 25 | /** See hsearch()/hsearch_r(). */ |
Elliott Hughes | 5702c6f | 2017-08-31 17:27:05 -0700 | [diff] [blame] | 26 | typedef struct entry { |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 27 | /** The string key. */ |
zijunzhao | fdf9e2e | 2023-04-05 19:40:21 +0000 | [diff] [blame] | 28 | char* _Nullable key; |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 29 | /** The associated data. */ |
zijunzhao | fdf9e2e | 2023-04-05 19:40:21 +0000 | [diff] [blame] | 30 | void* _Nullable data; |
Elliott Hughes | 5702c6f | 2017-08-31 17:27:05 -0700 | [diff] [blame] | 31 | } ENTRY; |
| 32 | |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 33 | /** |
| 34 | * Constants given to the twalk() visitor. |
| 35 | * Note that the constant names are misleading. |
| 36 | */ |
Elliott Hughes | 5702c6f | 2017-08-31 17:27:05 -0700 | [diff] [blame] | 37 | typedef enum { |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 38 | /** |
| 39 | * If this is the first visit to a non-leaf node. |
| 40 | * Use this for *preorder* traversal. |
| 41 | */ |
Elliott Hughes | 7f3a272 | 2014-04-01 12:40:00 -0700 | [diff] [blame] | 42 | preorder, |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 43 | /** |
| 44 | * If this is the second visit to a non-leaf node. |
| 45 | * Use this for *inorder* traversal. |
| 46 | */ |
Elliott Hughes | 7f3a272 | 2014-04-01 12:40:00 -0700 | [diff] [blame] | 47 | postorder, |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 48 | /** |
| 49 | * If this is the third visit to a non-leaf node. |
| 50 | * Use this for *postorder* traversal. |
| 51 | */ |
Elliott Hughes | 7f3a272 | 2014-04-01 12:40:00 -0700 | [diff] [blame] | 52 | endorder, |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 53 | /** If this is the first and only visit to a leaf node. */ |
Elliott Hughes | 7f3a272 | 2014-04-01 12:40:00 -0700 | [diff] [blame] | 54 | leaf |
Ben Cheng | 21eab51 | 2012-03-13 23:04:57 -0700 | [diff] [blame] | 55 | } VISIT; |
| 56 | |
Elliott Hughes | 5702c6f | 2017-08-31 17:27:05 -0700 | [diff] [blame] | 57 | #if defined(__USE_BSD) || defined(__USE_GNU) |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 58 | /** The hash table type for hcreate_r()/hdestroy_r()/hsearch_r(). */ |
Elliott Hughes | 5702c6f | 2017-08-31 17:27:05 -0700 | [diff] [blame] | 59 | struct hsearch_data { |
zijunzhao | fdf9e2e | 2023-04-05 19:40:21 +0000 | [diff] [blame] | 60 | struct __hsearch* _Nullable __hsearch; |
Elliott Hughes | 5702c6f | 2017-08-31 17:27:05 -0700 | [diff] [blame] | 61 | }; |
Ben Cheng | 21eab51 | 2012-03-13 23:04:57 -0700 | [diff] [blame] | 62 | #endif |
| 63 | |
| 64 | __BEGIN_DECLS |
Elliott Hughes | 7f3a272 | 2014-04-01 12:40:00 -0700 | [diff] [blame] | 65 | |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 66 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 67 | * [insque(3)](https://man7.org/linux/man-pages/man3/insque.3.html) inserts |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 68 | * an item in a queue (an intrusive doubly-linked list). |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 69 | */ |
Elliott Hughes | 655e430 | 2023-06-16 12:39:33 -0700 | [diff] [blame] | 70 | void insque(void* _Nonnull __element, void* _Nullable __previous); |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 71 | |
| 72 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 73 | * [remque(3)](https://man7.org/linux/man-pages/man3/remque.3.html) removes |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 74 | * an item from a queue (an intrusive doubly-linked list). |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 75 | */ |
Elliott Hughes | 655e430 | 2023-06-16 12:39:33 -0700 | [diff] [blame] | 76 | void remque(void* _Nonnull __element); |
Elliott Hughes | b902641 | 2014-07-23 16:02:26 -0700 | [diff] [blame] | 77 | |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 78 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 79 | * [hcreate(3)](https://man7.org/linux/man-pages/man3/hcreate.3.html) |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 80 | * initializes the global hash table, with space for at least `__n` elements. |
| 81 | * |
| 82 | * See hcreate_r() if you need more than one hash table. |
| 83 | * |
| 84 | * Returns *non-zero* on success and returns 0 and sets `errno` on failure. |
| 85 | * |
| 86 | * Available since API level 28. |
| 87 | */ |
Dan Albert | 02ce401 | 2024-10-25 19:13:49 +0000 | [diff] [blame] | 88 | |
| 89 | #if __BIONIC_AVAILABILITY_GUARD(28) |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 90 | int hcreate(size_t __n) __INTRODUCED_IN(28); |
| 91 | |
| 92 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 93 | * [hdestroy(3)](https://man7.org/linux/man-pages/man3/hdestroy.3.html) destroys |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 94 | * the global hash table. |
| 95 | * |
| 96 | * See hdestroy_r() if you need more than one hash table. |
| 97 | * |
| 98 | * Available since API level 28. |
| 99 | */ |
Elliott Hughes | cc0fe6e | 2018-01-30 08:54:12 -0800 | [diff] [blame] | 100 | void hdestroy(void) __INTRODUCED_IN(28); |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 101 | |
| 102 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 103 | * [hsearch(3)](https://man7.org/linux/man-pages/man3/hsearch.3.html) finds or |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 104 | * inserts `__entry` in the global hash table, based on `__action`. |
| 105 | * |
| 106 | * See hsearch_r() if you need more than one hash table. |
| 107 | * |
| 108 | * Returns a pointer to the entry on success, and returns NULL and sets |
| 109 | * `errno` on failure. |
| 110 | * |
| 111 | * Available since API level 28. |
| 112 | */ |
zijunzhao | fdf9e2e | 2023-04-05 19:40:21 +0000 | [diff] [blame] | 113 | ENTRY* _Nullable hsearch(ENTRY __entry, ACTION __action) __INTRODUCED_IN(28); |
Dan Albert | 02ce401 | 2024-10-25 19:13:49 +0000 | [diff] [blame] | 114 | #endif /* __BIONIC_AVAILABILITY_GUARD(28) */ |
| 115 | |
Elliott Hughes | 5702c6f | 2017-08-31 17:27:05 -0700 | [diff] [blame] | 116 | |
| 117 | #if defined(__USE_BSD) || defined(__USE_GNU) |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 118 | |
| 119 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 120 | * [hcreate_r(3)](https://man7.org/linux/man-pages/man3/hcreate_r.3.html) |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 121 | * initializes a hash table `__table` with space for at least `__n` elements. |
| 122 | * |
| 123 | * Returns *non-zero* on success and returns 0 and sets `errno` on failure. |
| 124 | * |
| 125 | * Available since API level 28. |
| 126 | */ |
Dan Albert | 02ce401 | 2024-10-25 19:13:49 +0000 | [diff] [blame] | 127 | |
| 128 | #if __BIONIC_AVAILABILITY_GUARD(28) |
zijunzhao | fdf9e2e | 2023-04-05 19:40:21 +0000 | [diff] [blame] | 129 | int hcreate_r(size_t __n, struct hsearch_data* _Nonnull __table) __INTRODUCED_IN(28); |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 130 | |
| 131 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 132 | * [hdestroy_r(3)](https://man7.org/linux/man-pages/man3/hdestroy_r.3.html) destroys |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 133 | * the hash table `__table`. |
| 134 | * |
| 135 | * Available since API level 28. |
| 136 | */ |
zijunzhao | fdf9e2e | 2023-04-05 19:40:21 +0000 | [diff] [blame] | 137 | void hdestroy_r(struct hsearch_data* _Nonnull __table) __INTRODUCED_IN(28); |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 138 | |
| 139 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 140 | * [hsearch_r(3)](https://man7.org/linux/man-pages/man3/hsearch_r.3.html) finds or |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 141 | * inserts `__entry` in the hash table `__table`, based on `__action`. |
| 142 | * |
| 143 | * Returns *non-zero* on success and returns 0 and sets `errno` on failure. |
| 144 | * A pointer to the entry is returned in `*__result`. |
| 145 | * |
| 146 | * Available since API level 28. |
| 147 | */ |
zijunzhao | fdf9e2e | 2023-04-05 19:40:21 +0000 | [diff] [blame] | 148 | int hsearch_r(ENTRY __entry, ACTION __action, ENTRY* _Nullable * _Nonnull __result, struct hsearch_data* _Nonnull __table) __INTRODUCED_IN(28); |
Dan Albert | 02ce401 | 2024-10-25 19:13:49 +0000 | [diff] [blame] | 149 | #endif /* __BIONIC_AVAILABILITY_GUARD(28) */ |
| 150 | |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 151 | |
Elliott Hughes | 5702c6f | 2017-08-31 17:27:05 -0700 | [diff] [blame] | 152 | #endif |
| 153 | |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 154 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 155 | * [lfind(3)](https://man7.org/linux/man-pages/man3/lfind.3.html) brute-force |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 156 | * searches the unsorted array `__array` (of `__count` items each of size `__size`) |
| 157 | * for `__key`, using `__comparator`. |
| 158 | * |
| 159 | * See bsearch() if you have a sorted array. |
| 160 | * |
| 161 | * Returns a pointer to the matching element on success, or NULL on failure. |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 162 | */ |
Elliott Hughes | 655e430 | 2023-06-16 12:39:33 -0700 | [diff] [blame] | 163 | void* _Nullable lfind(const void* _Nonnull __key, const void* _Nonnull __array, size_t* _Nonnull __count, size_t __size, int (* _Nonnull __comparator)(const void* _Nonnull, const void* _Nonnull)); |
Elliott Hughes | 7f3a272 | 2014-04-01 12:40:00 -0700 | [diff] [blame] | 164 | |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 165 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 166 | * [lsearch(3)](https://man7.org/linux/man-pages/man3/lsearch.3.html) brute-force |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 167 | * searches the unsorted array `__array` (of `__count` items each of size `__size`) |
| 168 | * for `__key`, using `__comparator`. |
| 169 | * |
| 170 | * Unlike lfind(), on failure lsearch() will *insert* `__key` at the end of |
| 171 | * `__array` and increment `*__count`. |
| 172 | * |
| 173 | * Returns a pointer to the matching element on success, or to the newly-added |
| 174 | * element on failure. |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 175 | */ |
Elliott Hughes | 655e430 | 2023-06-16 12:39:33 -0700 | [diff] [blame] | 176 | void* _Nonnull lsearch(const void* _Nonnull __key, void* _Nonnull __array, size_t* _Nonnull __count, size_t __size, int (* _Nonnull __comparator)(const void* _Nonnull, const void* _Nonnull)); |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 177 | |
| 178 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 179 | * [tdelete(3)](https://man7.org/linux/man-pages/man3/tdelete.3.html) searches |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 180 | * for and removes an element in the tree `*__root_ptr`. The search is performed |
| 181 | * using `__comparator`. |
| 182 | * |
| 183 | * Returns a pointer to the parent of the deleted node, or NULL on failure. |
| 184 | */ |
zijunzhao | fdf9e2e | 2023-04-05 19:40:21 +0000 | [diff] [blame] | 185 | void* _Nullable tdelete(const void* _Nonnull __key, void* _Nullable * _Nullable __root_ptr, int (* _Nonnull __comparator)(const void* _Nonnull, const void* _Nonnull)); |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 186 | |
| 187 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 188 | * [tdestroy(3)](https://man7.org/linux/man-pages/man3/tdestroy.3.html) destroys |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 189 | * the hash table `__root` using `__free_fn` on each node. |
| 190 | */ |
zijunzhao | fdf9e2e | 2023-04-05 19:40:21 +0000 | [diff] [blame] | 191 | void tdestroy(void* _Nullable __root, void (* _Nullable __free_fn)(void* _Nullable)); |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 192 | |
| 193 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 194 | * [tfind(3)](https://man7.org/linux/man-pages/man3/tfind.3.html) searches |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 195 | * for an element in the tree `*__root_ptr`. The search is performed using |
| 196 | * `__comparator`. |
| 197 | * |
| 198 | * Returns a pointer to the matching node, or NULL on failure. |
| 199 | */ |
zijunzhao | fdf9e2e | 2023-04-05 19:40:21 +0000 | [diff] [blame] | 200 | void* _Nullable tfind(const void* _Nonnull __key, void* _Nullable const* _Nullable __root_ptr, int (* _Nonnull __comparator)(const void* _Nonnull, const void* _Nonnull)); |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 201 | |
| 202 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 203 | * [tsearch(3)](https://man7.org/linux/man-pages/man3/tsearch.3.html) searches |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 204 | * for an element in the tree `*__root_ptr`. The search is performed using |
| 205 | * `__comparator`. |
| 206 | * |
| 207 | * Unlike tfind(), on failure tsearch() will *insert* `__key` into the tree. |
| 208 | * |
| 209 | * Returns a pointer to the matching node, or to the newly-added node. |
| 210 | */ |
zijunzhao | fdf9e2e | 2023-04-05 19:40:21 +0000 | [diff] [blame] | 211 | void* _Nullable tsearch(const void* _Nonnull __key, void* _Nullable * _Nullable __root_ptr, int (* _Nonnull __comparator)(const void* _Nonnull, const void* _Nonnull)); |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 212 | |
| 213 | /** |
Elliott Hughes | bbd39aa | 2024-08-13 20:59:16 +0000 | [diff] [blame] | 214 | * [twalk(3)](https://man7.org/linux/man-pages/man3/twalk.3.html) calls |
Elliott Hughes | a468123 | 2019-11-04 13:59:12 -0800 | [diff] [blame] | 215 | * `__visitor` on every node in the tree. |
| 216 | */ |
Elliott Hughes | 655e430 | 2023-06-16 12:39:33 -0700 | [diff] [blame] | 217 | void twalk(const void* _Nullable __root, void (* _Nullable __visitor)(const void* _Nullable, VISIT, int)); |
Elliott Hughes | 7f3a272 | 2014-04-01 12:40:00 -0700 | [diff] [blame] | 218 | |
Ben Cheng | 21eab51 | 2012-03-13 23:04:57 -0700 | [diff] [blame] | 219 | __END_DECLS |