]> git.lizzy.rs Git - linenoise.git/blob - stringbuf.c
Use CMake
[linenoise.git] / stringbuf.c
1 /**
2  * resizable string buffer
3  *
4  * (c) 2017-2020 Steve Bennett <steveb@workware.net.au>
5  *
6  * See utf8.c for licence details.
7  */
8 #include <stdlib.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include <ctype.h>
12 #include <assert.h>
13
14 #ifndef STRINGBUF_H
15 #include "stringbuf.h"
16 #endif
17 #ifdef USE_UTF8
18 #ifndef UTF8_UTIL_H
19 #include "utf8.h"
20 #endif
21 #endif
22
23 #define SB_INCREMENT 200
24
25 stringbuf *sb_alloc(void)
26 {
27         stringbuf *sb = (stringbuf *)malloc(sizeof(*sb));
28         sb->remaining = 0;
29         sb->last = 0;
30 #ifdef USE_UTF8
31         sb->chars = 0;
32 #endif
33         sb->data = NULL;
34
35         return(sb);
36 }
37
38 void sb_free(stringbuf *sb)
39 {
40         if (sb) {
41                 free(sb->data);
42         }
43         free(sb);
44 }
45
46 void sb_realloc(stringbuf *sb, int newlen)
47 {
48         sb->data = (char *)realloc(sb->data, newlen);
49         sb->remaining = newlen - sb->last;
50 }
51
52 void sb_append(stringbuf *sb, const char *str)
53 {
54         sb_append_len(sb, str, strlen(str));
55 }
56
57 void sb_append_len(stringbuf *sb, const char *str, int len)
58 {
59         if (sb->remaining < len + 1) {
60                 sb_realloc(sb, sb->last + len + 1 + SB_INCREMENT);
61         }
62         memcpy(sb->data + sb->last, str, len);
63         sb->data[sb->last + len] = 0;
64
65         sb->last += len;
66         sb->remaining -= len;
67 #ifdef USE_UTF8
68         sb->chars += utf8_strlen(str, len);
69 #endif
70 }
71
72 char *sb_to_string(stringbuf *sb)
73 {
74         if (sb->data == NULL) {
75                 /* Return an allocated empty string, not null */
76                 return strdup("");
77         }
78         else {
79                 /* Just return the data and free the stringbuf structure */
80                 char *pt = sb->data;
81                 free(sb);
82                 return pt;
83         }
84 }
85
86 /* Insert and delete operations */
87
88 /* Moves up all the data at position 'pos' and beyond by 'len' bytes
89  * to make room for new data
90  *
91  * Note: Does *not* update sb->chars
92  */
93 static void sb_insert_space(stringbuf *sb, int pos, int len)
94 {
95         assert(pos <= sb->last);
96
97         /* Make sure there is enough space */
98         if (sb->remaining < len) {
99                 sb_realloc(sb, sb->last + len + SB_INCREMENT);
100         }
101         /* Now move it up */
102         memmove(sb->data + pos + len, sb->data + pos, sb->last - pos);
103         sb->last += len;
104         sb->remaining -= len;
105         /* And null terminate */
106         sb->data[sb->last] = 0;
107 }
108
109 /**
110  * Move down all the data from pos + len, effectively
111  * deleting the data at position 'pos' of length 'len'
112  */
113 static void sb_delete_space(stringbuf *sb, int pos, int len)
114 {
115         assert(pos < sb->last);
116         assert(pos + len <= sb->last);
117
118 #ifdef USE_UTF8
119         sb->chars -= utf8_strlen(sb->data + pos, len);
120 #endif
121
122         /* Now move it up */
123         memmove(sb->data + pos, sb->data + pos + len, sb->last - pos - len);
124         sb->last -= len;
125         sb->remaining += len;
126         /* And null terminate */
127         sb->data[sb->last] = 0;
128 }
129
130 void sb_insert(stringbuf *sb, int index, const char *str)
131 {
132         if (index >= sb->last) {
133                 /* Inserting after the end of the list appends. */
134                 sb_append(sb, str);
135         }
136         else {
137                 int len = strlen(str);
138
139                 sb_insert_space(sb, index, len);
140                 memcpy(sb->data + index, str, len);
141 #ifdef USE_UTF8
142                 sb->chars += utf8_strlen(str, len);
143 #endif
144         }
145 }
146
147 /**
148  * Delete the bytes at index 'index' for length 'len'
149  * Has no effect if the index is past the end of the list.
150  */
151 void sb_delete(stringbuf *sb, int index, int len)
152 {
153         if (index < sb->last) {
154                 char *pos = sb->data + index;
155                 if (len < 0) {
156                         len = sb->last;
157                 }
158
159                 sb_delete_space(sb, pos - sb->data, len);
160         }
161 }
162
163 void sb_clear(stringbuf *sb)
164 {
165         if (sb->data) {
166                 /* Null terminate */
167                 sb->data[0] = 0;
168                 sb->last = 0;
169 #ifdef USE_UTF8
170                 sb->chars = 0;
171 #endif
172         }
173 }