Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/linenoise/stringbuf.c
2066 views
1
/**
2
* resizable string buffer
3
*
4
* (c) 2017-2020 Steve Bennett <[email protected]>
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
static 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
}
174
175