2 * resizable string buffer
4 * (c) 2017-2020 Steve Bennett <steveb@workware.net.au>
6 * See utf8.c for licence details.
15 #include "stringbuf.h"
23 #define SB_INCREMENT 200
25 stringbuf *sb_alloc(void)
27 stringbuf *sb = (stringbuf *)malloc(sizeof(*sb));
38 void sb_free(stringbuf *sb)
46 void sb_realloc(stringbuf *sb, int newlen)
48 sb->data = (char *)realloc(sb->data, newlen);
49 sb->remaining = newlen - sb->last;
52 void sb_append(stringbuf *sb, const char *str)
54 sb_append_len(sb, str, strlen(str));
57 void sb_append_len(stringbuf *sb, const char *str, int len)
59 if (sb->remaining < len + 1) {
60 sb_realloc(sb, sb->last + len + 1 + SB_INCREMENT);
62 memcpy(sb->data + sb->last, str, len);
63 sb->data[sb->last + len] = 0;
68 sb->chars += utf8_strlen(str, len);
72 char *sb_to_string(stringbuf *sb)
74 if (sb->data == NULL) {
75 /* Return an allocated empty string, not null */
79 /* Just return the data and free the stringbuf structure */
86 /* Insert and delete operations */
88 /* Moves up all the data at position 'pos' and beyond by 'len' bytes
89 * to make room for new data
91 * Note: Does *not* update sb->chars
93 static void sb_insert_space(stringbuf *sb, int pos, int len)
95 assert(pos <= sb->last);
97 /* Make sure there is enough space */
98 if (sb->remaining < len) {
99 sb_realloc(sb, sb->last + len + SB_INCREMENT);
102 memmove(sb->data + pos + len, sb->data + pos, sb->last - pos);
104 sb->remaining -= len;
105 /* And null terminate */
106 sb->data[sb->last] = 0;
110 * Move down all the data from pos + len, effectively
111 * deleting the data at position 'pos' of length 'len'
113 static void sb_delete_space(stringbuf *sb, int pos, int len)
115 assert(pos < sb->last);
116 assert(pos + len <= sb->last);
119 sb->chars -= utf8_strlen(sb->data + pos, len);
123 memmove(sb->data + pos, sb->data + pos + len, sb->last - pos - len);
125 sb->remaining += len;
126 /* And null terminate */
127 sb->data[sb->last] = 0;
130 void sb_insert(stringbuf *sb, int index, const char *str)
132 if (index >= sb->last) {
133 /* Inserting after the end of the list appends. */
137 int len = strlen(str);
139 sb_insert_space(sb, index, len);
140 memcpy(sb->data + index, str, len);
142 sb->chars += utf8_strlen(str, len);
148 * Delete the bytes at index 'index' for length 'len'
149 * Has no effect if the index is past the end of the list.
151 void sb_delete(stringbuf *sb, int index, int len)
153 if (index < sb->last) {
154 char *pos = sb->data + index;
159 sb_delete_space(sb, pos - sb->data, len);
163 void sb_clear(stringbuf *sb)