-
Notifications
You must be signed in to change notification settings - Fork 22
/
stringbuilder.c
153 lines (124 loc) · 3.37 KB
/
stringbuilder.c
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/**
* Stringbuilder - a library for working with C strings that can grow dynamically as they are appended
*
*/
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
//#include "platform.h"
#include "stringbuilder.h"
/**
* Creates a new stringbuilder with the default chunk size
*
*/
stringbuilder* sb_new() {
return sb_new_with_size(1024); // TODO: Is there a heurisitic for this?
}
/**
* Creates a new stringbuilder with initial size at least the given size
*/
stringbuilder* sb_new_with_size(int size) {
stringbuilder* sb;
sb = (stringbuilder*)malloc(sizeof(stringbuilder));
sb->size = size;
sb->cstr = (char*)malloc(size);
sb->pos = 0;
sb->reallocs = 0;
// Fill cstr with null to ensure it is always null terminated
memset(sb->cstr, '\0', size);
return sb;
}
void sb_reset(stringbuilder* sb) {
sb->pos = 0;
memset(sb->cstr, '\0', sb->size);
}
/**
* Destroys the given stringbuilder
*/
void sb_destroy(stringbuilder* sb, int free_string) {
if (free_string) {
free(sb->cstr);
}
free(sb);
}
/**
* Internal function to resize our string buffer's storage.
* \return 1 iff sb->cstr was successfully resized, otherwise 0
*/
int sb_resize(stringbuilder* sb, const int new_size) {
char* old_cstr = sb->cstr;
sb->cstr = (char *)realloc(sb->cstr, new_size);
if (sb->cstr == NULL) {
sb->cstr = old_cstr;
return 0;
}
memset(sb->cstr + sb->pos, '\0', new_size - sb->pos);
sb->size = new_size;
sb->reallocs++;
return 1;
}
int sb_double_size(stringbuilder* sb) {
return sb_resize(sb, sb->size * 2);
}
void sb_append_ch(stringbuilder* sb, const char ch) {
int new_size;
if (sb->pos == sb->size) {
sb_double_size(sb);
}
sb->cstr[sb->pos++] = ch;
}
/**
* Appends at most length of the given src string to the string buffer
*/
void sb_append_strn(stringbuilder* sb, const char* src, int length) {
int chars_remaining;
int chars_required;
int new_size;
// <buffer size> - <zero based index of next char to write> - <space for null terminator>
chars_remaining = sb->size - sb->pos - 1;
if (chars_remaining < length) {
chars_required = length - chars_remaining;
new_size = sb->size;
do {
new_size = new_size * 2;
} while (new_size < (sb->size + chars_required));
sb_resize(sb, new_size);
}
memcpy(sb->cstr + sb->pos, src, length);
sb->pos += length;
}
/**
* Appends the given src string to the string builder
*/
void sb_append_str(stringbuilder* sb, const char* src) {
sb_append_strn(sb, src, strlen(src));
}
/**
* Appends the formatted string to the given string builder
*/
/* Not used by golp, so commented out to avoid the need for platform.h and platform.c
void sb_append_strf(stringbuilder* sb, const char* fmt, ...) {
char *str;
va_list arglist;
va_start(arglist, fmt);
xp_vasprintf(&str, fmt, arglist);
va_end(arglist);
if (!str) {
return;
}
sb_append_str(sb, str);
free(str);
}
*/
/**
* Allocates and copies a new cstring based on the current stringbuilder contents
*/
char* sb_make_cstring(stringbuilder* sb) {
char* out;
if (!sb->pos) {
return 0;
}
out = (char*)malloc(sb->pos + 1);
strcpy(out, sb_cstring(sb));
return out;
}