core: rope: add bstr support

This commit is contained in:
2026-02-03 14:39:33 +00:00
parent c13b7a7e3a
commit 5889426478
2 changed files with 78 additions and 33 deletions

View File

@@ -3,10 +3,12 @@
#include <blue/core/hash.h> #include <blue/core/hash.h>
#include <blue/core/misc.h> #include <blue/core/misc.h>
#include <blue/core/stream.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
struct b_string; struct b_string;
struct b_bstr;
#define B_ROPE_TYPE(f) ((f) & 0xFF) #define B_ROPE_TYPE(f) ((f) & 0xFF)
@@ -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_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 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_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_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 #endif

View File

@@ -1,3 +1,4 @@
#include <blue/core/bstr.h>
#include <blue/core/rope.h> #include <blue/core/rope.h>
#include <inttypes.h> #include <inttypes.h>
#include <stdio.h> #include <stdio.h>
@@ -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) size_t b_rope_get_size(const struct b_rope *rope)
{ {
return rope->r_len_total; return rope->r_len_total;
@@ -181,56 +199,77 @@ static void rope_iterate(
} }
} }
struct to_cstr_args { static void to_bstr(const struct b_rope *rope, void *arg)
char *str;
size_t max;
size_t ptr;
};
static void to_cstr(const struct b_rope *rope, void *arg)
{ {
struct to_cstr_args *str = arg; b_bstr *str = arg;
if (str->ptr >= str->max) {
return;
}
unsigned int type = B_ROPE_TYPE(rope->r_flags); 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) { switch (type) {
case B_ROPE_F_CHAR: 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; break;
case B_ROPE_F_CSTR: case B_ROPE_F_CSTR:
case B_ROPE_F_CSTR_BORROWED: case B_ROPE_F_CSTR_BORROWED:
case B_ROPE_F_CSTR_STATIC: 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; break;
case B_ROPE_F_INT: case B_ROPE_F_INT:
nr_written b_bstr_write_fmt(str, NULL, "%" PRIdPTR, rope->r_v.v_int);
= snprintf(dest, capacity, "%" PRIdPTR, rope->r_v.v_int);
break; break;
case B_ROPE_F_UINT: case B_ROPE_F_UINT:
nr_written b_bstr_write_fmt(str, NULL, "%" PRIuPTR, rope->r_v.v_uint);
= snprintf(dest, capacity, "%" PRIuPTR, rope->r_v.v_uint);
break; break;
default: default:
break; 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 = { b_stream *out = arg;
.str = out,
.max = max,
.ptr = 0,
};
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;
} }