summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWormHeamer2026-01-02 19:34:24 -0500
committerWormHeamer2026-01-02 19:34:24 -0500
commit6d60c710747cbee755b9f50d88ee7c71096a289f (patch)
tree5735be559352e2f213243c9c103fd927ff07d1c5
parenta5996c4727705f3dd48d0b6d5cacc90392dd58d4 (diff)
try to concatenate strings in-place when possible
-rw-r--r--arena.h11
-rw-r--r--str.h45
2 files changed, 38 insertions, 18 deletions
diff --git a/arena.h b/arena.h
index 1be5cd7..5235204 100644
--- a/arena.h
+++ b/arena.h
@@ -24,6 +24,7 @@ void arena_free(Arena *a);
void arena_reset(Arena *a);
void *arena_alloc(Arena *a, size_t n, size_t align);
void *arena_realloc(Arena *a, void *old, size_t oldsz, size_t newsz, size_t align);
+void *arena_concat(Arena *m, void *a, size_t asz, void *b, size_t bsz, size_t align);
#define new(a, t)\
memset(arena_alloc(a, sizeof(t), _Alignof(__typeof__(t))), 0, sizeof(t))
@@ -89,5 +90,15 @@ void *arena_realloc(Arena *a, void *old, size_t oldsz, size_t newsz, size_t alig
}
}
+void *arena_concat(Arena *m, void *a, size_t asz, void *b, size_t bsz, size_t align) {
+ if (!asz)
+ return b;
+ if (!bsz || (char*)a + asz == b)
+ return a;
+ void *p = arena_realloc(m, a, asz, asz + bsz, align);
+ memcpy((char*)p + asz, b, bsz);
+ return p;
+}
+
#endif
#endif
diff --git a/str.h b/str.h
index b5f2889..1969d6b 100644
--- a/str.h
+++ b/str.h
@@ -17,36 +17,34 @@ typedef struct {
#define S(s) (Str){s,sizeof(s)-1}
-char *str_to_cstr(Str s, Arena *a);
Str str_from_cstr(const char *s);
+
int str_eql(Str a, Str b);
int str_starts(Str a, Str b);
int str_ends(Str a, Str b);
-void str_catc(Str *a, char b, Arena *m);
+
Str str_skip(Str a, ptrdiff_t n);
+Str str_trunc(Str a, ptrdiff_t n);
+
Str str_trim_left(Str a);
Str str_trim_right(Str a);
Str str_trim(Str a);
+
Cut str_cut(Str s, char c);
Str str_findc(Str s, char c);
Str str_find(Str haystack, Str needle);
int str_contains(Str a, Str b);
-Str str_dup(Str a, Arena *m);
+
+char *str_to_cstr(Str s, Arena *a);
void str_cat(Str *a, Str b, Arena *m);
+void str_catc(Str *a, char b, Arena *m);
+Str str_dup(Str a, Arena *m);
Str str_replace_end(Str s, Str a, Str b, Arena *m);
#ifdef STR_IMPL
/* conversions */
-char *str_to_cstr(Str s, Arena *a) {
- if (!s.n) return "";
- char *r = new_arr(a, char, s.n + 1);
- memcpy(r, s.s, s.n);
- r[s.n] = 0;
- return r;
-}
-
Str str_from_cstr(const char *s) {
return (Str) { (char*)s, strlen(s) };
}
@@ -65,15 +63,14 @@ int str_ends(Str a, Str b) {
return a.n >= b.n && !memcmp(&a.s[a.n - b.n], b.s, b.n);
}
-void str_catc(Str *a, char b, Arena *m) {
- a->s = resize(m, a->s, a->n, a->n + 1);
- a->s[a->n++] = b;
-}
-
Str str_skip(Str a, ptrdiff_t n) {
return (Str) { a.s + n, a.n - n };
}
+Str str_trunc(Str a, ptrdiff_t n) {
+ return (Str) { a.s, n < a.n ? n : a.n };
+}
+
static inline int str_is_space(char c) {
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
}
@@ -127,6 +124,14 @@ int str_contains(Str a, Str b) {
/* allocating */
+char *str_to_cstr(Str s, Arena *a) {
+ if (!s.n) return "";
+ char *r = new_arr(a, char, s.n + 1);
+ memcpy(r, s.s, s.n);
+ r[s.n] = 0;
+ return r;
+}
+
Str str_dup(Str a, Arena *m) {
char *s = new_arr(m, char, a.n);
memcpy(s, a.s, a.n);
@@ -135,11 +140,15 @@ Str str_dup(Str a, Arena *m) {
}
void str_cat(Str *a, Str b, Arena *m) {
- a->s = resize(m, a->s, a->n, a->n + b.n);
- memcpy(&a->s[a->n], b.s, b.n);
+ a->s = arena_concat(m, a->s, a->n, b.s, b.n, _Alignof(char));
a->n += b.n;
}
+void str_catc(Str *a, char b, Arena *m) {
+ a->s = arena_concat(m, a->s, a->n, &b, 1, _Alignof(char));
+ a->n++;
+}
+
Str str_replace_end(Str s, Str a, Str b, Arena *m) {
if (!str_ends(s, a)) return s;
char *p = new_arr(m, char, s.n + b.n - a.n);