summaryrefslogtreecommitdiff
path: root/userland
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-10-13 13:33:29 +0200
committerAnton Kling <anton@kling.gg>2024-10-13 13:34:01 +0200
commita67d4744d78fc58846f29667ae49cee70fa0bf16 (patch)
tree848dc06f4cf19d4a6560b7bea604d8177f06e7f7 /userland
parentedca64134a9873f32379b2b83bd925ecca1c19b1 (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.h18
-rw-r--r--userland/libc/stdlib/realpath.c2
-rw-r--r--userland/libc/tb/sb.c82
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);
}