From a5f1cb5ce34f31b9c46de94e55b5f85d571b792f Mon Sep 17 00:00:00 2001 From: justanothercatgirl Date: Tue, 1 Apr 2025 01:44:47 +0300 Subject: Added stringbuilder and STE --- include/stringbuilder.h | 114 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 include/stringbuilder.h (limited to 'include/stringbuilder.h') diff --git a/include/stringbuilder.h b/include/stringbuilder.h new file mode 100644 index 0000000..e695082 --- /dev/null +++ b/include/stringbuilder.h @@ -0,0 +1,114 @@ +#ifndef JAC_STRINGBUILDER +#define JAC_STRINGBUILDER + +#include +#include +#include +#include +#include + +typedef struct jac_sb { + char *data; + size_t size; + size_t cap; +} jac_sb; + +jac_sb jac_sb_empty(void); +jac_sb jac_sb_new(size_t size); +jac_sb jac_sb_from_buf(const char* buf); +jac_sb jac_sb_from_buf_n(const char* buf, size_t size); + +void jac_sb_append_buf(jac_sb *sb, const char *c); +void jac_sb_append_buf_n(jac_sb *sb, const char *c, size_t n); +void jac_sb_putc(jac_sb *sb, char c); +void jac_sb_snprintf(jac_sb *sb, const char* fmt, ...); +void jac_sb_vsnprintf(jac_sb *sb, const char* fmt, va_list list); + +void jac_sb_free(jac_sb sb); + +#define STRINGBUILDER_IMPLEMENTATION +#ifdef STRINGBUILDER_IMPLEMENTATION + +#define __SB_REALLOC(sb, n) \ +do { \ + if (sb->size + n >= sb->cap) { \ + size_t rsz = 1UL << \ + (64 - __builtin_clzl((unsigned long)(sb->size+n))); \ + sb->data = realloc(sb->data, rsz + 1); \ + sb->cap = rsz; \ + } \ + sb->size += n; \ +} while(0) \ + +jac_sb jac_sb_empty(void) { + return (jac_sb){.data = calloc(1, 1), .size = 0, .cap = 0}; +} +jac_sb jac_sb_new(size_t size) { + return (jac_sb){.data = calloc(size + 1, 1), .size = 0, .cap = size}; +} +jac_sb jac_sb_from_buf(const char* buf) { + size_t ln = strlen(buf); + jac_sb ret = {.data = malloc(ln + 1), .size = ln, .cap = ln}; + memcpy(ret.data, buf, ln); + ret.data[ret.size] = '\0'; + return ret; +} +jac_sb jac_sb_from_buf_n(const char* buf, size_t size) { + jac_sb ret = {.data = malloc(size + 1), .size = size, .cap = size}; + memcpy(ret.data, buf, size); + ret.data[size] = '\0'; + return ret; +} + +void jac_sb_append_buf(jac_sb *sb, const char *c) { + jac_sb_append_buf_n(sb, c, strlen(c)); +} +void jac_sb_append_buf_n(jac_sb *sb, const char *c, size_t n) { + __SB_REALLOC(sb, n); + memcpy(sb->data + sb->size - n, c, n); + sb->data[sb->size] = '\0'; +} +void jac_sb_putc(jac_sb *sb, char c) { + if (sb->size + 1 >= sb->cap) { + sb->cap <<= 1; + sb->data = realloc(sb->data, sb->cap + 1); + } + sb->data[sb->size++] = c; + sb->data[sb->size] = '\0'; +} + +void jac_sb_snprintf(jac_sb *sb, const char* fmt, ...) { + va_list l; + va_start(l, fmt); + jac_sb_vsnprintf(sb, fmt, l); +} +void jac_sb_vsnprintf(jac_sb *sb, const char* fmt, va_list list) { + va_list ls1; + size_t ln; +try_write: + /*cap: 4, size: 2 + * | a | b | \0 | \0 | \0 | + */ + va_copy(ls1, list); + ln = vsnprintf(sb->data + sb->size, sb->cap - sb->size + 1, fmt, ls1); + va_end(ls1); + if (ln >= sb->cap - sb->size + 1) { + sb->cap <<= 1; + sb->data = realloc(sb->data, sb->cap + 1); + goto try_write; + } + va_end(list); + sb->size += ln; +} + +void jac_sb_free(jac_sb sb) { + free(sb.data); +} + + +#undef __SB_REALLOC +#endif /* STRINGBUILDER_IMPLEMENTATION */ + +#endif /* JAC_STRINGBUILDER */ + +/* vim: set ts=8 noet: */ -- cgit v1.2.3-70-g09d2