/Users/alexjokela/projects/lattice/src/ds/str.c
Line | Count | Source |
1 | | #include "ds/str.h" |
2 | | #include <stdlib.h> |
3 | | #include <string.h> |
4 | | #include <stdarg.h> |
5 | | #include <stdio.h> |
6 | | |
7 | 66 | #define INITIAL_CAP 16 |
8 | | |
9 | 9 | LatStr lat_str_new(void) { |
10 | 9 | LatStr s; |
11 | 9 | s.data = malloc(INITIAL_CAP); |
12 | 9 | s.data[0] = '\0'; |
13 | 9 | s.len = 0; |
14 | 9 | s.cap = INITIAL_CAP; |
15 | 9 | return s; |
16 | 9 | } |
17 | | |
18 | 21 | LatStr lat_str_from(const char *cstr) { |
19 | 21 | size_t len = strlen(cstr); |
20 | 21 | return lat_str_from_len(cstr, len); |
21 | 21 | } |
22 | | |
23 | 24 | LatStr lat_str_from_len(const char *cstr, size_t len) { |
24 | 24 | LatStr s; |
25 | 24 | s.cap = len + 1; |
26 | 24 | if (s.cap < INITIAL_CAP) s.cap = INITIAL_CAP; |
27 | 24 | s.data = malloc(s.cap); |
28 | 24 | memcpy(s.data, cstr, len); |
29 | 24 | s.data[len] = '\0'; |
30 | 24 | s.len = len; |
31 | 24 | return s; |
32 | 24 | } |
33 | | |
34 | 3 | LatStr lat_str_dup(const LatStr *s) { |
35 | 3 | return lat_str_from_len(s->data, s->len); |
36 | 3 | } |
37 | | |
38 | 33 | void lat_str_free(LatStr *s) { |
39 | 33 | free(s->data); |
40 | 33 | s->data = NULL; |
41 | 33 | s->len = 0; |
42 | 33 | s->cap = 0; |
43 | 33 | } |
44 | | |
45 | 18 | static void lat_str_grow(LatStr *s, size_t needed) { |
46 | 18 | size_t new_cap = s->cap; |
47 | 18 | while (new_cap < needed) { |
48 | 0 | new_cap *= 2; |
49 | 0 | } |
50 | 18 | if (new_cap != s->cap) { |
51 | 0 | s->data = realloc(s->data, new_cap); |
52 | 0 | s->cap = new_cap; |
53 | 0 | } |
54 | 18 | } |
55 | | |
56 | 12 | void lat_str_push(LatStr *s, char c) { |
57 | 12 | lat_str_grow(s, s->len + 2); |
58 | 12 | s->data[s->len++] = c; |
59 | 12 | s->data[s->len] = '\0'; |
60 | 12 | } |
61 | | |
62 | 3 | void lat_str_append(LatStr *s, const char *cstr) { |
63 | 3 | size_t add_len = strlen(cstr); |
64 | 3 | lat_str_grow(s, s->len + add_len + 1); |
65 | 3 | memcpy(s->data + s->len, cstr, add_len); |
66 | 3 | s->len += add_len; |
67 | 3 | s->data[s->len] = '\0'; |
68 | 3 | } |
69 | | |
70 | 0 | void lat_str_append_str(LatStr *s, const LatStr *other) { |
71 | 0 | lat_str_grow(s, s->len + other->len + 1); |
72 | 0 | memcpy(s->data + s->len, other->data, other->len); |
73 | 0 | s->len += other->len; |
74 | 0 | s->data[s->len] = '\0'; |
75 | 0 | } |
76 | | |
77 | 3 | void lat_str_appendf(LatStr *s, const char *fmt, ...) { |
78 | 3 | va_list args; |
79 | 3 | va_start(args, fmt); |
80 | 3 | va_list args2; |
81 | 3 | va_copy(args2, args); |
82 | 3 | int needed = vsnprintf(NULL, 0, fmt, args); |
83 | 3 | va_end(args); |
84 | 3 | if (needed > 0) { |
85 | 3 | lat_str_grow(s, s->len + (size_t)needed + 1); |
86 | 3 | vsnprintf(s->data + s->len, (size_t)needed + 1, fmt, args2); |
87 | 3 | s->len += (size_t)needed; |
88 | 3 | } |
89 | 3 | va_end(args2); |
90 | 3 | } |
91 | | |
92 | 18 | const char *lat_str_cstr(const LatStr *s) { |
93 | 18 | return s->data; |
94 | 18 | } |
95 | | |
96 | 12 | bool lat_str_eq(const LatStr *a, const LatStr *b) { |
97 | 12 | if (a->len != b->len) return false; |
98 | 6 | return memcmp(a->data, b->data, a->len) == 0; |
99 | 12 | } |
100 | | |
101 | 0 | bool lat_str_eq_cstr(const LatStr *s, const char *cstr) { |
102 | 0 | return strcmp(s->data, cstr) == 0; |
103 | 0 | } |
104 | | |
105 | 3 | void lat_str_clear(LatStr *s) { |
106 | 3 | s->len = 0; |
107 | 3 | s->data[0] = '\0'; |
108 | 3 | } |