Add more guf_str functions

This commit is contained in:
jun 2025-03-20 23:30:45 +01:00
parent 21d1b04e6b
commit 275f46226d

View File

@ -90,15 +90,13 @@ GUF_STR_KWRDS void guf_str_free(guf_str *str, void *ctx);
GUF_STR_KWRDS guf_str *guf_str_copy(guf_str *dst, const guf_str *src, void *ctx); GUF_STR_KWRDS guf_str *guf_str_copy(guf_str *dst, const guf_str *src, void *ctx);
GUF_STR_KWRDS guf_str *guf_str_move(guf_str *dst, guf_str *src, void *ctx); GUF_STR_KWRDS guf_str *guf_str_move(guf_str *dst, guf_str *src, void *ctx);
GUF_STR_KWRDS bool guf_str_equal(const guf_str *a, const guf_str *b);
GUF_STR_KWRDS int guf_str_cmp(const guf_str *a, const guf_str *b);
// TODO: // TODO:
GUF_STR_KWRDS guf_str guf_str_try_new_substr(guf_str_view str_view, ptrdiff_t pos, ptrdiff_t len, guf_allocator *alloc, guf_err *err); GUF_STR_KWRDS guf_str guf_str_try_new_substr(guf_str_view str_view, ptrdiff_t pos, ptrdiff_t len, guf_allocator *alloc, guf_err *err);
GUF_STR_KWRDS guf_str guf_str_new_substr(guf_str_view str_view, ptrdiff_t pos, ptrdiff_t len, guf_allocator *alloc); GUF_STR_KWRDS guf_str guf_str_new_substr(guf_str_view str_view, ptrdiff_t pos, ptrdiff_t len, guf_allocator *alloc);
// TODO:
GUF_STR_KWRDS bool guf_str_equal(const guf_str *a, const guf_str *b);
GUF_STR_KWRDS bool guf_str_equals_cstr(const guf_str *a, const char *c_str);
GUF_STR_KWRDS bool guf_str_equals_strview(const guf_str *a, guf_str_view b);
// DONE: // DONE:
GUF_STR_KWRDS guf_str *guf_str_try_append_char(guf_str *str, char c, ptrdiff_t times, guf_err *err); GUF_STR_KWRDS guf_str *guf_str_try_append_char(guf_str *str, char c, ptrdiff_t times, guf_err *err);
GUF_STR_KWRDS guf_str *guf_str_append_char(guf_str *str, char c, ptrdiff_t times); GUF_STR_KWRDS guf_str *guf_str_append_char(guf_str *str, char c, ptrdiff_t times);
@ -363,7 +361,7 @@ GUF_STR_KWRDS guf_str *guf_str_try_reserve(guf_str *str, ptrdiff_t new_cap_min,
if (guf_str_is_short_internal_(str)) { // a.) Was short string -> need initial allocation. if (guf_str_is_short_internal_(str)) { // a.) Was short string -> need initial allocation.
char *c_str_new = str->allocator->alloc(new_cap_min_with_null, str->allocator->ctx); char *c_str_new = str->allocator->alloc(new_cap_min_with_null, str->allocator->ctx);
if (!c_str_new) { if (!c_str_new) {
guf_err_set_or_panic(err, GUF_ERR_ALLOC_FAIL, "in guf_str_try_grow_if_necessary: Initial allocation failed."); guf_err_set_or_panic(err, GUF_ERR_ALLOC_FAIL, "in guf_str_try_reserve: Initial allocation failed.");
return NULL; return NULL;
} }
memcpy(c_str_new, str->data.shrt.c_str, len_with_null); memcpy(c_str_new, str->data.shrt.c_str, len_with_null);
@ -372,7 +370,7 @@ GUF_STR_KWRDS guf_str *guf_str_try_reserve(guf_str *str, ptrdiff_t new_cap_min,
} else { // b) Was long string -> need re-allocation } else { // b) Was long string -> need re-allocation
char *c_str_new = str->allocator->realloc(str->data.lng.c_str, old_cap_with_null, new_cap_min_with_null, str->allocator->ctx); char *c_str_new = str->allocator->realloc(str->data.lng.c_str, old_cap_with_null, new_cap_min_with_null, str->allocator->ctx);
if (!c_str_new) { if (!c_str_new) {
guf_err_set_or_panic(err, GUF_ERR_ALLOC_FAIL, "in guf_str_try_grow_if_necessary: re-allocation failed."); guf_err_set_or_panic(err, GUF_ERR_ALLOC_FAIL, "in guf_str_try_reserve: re-allocation failed.");
return NULL; return NULL;
} }
str->data.lng.c_str = c_str_new; str->data.lng.c_str = c_str_new;
@ -557,6 +555,7 @@ GUF_STR_KWRDS guf_str *guf_str_copy(guf_str *dst, const guf_str *src, void *ctx)
(void)ctx; (void)ctx;
GUF_ASSERT_RELEASE(dst); GUF_ASSERT_RELEASE(dst);
GUF_ASSERT_RELEASE(guf_str_is_valid(src)); GUF_ASSERT_RELEASE(guf_str_is_valid(src));
GUF_ASSERT_RELEASE(!guf_str_is_readonly(src)); // // Doesn't make sense to deep-cpy in readonly mode (I think).
guf_str_init_empty(dst, src->allocator); guf_str_init_empty(dst, src->allocator);
GUF_ASSERT(guf_str_is_short_internal_(dst)); GUF_ASSERT(guf_str_is_short_internal_(dst));
@ -593,13 +592,40 @@ GUF_STR_KWRDS guf_str *guf_str_move(guf_str *dst, guf_str *src, void *ctx)
(void)ctx; (void)ctx;
GUF_ASSERT_RELEASE(dst); GUF_ASSERT_RELEASE(dst);
GUF_ASSERT_RELEASE(guf_str_is_valid(src)); GUF_ASSERT_RELEASE(guf_str_is_valid(src));
GUF_ASSERT_RELEASE(!guf_str_is_readonly(src)); // Doesn't make sense to move in readonly mode (I think).
*dst = *src; *dst = *src;
*src = guf_str_new_uninitialised(); *src = guf_str_new_uninitialised();
return dst; return dst;
} }
GUF_STR_KWRDS bool guf_str_equal(const guf_str *a, const guf_str *b)
{
GUF_ASSERT_RELEASE(guf_str_is_valid(a) && guf_str_is_valid(b));
if (guf_str_len(a) != guf_str_len(b)) {
return false;
}
const char *a_cstr = guf_str_const_cstr(a);
const char *b_cstr = guf_str_const_cstr(b);
GUF_ASSERT(a_cstr && b_cstr);
return 0 == memcmp(a_cstr, b_cstr, guf_str_len(a));
}
GUF_STR_KWRDS int guf_str_cmp(const guf_str *a, const guf_str *b)
{
GUF_ASSERT_RELEASE(guf_str_is_valid(a) && guf_str_is_valid(b));
GUF_ASSERT_RELEASE(guf_str_is_valid(a) && guf_str_is_valid(b));
const ptrdiff_t shorter_len = guf_min_ptrdiff_t(guf_str_len(a), guf_str_len(b));
const char *a_cstr = guf_str_const_cstr(a);
const char *b_cstr = guf_str_const_cstr(b);
GUF_ASSERT(a_cstr && b_cstr);
return memcmp(a_cstr, b_cstr, shorter_len);
}
GUF_STR_KWRDS guf_str *guf_str_try_append_char(guf_str *str, char c, ptrdiff_t times, guf_err *err) GUF_STR_KWRDS guf_str *guf_str_try_append_char(guf_str *str, char c, ptrdiff_t times, guf_err *err)
{ {
@ -622,8 +648,9 @@ GUF_STR_KWRDS guf_str *guf_str_try_append_char(guf_str *str, char c, ptrdiff_t t
const size_t old_cap = guf_str_cap_internal_(str); const size_t old_cap = guf_str_cap_internal_(str);
const size_t old_len = guf_str_len_internal_(str); const size_t old_len = guf_str_len_internal_(str);
const size_t new_len = old_len + (size_t)times; const size_t new_len = old_len + (size_t)times;
if (new_len <= old_len || new_len > (size_t)PTRDIFF_MAX) { // Handle overflow. if (new_len <= old_len || new_len >= (size_t)PTRDIFF_MAX) { // Handle overflow.
guf_err_set_or_panic(err, GUF_ERR_INT_OVERFLOW, "in guf_str_try_append_char: new length would overflow ptrdiff_t"); guf_err_set_or_panic(err, GUF_ERR_INT_OVERFLOW, "in guf_str_try_append_char: new length would overflow ptrdiff_t");
return NULL; return NULL;
} else if (new_len > old_cap) { // Need to grow capacity. } else if (new_len > old_cap) { // Need to grow capacity.
@ -686,7 +713,7 @@ GUF_STR_KWRDS guf_str *guf_str_try_append(guf_str *str, guf_str_view sv, guf_err
const size_t old_cap = guf_str_cap_internal_(str); const size_t old_cap = guf_str_cap_internal_(str);
const size_t old_len = guf_str_len_internal_(str); const size_t old_len = guf_str_len_internal_(str);
const size_t new_len = old_len + (size_t)sv.len; const size_t new_len = old_len + (size_t)sv.len;
if (new_len <= old_len || new_len > (size_t)PTRDIFF_MAX) { // Handle overflow. if (new_len <= old_len || new_len >= (size_t)PTRDIFF_MAX) { // Handle overflow.
guf_err_set_or_panic(err, GUF_ERR_INT_OVERFLOW, "in guf_str_try_append_view: new length would overflow ptrdiff_t"); guf_err_set_or_panic(err, GUF_ERR_INT_OVERFLOW, "in guf_str_try_append_view: new length would overflow ptrdiff_t");
return NULL; return NULL;
} else if (new_len > old_cap) { // Growth necessary. } else if (new_len > old_cap) { // Growth necessary.
@ -739,7 +766,11 @@ GUF_STR_KWRDS guf_str *guf_str_try_append_cstr(guf_str *str, const char *c_str,
GUF_ASSERT(len <= cap); GUF_ASSERT(len <= cap);
if (len == cap) { // Grow if necessary. if (len == cap) { // Grow if necessary.
guf_str_try_reserve(str, cap < PTRDIFF_MAX ? cap + 1 : PTRDIFF_MAX, err); if (cap == PTRDIFF_MAX) {
guf_err_set_or_panic(err, GUF_ERR_INT_OVERFLOW, "in guf_str_try_append_cstr: cannot grow (capacity is PTRDIFF_MAX)");
return NULL;
}
guf_str_try_reserve(str, cap + 1, err);
if (err && *err != GUF_ERR_NONE) { if (err && *err != GUF_ERR_NONE) {
guf_err_set_or_panic(err, GUF_ERR_INT_OVERFLOW, "in guf_str_try_append_cstr: failed to reserve"); guf_err_set_or_panic(err, GUF_ERR_INT_OVERFLOW, "in guf_str_try_append_cstr: failed to reserve");
return NULL; return NULL;