util.h (5843B)
1 /* This program is licensed under the terms of GNU GPL v3 or (at your option) 2 * any later version. Copyright (C) 2022-2026 Страхиња Радић. 3 * See the file LICENSE for exact copyright and license details. */ 4 5 #include <stdint.h> 6 #include <sys/types.h> 7 #include <unistd.h> 8 9 /* clang-format off */ 10 #define CLEAR(v, c) do { (v) &= ~(c); } while(0) 11 #define IN(v, c) (((v) & (c)) == (c)) 12 #define LEN(x) (sizeof(x) / sizeof(x[0])) 13 #define MAX(a, b) ((a > b) ? (a) : (b)) 14 #define MIN(a, b) ((a < b) ? (a) : (b)) 15 #define SET(v, c) do { (v) |= (c); } while(0) 16 #define TOGGLE(v, c) do { (v) ^= (c); } while(0) 17 #define UNUSED(x) ((void)(x)) 18 /* clang-format on */ 19 20 #define U32_REPL_CHAR ((uint32_t)0xFFFD) 21 22 #define MEMCCPY(to, from, tolen, temp) \ 23 do \ 24 { \ 25 temp = memccpy(to, from, 0, tolen); \ 26 if (!temp) \ 27 to[tolen > 0 ? tolen - 1 : 0] = 0; \ 28 } while (0) 29 #define MEMCCPY_EXT(to, fallbackto, from, tolen, temp) \ 30 do \ 31 { \ 32 temp = memccpy(to, from, 0, tolen); \ 33 if (!temp) \ 34 fallbackto[tolen > 0 ? tolen - 1 : 0] = 0; \ 35 } while (0) 36 #define U32_MEMCCPY(to, from, tolen, temp) \ 37 do \ 38 { \ 39 temp = u32_memccpy(to, from, 0L, tolen); \ 40 if (!temp) \ 41 to[tolen > 0 ? tolen - 1 : 0] = 0; \ 42 } while (0) 43 #define U32_U8_MEMCCPY(to, from, tolen, temp) \ 44 do \ 45 { \ 46 temp = u32_u8_memccpy(to, from, 0L, tolen); \ 47 if (!temp) \ 48 to[tolen > 0 ? tolen - 1 : 0] = 0; \ 49 } while (0) 50 #define U32_MEMCCPY_EXT(to, fallbackto, from, tolen, fbtolen, temp) \ 51 do \ 52 { \ 53 temp = u32_memccpy(to, from, 0L, tolen); \ 54 if (!temp) \ 55 fallbackto[fbtolen > 0 ? fbtolen - 1 : 0] = 0; \ 56 } while (0) 57 58 #define ENSURE_SIZE(to, temp, tosize, testsize, fromsize, label, type) \ 59 do \ 60 { \ 61 if (!(to) || (tosize) < (testsize)) \ 62 { \ 63 temp = realloc(to, (fromsize) * sizeof(type)); \ 64 if (!temp) \ 65 { \ 66 state->running = 0; \ 67 goto label; \ 68 } \ 69 tosize = fromsize; \ 70 to = temp; \ 71 } \ 72 } while (0) 73 /* 74 * - Make sure the size of the destination string is large enough to copy, and 75 * copy 76 * - Sizes are in bytes 77 * - We explicitly use fromsize in MEMCCPY, because we ensured that tosize is 78 * at least as big, and to allow a subset of from to be copied 79 */ 80 #define U8_SAFE_COPY(to, temp, tosize, from, fromsize, label) \ 81 do \ 82 { \ 83 ENSURE_SIZE(to, temp, tosize, fromsize, fromsize, label, char); \ 84 MEMCCPY(to, from, fromsize, temp); \ 85 } while (0) 86 /* 87 * - Make sure the size of the destination string is large enough to copy, and 88 * copy 89 * - Sizes are in uint32_t units 90 * - We explicitly use fromsize in U32_MEMCCPY, because we ensured that tosize 91 * is at least as big, and to allow a subset of from to be copied 92 */ 93 #define U32_SAFE_COPY(to, temp, tosize, from, fromsize, label) \ 94 do \ 95 { \ 96 ENSURE_SIZE(to, temp, tosize, fromsize, fromsize, label, \ 97 uint32_t); \ 98 U32_MEMCCPY(to, from, fromsize, temp); \ 99 } while (0) 100 101 #define CUSTOM_ERROR_START 200 102 103 enum { 104 ERR_NONE, 105 ERR_NO_CL_ARG, 106 ERR_BINARY, 107 ERR_NOTREG_FILE, 108 ERR_TB_ERROR, 109 ERR_UNKNOWN_KEY, 110 ERR_EXIT_KEY, 111 ERR_DLG_OPEN, 112 ERR_DLG_OPEN_QUIT, 113 ERR_INPUT_NONNUM, 114 ERR_INVALID_NUM, 115 ERR_NOT_IMP, 116 ERR_ERRNO_SET 117 }; 118 119 enum { ACT_IDLE, ACT_WRITING, ACT_READING, ACT_WRAPPING }; 120 121 size_t u8_string_to_unicode(uint32_t* us, const char* s, const ssize_t max); 122 size_t unicode_string_to_u8(char* s, const uint32_t* us, const ssize_t max); 123 int u32_has_nonblanks(const uint32_t* s); 124 uint32_t* u32_memccpy(uint32_t* dst, const uint32_t* src, uint32_t c, 125 size_t len); 126 uint32_t* u32_u8_memccpy(uint32_t* dst, const char* src, uint32_t c, size_t len); 127 size_t u8_strlen(const char* s); 128 size_t u32_strlen(const uint32_t* s); 129 const uint32_t* u32_strstr(const uint32_t* haystack, const uint32_t* needle); 130 const uint32_t* u32_strrstr(const uint32_t* haystack, const uint32_t* needle, 131 const uint32_t* haystack_tail); 132 const uint32_t* u32_strchr(const uint32_t* haystack, const uint32_t needle); 133 int is_word_boundary(const char ch, const int strictly_whitespace); 134 int u32_is_word_boundary(const uint32_t ch, const int strictly_whitespace); 135 int starts_with(const char* s, const char* with); 136 int u32_starts_with(const uint32_t* s, const uint32_t* with); 137 const char* u8_basename(const char* path);