From 8efdd3d26969db25ec113e94c5d2bb66373efaa0 Mon Sep 17 00:00:00 2001 From: Martin Michalec Date: Sun, 22 Feb 2026 02:56:50 +0300 Subject: add implementation --- .gitmodules | 3 ++ include/cmmm/string-builder.h | 99 +++++++++++++++++++++++++++++++++++++++++++ src/string-builder.c | 41 ++++++++++++++++++ vendor/cmmm/dynamic-array | 1 + 4 files changed, 144 insertions(+) create mode 100644 .gitmodules create mode 100644 include/cmmm/string-builder.h create mode 100644 src/string-builder.c create mode 160000 vendor/cmmm/dynamic-array diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4cce083 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vendor/cmmm/dynamic-array"] + path = vendor/cmmm/dynamic-array + url = https://git.michalec.dev/dynamic-array diff --git a/include/cmmm/string-builder.h b/include/cmmm/string-builder.h new file mode 100644 index 0000000..42fb24a --- /dev/null +++ b/include/cmmm/string-builder.h @@ -0,0 +1,99 @@ +#ifndef INCLUDED__CMMM__STRING_BUILDER__H +#define INCLUDED__CMMM__STRING_BUILDER__H + +// #define CMMM__STRING_BUILDER__STRIP_VENDOR +// #define CMMM__STRING_BUILDER__SHORT_NAMESPACE + +#include +#include +#include "cmmm/dynamic-array.h" + +#define CMMM__STRING_BUILDER struct string_builder * +struct cmmm__string_builder { + union { char *items, *string; }; + size_t count; + size_t capacity; +}; + +#define CMMM__STRING_BUILDER__APPEND_CHAR(SB, CHAR) \ + CMMM__DYNAMIC_ARRAY__APPEND (SB, CHAR) + +#define CMMM__STRING_BUILDER__APPEND_BUF(SB, BUF, SIZE) \ + CMMM__DYNAMIC_ARRAY__APPEND_MANY (SB, BUF, SIZE) + +#define CMMM__STRING_BUILDER__APPEND_CSTR(SB, CSTR) \ + ({ \ + const char *s = (CSTR); \ + size_t n = strlen (s); \ + CMMM__DYNAMIC_ARRAY__APPEND_MANY(SB, s, n); \ + }) + +#define CMMM__STRING_BUILDER__APPEND_CSTRS(SB, ...) \ + cmmm__string_builder__append_cstrs (&(SB), __VA_ARGS__, NULL) + +#define CMMM__STRING_BUILDER__APPEND_STRING_VIEW(SB, SV) \ + CMMM__DYNAMIC_ARRAY__APPEND_MANY(SB, (SV).beg, CMMM__STRING_VIEW__LENGTH (SV)); + +#define CMMM__STRING_BUILDER__APPEND_NULL(SB) \ + CMMM__DYNAMIC_ARRAY__APPEND (SB, '\0') + +#define CMMM__STRING_BUILDER__RESET(SB) CMMM__DYNAMIC_ARRAY__RESET (SB) +#define CMMM__STRING_BUILDER__FREE( SB) CMMM__DYNAMIC_ARRAY__FREE ( SB) + +void cmmm__string_builder__append_ntimes (CMMM__STRING_BUILDER, char c, size_t n); +void cmmm__string_builder__append_cstrs (CMMM__STRING_BUILDER, ...); +void cmmm__string_builder__printf (CMMM__STRING_BUILDER, const char *format, ...); + +#ifdef CMMM__STRING_BUILDER__SHORT_NAMESPACE +#define CMMM__SB_STRIP_VENDOR CMMM__STRING_BUILDER__STRIP_VENDOR +#define CMMM__SB_SHORT_NAMESPACE CMMM__STRING_BUILDER__SHORT_NAMESPACE +#define CMMM__SB CMMM__STRING_BUILDER +#define cmmm__sb cmmm__string_builder +#define CMMM__SB_APPEND_CHAR CMMM__STRING_BUILDER__APPEND_CHAR +#define CMMM__SB_APPEND_BUF CMMM__STRING_BUILDER__APPEND_BUF +#define CMMM__SB_APPEND_CSTR CMMM__STRING_BUILDER__APPEND_CSTR +#define CMMM__SB_APPEND_CSTRS CMMM__STRING_BUILDER__APPEND_CSTRS +#define CMMM__SB_APPEND_STRING_VIEW CMMM__STRING_BUILDER__APPEND_STRING_VIEW +#define CMMM__SB_APPEND_NULL CMMM__STRING_BUILDER__APPEND_NULL +#define CMMM__SB_RESET CMMM__STRING_BUILDER__RESET +#define CMMM__SB_FREE CMMM__STRING_BUILDER__FREE +#define cmmm__sb_append_ntimes cmmm__string_builder__append_ntimes +#define cmmm__sb_append_cstrs cmmm__string_builder__append_cstrs +#define cmmm__sb_printf cmmm__string_builder__printf +#endif // CMMM__STRING_BUILDER__SHORT_NAMESPACE + +#ifdef CMMM__STRING_BUILDER__STRIP_VENDOR +#define STRING_BUILDER__STRIP_VENDOR CMMM__STRING_BUILDER__STRIP_VENDOR +#define STRING_BUILDER__SHORT_NAMESPACE CMMM__STRING_BUILDER__SHORT_NAMESPACE +#define STRING_BUILDER CMMM__STRING_BUILDER +#define STRING_BUILDER__APPEND_CHAR CMMM__STRING_BUILDER__APPEND_CHAR +#define STRING_BUILDER__APPEND_BUF CMMM__STRING_BUILDER__APPEND_BUF +#define STRING_BUILDER__APPEND_CSTR CMMM__STRING_BUILDER__APPEND_CSTR +#define STRING_BUILDER__APPEND_CSTRS CMMM__STRING_BUILDER__APPEND_CSTRS +#define STRING_BUILDER__APPEND_STRING_VIEW CMMM__STRING_BUILDER__APPEND_STRING_VIEW +#define STRING_BUILDER__APPEND_NULL CMMM__STRING_BUILDER__APPEND_NULL +#define STRING_BUILDER__RESET CMMM__STRING_BUILDER__RESET +#define STRING_BUILDER__FREE CMMM__STRING_BUILDER__FREE +#define string_builder__append_ntimes cmmm__string_builder__append_ntimes +#define string_builder__append_cstrs cmmm__string_builder__append_cstrs +#define string_builder__printf cmmm__string_builder__printf + +#ifdef CMMM__STRING_BUILDER__SHORT_NAMESPACE +#define SB_STRIP_VENDOR CMMM__STRING_BUILDER__STRIP_VENDOR +#define SB_SHORT_NAMESPACE CMMM__STRING_BUILDER__SHORT_NAMESPACE +#define SB CMMM__STRING_BUILDER +#define SB_APPEND_CHAR CMMM__STRING_BUILDER__APPEND_CHAR +#define SB_APPEND_BUF CMMM__STRING_BUILDER__APPEND_BUF +#define SB_APPEND_CSTR CMMM__STRING_BUILDER__APPEND_CSTR +#define SB_APPEND_CSTRS CMMM__STRING_BUILDER__APPEND_CSTRS +#define SB_APPEND_STRING_VIEW CMMM__STRING_BUILDER__APPEND_STRING_VIEW +#define SB_APPEND_NULL CMMM__STRING_BUILDER__APPEND_NULL +#define SB_RESET CMMM__STRING_BUILDER__RESET +#define SB_FREE CMMM__STRING_BUILDER__FREE +#define sb_append_ntimes cmmm__string_builder__append_ntimes +#define sb_append_cstrs cmmm__string_builder__append_cstrs +#define sb_printf cmmm__string_builder__printf +#endif // CMMM__STRING_BUILDER__SHORT_NAMESPACE +#endif // CMMM__STRING_BUILDER__STRIP_VENDOR + +#endif // INCLUDED__STRING_BUILDER__H diff --git a/src/string-builder.c b/src/string-builder.c new file mode 100644 index 0000000..0c53367 --- /dev/null +++ b/src/string-builder.c @@ -0,0 +1,41 @@ +#include "string-builder.h" +#include +#include + +void +string_builder__append_ntimes (STRING_BUILDER sb, char c, size_t n) +{ + DYNAMIC_ARRAY__ENSURE_CAPACITY (*sb, n); + memset (sb->items + sb->count, c, n); + sb->count += n; +} + +void +string_builder__append_cstrs (STRING_BUILDER sb, ...) +{ + va_list args; + + va_start (args, sb); + const char *arg = va_arg (args, const char *); + while (arg) { + STRING_BUILDER__APPEND_CSTR(*sb, arg); + arg = va_arg (args, const char *); + } va_end (args); +} + +void +string_builder__printf (STRING_BUILDER sb, const char *format, ...) +{ + va_list args; + + va_start (args, format); + int size = vsnprintf (NULL, 0, format, args); + va_end (args); + ASSERT (size >= 0); + + DYNAMIC_ARRAY__ENSURE_CAPACITY (*sb, size + 1); + va_start (args, format); + vsnprintf (&sb->items[sb->count], size + 1, format, args); + va_end (args); + sb->count += size; +} diff --git a/vendor/cmmm/dynamic-array b/vendor/cmmm/dynamic-array new file mode 160000 index 0000000..f6e9aa1 --- /dev/null +++ b/vendor/cmmm/dynamic-array @@ -0,0 +1 @@ +Subproject commit f6e9aa1f489f2aa052e2caa5748f8d081346b8b1 -- cgit v1.3