summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-10-15 15:23:58 -0400
committerpommicket <pommicket@gmail.com>2023-10-15 15:23:58 -0400
commita01d4de1e2feda34a20bb8dd65ec76fef3c20d6b (patch)
treec24f71d8536663d6758a14194b50508041cc03ec /util.c
parent479219152b85b2cf12e5bfee6fdebca033355beb (diff)
use reference-counted strings for string settings
this lets us remove the length limitations which were previously imposed
Diffstat (limited to 'util.c')
-rw-r--r--util.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/util.c b/util.c
index 89b3dc2..1649f91 100644
--- a/util.c
+++ b/util.c
@@ -17,6 +17,42 @@
// on 16-bit systems, this is 16383. on 32/64-bit systems, this is 1073741823
// it is unusual to have a string that long.
#define STRLEN_SAFE_MAX (UINT_MAX >> 2)
+struct RcStr {
+ u32 ref_count;
+ char str[];
+};
+
+RcStr *rc_str_new(const char *s, i64 len) {
+ if (len < 0) {
+ len = (i64)strlen(s);
+ }
+ RcStr *rc = calloc(1, sizeof(RcStr) + (size_t)len + 1);
+ assert(rc);
+ memcpy(rc->str, s, (size_t)len);
+ rc->ref_count = 1;
+ return rc;
+}
+
+void rc_str_incref(RcStr *str) {
+ if (str)
+ str->ref_count += 1;
+}
+
+void rc_str_decref(RcStr **pstr) {
+ RcStr *const str = *pstr;
+ if (!str) return;
+ str->ref_count -= 1;
+ if (str->ref_count == 0) {
+ *pstr = NULL;
+ free(str);
+ }
+}
+
+const char *rc_str(RcStr *str, const char *default_value) {
+ if (!str) return default_value;
+ assert(str->ref_count > 0);
+ return str->str;
+}
bool is32_word(char32_t c) {
return c > WCHAR_MAX || c == '_' || iswalnum((wint_t)c);
@@ -151,6 +187,8 @@ bool str_has_path_prefix(const char *path, const char *prefix) {
}
bool streq(const char *a, const char *b) {
+ assert(a);
+ assert(b);
return strcmp(a, b) == 0;
}