From 588942647842c9488c6a9b72ee4e9715b31bb2fd Mon Sep 17 00:00:00 2001 From: Max Wash Date: Tue, 3 Feb 2026 14:39:33 +0000 Subject: [PATCH] core: rope: add bstr support --- core/include/blue/core/rope.h | 12 +++-- core/rope.c | 99 ++++++++++++++++++++++++----------- 2 files changed, 78 insertions(+), 33 deletions(-) diff --git a/core/include/blue/core/rope.h b/core/include/blue/core/rope.h index dd1632d..f6ed7ae 100644 --- a/core/include/blue/core/rope.h +++ b/core/include/blue/core/rope.h @@ -3,10 +3,12 @@ #include #include +#include #include #include struct b_string; +struct b_bstr; #define B_ROPE_TYPE(f) ((f) & 0xFF) @@ -17,7 +19,7 @@ struct b_string; .r_v = {.v_char = (c) } \ } -#define B_ROPE_CSTR(str) \ +#define B_ROPE_CSTR(str) \ { \ .r_flags = B_ROPE_F_CSTR_BORROWED, \ .r_len_total = strlen(str), \ @@ -29,7 +31,7 @@ struct b_string; }, \ } -#define B_ROPE_CSTR_STATIC(str) \ +#define B_ROPE_CSTR_STATIC(str) \ { \ .r_flags = B_ROPE_F_CSTR_STATIC, \ .r_len_total = strlen(str), \ @@ -94,10 +96,14 @@ BLUE_API void b_rope_init_uint(b_rope *rope, uintptr_t v); BLUE_API void b_rope_destroy(b_rope *rope); +BLUE_API void b_rope_iterate( + const b_rope *rope, void (*func)(const b_rope *, void *), void *arg); BLUE_API size_t b_rope_get_size(const b_rope *rope); BLUE_API void b_rope_concat(b_rope *result, const b_rope *left, const b_rope *right); BLUE_API void b_rope_join(b_rope *result, const b_rope **ropes, size_t nr_ropes); -BLUE_API void b_rope_to_cstr(const b_rope *rope, char *out, size_t max); +BLUE_API b_status b_rope_to_cstr(const b_rope *rope, char *out, size_t max); +BLUE_API b_status b_rope_to_bstr(const b_rope *rope, struct b_bstr *str); +BLUE_API b_status b_rope_to_string(const b_rope *rope, b_stream *out); #endif diff --git a/core/rope.c b/core/rope.c index ecab2ae..1fe2c59 100644 --- a/core/rope.c +++ b/core/rope.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -86,6 +87,23 @@ void b_rope_destroy(struct b_rope *rope) } } +void b_rope_iterate( + const struct b_rope *rope, void (*func)(const b_rope *, void *), void *arg) +{ + if (B_ROPE_TYPE(rope->r_flags) != B_ROPE_F_COMPOSITE) { + func(rope, arg); + return; + } + + if (rope->r_v.v_composite.r_left) { + b_rope_iterate(rope->r_v.v_composite.r_left, func, arg); + } + + if (rope->r_v.v_composite.r_right) { + b_rope_iterate(rope->r_v.v_composite.r_right, func, arg); + } +} + size_t b_rope_get_size(const struct b_rope *rope) { return rope->r_len_total; @@ -181,56 +199,77 @@ static void rope_iterate( } } -struct to_cstr_args { - char *str; - size_t max; - size_t ptr; -}; - -static void to_cstr(const struct b_rope *rope, void *arg) +static void to_bstr(const struct b_rope *rope, void *arg) { - struct to_cstr_args *str = arg; - if (str->ptr >= str->max) { - return; - } + b_bstr *str = arg; unsigned int type = B_ROPE_TYPE(rope->r_flags); - char *dest = str->str + str->ptr; - size_t capacity = str->max - str->ptr; - size_t nr_written = 0; - switch (type) { case B_ROPE_F_CHAR: - nr_written = snprintf(dest, capacity, "%c", rope->r_v.v_char); + b_bstr_write_char(str, rope->r_v.v_char); break; case B_ROPE_F_CSTR: case B_ROPE_F_CSTR_BORROWED: case B_ROPE_F_CSTR_STATIC: - nr_written = snprintf(dest, capacity, "%s", rope->r_v.v_cstr.s); + b_bstr_write_cstr(str, rope->r_v.v_cstr.s, NULL); break; case B_ROPE_F_INT: - nr_written - = snprintf(dest, capacity, "%" PRIdPTR, rope->r_v.v_int); + b_bstr_write_fmt(str, NULL, "%" PRIdPTR, rope->r_v.v_int); break; case B_ROPE_F_UINT: - nr_written - = snprintf(dest, capacity, "%" PRIuPTR, rope->r_v.v_uint); + b_bstr_write_fmt(str, NULL, "%" PRIuPTR, rope->r_v.v_uint); break; default: break; } - - str->ptr += nr_written; } -void b_rope_to_cstr(const struct b_rope *rope, char *out, size_t max) +static void to_stream(const struct b_rope *rope, void *arg) { - struct to_cstr_args args = { - .str = out, - .max = max, - .ptr = 0, - }; + b_stream *out = arg; - rope_iterate(rope, to_cstr, &args); + unsigned int type = B_ROPE_TYPE(rope->r_flags); + + switch (type) { + case B_ROPE_F_CHAR: + b_stream_write_char(out, rope->r_v.v_char); + break; + case B_ROPE_F_CSTR: + case B_ROPE_F_CSTR_BORROWED: + case B_ROPE_F_CSTR_STATIC: + b_stream_write_string(out, rope->r_v.v_cstr.s, NULL); + break; + case B_ROPE_F_INT: + b_stream_write_fmt(out, NULL, "%" PRIdPTR, rope->r_v.v_int); + break; + case B_ROPE_F_UINT: + b_stream_write_fmt(out, NULL, "%" PRIuPTR, rope->r_v.v_uint); + break; + default: + break; + } +} + +b_status b_rope_to_cstr(const struct b_rope *rope, char *out, size_t max) +{ + b_bstr str; + b_bstr_begin(&str, out, max); + rope_iterate(rope, to_bstr, &str); + + return B_SUCCESS; +} + +b_status b_rope_to_bstr(const struct b_rope *rope, b_bstr *str) +{ + rope_iterate(rope, to_bstr, str); + + return B_SUCCESS; +} + +b_status b_rope_to_string(const struct b_rope *rope, b_stream *out) +{ + rope_iterate(rope, to_stream, out); + + return B_SUCCESS; }