summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-01-17 11:20:17 -0500
committerAndrew Opalach <andrew@akon.city> 2025-01-17 11:20:17 -0500
commit209310c561d89c9ed2040aa7053b320d32cc393c (patch)
treecb26e18d275fa1d37afa903134e90e7c4c260484 /src
parent27b5e13d75c58d5e32538a4b5aef65ab86f4bb38 (diff)
downloadlibalabaster-209310c561d89c9ed2040aa7053b320d32cc393c.tar.gz
libalabaster-209310c561d89c9ed2040aa7053b320d32cc393c.tar.bz2
libalabaster-209310c561d89c9ed2040aa7053b320d32cc393c.zip
all: Consider types and numerical limits
- Vastly improve tests. - Change array/str/wstr APIs. - Use ptrdiff_t instead of size_t in ring buffer. - Make random seed thread-local. - Log now uses a static thread-local buffer instead of a malloc'd buffer. Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src')
-rw-r--r--src/array.c244
-rw-r--r--src/lib.c19
-rw-r--r--src/log.c45
-rw-r--r--src/random.c4
-rw-r--r--src/ring_buffer.c68
-rw-r--r--src/str.c47
6 files changed, 220 insertions, 207 deletions
diff --git a/src/array.c b/src/array.c
index 3236f67..6021a85 100644
--- a/src/array.c
+++ b/src/array.c
@@ -7,171 +7,159 @@
#define array(type) \
struct { \
- u32 size; \
+ u32 count; \
u32 alloc; \
type *__sized_by(alloc) data; \
}
-#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_init(array) ((array).count = 0, (array).alloc = 0, (array).data = NULL)
-#define al_array_is_empty(arr) ((arr).size == 0)
+#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(arr, i) ((arr).data + (i))
-
-#define al_array_at(arr, i) ((arr).data[i])
-#define al_array_last(arr) al_array_at(arr, (arr).size - 1)
-
-#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_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).size); \
- (dest).size = (src).size; \
+ 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).size); \
-})
+ al_array_item_size(dest) * (dest).count); \
+} AL_MACRO_END
#define al_array_copy(dest, src) \
AL_MACRO_WRAP \
-({ \
- al_array_reserve(dest, (src).size); \
- (dest).size = (src).size; \
+{ \
+ 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).size); \
-})
+ al_array_item_size(dest) * (dest).count); \
+} AL_MACRO_END
-#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_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(arr, i, item) \
-AL_MACRO_WRAP \
-({ \
- if ((arr).size > i) { \
- al_array_reserve(arr, (arr).size + 1); \
- al_memmove(al_array_offset(arr, i + 1), al_array_offset(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_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_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(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(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(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_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_check_remove(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_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_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_at(arr, i) \
-AL_MACRO_WRAP \
-({ \
- if (i == (arr).size - 1) { \
- (arr).size--; \
- } else { \
- al_memmove(al_array_offset(arr, i), al_array_offset(arr, i + 1), \
- al_array_item_size(arr) * (--(arr).size - i)); \
- } \
-})
+#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
-#define al_array_remove_range(arr, i, e) \
-AL_MACRO_WRAP \
-({ \
- if (e != (arr).size) { \
- al_memmove(al_array_offset(arr, i), al_array_offset(arr, e), \
- al_array_item_size(arr) * ((arr).size - e)); \
- } \
- (arr).size -= e - i; \
-})
+#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
#ifdef AL_USE_STDLIB
-#define al_array_sort(arr, type, cmp) AL_STDLIB_QSORT((arr).data, type, (arr).size, cmp)
+#define al_array_sort(array, type, cmp) AL_STDLIB_QSORT((array).data, type, (array).count, cmp)
#else
-#define al_array_sort(arr, type, cmp) AL_INSERSION_SORT((arr).data, type, (arr).size, cmp)
+#define al_array_sort(array, type, cmp) AL_INSERSION_SORT((array).data, type, (array).count, cmp)
#endif
-#define al_array_free(arr) \
- if ((arr).alloc) AL_ARRAY_FREE((arr).data)
+#define al_array_free(array) \
+ if ((array).alloc) AL_ARRAY_FREE((array).data)
-#define al_array_foreach(arr, i, item) \
- for (u32 i = 0; (i < (arr).size && (item = al_array_at(arr, i), 1)); i++)
+#define al_array_foreach(array, i, item) \
+ for (u32 i = 0; (i < (array).count && (item = al_array_at(array, i), 1)); i++)
-#define al_array_foreach_rev(arr, i, item) \
- for (u32 i = (arr).size; (i-- > 0 && (item = al_array_at(arr, i), 1));)
+#define al_array_foreach_rev(array, i, item) \
+ for (u32 i = (array).count; (i-- > 0 && (item = al_array_at(array, i), 1));)
-#define al_array_foreach_ptr(arr, i, item) \
- for (u32 i = 0; (i < (arr).size && (item = al_array_offset(arr, i), 1)); i++)
+#define al_array_foreach_ptr(array, i, item) \
+ for (u32 i = 0; (i < (array).count && (item = al_array_offset(array, i), 1)); i++)
-#define al_array_foreach_ptr_rev(arr, i, item) \
- for (u32 i = (arr).size; (i-- > 0 && (item = al_array_offset(arr, i), 1));)
+#define al_array_foreach_ptr_rev(array, i, item) \
+ for (u32 i = (array).count; (i-- > 0 && (item = al_array_offset(array, i), 1));)
-#define al_array_remove_at_iter(arr, i) \
-AL_MACRO_WRAP \
-({ \
- al_array_remove_at(arr, i); \
- i--; \
-})
+#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
-static inline u32 _al_array_reserve(void **ptr, u32 item_size, u32 prev_size, u32 size)
+static inline u32 _al_array_reserve(void **ptr, u32 prev_size, u32 size)
{
- 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);
-
- return size;
+ return al_default_growing_allocation(ptr, prev_size, size, AL_ARRAY_MALLOC, AL_ARRAY_REALLOC);
}
AL_UNUSED_FUNCTION_POP
diff --git a/src/lib.c b/src/lib.c
index ca737e4..9641976 100644
--- a/src/lib.c
+++ b/src/lib.c
@@ -201,7 +201,24 @@ void al_set_alloc(void *(*malloc_func)(size_t), void *(*calloc_func)(size_t, siz
}
#endif
-u32 al_grow_step = 0xfff;
+u32 al_grow_step = 0x3fff; // 0b11111111111111
+
+u32 al_default_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).
+ if (size == 0) size = MAX_ALLOC_32;
+
+ *ptr = (!*ptr) ? malloc_func(size) : realloc_func(*ptr, size);
+ al_assert(*ptr);
+
+ return size;
+}
size_t al_page_size = 0x1000;
void al_set_page_size(size_t size)
diff --git a/src/log.c b/src/log.c
index 748f0d5..ea39b98 100644
--- a/src/log.c
+++ b/src/log.c
@@ -1,14 +1,11 @@
#include "../include/al/log.h"
+#include "../include/al/macros.h"
//#define AL_LOG_SKIP
-#define AL_LOG_USE_SECTION
-#ifdef AL_LOG_USE_SECTION
-#define AL_LOG_TEMPLATE "%s:%d %s(): %s -> (%s) "
-#else
#define AL_LOG_TEMPLATE "%s:%d %s(): %s -> "
-#endif
+#define AL_LOG_TEMPLATE_SECTION AL_LOG_TEMPLATE"(%s) "
-#define AL_LOG_MESSAGE_MAX (AL_LOG_MESSAGE_SIZE - 1) // Space for newline.
+#define AL_LOG_MESSAGE_MAX ((size_t)(AL_LOG_MESSAGE_SIZE - 1u)) // Space for newline.
#ifndef AL_FORCE_DISABLE_OUTPUT
static s32 (*_al_print)(void *, u8, char *) = NULL;
@@ -23,39 +20,39 @@ void al_set_print(s32 (*print_func)(void *, u8, char *), void *userdata)
static const char *levels[] = { "info", "warn", "error", "debug" };
#ifndef 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)
+static __thread char messagebuf[AL_LOG_MESSAGE_SIZE];
+
+static char *get_message_buffer(u8 level, const char *section, const char *name, const s32 line, const char *func, const char *fmt, va_list args)
{
- char *buffer = al_malloc(AL_LOG_MESSAGE_SIZE);
s32 prefix = 0;
-#ifdef AL_LOG_USE_SECTION
- prefix = al_snprintf(buffer, AL_LOG_MESSAGE_MAX, AL_LOG_TEMPLATE, name, line, func, levels[level], section);
-#else
- (void)section;
- 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;
+ if (!section) {
+ prefix = al_snprintf(messagebuf, AL_LOG_MESSAGE_MAX, AL_LOG_TEMPLATE, name, line, func, levels[level]);
+ } else {
+ prefix = al_snprintf(messagebuf, AL_LOG_MESSAGE_MAX, AL_LOG_TEMPLATE_SECTION, name, line, func, levels[level], section);
+ }
+ al_assert(prefix > 0);
+ al_vsnprintf(messagebuf + prefix, AL_LOG_MESSAGE_MAX - (size_t)prefix, fmt, args);
+ messagebuf[strcspn(messagebuf, "\r\n")] = '\0';
+ return messagebuf;
}
#endif
s32 _al_logv(u8 level, const char *section, const char *name, const s32 line, const char *func, const char *fmt, va_list args)
{
- if (!section) section = "";
#ifdef AL_LOG_SKIP
s32 ret = 0;
-#ifdef AL_LOG_USE_SECTION
- ret += al_printf(AL_LOG_TEMPLATE, name, line, func, levels[level], section);
-#else
- ret += al_printf(AL_LOG_TEMPLATE, name, line, func, levels[level]);
-#endif
+ if (!section) {
+ ret += al_printf(AL_LOG_TEMPLATE, name, line, func, levels[level]);
+ } else {
+ ret += al_printf(AL_LOG_TEMPLATE_SECTION, name, line, func, levels[level], section);
+ }
ret += al_vprintf(fmt, args);
if (strcspn(fmt, "\r\n") == al_strlen(fmt)) {
ret += al_printf("\n");
}
return ret;
#else
- return _al_print(_al_log_userdata, level, get_message_buffer(level, section, fmt, name, line, func, args));
+ return _al_print(_al_log_userdata, level, get_message_buffer(level, section, name, line, func, fmt, args));
#endif
}
diff --git a/src/random.c b/src/random.c
new file mode 100644
index 0000000..1bbf152
--- /dev/null
+++ b/src/random.c
@@ -0,0 +1,4 @@
+#include "../include/al/random.h"
+
+u32 al_rand_seed = 1738;
+__thread bool al_rand_set = false;
diff --git a/src/ring_buffer.c b/src/ring_buffer.c
index 1c39b7b..ded0138 100644
--- a/src/ring_buffer.c
+++ b/src/ring_buffer.c
@@ -3,9 +3,12 @@
#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
-void al_ring_buffer_init(struct al_ring_buffer *buf, u8 *data, size_t length)
+void al_ring_buffer_init(struct al_ring_buffer *buf, u8 *data, ptrdiff_t length)
{
buf->start = data;
buf->end = data + length;
@@ -20,7 +23,7 @@ static inline u8 *previous(struct al_ring_buffer *buf, u8 *ptr)
return --ptr;
}
-static inline void add(struct al_ring_buffer *buf, u8 **v, u8 *ptr, size_t n)
+static inline void add(struct al_ring_buffer *buf, u8 **v, u8 *ptr, ptrdiff_t n)
{
ptr += n;
al_assert(ptr <= buf->end);
@@ -28,14 +31,14 @@ static inline void add(struct al_ring_buffer *buf, u8 **v, u8 *ptr, size_t n)
al_atomic_store(void)(v, ptr, AL_ATOMIC_RELEASE);
}
-size_t al_ring_buffer_space(struct al_ring_buffer *buf)
+ptrdiff_t al_ring_buffer_space(struct al_ring_buffer *buf)
{
u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_RELAXED);
u8 *rp = previous(buf, (u8 *)al_atomic_load(void)(&buf->read, AL_ATOMIC_RELAXED));
return (wp <= rp) ? rp - wp : (buf->end - wp) + (rp - buf->start);
}
-u8 *al_ring_buffer_write_chunk(struct al_ring_buffer *buf, size_t *size)
+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));
@@ -43,19 +46,19 @@ u8 *al_ring_buffer_write_chunk(struct al_ring_buffer *buf, size_t *size)
return wp;
}
-void al_ring_buffer_append(struct al_ring_buffer *buf, u8 *ptr, size_t n)
+void al_ring_buffer_append(struct al_ring_buffer *buf, u8 *ptr, ptrdiff_t n)
{
add(buf, &buf->write, ptr, n);
}
-size_t al_ring_buffer_occupied(struct al_ring_buffer *buf)
+ptrdiff_t al_ring_buffer_occupied(struct al_ring_buffer *buf)
{
u8 *rp = al_atomic_load(void)(&buf->read, AL_ATOMIC_RELAXED);
u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_RELAXED);
return (rp <= wp) ? wp - rp : (buf->end - rp) + (wp - buf->start);
}
-u8 *al_ring_buffer_read_chunk(struct al_ring_buffer *buf, size_t *size)
+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);
@@ -63,24 +66,25 @@ u8 *al_ring_buffer_read_chunk(struct al_ring_buffer *buf, size_t *size)
return rp;
}
-void al_ring_buffer_consume(struct al_ring_buffer *buf, u8 *ptr, size_t n)
+void al_ring_buffer_consume(struct al_ring_buffer *buf, u8 *ptr, ptrdiff_t n)
{
add(buf, &buf->read, ptr, n);
}
-size_t al_ring_buffer_write(struct al_ring_buffer *buf, u8 *data, size_t n)
+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));
- size_t size = MIN((wp <= rp ? rp : buf->end) - wp, (ptrdiff_t)n);
+ ptrdiff_t size, wrap;
- al_memcpy(wp, data, size);
+ size = MIN((wp <= rp ? rp : buf->end) - wp, n);
+ al_memcpy(wp, data, (size_t)size);
wp += size;
if (wp >= buf->end) {
- size_t wrap = MIN(rp - buf->start, (ptrdiff_t)(n - size));
- al_memcpy(buf->start, data + size, wrap);
+ wrap = MIN(rp - buf->start, n - size);
+ al_memcpy(buf->start, data + size, (size_t)wrap);
wp = buf->start + wrap;
size += wrap;
}
@@ -90,19 +94,20 @@ size_t al_ring_buffer_write(struct al_ring_buffer *buf, u8 *data, size_t n)
return size;
}
-size_t al_ring_buffer_read(struct al_ring_buffer *buf, u8 *ptr, size_t n)
+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);
- size_t size = MIN((rp <= wp ? wp : buf->end) - rp, (ptrdiff_t)n);
+ ptrdiff_t size, wrap;
- al_memcpy(ptr, rp, size);
+ size = MIN((rp <= wp ? wp : buf->end) - rp, n);
+ al_memcpy(ptr, rp, (size_t)size);
rp += size;
if (rp >= buf->end) {
- size_t wrap = MIN(wp - buf->start, (ptrdiff_t)(n - size));
- al_memcpy(ptr + size, buf->start, wrap);
+ wrap = MIN(wp - buf->start, n - size);
+ al_memcpy(ptr + size, buf->start, (size_t)wrap);
rp = buf->start + wrap;
size += wrap;
}
@@ -112,27 +117,28 @@ size_t al_ring_buffer_read(struct al_ring_buffer *buf, u8 *ptr, size_t n)
return size;
}
-size_t al_ring_buffer_peek(struct al_ring_buffer *buf, u8 *ptr, size_t offset, size_t n)
+ptrdiff_t al_ring_buffer_peek(struct al_ring_buffer *buf, u8 *ptr, ptrdiff_t offset, ptrdiff_t n)
{
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;
+ ptrdiff_t size, wrap;
if (rp <= wp) {
rp += offset;
- size = MIN(wp - rp, (ptrdiff_t)n);
- if (size < 0)
+ size = MIN(wp - rp, n);
+ if (size < 0) {
return 0;
+ }
- al_memcpy(ptr, rp, size);
+ al_memcpy(ptr, rp, (size_t)size);
} else {
rp += offset;
- size = MIN(buf->end - rp, (ptrdiff_t)n);
+ size = MIN(buf->end - rp, n);
if (size > 0) {
- al_memcpy(ptr, rp, size);
+ al_memcpy(ptr, rp, (size_t)size);
n -= size;
rp = buf->start;
} else {
@@ -140,9 +146,9 @@ size_t al_ring_buffer_peek(struct al_ring_buffer *buf, u8 *ptr, size_t offset, s
size = 0;
}
- ptrdiff_t wrap = MIN(wp - rp, (ptrdiff_t)n);
+ wrap = MIN(wp - rp, n);
if (wrap > 0) {
- al_memcpy(ptr + size, rp, wrap);
+ al_memcpy(ptr + size, rp, (size_t)wrap);
size += wrap;
}
}
@@ -150,16 +156,18 @@ size_t al_ring_buffer_peek(struct al_ring_buffer *buf, u8 *ptr, size_t offset, s
return size;
}
-size_t al_ring_buffer_discard(struct al_ring_buffer *buf, size_t n)
+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);
- size_t discard = MIN((rp <= wp ? wp : buf->end) - rp, (ptrdiff_t)n);
+ ptrdiff_t discard, wrap;
+
+ discard = MIN((rp <= wp ? wp : buf->end) - rp, n);
rp += discard;
if (rp >= buf->end) {
- size_t wrap = MIN(wp - buf->start, (ptrdiff_t)(n - discard));
+ wrap = MIN(wp - buf->start, n - discard);
rp = buf->start + wrap;
discard += wrap;
}
diff --git a/src/str.c b/src/str.c
index c955d51..2ad46aa 100644
--- a/src/str.c
+++ b/src/str.c
@@ -1,18 +1,18 @@
#include "../include/al/str.h"
// https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=newlib/libc/stdlib/strtol.c;h=09d4333ed05f497ec00b7192204644349441e58d;hb=HEAD#l130
-s64 al_str_to_long(str *s, s32 base)
+s64 al_str_to_long(str *s, u32 base, bool *error)
{
u64 ret = 0;
u32 i = 0;
- s32 neg = 0;
+ bool neg = 0;
- while (al_isspace(al_str_at(s, i)) && i < s->len) {
+ while (al_isspace(al_str_at(s, i)) && i < s->length) {
i++;
}
if (al_str_at(s, i) == '-') {
- neg = 1;
+ neg = true;
i++;
} else if (al_str_at(s, i) == '+') {
i++;
@@ -24,41 +24,35 @@ s64 al_str_to_long(str *s, s32 base)
i += 2;
}
- u64 cutoff = neg ? -(u64)INT64_MIN : INT64_MAX;
- s32 add_limit = cutoff % (u64)base;
- cutoff /= (u64)base;
+ u64 cutoff = neg ? ((u64)INT64_MAX + 1) : (u64)INT64_MAX;
+ u64 add_limit = cutoff % base;
+ cutoff /= base;
- bool error = false;
+ *error = false;
- for (; i < s->len; i++) {
- char c = al_str_at(s, i);
+ for (; i < s->length; i++) {
+ uchar c = (uchar)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 for expressing a number.
- error = true;
+ *error = true;
break;
}
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;
+ *error = true;
break;
}
ret = ret * base + c;
}
- if (error) {
- ret = neg ? INT64_MIN : INT64_MAX;
- } else if (neg) {
- ret = -ret;
- }
-
- return ret;
+ return neg ? -(s64)ret : (s64)ret;
}
bool al_str_get_line(str *buffer, char sep, str *line)
@@ -70,17 +64,22 @@ bool al_str_get_line(str *buffer, char sep, str *line)
*line = *buffer;
} 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.
+ line->data += line->length + 1;
+ if ((bytes = (u32)(line->data - buffer->data)) >= buffer->length) {
+ // No more lines.
+ return false;
+ }
}
- bytes = buffer->len - bytes;
+ if ((bytes = buffer->length - bytes) == 0) {
+ // buffer is completely empty.
+ return false;
+ }
char *nl = (char *)al_memchr(line->data, sep, bytes);
// If we couldn't find a separator, move to the end of the buffer.
- line->len = !nl ? bytes : (u32)(nl - line->data);
+ line->length = !nl ? bytes : (u32)(nl - line->data);
return true;
}