diff options
| author | 2024-12-22 18:27:58 -0500 | |
|---|---|---|
| committer | 2024-12-22 18:27:58 -0500 | |
| commit | 42c161bbeb30c17c1ef39f84e13e54ff207f09da (patch) | |
| tree | b5d69e36ef2cbe1e5435b5d70c6bfde6b5cb90c8 /src | |
| parent | ec924efb4168f906efe8978a6c083d63e550ae3f (diff) | |
| download | libalabaster-42c161bbeb30c17c1ef39f84e13e54ff207f09da.tar.gz libalabaster-42c161bbeb30c17c1ef39f84e13e54ff207f09da.tar.bz2 libalabaster-42c161bbeb30c17c1ef39f84e13e54ff207f09da.zip | |
all: Major cleanup and pass on readability
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src')
| -rw-r--r-- | src/array.c | 166 | ||||
| -rw-r--r-- | src/lib.c | 211 | ||||
| -rw-r--r-- | src/log.c | 104 | ||||
| -rw-r--r-- | src/ring_buffer.c | 7 | ||||
| -rw-r--r-- | src/str.c | 39 |
5 files changed, 309 insertions, 218 deletions
diff --git a/src/array.c b/src/array.c index 14db581..0459c96 100644 --- a/src/array.c +++ b/src/array.c @@ -13,7 +13,7 @@ } #define al_array_init(arr) ((arr).size = 0, (arr).alloc = 0, (arr).data = NULL) -#define al_array_item_size(arr) (sizeof(*(arr).data)) // NOLINT(bugprone-sizeof-expression) +#define al_array_item_size(arr) sizeof(*(arr).data) // NOLINT(bugprone-sizeof-expression) #define al_array_is_empty(arr) ((arr).size == 0) @@ -23,62 +23,99 @@ #define al_array_reserve(arr, size) \ ((arr).alloc = _al_array_reserve((void *)&(arr).data, al_array_item_size(arr), (arr).alloc, size)) -#define al_array_clone(dest, src) \ - do { \ - al_array_init(dest); \ - al_array_reserve(dest, (src).size); \ - (dest).size = (src).size; \ - al_memcpy(&al_array_at(dest, 0), &al_array_at(src, 0), \ - al_array_item_size(dest) * (dest).size); \ - } while (0) +#define al_array_clone(dest, src) \ +AL_MACRO_WRAP \ +({ \ + al_array_init(dest); \ + al_array_reserve(dest, (src).size); \ + (dest).size = (src).size; \ + al_memcpy(&al_array_at(dest, 0), &al_array_at(src, 0), \ + al_array_item_size(dest) * (dest).size); \ +}) -#define al_array_push(arr, item) \ - do { \ - al_array_reserve(arr, (arr).size + 1); \ - al_array_at(arr, (arr).size++) = item; \ - } while (0) +#define al_array_push(arr, item) \ +AL_MACRO_WRAP \ +({ \ + al_array_reserve(arr, (arr).size + 1); \ + al_array_at(arr, (arr).size++) = item; \ +}) -#define al_array_insert(arr, i, item) \ - do { \ - if ((arr).size > i) { \ - al_array_reserve(arr, (arr).size + 1); \ - al_memmove(&al_array_at(arr, i + 1), &al_array_at(arr, i), \ - al_array_item_size(arr) * ((arr).size - i)); \ - (arr).size++; \ - } else { \ - al_array_reserve(arr, i + 1); \ - (arr).size = i + 1; \ - } \ - al_array_at(arr, i) = item; \ - } while (0) +#define al_array_insert(arr, i, item) \ +AL_MACRO_WRAP \ +({ \ + if ((arr).size > i) { \ + al_array_reserve(arr, (arr).size + 1); \ + al_memmove(&al_array_at(arr, i + 1), &al_array_at(arr, i), \ + al_array_item_size(arr) * ((arr).size - i)); \ + (arr).size++; \ + } else { \ + al_array_reserve(arr, i + 1); \ + (arr).size = i + 1; \ + } \ + al_array_at(arr, i) = item; \ +}) -#define al_array_pop_at(arr, i, r) \ - do { \ - r = al_array_at((arr), i); \ - al_array_remove_at((arr), i); \ - } while (0) +#define al_array_pop(arr) al_array_at(arr, --(arr).size) +#define al_array_pop_at(arr, i, r) \ +AL_MACRO_WRAP \ +({ \ + r = al_array_at(arr, i); \ + al_array_remove_at(arr, i); \ +}) -#define al_array_pop(arr) (al_array_at(arr, --(arr).size)) -#define al_array_pop_front(arr) al_array_pop_at(arr, 0) +#define al_array_remove(arr, elem) \ +AL_MACRO_WRAP \ +({ \ + for (u32 i = 0; i < (arr).size; i++) { \ + if (al_array_at(arr, i) == elem) { \ + al_array_remove_at(arr, i); \ + break; \ + } \ + } \ +}) -#define al_array_remove_at(arr, i) \ - do { \ - if (i == (arr).size - 1) { \ - (arr).size--; \ - } else { \ - al_memmove(&al_array_at(arr, i), &al_array_at(arr, i + 1), \ - al_array_item_size(arr) * (--(arr).size - i)); \ - } \ - } while (0) +#define al_array_check_remove(arr, elem, removed) \ +AL_MACRO_WRAP \ +({ \ + removed = false; \ + for (u32 i = 0; i < (arr).size; i++) { \ + if (al_array_at(arr, i) == elem) { \ + al_array_remove_at(arr, i); \ + removed = true; \ + break; \ + } \ + } \ +}) -#define al_array_remove_range(arr, i, e) \ - do { \ - if (e != (arr).size) { \ - al_memmove(&al_array_at(arr, i), &al_array_at(arr, e), \ - al_array_item_size(arr) * ((arr).size - e)); \ - } \ - (arr).size -= e - i; \ - } while (0) +#define al_array_remove_all(arr, elem) \ +AL_MACRO_WRAP \ +({ \ + for (u32 i = (arr).size; i-- > 0;) { \ + if (al_array_at(arr, i) == elem) \ + al_array_remove_at(arr, i); \ + } \ +}) + +#define al_array_remove_at(arr, i) \ +AL_MACRO_WRAP \ +({ \ + if (i == (arr).size - 1) { \ + (arr).size--; \ + } else { \ + al_memmove(&al_array_at(arr, i), &al_array_at(arr, i + 1), \ + al_array_item_size(arr) * (--(arr).size - i)); \ + } \ +}) + +#define al_array_remove_range(arr, i, e) \ +AL_MACRO_WRAP \ +({ \ + if (e != (arr).size) { \ + al_memmove(&al_array_at(arr, i), &al_array_at(arr, e), \ + al_array_item_size(arr) * ((arr).size - e)); \ + } \ + (arr).size -= e - i; \ +}) #ifdef AL_USE_STDLIB #define al_array_sort(arr, type, cmp) AL_STDLIB_QSORT((arr).data, type, (arr).size, cmp) @@ -98,26 +135,25 @@ #define al_array_foreach_ptr(arr, i, item) \ for (u32 i = 0; (i < (arr).size && (item = &al_array_at(arr, i), 1)); i++) -#define al_array_remove_at_iter(arr, i) \ - do { \ - al_array_remove_at(arr, i); \ - i--; \ - } while (0) +#define al_array_foreach_ptr_rev(arr, i, item) \ + for (u32 i = (arr).size; (i-- > 0 && (item = &al_array_at(arr, i), 1));) + +#define al_array_remove_at_iter(arr, i) \ +AL_MACRO_WRAP \ +({ \ + al_array_remove_at(arr, i); \ + i--; \ +}) AL_UNUSED_FUNCTION_PUSH static inline u32 _al_array_reserve(void **ptr, u32 item_size, u32 prev_size, u32 size) { - if (size < al_grow_limit) { - size = (u32)al_next_power_of_two(size + 1); - } else { - size = (u32)((size + al_grow_limit) & ~al_grow_limit); - } - - if (size <= prev_size) { - al_assert(prev_size > 0); + if (size <= prev_size) return prev_size; - } + + size = size < al_grow_step ? al_next_power_of_two(size) : + (size + al_grow_step) & ~al_grow_step; *ptr = (!*ptr) ? AL_ARRAY_MALLOC(item_size * size) : AL_ARRAY_REALLOC(*ptr, item_size * size); al_assert(*ptr); @@ -2,28 +2,30 @@ // 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] + typedef char type##__size_test[(!!(sizeof(type) == size)) * 2 - 1] AL_ASSERT_TYPE_SIZE(int, 4); AL_ASSERT_TYPE_SIZE(unsigned, 4); #ifdef AL_MEMORY_TRACKING -#ifdef AL_USE_STDLIB -static void *(*_al_malloc)(size_t) = malloc; -static void *(*_al_calloc)(size_t, size_t) = calloc; -static void *(*_al_realloc)(void *, size_t) = realloc; -static void (*_al_free)(void *) = free; +static void *(*_al_malloc)(size_t) = NULL; +static void *(*_al_calloc)(size_t, size_t) = NULL; +static void *(*_al_realloc)(void *, size_t) = NULL; +static void (*_al_free)(void *) = NULL; #ifdef AL_HAVE_POSIX_MEMALIGN -s32 (*_al_posix_memalign)(void **, size_t, size_t) = posix_memalign; +s32 (*_al_posix_memalign)(void **, size_t, size_t) = NULL; #endif -// Testing allocation tracking stuff (Very scuffed, not thread-safe!). -struct alloc_t { +static void (*_al_malloc_lock)(void) = NULL; +static void (*_al_malloc_unlock)(void) = NULL; + +// Testing allocation tracking stuff (Very scuffed). +struct al_alloc_t { void *ptr; size_t size; }; -// Use stdlib allocation for the allocation tracking array. +// Use stdlib malloc for the allocation tracking array. // This avoids a circular dependency and also keeps allocations // from the memory tracking code out of the stats. #include "../include/al/types.h" @@ -32,10 +34,18 @@ struct alloc_t { #define AL_ARRAY_FREE free #include "array.c" -static array(struct alloc_t) allocations; -static u32 currently_allocated = 0; -static u32 peak_allocated = 0; -static u32 total_allocated = 0; +static array(struct al_alloc_t) allocations; +static size_t current_alloc = 0; +static size_t peak_alloc = 0; +static size_t total_alloc = 0; + +#define total_changed_by(n) \ + total_alloc += (n); \ + +#define current_changed_by(n) \ + current_alloc += (n); \ + if (current_alloc > peak_alloc) \ + peak_alloc = current_alloc; void al_malloc_init(void) { @@ -49,127 +59,152 @@ void al_malloc_close(void) void *al_malloc(size_t n) { + al_printf("**al_malloc(%zu)\n", n); + void *ptr = _al_malloc(n); - printf("**al_malloc(%zu)\n", n); - struct alloc_t a = { - .ptr = ptr, - .size = n - }; - total_allocated += a.size; - currently_allocated += a.size; - if (currently_allocated > peak_allocated) { - peak_allocated = currently_allocated; - } - al_array_push(allocations, a); + + _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); - printf("**al_calloc(%zu, %zu)\n", n, size); - struct alloc_t a = { - .ptr = ptr, - .size = n * size - }; - total_allocated += a.size; - currently_allocated += a.size; - if (currently_allocated > peak_allocated) { - peak_allocated = currently_allocated; - } - al_array_push(allocations, a); + + 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) { - void *nptr = _al_realloc(ptr, n); - printf("**al_realloc(%p, %zu)\n", ptr, n); - for (u32 i = 0; i < allocations.size; i++) { - struct alloc_t *a = &al_array_at(allocations, i); - if (a->ptr == ptr) { - currently_allocated += (ssize_t)n - (ssize_t)a->size; - if (currently_allocated > peak_allocated) { - peak_allocated = currently_allocated; - } - a->ptr = nptr; - a->size = 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) { - struct alloc_t a = { - .ptr = nptr, - .size = n - }; - currently_allocated += a.size; - if (currently_allocated > peak_allocated) { - peak_allocated = currently_allocated; + current_changed_by(n); + al_array_push(allocations, ((struct al_alloc_t){ ptr, n })); + } else { + struct al_alloc_t *alloc; + al_array_foreach_ptr(allocations, i, alloc) { + if (alloc->ptr == ptr) { + ptrdiff_t diff = (ptrdiff_t)n - (ptrdiff_t)alloc->size; + current_changed_by(diff); + alloc->ptr = new_ptr; + alloc->size = n; + break; + } } - al_array_push(allocations, a); } - total_allocated += n; - return nptr; + + _al_malloc_unlock(); + + return new_ptr; } void al_free(void *ptr) { - printf("**al_free(%p)\n", ptr); - for (u32 i = 0; i < allocations.size; i++) { - struct alloc_t *a = &al_array_at(allocations, i); - if (a->ptr == ptr) { - currently_allocated -= a->size; + 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) { + if (alloc->ptr == ptr) { + current_changed_by(-alloc->size); al_array_remove_at(allocations, i); + found = true; break; } } + al_assert(found); + + _al_malloc_unlock(); + _al_free(ptr); } #ifdef AL_HAVE_POSIX_MEMALIGN s32 al_posix_memalign(void **ptr, size_t alignment, size_t n) { - s32 res = _al_posix_memalign(ptr, alignment, n); - size_t actual_size = (n + alignment) - ((n + alignment) % alignment); - printf("**al_posix_memalign(%zu, %zu(%zu))\n", alignment, n, actual_size); - struct alloc_t a = { - .ptr = *ptr, - .size = actual_size - }; - total_allocated += actual_size; - currently_allocated += actual_size; - if (currently_allocated > peak_allocated) { - peak_allocated = currently_allocated; - } - al_array_push(allocations, a); - return res; + 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 -void al_malloc_stats(u32 *current, u32 *peak, u32 *total) +void al_malloc_stats(size_t *current, size_t *peak, size_t *total) { - *current = currently_allocated; - *peak = peak_allocated; - *total = total_allocated; + _al_malloc_lock(); + + *current = current_alloc; + *peak = peak_alloc; + *total = total_alloc; + + _al_malloc_unlock(); } void al_set_alloc(void *(*malloc_func)(size_t), void *(*calloc_func)(size_t, size_t), - void *(*realloc_func)(void *, size_t), void (*free_func)(void *)) + void *(*realloc_func)(void *, size_t), +#ifdef AL_HAVE_POSIX_MEMALIGN + s32 (*posix_memalign_func)(void **, size_t, size_t), +#endif + void (*free_func)(void *), void (*lock_func)(void), void (*unlock_func)(void)) { _al_malloc = malloc_func; _al_calloc = calloc_func; _al_realloc = realloc_func; +#ifdef AL_HAVE_POSIX_MEMALIGN + _al_posix_memalign = posix_memalign_func; +#endif _al_free = free_func; + _al_malloc_lock = lock_func; + _al_malloc_unlock = unlock_func; } #endif -#endif -// Default to 4KB. -size_t al_page_size = 0x1000; -size_t al_grow_limit = 0xfff; +u32 al_grow_step = 0xfff; +size_t al_page_size = 0x1000; void al_set_page_size(size_t size) { al_assert(size > 0); al_page_size = size; - al_grow_limit = al_page_size - 1; } @@ -8,46 +8,70 @@ #define AL_LOG_TEMPLATE "%s:%d %s(): %s -> " #endif -#define AL_LOG_MESSAGE_MAX 511 +#define AL_LOG_MESSAGE_MAX (AL_LOG_MESSAGE_SIZE - 1) // Space for newline. -#ifndef AL_LOG_SKIP -static s32 al_print_default(void *userdata, char *message) -{ - (void)userdata; - s32 ret = al_printf("%*.*s\n", 0, AL_LOG_MESSAGE_MAX, message); - al_free(message); - return ret; -} - -static s32 (*_al_print)(void *, char *) = al_print_default; -static void *_al_log_userdata = NULL; - -void al_set_print(s32 (*print_func)(void *, char *), void *userdata) +#ifndef AL_FORCE_DISABLE_OUTPUT +static const char *levels[] = { "info", "warn", "error", "debug" }; +static inline const char *get_color_for_level(u8 level) { - _al_print = print_func; - _al_log_userdata = userdata; +#define NORMAL "\x1B[0m" +#define RED "\x1B[31m" +#define GREEN "\x1B[32m" +#define YELLOW "\x1B[33m" +#define BLUE "\x1B[34m" +#define MAGENTA "\x1B[35m" +#define CYAN "\x1B[36m" +#define WHITE "\x1B[37m" +#define RESET "\033[0m" + switch (level) { + case AL_LOG_ERROR: return RED; + case AL_LOG_WARN: return YELLOW; + default: return NORMAL; + } } +#endif -#ifndef AL_FORCE_DISABLE_OUTPUT -static char *get_buffer(const char *level, const char *section, const char *fmt, const char *name, const s32 line, const char *func, va_list args) +#if !defined AL_FORCE_DISABLE_OUTPUT && !defined AL_LOG_SKIP +static char *get_message_buffer(u8 level, const char *section, const char *fmt, const char *name, const s32 line, const char *func, va_list args) { - char *buffer = al_malloc(AL_LOG_MESSAGE_MAX + 1); + char *buffer = al_malloc(AL_LOG_MESSAGE_SIZE); #ifdef AL_LOG_USE_SECTION - s32 prefix = al_snprintf(buffer, AL_LOG_MESSAGE_MAX, AL_LOG_TEMPLATE, name, line, func, level, section); + s32 prefix = al_snprintf(buffer, AL_LOG_MESSAGE_MAX, AL_LOG_TEMPLATE, name, line, func, levels[level], section); #else (void)section; - s32 prefix = al_snprintf(buffer, AL_LOG_MESSAGE_MAX, AL_LOG_TEMPLATE, name, line, func, level); + s32 prefix = al_snprintf(buffer, AL_LOG_MESSAGE_MAX, AL_LOG_TEMPLATE, name, line, func, levels[level]); #endif al_vsnprintf(buffer + prefix, AL_LOG_MESSAGE_MAX - prefix, fmt, args); buffer[strcspn(buffer, "\r\n")] = '\0'; return buffer; } + +s32 al_print_default(void *userdata, u8 level, char *message) +{ + (void)userdata; +#ifndef _WIN32 + s32 ret = al_printf("%s%*.*s\n", get_color_for_level(level), 0, AL_LOG_MESSAGE_SIZE, message); +#else + (void)level; + s32 ret = al_printf("%*.*s\n", 0, AL_LOG_MESSAGE_SIZE, message); #endif + al_free(message); + return ret; +} + +static s32 (*_al_print)(void *, u8, char *) = al_print_default; +static void *_al_log_userdata = NULL; + +void al_set_print(s32 (*print_func)(void *, u8, char *), void *userdata) +{ + _al_print = print_func; + _al_log_userdata = userdata; +} #else -void al_set_print(s32 (*print_func)(void *, char *), void *userdata) { (void)print_func; (void)userdata; } +void al_set_print(s32 (*print_func)(void *, u8, char *), void *userdata) { (void)print_func; (void)userdata; } #endif -s32 _al_log(const char *level, const char *section, const char *name, const s32 line, const char *func, const char *fmt, ...) +s32 _al_logv(u8 level, const char *section, const char *name, const s32 line, const char *func, const char *fmt, va_list args) { #ifdef AL_FORCE_DISABLE_OUTPUT (void)level; @@ -56,28 +80,31 @@ s32 _al_log(const char *level, const char *section, const char *name, const s32 (void)line; (void)func; (void)fmt; + (void)args; return 0; #else - va_list args; - va_start(args, fmt); if (!section) section = ""; #ifdef AL_LOG_SKIP - s32 ret = al_printf(AL_LOG_TEMPLATE, name, line, func, level, section); + s32 ret = al_printf(get_color_for_level(level)); +#ifdef AL_LOG_USE_SECTION + ret += al_printf(AL_LOG_TEMPLATE, name, line, func, level, section); +#else + ret += al_printf(AL_LOG_TEMPLATE, name, line, func, level); +#endif ret += al_vprintf(fmt, args); if (strcspn(fmt, "\r\n") == al_strlen(fmt)) ret += al_printf("\n"); #else - char *buffer = get_buffer(level, section, fmt, name, line, func, args); + char *buffer = get_message_buffer(level, section, fmt, name, line, func, args); #endif - va_end(args); #ifdef AL_LOG_SKIP return ret; #else - return _al_print(_al_log_userdata, buffer); + return _al_print(_al_log_userdata, level, buffer); #endif #endif } -s32 _al_logv(const char *level, const char *section, const char *name, const s32 line, const char *func, const char *fmt, va_list args) +s32 _al_log(u8 level, const char *section, const char *name, const s32 line, const char *func, const char *fmt, ...) { #ifdef AL_FORCE_DISABLE_OUTPUT (void)level; @@ -86,21 +113,12 @@ s32 _al_logv(const char *level, const char *section, const char *name, const s32 (void)line; (void)func; (void)fmt; - (void)args; return 0; #else - if (!section) section = ""; -#ifdef AL_LOG_SKIP - s32 ret = al_printf(AL_LOG_TEMPLATE, name, line, func, level, section); - ret += al_vprintf(fmt, args); - if (strcspn(fmt, "\r\n") == al_strlen(fmt)) ret += al_printf("\n"); -#else - char *buffer = get_buffer(level, section, fmt, name, line, func, args); -#endif -#ifdef AL_LOG_SKIP + va_list args; + va_start(args, fmt); + s32 ret = _al_logv(level, section, name, line, func, fmt, args); + va_end(args); return ret; -#else - return _al_print(_al_log_userdata, buffer); -#endif #endif } diff --git a/src/ring_buffer.c b/src/ring_buffer.c index a96584f..cf72d2b 100644 --- a/src/ring_buffer.c +++ b/src/ring_buffer.c @@ -119,11 +119,15 @@ size_t al_ring_buffer_peek(struct al_ring_buffer *buf, u8 *ptr, size_t offset, s if (rp <= wp) { rp += offset; + size = MIN(wp - rp, (ptrdiff_t)n); - if (size < 0) return 0; + if (size < 0) + return 0; + al_memcpy(ptr, rp, size); } else { rp += offset; + size = MIN(buf->end - rp, (ptrdiff_t)n); if (size > 0) { al_memcpy(ptr, rp, size); @@ -133,6 +137,7 @@ size_t al_ring_buffer_peek(struct al_ring_buffer *buf, u8 *ptr, size_t offset, s rp = buf->start - size; size = 0; } + ptrdiff_t wrap = MIN(wp - rp, (ptrdiff_t)n); if (wrap > 0) { al_memcpy(ptr + size, rp, wrap); @@ -16,10 +16,9 @@ s64 al_str_to_long(str *s, s32 base) i++; } - if ((base == 16 && al_str_at(s, i) == '0' && // 0xbecd - (al_str_at(s, i + 1) == 'x' || al_str_at(s, i + 1) == 'X')) || - (base == 2 && al_str_at(s, i) == '0' && // 0b01011101 - (al_str_at(s, i + 1) == 'b' || al_str_at(s, i + 1) == 'B'))) { + if (al_str_at(s, i) == '0' && + ((base == 16 && (al_str_at(s, i + 1) == 'x' || al_str_at(s, i + 1) == 'X')) || + (base == 2 && (al_str_at(s, i + 1) == 'b' || al_str_at(s, i + 1) == 'B')))) { i += 2; } @@ -32,26 +31,23 @@ s64 al_str_to_long(str *s, s32 base) for (; i < s->len; i++) { char c = al_str_at(s, i); - if (c >= '0' && c <= '9') { - c -= '0'; - } else if (c >= 'A' && c <= 'Z') { - c -= 'A' - 10; - } else if (c >= 'a' && c <= 'z') { - c -= 'a' - 10; - } else { - // Character not valid when expressing a number. + if (c >= '0' && c <= '9') c -= '0'; + else if (c >= 'A' && c <= 'Z') c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') c -= 'a' - 10; + else { + // Character not valid for expressing a number. error = true; break; } - // Character invalid for given base or trying to add the next digit - // would cause an overflow/underflow. if (c >= base || ret > cutoff || (ret == cutoff && c > add_limit)) { + // Either the character is invalid for the requested base or + // attempting to add it would cause an overflow. error = true; break; } - ret = (ret * base) + c; + ret = ret * base + c; } if (error) ret = neg ? INT64_MIN : INT64_MAX; @@ -64,20 +60,21 @@ bool al_str_get_line(str *buffer, char sep, str *line) { u32 bytes = 0; + // line must be zero'd before calling get_line() for the first time. if (line->data == NULL) { *line = *buffer; - } else if ((bytes = (u32)((line->data += line->len + 1) - buffer->data)) >= buffer->len) { - // Move to the start of the assumed next line. If bytes >= buffer->len, - // there is no next line. - return false; + } else { + // Move to the start of the next line, if it exists. + line->data += line->len + 1; + if ((bytes = line->data - buffer->data) >= buffer->len) + return false; // No more lines. } - // Remaining bytes. bytes = buffer->len - bytes; char *nl = (char *)al_memchr(line->data, sep, bytes); - // If !nl, move to the end of the buffer. + // If we couldn't find a separator, move to the end of the buffer. line->len = !nl ? bytes : (u32)(nl - line->data); return true; |