diff options
| -rw-r--r-- | include/al/array_sort.h | 31 | ||||
| -rw-r--r-- | include/al/array_typed.h | 4 | ||||
| -rw-r--r-- | include/al/lib.h | 75 | ||||
| -rw-r--r-- | include/al/list.h | 4 | ||||
| -rw-r--r-- | include/al/log.h | 4 | ||||
| -rw-r--r-- | include/al/macros.h | 49 | ||||
| -rw-r--r-- | include/al/random.h | 10 | ||||
| -rw-r--r-- | include/al/str.h | 21 | ||||
| -rw-r--r-- | include/al/test.h | 44 | ||||
| -rw-r--r-- | include/al/wstr.h | 19 | ||||
| -rw-r--r-- | meson.build | 3 | ||||
| -rw-r--r-- | src/array.c | 182 | ||||
| -rw-r--r-- | src/lib.c | 56 | ||||
| -rw-r--r-- | src/ring_buffer.c | 40 | ||||
| -rw-r--r-- | tests/array.c | 10 | ||||
| -rw-r--r-- | tests/array_typed.c | 4 | ||||
| -rw-r--r-- | tests/lib.c | 16 | ||||
| -rw-r--r-- | tests/str.c | 4 |
18 files changed, 240 insertions, 336 deletions
diff --git a/include/al/array_sort.h b/include/al/array_sort.h index f10766f..a4c881e 100644 --- a/include/al/array_sort.h +++ b/include/al/array_sort.h @@ -17,22 +17,21 @@ while i < length(A) end while */ -#define AL_INSERSION_SORT(data, type, count, cmp) \ -AL_MACRO_WRAP \ -{ \ - u32 i = 1, k; \ - type x; \ - while (i < count) { \ - k = i; \ - x = (data)[i]; \ - while (k > 0 && cmp(&(data)[k - 1], &x) > 0) { \ - (data)[k] = (data)[k - 1]; \ - k--; \ - } \ - (data)[k] = x; \ - i++; \ - } \ -} AL_MACRO_END +#define AL_INSERSION_SORT(data, type, count, cmp) \ + do { \ + u32 i = 1, k; \ + type x; \ + while (i < count) { \ + k = i; \ + x = (data)[i]; \ + while (k > 0 && cmp(&(data)[k - 1], &x) > 0) { \ + (data)[k] = (data)[k - 1]; \ + k--; \ + } \ + (data)[k] = x; \ + i++; \ + } \ + } while (0) #ifdef AL_USE_STDLIB #define AL_STDLIB_QSORT(data, type, count, cmp) qsort(data, (size_t)count, sizeof(type), cmp) diff --git a/include/al/array_typed.h b/include/al/array_typed.h index e7a4f80..2092160 100644 --- a/include/al/array_typed.h +++ b/include/al/array_typed.h @@ -47,7 +47,7 @@ { \ return al_array_at(N, __VA_ARGS__)(array, array->count - 1); \ } \ - static void al_array_reserve(N, __VA_ARGS__)(array(N, __VA_ARGS__) *array, u32 count); \ + static inline void al_array_reserve(N, __VA_ARGS__)(array(N, __VA_ARGS__) *array, u32 count); \ static inline void al_array_push(N, __VA_ARGS__)(array(N, __VA_ARGS__) *array, T value) \ { \ al_array_reserve(N, __VA_ARGS__)(array, array->count + 1); \ @@ -84,7 +84,7 @@ } \ static inline void _al_array_reserve_internal(N, __VA_ARGS__)(array(N, __VA_ARGS__) *array, u32 size) \ { \ - array->alloc = al_default_growing_allocation((void **)&array->data, array->alloc, size, al_malloc, al_realloc); \ + array->alloc = al_growing_allocation((void **)&array->data, array->alloc, size, al_malloc, al_realloc); \ } \ static inline void al_array_free(N, __VA_ARGS__)(array(N, __VA_ARGS__) *array) \ { \ diff --git a/include/al/lib.h b/include/al/lib.h index ac47896..cb5101a 100644 --- a/include/al/lib.h +++ b/include/al/lib.h @@ -7,26 +7,33 @@ // Piggyback off c89atomic for pointer size macros. #include <c89atomic.h> +#if defined C89ATOMIC_64BIT +#define AL_WE_64BIT +#elif defined C89ATOMIC_32BIT +#define AL_WE_32BIT +#endif + +// https://forum.vcfed.org/index.php?threads/c-item-size-check-at-compile-time.1244920/ +#define AL_ASSERT_TYPE_SIZE(type, size) \ + typedef char type##__size_test[(!!(sizeof(type) == size)) * 2 - 1] + #define AL_USE_STDLIB //#define AL_MEMORY_TRACKING //#define AL_FORCE_DISABLE_OUTPUT -#if defined __GNUC__ || defined __clang__ -#define AL_UNUSED_FUNCTION_PUSH \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wunused-function\"") -#define AL_UNUSED_FUNCTION_POP \ - _Pragma("GCC diagnostic pop") -#define AL_UNUSED_VARIABLE_PUSH \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wunused-variable\"") -#define AL_UNUSED_VARIABLE_POP \ - _Pragma("GCC diagnostic pop") +#if defined __clang__ +#define AL_IGNORE_WARNING(warning) \ + _Pragma(XSTR(clang diagnostic push)) \ + _Pragma(XSTR(clang diagnostic ignored warning)) +#define AL_IGNORE_WARNING_END _Pragma(XSTR(clang diagnostic pop)) +#elif defined __GNUC__ +#define AL_IGNORE_WARNING(warning) \ + _Pragma(XSTR(GCC diagnostic push)) \ + _Pragma(XSTR(GCC diagnostic ignored warning)) +#define AL_IGNORE_WARNING_END _Pragma(XSTR(GCC diagnostic pop)) #else -#define AL_UNUSED_FUNCTION_PUSH -#define AL_UNUSED_FUNCTION_POP -#define AL_UNUSED_VARIABLE_PUSH -#define AL_UNUSED_VARIABLE_POP +#define AL_IGNORE_WARNING(warning) +#define AL_IGNORE_WARNING_END #endif #ifdef AL_USE_STDLIB @@ -86,17 +93,13 @@ void al_malloc_stats(size_t *current, size_t *peak, size_t *total); #define al_assert(expr) do { (void)sizeof(expr); } while (0) // NOLINT(bugprone-sizeof-expression) #endif -#define al_assert_and_return(...) \ -AL_MACRO_WRAP \ -{ \ +#define al_assert_and_return(...) do { \ al_assert(false); \ return __VA_ARGS__; \ -} AL_MACRO_END +} while (0) #define al_alloc_object(type) (type *)al_calloc(1, sizeof(type)) -AL_UNUSED_FUNCTION_PUSH - // https://stackoverflow.com/a/66346831 static inline size_t al_strnlen(const char *s, size_t n) { @@ -107,7 +110,7 @@ static inline size_t al_strnlen(const char *s, size_t n) static inline char *al_strndup(const char *s, size_t n) { size_t len = al_strnlen(s, n); - char *ret = al_malloc(len + 1); + char *ret = (char *)al_malloc(len + 1); al_memcpy(ret, s, len); ret[len] = '\0'; return ret; @@ -160,11 +163,8 @@ static inline char *al_memdup0(const char *s, size_t n) return buf; } -AL_UNUSED_FUNCTION_POP #endif -AL_UNUSED_FUNCTION_PUSH - static inline u32 al_next_power_of_two(u32 n) { n--; @@ -211,38 +211,35 @@ static inline u32 al_u32_dec_wrap(u32 v) return (v == 0) ? UINT32_MAX : v - 1; } -static inline u16 al_u16_inc_wrap(u16 v) +static inline u32 al_u32_add_wrap(u32 v, u32 add, u32 max) { - return (v == UINT16_MAX) ? 0 : v + 1; + return (v > max - add) ? (add - (max - v)) : v + add; } -static inline u32 al_add_wrap(u32 v, u32 add, u32 max) +static inline u16 al_u16_inc_wrap(u16 v) { - return (v > max - add) ? (add - (max - v)) : v + add; + return (v == UINT16_MAX) ? 0 : v + 1; } -static inline u32 al_u32_add_wrap(u32 v, u32 add) +static inline u16 al_u16_dec_wrap(u16 v) { - return (v > UINT32_MAX - add) ? (add - (UINT32_MAX - v)) : v + add; + return (v == 0) ? UINT16_MAX : v - 1; } -static inline u16 al_u16_add_wrap(u16 v, u16 add) +static inline u16 al_u16_add_wrap(u16 v, u16 add, u16 max) { - return (v > UINT16_MAX - add) ? (u16)(add - (UINT16_MAX - v)) : v + add; + return (v > max - add) ? (u16)(add - (max - v)) : v + add; } -AL_UNUSED_FUNCTION_POP - -#if defined C89ATOMIC_64BIT +#if defined AL_WE_64BIT #define MAX_ALLOC_32 UINT32_MAX -#elif defined C89ATOMIC_32BIT +#elif defined AL_WE_32BIT #define MAX_ALLOC_32 ((INT32_MAX - 1) / 4) #endif // Once a growing allocation expands past this number, only grow in multiples of it. extern u32 al_grow_step; - -u32 al_default_growing_allocation(void **ptr, u32 prev_size, u32 size, +u32 al_growing_allocation(void **ptr, u32 prev_size, u32 size, void *(*malloc_func)(size_t), void *(*realloc_func)(void *, size_t)); // Defaults to 4KB. diff --git a/include/al/list.h b/include/al/list.h index 333d2a4..6f33b93 100644 --- a/include/al/list.h +++ b/include/al/list.h @@ -4,7 +4,6 @@ #include "lib.h" #define AL_LIST_DEFINE(type, name) \ - AL_UNUSED_FUNCTION_PUSH \ typedef struct list_##name list_##name; \ struct list_##name { \ type value; \ @@ -109,8 +108,7 @@ list_free_node_##name(n); \ } \ return l; \ - } \ - AL_UNUSED_FUNCTION_POP + } #define list(name) list_##name diff --git a/include/al/log.h b/include/al/log.h index da3f21d..2fb0c26 100644 --- a/include/al/log.h +++ b/include/al/log.h @@ -59,13 +59,9 @@ s32 _al_logv(u8 level, const char *section, const char *name, const s32 line, co #define al_log_trace(section, fmt, ...) al_log_nop(section, fmt, ##__VA_ARGS__) #endif -AL_UNUSED_FUNCTION_PUSH - static inline s32 al_log_nop(const char *section, const char *fmt, ...) { (void)section; (void)fmt; return 0; } -AL_UNUSED_FUNCTION_POP - #endif // _AL_LOG_H diff --git a/include/al/macros.h b/include/al/macros.h index 715718a..3932c37 100644 --- a/include/al/macros.h +++ b/include/al/macros.h @@ -1,9 +1,6 @@ #ifndef _AL_MACROS_H #define _AL_MACROS_H -#define AL_MACRO_WRAP do { -#define AL_MACRO_END } while(0) - #define AL_PASTER_EVALUATOR(X, Y) X##_##Y #define AL_PASTER(X, Y) AL_PASTER_EVALUATOR(X, Y) @@ -23,47 +20,49 @@ #define UNLIKELY(x) x #endif -#if defined MAX || defined MIN || defined CLAMP || defined SWAP || defined ARRAY_SIZE || defined BOOLSTR +#if defined MIN || defined MAX || defined CLAMP || defined SWAP || defined ARRAY_SIZE || defined STR || defined XSTR || defined BOOLSTR #error "Conflicting definitions for common macros" #endif #ifdef AL_HAVE_GNU_EXTENSIONS -#define MIN(a, b) \ -({ \ - __typeof__(a) _a = a; \ - __typeof__(b) _b = b; \ - (void)(&_a == &_b); \ - _a < _b ? _a : _b; \ -}) -#define MAX(a, b) \ -({ \ - __typeof__(a) _a = a; \ - __typeof__(b) _b = b; \ - (void)(&_a == &_b); \ - _a > _b ? _a : _b; \ -}) +#define MIN(a, b) \ + ({ \ + __typeof__(a) ac = a; \ + __typeof__(b) bc = b; \ + (void)(&ac == &bc); \ + (ac < bc) ? ac : bc; \ + }) +#define MAX(a, b) \ + ({ \ + __typeof__(a) ac = a; \ + __typeof__(b) bc = b; \ + (void)(&ac == &bc); \ + (ac > bc) ? ac : bc; \ + }) #define CLAMP(n, lo, hi) MIN(hi, MAX(lo, n)) #else -// Compatible/Pedantic min/max. /* #error "MIN/MAX/CLAMP should not be used in this mode as they\ differ in behavior without support for statement expressions" */ +// Compatible/Pedantic min/max. #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define CLAMP(n, lo, hi) MIN(hi, MAX(lo, n)) #endif #define SWAP(a, b) \ -AL_MACRO_WRAP \ -{ \ - __typeof__(a) tmp = a; \ - a = b; \ - b = tmp; \ -} AL_MACRO_END + do { \ + __typeof__(a) tmp = a; \ + a = b; \ + b = tmp; \ + } while (0) #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) +#define STR(s) #s +#define XSTR(s) STR(s) + #define BOOLSTR(b) ((b) ? "true" : "false") #if defined KB || defined MB || defined GB || defined TB diff --git a/include/al/random.h b/include/al/random.h index 3d0d7cb..f92a77b 100644 --- a/include/al/random.h +++ b/include/al/random.h @@ -6,26 +6,22 @@ #define AL_RAND_MAX RAND_MAX -AL_UNUSED_FUNCTION_PUSH - extern u32 al_rand_seed; extern __thread bool al_rand_set; -static void al_rand_init(u32 seed) +static inline void al_rand_init(u32 seed) { al_rand_seed = seed; } -static s32 al_rand(void) +static inline s32 al_rand(void) { if (UNLIKELY(!al_rand_set)) { - // srand() is thread-local on Windows CRT. + // srand() is thread-local in Windows CRT. srand(al_rand_seed); al_rand_set = true; } return rand(); } -AL_UNUSED_FUNCTION_POP - #endif // _AL_RANDOM_H diff --git a/include/al/str.h b/include/al/str.h index fce2486..d7dab1c 100644 --- a/include/al/str.h +++ b/include/al/str.h @@ -10,9 +10,10 @@ typedef struct { char *__sized_by(alloc) data; } str; +#define AL_STR_NPOS ((u32)-1) + #define al_str_null() ((str){ 0, 0, NULL }) -#define al_str_npos ((u32)-1) #define al_str_at(s, i) (s)->data[i] #define al_str_atr(s, i) (s)->data[(s)->length - (i)] @@ -21,13 +22,11 @@ typedef struct { #define al_str_cs(c) ((str){ (u32)al_strnlen(c, sizeof(c)), 0, ((char *)(c)) }) // (s)ized #define al_str_cr(c) ((str){ (u32)al_strnlen(c, MAX_ALLOC_32), 0, ((char *)(c)) }) // (r)untime -#define al_str_w(c, i, n) ((str){ ((u32)(n)), 0, &(c)[i] }) +#define al_str_w(c, i, n) ((str){ ((u32)(n)), 0, (c) + (i) }) #define al_str_substr(s, start, end) al_str_w((s)->data, start, ((end) - (start))) -#define al_str_fmt(s) (s)->length, (s)->data -#define al_str_fmt_maxlen(s, l) MIN((s)->length, (l)), (s)->data - -AL_UNUSED_FUNCTION_PUSH +#define al_str_x(s) (s)->length, (s)->data // e(x)pand +#define al_str_x_maxlen(s, l) MIN((s)->length, (l)), (s)->data static inline bool al_str_is_empty(str *s) { @@ -41,7 +40,7 @@ static inline void al_str_free(str *s) static inline u32 al_str_reserve(str *s, u32 size) { - return al_default_growing_allocation((void **)&s->data, s->alloc, size, al_malloc, al_realloc); + return al_growing_allocation((void **)&s->data, s->alloc, size, al_malloc, al_realloc); } static inline void al_str_sized(str *s, u32 size) @@ -119,13 +118,13 @@ static inline bool al_str_eq(str *s, str *c) static inline u32 al_str_find(str *s, char c) { char *loc = (char *)al_memchr(s->data, c, s->length); - return loc ? (u32)(loc - s->data) : al_str_npos; + return loc ? (u32)(loc - s->data) : AL_STR_NPOS; } static inline u32 al_str_rfind(str *s, char c) { char *loc = (char *)al_memrchr(s->data, c, s->length); - return loc ? (u32)(loc - s->data) : al_str_npos; + return loc ? (u32)(loc - s->data) : AL_STR_NPOS; } // extremely slow. @@ -139,7 +138,7 @@ static inline u32 al_str_find_str(str *s, str *c) } } } - return al_str_npos; + return AL_STR_NPOS; } static inline u32 al_str_hash(str *s) @@ -152,8 +151,6 @@ static inline u32 al_str_hash(str *s) return hash; } -AL_UNUSED_FUNCTION_POP - s64 al_str_to_long(str *s, u32 base, bool *error); bool al_str_get_line(str *buffer, char sep, str *line); diff --git a/include/al/test.h b/include/al/test.h index 8fc37e3..bed3102 100644 --- a/include/al/test.h +++ b/include/al/test.h @@ -14,58 +14,56 @@ if (!test()) return false; #define AL_TEST_START(name) \ -AL_MACRO_WRAP \ -{ \ - al_printf(" "name"..."); \ - al_fflush(stdout); \ -} AL_MACRO_END + do { \ + al_printf(" "name"..."); \ + al_fflush(stdout); \ + } while (0) #define AL_TEST_END() \ al_printf("OK\n"); \ return true #define AL_TEST_DEF(a, b, T, cmp, explain) \ -AL_MACRO_WRAP \ -{ \ - AL_TEST_TYPE_##T _a = a; \ - AL_TEST_TYPE_##T _b = b; \ - if (cmp) { \ - al_printf("FAIL "#a"("AL_TEST_FMT_##T") "explain" "#b"("AL_TEST_FMT_##T")\n", \ - AL_TEST_PRINTF_##T(_a), AL_TEST_PRINTF_##T(_b)); \ - return false; \ - } \ -} AL_MACRO_END + do { \ + AL_TEST_TYPE_##T ac = a; \ + AL_TEST_TYPE_##T bc = b; \ + if (cmp) { \ + al_printf("FAIL "#a"("AL_TEST_FMT_##T") "explain" "#b"("AL_TEST_FMT_##T")\n", \ + AL_TEST_PRINTF_##T(ac), AL_TEST_PRINTF_##T(bc)); \ + return false; \ + } \ + } while (0) #define AL_TEST_EQ(a, b, T) \ - AL_TEST_DEF(a, b, T, (AL_TEST_CMP_##T(_a, _b) != 0), \ + AL_TEST_DEF(a, b, T, (AL_TEST_CMP_##T(ac, bc) != 0), \ "is not equal to") #define AL_TEST_NEQ(a, b, T) \ - AL_TEST_DEF(a, b, T, (AL_TEST_CMP_##T(_a, _b) == 0), \ + AL_TEST_DEF(a, b, T, (AL_TEST_CMP_##T(ac, bc) == 0), \ "is equal to") #define AL_TEST_GT(a, b, T) \ - AL_TEST_DEF(a, b, T, (AL_TEST_CMP_##T(_a, _b) != 1), \ + AL_TEST_DEF(a, b, T, (AL_TEST_CMP_##T(ac, bc) != 1), \ "is less than or equal to") #define AL_TEST_GTE(a, b, T) \ - AL_TEST_DEF(a, b, T, (AL_TEST_CMP_##T(_a, _b) != 0 && AL_TEST_CMP_##T(_a, _b) != 1), \ + AL_TEST_DEF(a, b, T, (AL_TEST_CMP_##T(ac, bc) != 0 && AL_TEST_CMP_##T(ac, bc) != 1), \ "is less than") #define AL_TEST_LT(a, b, T) \ - AL_TEST_DEF(a, b, T, (AL_TEST_CMP_##T(_a, _b) != -1), \ + AL_TEST_DEF(a, b, T, (AL_TEST_CMP_##T(ac, bc) != -1), \ "is greater than or equal to") #define AL_TEST_LTE(a, b, T) \ - AL_TEST_DEF(a, b, T, (AL_TEST_CMP_##T(_a, _b) != 0 && AL_TEST_CMP_##T(_a, _b) != -1), \ + AL_TEST_DEF(a, b, T, (AL_TEST_CMP_##T(ac, bc) != 0 && AL_TEST_CMP_##T(ac, bc) != -1), \ "is greater than") #define AL_TEST_TRUE(a) \ - AL_TEST_DEF(a, true, bool, (AL_TEST_CMP_bool(_a, _b) != 0), \ + AL_TEST_DEF(a, true, bool, (AL_TEST_CMP_bool(ac, bc) != 0), \ "is not") #define AL_TEST_FALSE(a) \ - AL_TEST_DEF(a, false, bool, (AL_TEST_CMP_bool(_a, _b) != 0), \ + AL_TEST_DEF(a, false, bool, (AL_TEST_CMP_bool(ac, bc) != 0), \ "is not") // bool diff --git a/include/al/wstr.h b/include/al/wstr.h index 3eb366c..5d5f6ac 100644 --- a/include/al/wstr.h +++ b/include/al/wstr.h @@ -12,9 +12,10 @@ typedef struct { wchar_t *__sized_by(alloc) data; } wstr; +#define AL_WSTR_NPOS ((u32)-1) + #define al_wstr_null() ((wstr){ 0, 0, NULL }) -#define al_wstr_npos ((u32)-1) #define al_wstr_at(w, i) (w)->data[i] #define al_wstr_atr(w, i) (w)->data[(w)->length - (i)] @@ -23,12 +24,10 @@ typedef struct { #define al_wstr_cs(wc) ((wstr){ (u32)wcsnlen(wc, sizeof(wc)), 0, ((wchar_t *)(wc)) }) // (s)ized #define al_wstr_cr(wc) ((wstr){ (u32)wcsnlen(wc, MAX_ALLOC_32), 0, ((wchar_t *)(wc)) }) // (r)untime -#define al_wstr_w(wc, i, n) ((wstr){ ((u32)(n)), 0, &(wc)[i] }) +#define al_wstr_w(wc, i, n) ((wstr){ ((u32)(n)), 0, (wc) + (i) }) #define al_wstr_substr(w, start, end) al_wstr_w((w)->data, start, ((end) - (start))) -#define al_wstr_fmt(w) (w)->data - -AL_UNUSED_FUNCTION_PUSH +#define al_wstr_x(w) (w)->data // e(x)pand static inline bool al_wstr_is_empty(wstr *w) { @@ -52,7 +51,7 @@ static inline void al_wstr_free(wstr *w) static inline u32 al_wstr_reserve(wstr *w, u32 size) { - return al_default_growing_allocation((void **)&w->data, w->alloc, size, al_malloc, al_realloc); + return al_growing_allocation((void **)&w->data, w->alloc, size, al_malloc, al_realloc); } static inline void al_wstr_sized(wstr *w, u32 size) @@ -188,7 +187,7 @@ static inline u32 al_wstr_find(wstr *w, wchar_t c) return i; } } - return al_wstr_npos; + return AL_WSTR_NPOS; } static inline u32 al_wstr_rfind(wstr *w, wchar_t c) @@ -198,13 +197,13 @@ static inline u32 al_wstr_rfind(wstr *w, wchar_t c) return i; } } - return al_wstr_npos; + return AL_WSTR_NPOS; } static inline bool al_wstr_tok(wstr *result, wchar_t delim) { u32 index = al_wstr_find(result, delim); - if (index == al_str_npos) { + if (index == AL_WSTR_NPOS) { return false; } *result = al_wstr_substr(result, index + 1, result->length); @@ -220,6 +219,4 @@ static inline s64 al_wstr_to_long(wstr *w, u32 base, bool *error) return num; } -AL_UNUSED_FUNCTION_POP - #endif // _AL_WSTR_H diff --git a/meson.build b/meson.build index 7940f25..2cc4da8 100644 --- a/meson.build +++ b/meson.build @@ -18,7 +18,8 @@ have_posix_memalign = compiler.has_function( have_wide_string = compiler.has_function('wcsrtombs') have_wide_string_width = compiler.has_function('wcswidth') -alabaster_args = [] +# For testing: '-Wshadow', '-Wconversion' +alabaster_args = ['-fstrict-aliasing', '-Wstrict-aliasing'] if is_debug alabaster_args += ['-D_DEBUG_'] diff --git a/src/array.c b/src/array.c index 0019a63..46d7951 100644 --- a/src/array.c +++ b/src/array.c @@ -14,118 +14,91 @@ #define al_array_init(array) ((array).count = 0, (array).alloc = 0, (array).data = NULL) -#define al_array_offset(array, n) ((array).data + (n)) #define al_array_at(array, i) ((array).data[i]) #define al_array_last(array) al_array_at(array, (array).count - 1) +#define al_array_offset(array, n) ((array).data + (n)) #define al_array_item_size(array) sizeof(*(array).data) // NOLINT(bugprone-sizeof-expression) #define al_array_reserve(array, count) \ ((array).alloc = _al_array_reserve((void **)&(array).data, (array).alloc, ((count) * al_array_item_size(array)))) -#define al_array_clone(dest, src) \ -AL_MACRO_WRAP \ -{ \ - al_array_init(dest); \ - al_array_reserve(dest, (src).count); \ - (dest).count = (src).count; \ - al_memcpy(al_array_offset(dest, 0), al_array_offset(src, 0), \ - al_array_item_size(dest) * (dest).count); \ -} AL_MACRO_END +#define al_array_copy(dest, src) \ + do { \ + al_array_reserve(dest, (src).count); \ + (dest).count = (src).count; \ + al_memcpy(al_array_offset(dest, 0), al_array_offset(src, 0), \ + al_array_item_size(dest) * (dest).count); \ + } while (0) -#define al_array_copy(dest, src) \ -AL_MACRO_WRAP \ -{ \ - al_array_reserve(dest, (src).count); \ - (dest).count = (src).count; \ - al_memcpy(al_array_offset(dest, 0), al_array_offset(src, 0), \ - al_array_item_size(dest) * (dest).count); \ -} AL_MACRO_END +#define al_array_push(array, item) \ + do { \ + al_array_reserve(array, (array).count + 1); \ + al_array_at(array, (array).count++) = item; \ + } while (0) -#define al_array_push(array, item) \ -AL_MACRO_WRAP \ -{ \ - al_array_reserve(array, (array).count + 1); \ - __typeof__(item) v = item; \ - (void)((array).data == &v); \ - al_array_at(array, (array).count++) = v; \ -} AL_MACRO_END - -#define al_array_insert(array, i, item) \ -AL_MACRO_WRAP \ -{ \ - al_array_reserve(array, (array).count + 1); \ - if (i != (array).count - 1) { \ - al_memmove(al_array_offset(array, i + 1), al_array_offset(array, i), \ - al_array_item_size(array) * ((array).count - i)); \ - } \ - (array).count++; \ - __typeof__(item) v = item; \ - (void)((array).data == &v); \ - al_array_at(array, i) = v; \ -} AL_MACRO_END +#define al_array_insert(array, i, item) \ + do { \ + al_array_reserve(array, (array).count + 1); \ + if (i != (array).count - 1) { \ + al_memmove(al_array_offset(array, i + 1), al_array_offset(array, i), \ + al_array_item_size(array) * ((array).count - i)); \ + } \ + (array).count++; \ + al_array_at(array, i) = item; \ + } while (0) #define al_array_pop(array) al_array_at(array, --(array).count) -#define al_array_pop_at(array, i, r) \ -AL_MACRO_WRAP \ -{ \ - r = al_array_at(array, i); \ - al_array_remove_at(array, i); \ -} AL_MACRO_END - -#define al_array_remove(array, elem) \ -AL_MACRO_WRAP \ -{ \ - for (u32 i = 0; i < (array).count; i++) { \ - if (al_array_at(array, i) == elem) { \ - al_array_remove_at(array, i); \ - break; \ - } \ - } \ -} AL_MACRO_END +#define al_array_pop_at(array, i, r) \ + do { \ + r = al_array_at(array, i); \ + al_array_remove_at(array, i); \ + } while (0) -#define al_array_remove_checked(array, elem, removed) \ -AL_MACRO_WRAP \ -{ \ - removed = false; \ - for (u32 i = 0; i < (array).count; i++) { \ - if (al_array_at(array, i) == elem) { \ - al_array_remove_at(array, i); \ - removed = true; \ - break; \ - } \ - } \ -} AL_MACRO_END +#define al_array_remove_at(array, i) \ + do { \ + if (i == (array).count - 1) { \ + (array).count--; \ + } else { \ + al_memmove(al_array_offset(array, i), al_array_offset(array, i + 1), \ + al_array_item_size(array) * (--(array).count - i)); \ + } \ + } while (0) -#define al_array_remove_all(array, elem) \ -AL_MACRO_WRAP \ -{ \ - for (u32 i = (array).count; i-- > 0;) { \ - if (al_array_at(array, i) == elem) { \ - al_array_remove_at(array, i); \ - } \ - } \ -} AL_MACRO_END +#define al_array_remove_range(array, start, end) \ + do { \ + if (end != (array).count) { \ + al_memmove(al_array_offset(array, start), al_array_offset(array, end), \ + al_array_item_size(array) * ((array).count - end)); \ + } \ + (array).count -= end - start; \ + } while (0) -#define al_array_remove_at(array, i) \ -AL_MACRO_WRAP \ -{ \ - if (i == (array).count - 1) { \ - (array).count--; \ - } else { \ - al_memmove(al_array_offset(array, i), al_array_offset(array, i + 1), \ - al_array_item_size(array) * (--(array).count - i)); \ - } \ -} AL_MACRO_END +#ifdef AL_HAVE_GNU_EXTENSIONS +#define al_array_remove(array, elem) \ + ({ \ + bool removed = false; \ + for (u32 i = 0; i < (array).count; i++) { \ + if (al_array_at(array, i) == elem) { \ + al_array_remove_at(array, i); \ + removed = true; \ + break; \ + } \ + } \ + removed; \ + }) -#define al_array_remove_range(array, start, end) \ -AL_MACRO_WRAP \ -{ \ - if (end != (array).count) { \ - al_memmove(al_array_offset(array, start), al_array_offset(array, end), \ - al_array_item_size(array) * ((array).count - end)); \ - } \ - (array).count -= end - start; \ -} AL_MACRO_END +#define al_array_remove_all(array, elem) \ + ({ \ + bool removed = false; \ + for (u32 i = (array).count; i-- > 0;) { \ + if (al_array_at(array, i) == elem) { \ + al_array_remove_at(array, i); \ + removed = true; \ + } \ + } \ + removed; \ + }) +#endif #ifdef AL_USE_STDLIB #define al_array_sort(array, type, cmp) AL_STDLIB_QSORT((array).data, type, (array).count, cmp) @@ -149,17 +122,12 @@ AL_MACRO_WRAP for (u32 i = (array).count; (i-- > 0 && (item = al_array_offset(array, i), 1));) #define al_array_remove_at_iter(array, i) \ -AL_MACRO_WRAP \ -{ \ - al_array_remove_at(array, i); \ - i--; \ -} AL_MACRO_END - -AL_UNUSED_FUNCTION_PUSH + do { \ + al_array_remove_at(array, i); \ + i--; \ + } while (0) static inline u32 _al_array_reserve(void **ptr, u32 prev_size, u32 size) { - return al_default_growing_allocation(ptr, prev_size, size, AL_ARRAY_MALLOC, AL_ARRAY_REALLOC); + return al_growing_allocation(ptr, prev_size, size, AL_ARRAY_MALLOC, AL_ARRAY_REALLOC); } - -AL_UNUSED_FUNCTION_POP @@ -1,11 +1,13 @@ #include "../include/al/lib.h" -// https://forum.vcfed.org/index.php?threads/c-item-size-check-at-compile-time.1244920/ -#define AL_ASSERT_TYPE_SIZE(type, size) \ - typedef char type##__size_test[(!!(sizeof(type) == size)) * 2 - 1] - AL_ASSERT_TYPE_SIZE(int, 4); AL_ASSERT_TYPE_SIZE(unsigned, 4); +#if defined AL_WE_64BIT +AL_ASSERT_TYPE_SIZE(intptr_t, 8); +#elif defined AL_WE_32BIT +AL_ASSERT_TYPE_SIZE(long, 4); +AL_ASSERT_TYPE_SIZE(intptr_t, 4); +#endif #ifdef AL_MEMORY_TRACKING static void *(*_al_malloc)(size_t) = NULL; @@ -61,51 +63,34 @@ void al_malloc_close(void) void *al_malloc(size_t n) { al_printf("**al_malloc(%zu)\n", n); - void *ptr = _al_malloc(n); - _al_malloc_lock(); - total_changed_by(n); current_changed_by(n); - al_array_push(allocations, ((struct al_alloc_t){ ptr, n })); - _al_malloc_unlock(); - return ptr; } void *al_calloc(size_t n, size_t size) { al_printf("**al_calloc(%zu, %zu)\n", n, size); - void *ptr = _al_calloc(n, size); - size_t real_size = n * size; - _al_malloc_lock(); - total_changed_by(real_size); current_changed_by(real_size); - al_array_push(allocations, ((struct al_alloc_t){ ptr, real_size })); - _al_malloc_unlock(); - return ptr; } void *al_realloc(void *ptr, size_t n) { al_printf("**al_realloc(%p, %zu)\n", ptr, n); - void *new_ptr = _al_realloc(ptr, n); - _al_malloc_lock(); - total_changed_by(n); - if (!ptr) { current_changed_by(n); al_array_push(allocations, ((struct al_alloc_t){ ptr, n })); @@ -121,18 +106,14 @@ void *al_realloc(void *ptr, size_t n) } } } - _al_malloc_unlock(); - return new_ptr; } void al_free(void *ptr) { al_printf("**al_free(%p)\n", ptr); - _al_malloc_lock(); - bool found = false; struct al_alloc_t *alloc; al_array_foreach_ptr(allocations, i, alloc) { @@ -144,9 +125,7 @@ void al_free(void *ptr) } } al_assert(found); - _al_malloc_unlock(); - _al_free(ptr); } @@ -155,18 +134,12 @@ s32 al_posix_memalign(void **ptr, size_t alignment, size_t n) { size_t real_size = (n + alignment) - ((n + alignment) % alignment); al_printf("**al_posix_memalign(%zu, %zu(%zu))\n", alignment, n, real_size); - s32 result = _al_posix_memalign(ptr, alignment, n); - _al_malloc_lock(); - total_changed_by(real_size); current_changed_by(real_size); - al_array_push(allocations, ((struct al_alloc_t){ *ptr, real_size })); - _al_malloc_unlock(); - return result; } #endif @@ -174,11 +147,9 @@ s32 al_posix_memalign(void **ptr, size_t alignment, size_t n) void al_malloc_stats(size_t *current, size_t *peak, size_t *total) { _al_malloc_lock(); - *current = current_alloc; *peak = peak_alloc; *total = total_alloc; - _al_malloc_unlock(); } @@ -203,15 +174,18 @@ void al_set_alloc(void *(*malloc_func)(size_t), void *(*calloc_func)(size_t, siz u32 al_grow_step = 0x3fff; // 0b11111111111111 -u32 al_default_growing_allocation(void **ptr, u32 prev_size, u32 size, +u32 al_growing_allocation(void **ptr, u32 prev_size, u32 size, void *(*malloc_func)(size_t), void *(*realloc_func)(void *, size_t)) { if (size <= prev_size) return prev_size; - al_assert(size > 0); - size = size < al_grow_step ? al_next_power_of_two(size) : - al_add_wrap(size, al_grow_step, MAX_ALLOC_32) & ~al_grow_step; - // This should only happen after wrapping around MAX_ALLOC_32 (zero all possible bits). + al_assert(size > 0); + if (size < al_grow_step) { + size = al_next_power_of_two(size); + } else { + size = al_u32_add_wrap(size, al_grow_step, MAX_ALLOC_32) & ~al_grow_step; + } + // size can only be 0 after wrapping around MAX_ALLOC_32 (zero all possible bits). if (size == 0) size = MAX_ALLOC_32; *ptr = (!*ptr) ? malloc_func(size) : realloc_func(*ptr, size); @@ -220,7 +194,7 @@ u32 al_default_growing_allocation(void **ptr, u32 prev_size, u32 size, return size; } -size_t al_page_size = 0x1000; +size_t al_page_size = 0x1000; // 4096 void al_set_page_size(size_t size) { al_assert(size > 0); diff --git a/src/ring_buffer.c b/src/ring_buffer.c index ded0138..b1c2fe5 100644 --- a/src/ring_buffer.c +++ b/src/ring_buffer.c @@ -3,7 +3,6 @@ #include "../include/al/macros.h" // https://github.com/MusicPlayerDaemon/MPD/blob/master/src/util/RingBuffer.hxx -// // This is no longer an implementation of a "contiguous" ring buffer but I used this as reference. // Wrapping is handled in read() and write(). // https://andrea.lattuada.me/blog/2019/the-design-and-implementation-of-a-lock-free-ring-buffer-with-contiguous-reservations.html @@ -17,9 +16,7 @@ void al_ring_buffer_init(struct al_ring_buffer *buf, u8 *data, ptrdiff_t length) static inline u8 *previous(struct al_ring_buffer *buf, u8 *ptr) { - if (ptr == buf->start) { - ptr = buf->end; - } + if (ptr == buf->start) ptr = buf->end; return --ptr; } @@ -42,7 +39,7 @@ u8 *al_ring_buffer_write_chunk(struct al_ring_buffer *buf, ptrdiff_t *size) { u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_ACQUIRE); u8 *rp = previous(buf, al_atomic_load(void)(&buf->read, AL_ATOMIC_RELAXED)); - *size = (wp <= rp ? rp : buf->end) - wp; + *size = ((wp <= rp) ? rp : buf->end) - wp; return wp; } @@ -62,7 +59,7 @@ u8 *al_ring_buffer_read_chunk(struct al_ring_buffer *buf, ptrdiff_t *size) { u8 *rp = al_atomic_load(void)(&buf->read, AL_ATOMIC_ACQUIRE); u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_RELAXED); - *size = (rp <= wp ? wp : buf->end) - rp; + *size = ((rp <= wp) ? wp : buf->end) - rp; return rp; } @@ -76,14 +73,12 @@ ptrdiff_t al_ring_buffer_write(struct al_ring_buffer *buf, u8 *data, ptrdiff_t n u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_ACQUIRE); u8 *rp = previous(buf, al_atomic_load(void)(&buf->read, AL_ATOMIC_RELAXED)); - ptrdiff_t size, wrap; - - size = MIN((wp <= rp ? rp : buf->end) - wp, n); + ptrdiff_t size = MIN(((wp <= rp) ? rp : buf->end) - wp, n); al_memcpy(wp, data, (size_t)size); wp += size; if (wp >= buf->end) { - wrap = MIN(rp - buf->start, n - size); + ptrdiff_t wrap = MIN(rp - buf->start, n - size); al_memcpy(buf->start, data + size, (size_t)wrap); wp = buf->start + wrap; size += wrap; @@ -99,14 +94,12 @@ ptrdiff_t al_ring_buffer_read(struct al_ring_buffer *buf, u8 *ptr, ptrdiff_t n) u8 *rp = al_atomic_load(void)(&buf->read, AL_ATOMIC_ACQUIRE); u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_RELAXED); - ptrdiff_t size, wrap; - - size = MIN((rp <= wp ? wp : buf->end) - rp, n); + ptrdiff_t size = MIN(((rp <= wp) ? wp : buf->end) - rp, n); al_memcpy(ptr, rp, (size_t)size); rp += size; if (rp >= buf->end) { - wrap = MIN(wp - buf->start, n - size); + ptrdiff_t wrap = MIN(wp - buf->start, n - size); al_memcpy(ptr + size, buf->start, (size_t)wrap); rp = buf->start + wrap; size += wrap; @@ -122,20 +115,14 @@ ptrdiff_t al_ring_buffer_peek(struct al_ring_buffer *buf, u8 *ptr, ptrdiff_t off u8 *rp = al_atomic_load(void)(&buf->read, AL_ATOMIC_RELAXED); u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_RELAXED); - ptrdiff_t size, wrap; - + ptrdiff_t size; if (rp <= wp) { rp += offset; - size = MIN(wp - rp, n); - if (size < 0) { - return 0; - } - + if (size < 0) return 0; al_memcpy(ptr, rp, (size_t)size); } else { rp += offset; - size = MIN(buf->end - rp, n); if (size > 0) { al_memcpy(ptr, rp, (size_t)size); @@ -145,8 +132,7 @@ ptrdiff_t al_ring_buffer_peek(struct al_ring_buffer *buf, u8 *ptr, ptrdiff_t off rp = buf->start - size; size = 0; } - - wrap = MIN(wp - rp, n); + ptrdiff_t wrap = MIN(wp - rp, n); if (wrap > 0) { al_memcpy(ptr + size, rp, (size_t)wrap); size += wrap; @@ -161,13 +147,11 @@ ptrdiff_t al_ring_buffer_discard(struct al_ring_buffer *buf, ptrdiff_t n) u8 *rp = al_atomic_load(void)(&buf->read, AL_ATOMIC_ACQUIRE); u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_RELAXED); - ptrdiff_t discard, wrap; - - discard = MIN((rp <= wp ? wp : buf->end) - rp, n); + ptrdiff_t discard = MIN(((rp <= wp) ? wp : buf->end) - rp, n); rp += discard; if (rp >= buf->end) { - wrap = MIN(wp - buf->start, n - discard); + ptrdiff_t wrap = MIN(wp - buf->start, n - discard); rp = buf->start + wrap; discard += wrap; } diff --git a/tests/array.c b/tests/array.c index 6cc88c6..2c7746f 100644 --- a/tests/array.c +++ b/tests/array.c @@ -89,16 +89,16 @@ static bool array_test_last(void) AL_TEST_END(); } -AL_UNUSED_FUNCTION_PUSH +//#define ENABLE_MAX_ALLOC_SORT +#ifdef ENABLE_MAX_ALLOC_SORT static s32 uint8_compare(const void *a, const void *b) { if (*(u8 *)a < *(u8 *)b) return 1; else if (*(u8 *)b < *(u8 *)a) return -1; return 0; } - -AL_UNUSED_FUNCTION_POP +#endif static bool array_test_push(void) { @@ -109,7 +109,7 @@ static bool array_test_push(void) u8 increment = 0; for (u32 i = 0; i < MAX_ALLOC_32; i++) { - al_array_push(bytes, (increment = (u8)al_add_wrap(increment, 2, UINT8_MAX))); + al_array_push(bytes, (increment = (u8)al_u32_add_wrap((u32)increment, 2, UINT8_MAX))); } AL_TEST_EQ(bytes.count, MAX_ALLOC_32, u32); AL_TEST_EQ(bytes.alloc, MAX_ALLOC_32, u32); @@ -126,7 +126,7 @@ static bool array_test_push(void) AL_TEST_EQ(al_array_at(bytes, 2923789681), 199, u8); } -#if 0 // This is very slow. +#ifdef ENABLE_MAX_ALLOC_SORT // This is very slow. al_array_sort(bytes, u8, uint8_compare); AL_TEST_LTE(al_array_at(bytes, MAX_ALLOC_32 - 1), al_array_at(bytes, MAX_ALLOC_32 - 26000000), u8); AL_TEST_LTE(al_array_at(bytes, MAX_ALLOC_32 - 27000000), al_array_at(bytes, MAX_ALLOC_32 - 52000000), u8); diff --git a/tests/array_typed.c b/tests/array_typed.c index f61634d..5397c5d 100644 --- a/tests/array_typed.c +++ b/tests/array_typed.c @@ -4,14 +4,14 @@ #include "array_typed.h" #include "common.h" -AL_UNUSED_FUNCTION_PUSH +AL_IGNORE_WARNING("-Wunused-function") AL_ARRAY_INLINE_STORAGE_DEFINE(u32, u32, 64) AL_ARRAY_DEFINE(u32, u32) AL_ARRAY_DEFINE(u8, u8) AL_ARRAY_INLINE_STORAGE_DEFINE(test_t, struct test_t, 16) -AL_UNUSED_FUNCTION_POP +AL_IGNORE_WARNING_END static bool array_test_init(void) { diff --git a/tests/lib.c b/tests/lib.c index 48b6c02..51b058f 100644 --- a/tests/lib.c +++ b/tests/lib.c @@ -11,32 +11,32 @@ static bool lib_test_add_wrap(void) // u32 u32 counter32 = UINT32_MAX - 5; - counter32 = al_u32_add_wrap(counter32, 15); + counter32 = al_u32_add_wrap(counter32, 15, UINT32_MAX); AL_TEST_EQ(counter32, 10, u32); counter32 = UINT32_MAX; - counter32 = al_u32_add_wrap(counter32, 1); + counter32 = al_u32_add_wrap(counter32, 1, UINT32_MAX); AL_TEST_EQ(counter32, 1, u32); counter32 = UINT32_MAX - 25; - counter32 = al_u32_add_wrap(counter32, 20); + counter32 = al_u32_add_wrap(counter32, 20, UINT32_MAX); AL_TEST_EQ(counter32, UINT32_MAX - 5, u32); - counter32 = al_u32_add_wrap(counter32, 6); + counter32 = al_u32_add_wrap(counter32, 6, UINT32_MAX); AL_TEST_EQ(counter32, 1, u32); // u16 u16 counter16 = UINT16_MAX - 5; - counter16 = al_u16_add_wrap(counter16, 15); + counter16 = al_u16_add_wrap(counter16, 15, UINT16_MAX); AL_TEST_EQ(counter16, 10, u16); counter16 = UINT16_MAX; - counter16 = al_u16_add_wrap(counter16, 1); + counter16 = al_u16_add_wrap(counter16, 1, UINT16_MAX); AL_TEST_EQ(counter16, 1, u16); counter16 = UINT16_MAX - 25; - counter16 = al_u16_add_wrap(counter16, 20); + counter16 = al_u16_add_wrap(counter16, 20, UINT16_MAX); AL_TEST_EQ(counter16, UINT16_MAX - 5, u16); - counter16 = al_u16_add_wrap(counter16, 6); + counter16 = al_u16_add_wrap(counter16, 6, UINT16_MAX); AL_TEST_EQ(counter16, 1, u16); // inc_wrap diff --git a/tests/str.c b/tests/str.c index 51b0bf1..2f7f686 100644 --- a/tests/str.c +++ b/tests/str.c @@ -92,10 +92,10 @@ static bool str_test_find_rfind(void) AL_TEST_EQ(al_str_find(&string0, '\\'), 7, u32); AL_TEST_EQ(al_str_rfind(&string0, '\\'), 10, u32); - AL_TEST_EQ(al_str_find(&string0, 'P'), al_str_npos, u32); + AL_TEST_EQ(al_str_find(&string0, 'P'), AL_STR_NPOS, u32); AL_TEST_EQ(al_str_find_str(&string0, &al_str_c("wow\\")), 4, u32); - AL_TEST_EQ(al_str_find_str(&string0, &al_str_c("John\\")), al_str_npos, u32); + AL_TEST_EQ(al_str_find_str(&string0, &al_str_c("John\\")), AL_STR_NPOS, u32); AL_TEST_END(); } |