1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
#include "cstring.h"
#include <string.h>
#define STRING_MIN_CAP 8
string_t *string_new(void) {
string_t *ret = malloc(sizeof(*ret));
if (!ret) return NULL;
char *buf = malloc(sizeof(char));
if (!buf) {
free(ret);
return NULL;
}
buf[0] = '\0';
ret->ssize = ret->scap = 0; ret->buf = buf;
return ret;
}
string_t *string_new_cap(size_t cap) {
string_t *ret = malloc(sizeof(*ret));
if (!ret) return NULL;
cap = (cap < STRING_MIN_CAP) ? STRING_MIN_CAP : cap;
ret->buf = malloc((cap + 1) * sizeof(char));
if (!ret->buf) {
free(ret);
return NULL;
}
ret->buf[0] = '\0';
ret->scap = cap;
ret->ssize = 0;
return ret;
}
int string_reserve(string_t *s, size_t cap) {
size_t new_cap = (cap < STRING_MIN_CAP) ? STRING_MIN_CAP : cap;
if (new_cap <= s->scap) return 1;
void *new_buf = realloc(s->buf, sizeof(char) * (new_cap + 1));
if (!new_buf) return 0;
s->buf = new_buf;
s->scap = new_cap;
return 1;
}
void string_del(string_t *s) {
if (s->buf) free(s->buf);
free(s);
}
char *string_steal(string_t *s) {
char *ret = s->buf;
free(s);
return ret;
}
int string_add_char(string_t *s, char elem) {
if (s->ssize >= s->scap) {
size_t new_cap = (s->scap < STRING_MIN_CAP) ? STRING_MIN_CAP : s->scap * 2;
char *new_buf = realloc(s->buf, sizeof(char) * (new_cap + 1));
if (!new_buf) return 0;
s->buf = new_buf;
s->scap = new_cap;
}
s->buf[s->ssize++] = elem;
s->buf[s->ssize] = '\0';
return 1;
}
int string_add_string(string_t *s1, string_t *s2) {
if (s1->ssize + s2->ssize > s1->scap) {
size_t new_cap = (s1->scap < STRING_MIN_CAP) ? STRING_MIN_CAP : s1->scap * 2;
while (s1->ssize + s2->ssize > new_cap) {
new_cap = new_cap * 2;
}
char *new_buf = realloc(s1->buf, sizeof(char) * (new_cap + 1));
if (!new_buf) return 0;
s1->buf = new_buf;
s1->scap = new_cap;
}
memcpy(s1->buf + s1->ssize, s2->buf, s2->ssize);
s1->ssize += s2->ssize;
s1->buf[s1->ssize] = '\0';
return 1;
}
void string_pop(string_t *s) {
if (!s->ssize) return;
s->buf[--s->ssize] = '\0';
if (s->ssize < s->scap / 4) {
size_t new_cap = (s->scap / 2 < STRING_MIN_CAP) ? STRING_MIN_CAP : s->scap / 2;
if (new_cap == s->scap) return;
void *new_buf = realloc(s->buf, sizeof(char) * (new_cap + 1));
if (!new_buf) return; // We don't really care if the realloc fails, we just need to not update anything
s->buf = new_buf;
s->scap = new_cap;
}
}
string_t *string_dup(string_t const *s) {
string_t *ret = string_new_cap(s->ssize);
if (!ret) return NULL;
memcpy(ret->buf, s->buf, s->ssize + 1);
ret->ssize = s->ssize;
return ret;
}
string_t *string_concat(string_t const *l, string_t const *r) {
string_t *ret = string_new_cap(l->ssize + r->ssize);
if (!ret) return NULL;
memcpy(ret->buf, l->buf, l->ssize);
memcpy(ret->buf + l->ssize, r->buf, r->ssize);
ret->buf[ret->ssize] = '\0';
return ret;
}
|