diff options
author | Anton Kling <anton@kling.gg> | 2024-10-13 13:33:29 +0200 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2024-10-13 13:34:01 +0200 |
commit | a67d4744d78fc58846f29667ae49cee70fa0bf16 (patch) | |
tree | 848dc06f4cf19d4a6560b7bea604d8177f06e7f7 /userland | |
parent | edca64134a9873f32379b2b83bd925ecca1c19b1 (diff) |
libc/sb: Refactor string builder to allow for none malloc allocations
A lot of code written usually has means of doing allocations in a more
optimal way than having the string builder library doing it itself.
For example a temporary buffer can be allocated on the stack and the
string builder functions can then make use of this buffer without ever
having to run malloc/free(which would be expensive)
Diffstat (limited to 'userland')
-rw-r--r-- | userland/libc/include/tb/sb.h | 18 | ||||
-rw-r--r-- | userland/libc/stdlib/realpath.c | 2 | ||||
-rw-r--r-- | userland/libc/tb/sb.c | 82 |
3 files changed, 76 insertions, 26 deletions
diff --git a/userland/libc/include/tb/sb.h b/userland/libc/include/tb/sb.h index c2fa1cf..8493997 100644 --- a/userland/libc/include/tb/sb.h +++ b/userland/libc/include/tb/sb.h @@ -2,25 +2,29 @@ #define SB_H #include "sv.h" #include <stddef.h> +#include <stdint.h> struct sb { char *string; size_t length; size_t capacity; + uint8_t prebuffer; }; struct sv; -void sb_init(struct sb *ctx, size_t starting_capacity); +void sb_init(struct sb *ctx); +int sb_init_capacity(struct sb *ctx, size_t starting_capacity); +void sb_init_buffer(struct sb *ctx, char *buffer, size_t size); void sb_free(struct sb *ctx); void sb_reset(struct sb *ctx); int sb_isempty(const struct sb *ctx); -void sb_append_char(struct sb *ctx, char c); +int sb_append_char(struct sb *ctx, char c); int sb_delete_right(struct sb *ctx, size_t n); -void sb_append(struct sb *ctx, const char *s); -void sb_append_buffer(struct sb *ctx, const char *buffer, +int sb_append(struct sb *ctx, const char *s); +int sb_append_buffer(struct sb *ctx, const char *buffer, size_t length); -void sb_append_sv(struct sb *ctx, struct sv sv); -void sb_prepend_sv(struct sb *ctx, struct sv sv); -void sb_prepend_buffer(struct sb *ctx, const char *buffer, size_t length); +int sb_append_sv(struct sb *ctx, struct sv sv); +int sb_prepend_sv(struct sb *ctx, struct sv sv); +int sb_prepend_buffer(struct sb *ctx, const char *buffer, size_t length); #endif diff --git a/userland/libc/stdlib/realpath.c b/userland/libc/stdlib/realpath.c index 7ce0f6c..86ac4ed 100644 --- a/userland/libc/stdlib/realpath.c +++ b/userland/libc/stdlib/realpath.c @@ -16,7 +16,7 @@ char *realpath(const char *filename, char *resolvedname) { strcat(cwd, filename); // FIXME: bounds check struct sb string; - sb_init(&string, 512); + sb_init_capacity(&string, 256); struct sv path = C_TO_SV(cwd); diff --git a/userland/libc/tb/sb.c b/userland/libc/tb/sb.c index 7ba83af..c379082 100644 --- a/userland/libc/tb/sb.c +++ b/userland/libc/tb/sb.c @@ -3,13 +3,36 @@ #include <string.h> #include <tb/sb.h> -void sb_init(struct sb *ctx, size_t starting_capacity) { - ctx->string = malloc(starting_capacity); +#define DEFAULT_CAPACITY 256 + +void sb_init(struct sb *ctx) { + (void)sb_init_capacity(ctx, DEFAULT_CAPACITY); +} + +int sb_init_capacity(struct sb *ctx, size_t starting_capacity) { ctx->length = 0; + ctx->prebuffer = 0; + ctx->string = malloc(starting_capacity); + if (NULL == ctx->string) { + ctx->capacity = 0; + return 0; + } ctx->capacity = starting_capacity; + return 1; +} + +void sb_init_buffer(struct sb *ctx, char *buffer, size_t size) { + ctx->string = buffer; + ctx->capacity = size; + ctx->length = 0; + ctx->prebuffer = 1; } void sb_free(struct sb *ctx) { + if (ctx->prebuffer) { + ctx->length = 0; + return; + } ctx->length = 0; ctx->capacity = 0; free(ctx->string); @@ -24,13 +47,30 @@ int sb_isempty(const struct sb *ctx) { return (0 == ctx->length); } -void sb_append_char(struct sb *ctx, char c) { +int sb_increase_buffer(struct sb *ctx, size_t min) { + if (ctx->prebuffer) { + return 0; + } + size_t new_capacity = ctx->capacity + max(32, min); + char *new_allocation = realloc(ctx->string, new_capacity); + if (!new_allocation) { + return 0; + } + + ctx->string = new_allocation; + ctx->capacity = new_capacity; + return 1; +} + +int sb_append_char(struct sb *ctx, char c) { if (1 > ctx->capacity - ctx->length) { - ctx->capacity += 32; - ctx->string = realloc(ctx->string, ctx->capacity); + if (!sb_increase_buffer(ctx, 1)) { + return 0; + } } memcpy(ctx->string + ctx->length, &c, 1); ctx->length++; + return 1; } int sb_delete_right(struct sb *ctx, size_t n) { @@ -39,39 +79,45 @@ int sb_delete_right(struct sb *ctx, size_t n) { return n; } -void sb_append(struct sb *ctx, const char *s) { +int sb_append(struct sb *ctx, const char *s) { size_t l = strlen(s); if (l > ctx->capacity - ctx->length) { - ctx->capacity += l; - ctx->string = realloc(ctx->string, ctx->capacity); + if (!sb_increase_buffer(ctx, l)) { + return 0; + } } memcpy(ctx->string + ctx->length, s, l); ctx->length += l; + return 1; } -void sb_prepend_sv(struct sb *ctx, struct sv sv) { - sb_prepend_buffer(ctx, sv.s, sv.length); +int sb_prepend_sv(struct sb *ctx, struct sv sv) { + return sb_prepend_buffer(ctx, sv.s, sv.length); } -void sb_prepend_buffer(struct sb *ctx, const char *buffer, size_t length) { +int sb_prepend_buffer(struct sb *ctx, const char *buffer, size_t length) { if (length > ctx->capacity - ctx->length) { - ctx->capacity += length; - ctx->string = realloc(ctx->string, ctx->capacity); + if (!sb_increase_buffer(ctx, length)) { + return 0; + } } memmove(ctx->string + length, ctx->string, ctx->length); memcpy(ctx->string, buffer, length); ctx->length += length; + return 1; } -void sb_append_buffer(struct sb *ctx, const char *buffer, size_t length) { +int sb_append_buffer(struct sb *ctx, const char *buffer, size_t length) { if (length > ctx->capacity - ctx->length) { - ctx->capacity += length; - ctx->string = realloc(ctx->string, ctx->capacity); + if (!sb_increase_buffer(ctx, length)) { + return 0; + } } memcpy(ctx->string + ctx->length, buffer, length); ctx->length += length; + return 1; } -void sb_append_sv(struct sb *ctx, struct sv sv) { - sb_append_buffer(ctx, sv.s, sv.length); +int sb_append_sv(struct sb *ctx, struct sv sv) { + return sb_append_buffer(ctx, sv.s, sv.length); } |