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
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/>.
25 #ifndef DEBUG_TRACK_FILE_LINE
26 const char *position_string(void *ptr
)
29 static char buffer
[sizeof(uintptr_t) * 2 + 1];
31 str_add_unsigned(&b
, NULL
, ptr_to_num(ptr
), 16);
34 return str_from_unsigned(ptr_to_num(ptr
), 16);
37 const char *position_string_alloc(void *ptr
)
39 return str_from_unsigned(ptr_to_num(ptr
), 16);
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)) {
49 return (size_t)2 << ((unsigned)(sizeof(size_t) * 8 - 1) CLZ_BSR_OP
__builtin_clzl(len
));
56 len
|= len
>> 15 >> 1;
57 len
|= len
>> 15 >> 15 >> 2;
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
)
65 if (unlikely(new_length
<= old_length
)) {
66 if (unlikely(new_length
== old_length
))
69 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), mayfail
, "array allocation size overflow");
74 #ifdef HAVE_BUILTIN_ADD_SUB_OVERFLOW
75 if (unlikely(__builtin_sub_overflow(old_length
, 1, &old_length
)))
78 if (unlikely(!old_length
))
82 if (unlikely((old_length
^ new_length
) >= old_length
)) {
85 new_length
= next_power_of_2(new_length
);
86 if (unlikely(!new_length
))
88 #ifdef HAVE_BUILTIN_MUL_OVERFLOW
89 if (unlikely(__builtin_mul_overflow(new_length
, element_size
, &total_size
)))
92 total_size
= new_length
* element_size
;
93 if (unlikely(total_size
/ new_length
!= element_size
))
96 pp
= mem_realloc_mayfail(void *, p
, total_size
, mayfail
);
108 void * attr_fastcall
array_finish_realloc(void *p
, size_t length
)
112 if (unlikely(!(n
= mem_realloc_mayfail(void *, p
, length
, &sink
))))
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
)
136 uintbig_t limit
= i
/ base
;
140 char p
= (char)(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
);
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 */
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
, '-');
165 str_add_unsigned(s
, l
, ui
, base
);
168 void attr_fastcall
str_add_hex(char **s
, size_t *l
, const char *hex
)
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;
177 internal(file_line
, "str_add_hex: invalid string: %s", hex
);
179 if (hex
[0] >= '0' && hex
[0] <= '9')
181 else if (hex
[0] >= 'a' && hex
[0] <= 'f')
182 c
+= hex
[0] - 'a' + 10;
184 internal(file_line
, "str_add_hex: invalid string: %s", hex
);
186 str_add_char(s
, l
, c
);
190 char *str_dup(const char *str
, size_t max_len
, ajla_error_t
*err
)
194 l
= strnlen(str
, max_len
);
195 c
= mem_alloc_mayfail(char *, l
+ 1, err
);
199 return memcpy(c
, str
, l
);