keys.h (4578B)
1 /* 2 * Copyright (c) 2023-2024 lumidify <nobody@lumidify.org> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #ifndef LTK_KEYS_H 18 #define LTK_KEYS_H 19 20 #include <stddef.h> 21 22 #include "util.h" 23 24 /* FIXME: replace with proper string type */ 25 struct ltk_search_cmp_helper { 26 const char *text; 27 size_t len; 28 }; 29 30 /* FIXME: documentation */ 31 #define GEN_CB_MAP_HELPERS(name, typename, cmp_entry) \ 32 \ 33 static int name##_sorted = 0; \ 34 \ 35 /* \ 36 * IMPORTANT: The text passed to *_get_entry may not be nul-terminated, \ 37 * so ltk_search_cmp_helper has to be used for the bsearch comparison \ 38 * helper. \ 39 */ \ 40 \ 41 static int \ 42 name##_search_helper(const void *keyv, const void *entryv) { \ 43 struct ltk_search_cmp_helper *key = (struct ltk_search_cmp_helper *)keyv; \ 44 typename *entry = (typename *)entryv; \ 45 int ret = strncmp(key->text, entry->cmp_entry, key->len); \ 46 if (ret == 0) { \ 47 if (entry->cmp_entry[key->len] == '\0') \ 48 return 0; \ 49 else \ 50 return -1; \ 51 } \ 52 return ret; \ 53 } \ 54 \ 55 static int \ 56 name##_sort_helper(const void *entry1v, const void *entry2v) { \ 57 typename *entry1 = (typename *)entry1v; \ 58 typename *entry2 = (typename *)entry2v; \ 59 return strcmp(entry1->cmp_entry, entry2->cmp_entry); \ 60 } \ 61 \ 62 static typename * \ 63 name##_get_entry(const char *text, size_t len) { \ 64 /* just in case */ \ 65 if (!name##_sorted) { \ 66 qsort( \ 67 name, LENGTH(name), \ 68 sizeof(name[0]), &name##_sort_helper); \ 69 name##_sorted = 1; \ 70 } \ 71 struct ltk_search_cmp_helper tmp = {.len = len, .text = text}; \ 72 return bsearch( \ 73 &tmp, name, LENGTH(name), \ 74 sizeof(name[0]), &name##_search_helper \ 75 ); \ 76 } 77 78 #endif /* LTK_KEYS_H */