util.h (7566B)
1 /* This program is licensed under the terms of GNU GPL v3 or (at your option) 2 * any later version. Copyright (C) 2021-2026 Страхиња Радић. 3 * See the file LICENSE for exact copyright and license details. */ 4 5 #include <stdint.h> 6 #include <sys/types.h> 7 8 /* Whitespace definition for determining word boundaries */ 9 #define B_WS " \v\t-" 10 /* Full word boundary delimiter definition */ 11 #define B_FULL " \v\t-()[]{},.;:/\\" 12 13 /* 32-bit char constants */ 14 #define BSLASH ((uint32_t)0x0000005c) 15 #define DOT ((uint32_t)0x0000002e) 16 #define EN ((uint32_t)0x0000006e) 17 #define NINE ((uint32_t)0x00000039) 18 #define SPACE ((uint32_t)0x00000020) 19 #define SEMICOL ((uint32_t)0x0000003b) 20 #define TAB ((uint32_t)0x00000009) 21 #define ZERO ((uint32_t)0x00000030) 22 23 /* 32-bit string constants */ 24 extern const uint32_t bslash_en[]; 25 extern const uint32_t space_dot[]; 26 27 #define ABS(a) ((a < 0) ? (-a) : (a)) 28 #define LEN(x) (sizeof(x) / sizeof(x[0])) 29 #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 30 #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 31 #define MEMCCPY(to, from, tolen, temp) \ 32 do \ 33 { \ 34 temp = memccpy((to), (from), 0, (tolen)); \ 35 if (!(temp)) \ 36 (to)[(tolen) > 0 ? (tolen) - 1 : 0] = 0; \ 37 } while (0) 38 #define MEMCCPY_EXT(to, fallbackto, from, tolen, temp) \ 39 do \ 40 { \ 41 temp = memccpy((to), (from), 0, (tolen)); \ 42 if (!(temp)) \ 43 (fallbackto)[(tolen) > 0 ? (tolen) - 1 : 0] = 0; \ 44 } while (0) 45 #define U32_MEMCCPY(to, from, tolen, temp) \ 46 do \ 47 { \ 48 (temp) = u32_memccpy((to), (from), 0L, (tolen)); \ 49 if (!(temp)) \ 50 (to)[(tolen) > 0 ? (tolen) - 1 : 0] = 0; \ 51 } while (0) 52 #define U32_U8_MEMCCPY(to, from, tolen, temp) \ 53 do \ 54 { \ 55 (temp) = u32_u8_memccpy((to), (from), 0L, (tolen)); \ 56 if (!(temp)) \ 57 (to)[(tolen) > 0 ? (tolen) - 1 : 0] = 0; \ 58 } while (0) 59 #define U32_MEMCCPY_EXT(to, fallbackto, from, tolen, fbtolen, temp) \ 60 do \ 61 { \ 62 temp = u32_memccpy((to), (from), 0L, (tolen)); \ 63 if (!temp) \ 64 (fallbackto)[(fbtolen) > 0 ? (fbtolen) - 1 : 0] = 0; \ 65 } while (0) 66 67 #define ENSURE_SIZE(to, temp, tosize, testsize, fromsize, label, type) \ 68 do \ 69 { \ 70 if (!(to) || (tosize) < (testsize)) \ 71 { \ 72 temp = realloc((to), (fromsize) * sizeof(type)); \ 73 if (!temp) \ 74 { \ 75 state->running = 0; \ 76 goto label; \ 77 } \ 78 tosize = (fromsize); \ 79 to = temp; \ 80 } \ 81 } while (0) 82 /* 83 * - Make sure the size of the destination string is large enough to copy, and 84 * copy 85 * - Sizes are in bytes 86 * - We explicitly use fromsize in MEMCCPY, because we ensured that tosize is 87 * at least as big, and to allow a subset of from to be copied 88 */ 89 #define U8_SAFE_COPY(to, temp, tosize, from, fromsize, label) \ 90 do \ 91 { \ 92 ENSURE_SIZE(to, temp, tosize, fromsize, fromsize, label, char); \ 93 MEMCCPY(to, from, fromsize, temp); \ 94 } while (0) 95 /* 96 * - Make sure the size of the destination string is large enough to copy, and 97 * copy 98 * - Sizes are in uint32_t units 99 * - We explicitly use fromsize in U32_MEMCCPY, because we ensured that tosize 100 * is at least as big, and to allow a subset of from to be copied 101 */ 102 #define U32_SAFE_COPY(to, temp, tosize, from, fromsize, label) \ 103 do \ 104 { \ 105 ENSURE_SIZE(to, temp, tosize, fromsize, fromsize, label, \ 106 uint32_t); \ 107 U32_MEMCCPY(to, from, fromsize, temp); \ 108 } while (0) 109 #define UNUSED(x) ((void)(x)) 110 111 #define CUSTOM_ERROR_START 200 112 113 enum { 114 ERR_NONE, 115 ERR_NO_CL_ARG, 116 ERR_NO_CL_ARG_PARAM, 117 ERR_BAD_CL_ARG, 118 ERR_NOTPO_FILE, 119 ERR_NOTREG_FILE, 120 ERR_TB_ERROR, 121 ERR_UNKNOWN_KEY, 122 ERR_UNKNOWN_KEY_HELP, 123 ERR_EXIT_KEY, 124 ERR_DLG_OPEN, 125 ERR_DLG_OPEN_QUIT, 126 ERR_DLG_FOCUS_EDIT, 127 ERR_CANT_ALLOC, 128 ERR_ILLEGAL_ON_FIRST, 129 ERR_SYNTAX, 130 ERR_NO_PLURAL_FORMS, 131 ERR_BAD_NPLURALS, 132 ERR_ERRNO_SET 133 }; 134 135 enum { ACT_IDLE, ACT_WRITING, ACT_READING }; 136 137 // #define MAXBUFLINE 4096 138 #define MAXCOPYBUF 8192 139 #define MAXDATEBUF 80 140 #define MAXFLAGSBUF (2 + 4 + 2 + 1) 141 #define MAXMSGLINE 1024 142 #define MSGDELTA 1024 143 #define MAXPATH 1024 144 /* maximum chars for UTF-8 representations of Unicode chars, per Unicode char */ 145 #define UTF8REPMAX 6 146 147 size_t u8_string_to_unicode(uint32_t* us, const char* s, const size_t max); 148 size_t unicode_string_to_u8(char* s, const uint32_t* us, const size_t max); 149 ssize_t u32_match_msgid_ending(struct DrawState* state, const uint32_t* msgid, 150 uint32_t* msgstr, size_t max); 151 uint32_t* u32_memccpy(uint32_t* dst, const uint32_t* src, uint32_t c, 152 size_t len); 153 uint32_t* u32_u8_memccpy(uint32_t* dst, const char* src, uint32_t c, size_t len); 154 size_t u32_count_chars(const uint32_t* s, const uint32_t ch); 155 size_t u32_count_strings(const uint32_t* haystack, const uint32_t* needle); 156 ssize_t u32_encode_tabs(struct DrawState* state, uint32_t* s, size_t max); 157 ssize_t u32_decode_tabs(struct DrawState* state, uint32_t* s, size_t max); 158 size_t u8_strlen(const char* s); 159 size_t u32_strlen(const uint32_t* s); 160 const uint32_t* u32_strstr(const uint32_t* haystack, const uint32_t* needle); 161 const uint32_t* u32_strchr(const uint32_t* haystack, const uint32_t needle); 162 size_t u32_strncpy(uint32_t* to, const uint32_t* from, size_t max); 163 size_t u32_strncat(uint32_t* to, const uint32_t* from, size_t max); 164 size_t u32_u8_strncpy(uint32_t* to, const char* from, size_t max); 165 ssize_t u8_u32_strncpy(char* to, const uint32_t* from, size_t max); 166 size_t u32_lines_in_string(const uint32_t* s, const int include_eol, 167 const size_t wrap); 168 size_t u32_next_line(const uint32_t* s, const uint32_t** sptr, 169 const int include_eol, const size_t wrap); 170 int is_word_boundary(const char ch, const int strictly_whitespace); 171 int u32_is_word_boundary(const uint32_t ch, const int strictly_whitespace); 172 int starts_with(const char* s, const char* with); 173 int u32_starts_with(const uint32_t* s, const uint32_t* with); 174 const char* u8_basename(const char* path); 175 /*void poe_log(const char* msg, ...);*/