From bdcd4163c7fd03b80934b5499fc4e07b65ad36bd Mon Sep 17 00:00:00 2001 From: Max Wash Date: Tue, 3 Feb 2026 14:33:06 +0000 Subject: [PATCH] core: stringstream: added read-support any characters written to a stringstream can be optionally read back again using the b_stream read API. this functions similar to a ringbuffer, with two key differences: 1) the buffer is not circular, and will continuously expand to accomodate all incoming data. 2) reading data from the stringstream does not remove it from the buffer. --- core/include/blue/core/stringstream.h | 14 ----- core/stringstream.c | 73 +++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/core/include/blue/core/stringstream.h b/core/include/blue/core/stringstream.h index 51d9d06..18e9b7e 100644 --- a/core/include/blue/core/stringstream.h +++ b/core/include/blue/core/stringstream.h @@ -30,20 +30,6 @@ BLUE_API char *b_stringstream_steal(b_stringstream *strv); BLUE_API size_t b_stringstream_get_length(const b_stringstream *strv); -#if 0 -BLUE_API void b_stringstream_push_indent(b_stringstream *strv, int indent); -BLUE_API void b_stringstream_pop_indent(b_stringstream *strv); - -BLUE_API b_status b_stringstream_add(b_stringstream *strv, const char *str); -BLUE_API b_status b_stringstream_addf(b_stringstream *strv, const char *format, ...); -BLUE_API b_status b_stringstream_addv(b_stringstream *strv, const char **strs); -BLUE_API b_status b_stringstream_addvf( - b_stringstream *strv, const char *format, va_list arg); -BLUE_API b_status b_stringstream_addvl( - b_stringstream *strv, const char **strs, size_t count); -BLUE_API b_status b_stringstream_add_many(b_stringstream *strv, ...); -#endif - B_DECLS_END; #endif diff --git a/core/stringstream.c b/core/stringstream.c index 1c0297f..b5bee2a 100644 --- a/core/stringstream.c +++ b/core/stringstream.c @@ -10,6 +10,7 @@ struct b_stringstream_p { char *ss_buf; + size_t ss_ptr; size_t ss_len; size_t ss_max; unsigned char ss_alloc; @@ -17,6 +18,50 @@ struct b_stringstream_p { /*** PRIVATE FUNCTIONS ********************************************************/ +static enum b_status __getc(struct b_stringstream_p *ss, b_wchar *out) +{ + size_t available = ss->ss_len - ss->ss_ptr; + + const char *p = ss->ss_buf + ss->ss_ptr; + + size_t to_copy = b_wchar_utf8_codepoint_stride(p); + if (to_copy > available) { + return B_ERR_BAD_STATE; + } + + b_wchar c = b_wchar_utf8_codepoint_decode(p); + *out = c; + + if (c == B_WCHAR_INVALID) { + return B_ERR_BAD_STATE; + } + + ss->ss_ptr += to_copy; + + return B_SUCCESS; +} + +static enum b_status __gets( + struct b_stringstream_p *ss, char *s, size_t len, size_t *nr_read) +{ + size_t available = ss->ss_len - ss->ss_ptr; + size_t to_copy = len; + + if (available < to_copy) { + to_copy = available; + } + + memcpy(s, ss->ss_buf + ss->ss_ptr, to_copy); + + ss->ss_ptr += to_copy; + + if (nr_read) { + *nr_read = to_copy; + } + + return B_SUCCESS; +} + static enum b_status __puts( struct b_stringstream_p *ss, const char *s, size_t len, size_t *nr_written) { @@ -111,7 +156,7 @@ b_stringstream *b_stringstream_create_with_buffer(char *buf, size_t max) b_stream_cfg *cfg = b_object_get_protected(s, B_TYPE_STREAM); struct b_stringstream_p *p = b_object_get_private(s, B_TYPE_STRINGSTREAM); - cfg->s_mode = B_STREAM_WRITE | Z__B_STREAM_STATIC; + cfg->s_mode = B_STREAM_READ | B_STREAM_WRITE | Z__B_STREAM_STATIC; p->ss_buf = buf; p->ss_max = max; @@ -131,7 +176,7 @@ b_stringstream *b_stringstream_create(void) b_stream_cfg *cfg = b_object_get_protected(s, B_TYPE_STREAM); struct b_stringstream_p *p = b_object_get_private(s, B_TYPE_STRINGSTREAM); - cfg->s_mode = B_STREAM_WRITE | Z__B_STREAM_STATIC; + cfg->s_mode = B_STREAM_READ | B_STREAM_WRITE | Z__B_STREAM_STATIC; p->ss_buf = malloc(DEFAULT_CAPACITY + 1); if (!p->ss_buf) { @@ -193,6 +238,26 @@ static void stringstream_fini(b_object *obj, void *priv) } } +enum b_status stream_getc(b_stream *stream, b_wchar *c) +{ + struct b_stringstream_p *s + = b_object_get_private(stream, B_TYPE_STRINGSTREAM); + + enum b_status status = __getc(s, c); + + return status; +} + +enum b_status stream_read(b_stream *stream, void *buf, size_t count, size_t *nr_read) +{ + struct b_stringstream_p *s + = b_object_get_private(stream, B_TYPE_STRINGSTREAM); + + enum b_status status = __gets(s, buf, count, nr_read); + + return status; +} + enum b_status stream_write( b_stream *stream, const void *buf, size_t count, size_t *nr_written) { @@ -215,8 +280,8 @@ B_TYPE_CLASS_DEFINITION_BEGIN(b_stringstream) B_INTERFACE_ENTRY(s_close) = NULL; B_INTERFACE_ENTRY(s_seek) = NULL; B_INTERFACE_ENTRY(s_tell) = NULL; - B_INTERFACE_ENTRY(s_getc) = NULL; - B_INTERFACE_ENTRY(s_read) = NULL; + B_INTERFACE_ENTRY(s_getc) = stream_getc; + B_INTERFACE_ENTRY(s_read) = stream_read; B_INTERFACE_ENTRY(s_write) = stream_write; B_INTERFACE_ENTRY(s_reserve) = NULL; B_TYPE_CLASS_INTERFACE_END(b_stream, B_TYPE_STREAM)