codegen: fixed crash on risc architectures because of missing i_size
[ajla.git] / str.c
blob13426b4b521dbdf5057596d206dc1afb82b8464b
1 /*
2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
9 * version.
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
19 #include "ajla.h"
21 #include "mem_al.h"
23 #include "str.h"
25 #ifndef DEBUG_TRACK_FILE_LINE
26 const char *position_string(void *ptr)
28 #if 1
29 static char buffer[sizeof(uintptr_t) * 2 + 1];
30 char *b = buffer;
31 str_add_unsigned(&b, NULL, ptr_to_num(ptr), 16);
32 return buffer;
33 #else
34 return str_from_unsigned(ptr_to_num(ptr), 16);
35 #endif
37 const char *position_string_alloc(void *ptr)
39 return str_from_unsigned(ptr_to_num(ptr), 16);
41 #endif
43 static size_t next_power_of_2(size_t len)
45 #if defined(HAVE_BUILTIN_CLZ)
46 if (is_power_of_2(sizeof(size_t)) && sizeof(size_t) == sizeof(unsigned long)) {
47 if (!len)
48 return 1;
49 return (size_t)2 << ((unsigned)(sizeof(size_t) * 8 - 1) CLZ_BSR_OP __builtin_clzl(len));
51 #endif
52 len |= len >> 1;
53 len |= len >> 2;
54 len |= len >> 4;
55 len |= len >> 8;
56 len |= len >> 15 >> 1;
57 len |= len >> 15 >> 15 >> 2;
58 len++;
59 return len;
62 void * attr_fastcall array_realloc_mayfail(void *p, size_t element_size, size_t old_length, size_t new_length, void **err_ptr, ajla_error_t *mayfail)
64 void *pp;
65 if (unlikely(new_length <= old_length)) {
66 if (unlikely(new_length == old_length))
67 return p;
68 array_overflow:
69 fatal_mayfail(error_ajla(EC_ASYNC, AJLA_ERROR_SIZE_OVERFLOW), mayfail, "array allocation size overflow");
70 mem_free(p);
71 return NULL;
73 new_length--;
74 #ifdef HAVE_BUILTIN_ADD_SUB_OVERFLOW
75 if (unlikely(__builtin_sub_overflow(old_length, 1, &old_length)))
76 goto do_realloc;
77 #else
78 if (unlikely(!old_length))
79 goto do_realloc;
80 old_length--;
81 #endif
82 if (unlikely((old_length ^ new_length) >= old_length)) {
83 size_t total_size;
84 do_realloc:
85 new_length = next_power_of_2(new_length);
86 if (unlikely(!new_length))
87 goto array_overflow;
88 #ifdef HAVE_BUILTIN_MUL_OVERFLOW
89 if (unlikely(__builtin_mul_overflow(new_length, element_size, &total_size)))
90 goto array_overflow;
91 #else
92 total_size = new_length * element_size;
93 if (unlikely(total_size / new_length != element_size))
94 goto array_overflow;
95 #endif
96 pp = mem_realloc_mayfail(void *, p, total_size, mayfail);
97 if (unlikely(!pp)) {
98 if (err_ptr)
99 *err_ptr = p;
100 else
101 mem_free(p);
103 p = pp;
105 return p;
108 void * attr_fastcall array_finish_realloc(void *p, size_t length)
110 void *n;
111 ajla_error_t sink;
112 if (unlikely(!(n = mem_realloc_mayfail(void *, p, length, &sink))))
113 return p;
114 return n;
118 void attr_fastcall str_add_bytes(char **s, size_t *l, const char *a, size_t ll)
120 array_add_multiple(char, s, l, a, ll);
123 void attr_fastcall str_add_string(char **s, size_t *l, const char *a)
125 str_add_bytes(s, l, a, strlen(a));
128 void attr_fastcall str_add_char(char **s, size_t *l, char c)
130 array_add(char, s, l, c);
133 void attr_fastcall str_add_unsigned(char **s, size_t *l, uintbig_t i, int base)
135 uintbig_t n = 1;
136 uintbig_t limit = i / base;
137 while (n <= limit)
138 n *= base;
139 do {
140 char p = (char)(i / n);
141 i %= n;
142 p += '0' + (((p < 10) - 1) & ('a' - '9' - 1));
143 if (likely(l != NULL)) /* see position_string */
144 str_add_char(s, l, p);
145 else
146 *(*s)++ = p;
147 n /= base;
148 } while (n);
149 if (unlikely(!l))
150 **s = 0;
153 void attr_fastcall str_add_signed(char **s, size_t *l, intbig_t i, int base)
155 #if defined(__IBMC__)
156 /* compiler bug - causes internal error */
157 volatile
158 #endif
159 uintbig_t ui = (uintbig_t)i;
160 /*debug("number: %llx %llx", (unsigned long long)(ui >> 64), (unsigned long long)ui);*/
161 if (unlikely(i < 0)) {
162 str_add_char(s, l, '-');
163 ui = -ui;
165 str_add_unsigned(s, l, ui, base);
168 void attr_fastcall str_add_hex(char **s, size_t *l, const char *hex)
170 while (*hex) {
171 char c = 0;
172 if (hex[0] >= '0' && hex[0] <= '9')
173 c += (hex[0] - '0') << 4;
174 else if (hex[0] >= 'a' && hex[0] <= 'f')
175 c += (hex[0] - 'a' + 10) << 4;
176 else
177 internal(file_line, "str_add_hex: invalid string: %s", hex);
178 hex++;
179 if (hex[0] >= '0' && hex[0] <= '9')
180 c += hex[0] - '0';
181 else if (hex[0] >= 'a' && hex[0] <= 'f')
182 c += hex[0] - 'a' + 10;
183 else
184 internal(file_line, "str_add_hex: invalid string: %s", hex);
185 hex++;
186 str_add_char(s, l, c);
190 char *str_dup(const char *str, size_t max_len, ajla_error_t *err)
192 size_t l;
193 char *c;
194 l = strnlen(str, max_len);
195 c = mem_alloc_mayfail(char *, l + 1, err);
196 if (unlikely(!c))
197 return NULL;
198 c[l] = 0;
199 return memcpy(c, str, l);