]> git.ipfire.org Git - thirdparty/util-linux.git/blame - lib/buffer.c
Merge branch 'meson-build-dmesg' of https://github.com/jwillikers/util-linux
[thirdparty/util-linux.git] / lib / buffer.c
CommitLineData
3836cd2d
KZ
1/*
2 * No copyright is claimed. This code is in the public domain; do with
3 * it what you wish.
4 *
5 * Written by Karel Zak <kzak@redhat.com>
6 */
0a993981 7#include "buffer.h"
9ea47344 8#include "mbsalign.h"
cba33452 9#include "strutils.h"
0a993981
KZ
10
11void ul_buffer_reset_data(struct ul_buffer *buf)
12{
13 if (buf->begin)
f9ba5fa0 14 memset(buf->begin, 0, buf->sz);
0a993981 15 buf->end = buf->begin;
68463f5a
KZ
16
17 if (buf->ptrs && buf->nptrs)
18 memset(buf->ptrs, 0, buf->nptrs * sizeof(char *));
0a993981
KZ
19}
20
21void ul_buffer_free_data(struct ul_buffer *buf)
22{
23 assert(buf);
24
25 free(buf->begin);
26 buf->begin = NULL;
27 buf->end = NULL;
28 buf->sz = 0;
f55be401
KZ
29
30 free(buf->ptrs);
31 buf->ptrs = NULL;
32 buf->nptrs = 0;
9ea47344
KZ
33
34 free(buf->encoded);
35 buf->encoded = NULL;
36 buf->encoded_sz = 0;
0a993981
KZ
37}
38
39void ul_buffer_set_chunksize(struct ul_buffer *buf, size_t sz)
40{
41 buf->chunksize = sz;
42}
43
44int ul_buffer_is_empty(struct ul_buffer *buf)
45{
46 return buf->begin == buf->end;
47}
48
f55be401
KZ
49int ul_buffer_save_pointer(struct ul_buffer *buf, unsigned short ptr_idx)
50{
51 if (ptr_idx >= buf->nptrs) {
64d6d400 52 char **tmp = reallocarray(buf->ptrs, ptr_idx + 1, sizeof(char *));
f55be401
KZ
53
54 if (!tmp)
55 return -EINVAL;
56 buf->ptrs = tmp;
57 buf->nptrs = ptr_idx + 1;
58 }
59
60 buf->ptrs[ptr_idx] = buf->end;
61 return 0;
62}
63
64
65char *ul_buffer_get_pointer(struct ul_buffer *buf, unsigned short ptr_idx)
66{
67 if (ptr_idx < buf->nptrs)
68 return buf->ptrs[ptr_idx];
69 return NULL;
70}
71
9ea47344 72/* returns length from begin to the pointer */
f55be401
KZ
73size_t ul_buffer_get_pointer_length(struct ul_buffer *buf, unsigned short ptr_idx)
74{
75 char *ptr = ul_buffer_get_pointer(buf, ptr_idx);
76
9ea47344 77 if (ptr && ptr > buf->begin)
f55be401
KZ
78 return ptr - buf->begin;
79 return 0;
80}
81
9ea47344
KZ
82/* returns width of data in safe encoding (from the begin to the pointer) */
83size_t ul_buffer_get_safe_pointer_width(struct ul_buffer *buf, unsigned short ptr_idx)
84{
85 size_t len = ul_buffer_get_pointer_length(buf, ptr_idx);
86
87 if (!len)
88 return 0;
89
90 return mbs_safe_nwidth(buf->begin, len, NULL);
91}
f55be401 92
0a993981
KZ
93void ul_buffer_refer_string(struct ul_buffer *buf, char *str)
94{
95 if (buf->sz)
96 ul_buffer_free_data(buf);
97 buf->begin = str;
98 buf->sz = str ? strlen(str) : 0;
c76f79e9 99 buf->end = buf->begin ? buf->begin + buf->sz : buf->begin;
0a993981
KZ
100}
101
102int ul_buffer_alloc_data(struct ul_buffer *buf, size_t sz)
103{
104 char *tmp;
105 size_t len = 0;
106
107 assert(buf);
108
109 if (sz <= buf->sz)
110 return 0;
111
112 if (buf->end && buf->begin)
113 len = buf->end - buf->begin;
114
115 if (buf->chunksize)
116 sz = ((sz + buf->chunksize) / buf->chunksize) * buf->chunksize + 1;
117
118 tmp = realloc(buf->begin, sz);
119 if (!tmp)
120 return -ENOMEM;
121
122 buf->begin = tmp;
123 buf->end = buf->begin + len;
124 buf->sz = sz;
125
43485143
KZ
126 memset(buf->end, '\0', sz - len);
127
0a993981
KZ
128 return 0;
129}
130
131int ul_buffer_append_data(struct ul_buffer *buf, const char *data, size_t sz)
132{
133 size_t maxsz = 0;
134
135 if (!buf)
136 return -EINVAL;
f9ba5fa0 137 if (!data)
0a993981
KZ
138 return 0;
139
140 if (buf->begin && buf->end)
141 maxsz = buf->sz - (buf->end - buf->begin);
0a993981
KZ
142 if (maxsz <= sz + 1) {
143 int rc = ul_buffer_alloc_data(buf, buf->sz + sz + 1);
144 if (rc)
145 return rc;
146 }
f831651e
KZ
147 if (!buf->end)
148 return -EINVAL; /* make static analyzers happy */
149
cba33452 150 buf->end = mempcpy(buf->end, data, sz);
0a993981
KZ
151 *buf->end = '\0'; /* make sure it's terminated */
152 return 0;
153}
154
155int ul_buffer_append_string(struct ul_buffer *buf, const char *str)
156{
cc9e5641
KZ
157 if (!str)
158 return 0;
159
0a993981
KZ
160 return ul_buffer_append_data(buf, str, strlen(str));
161}
162
163int ul_buffer_append_ntimes(struct ul_buffer *buf, size_t n, const char *str)
164{
165 size_t i;
166 size_t len = strlen(str);
167
168 for (i = 0; len && i < n; i++) {
169 int rc = ul_buffer_append_data(buf, str, len);
170 if (rc)
171 return rc;
172 }
173 return 0;
174}
175
176int ul_buffer_set_data(struct ul_buffer *buf, const char *data, size_t sz)
177{
178 ul_buffer_reset_data(buf);
179 return ul_buffer_append_data(buf, data, sz);
180}
181
9ea47344 182char *ul_buffer_get_data(struct ul_buffer *buf, size_t *sz, size_t *width)
0a993981 183{
f60dc888
KZ
184 if (sz)
185 *sz = buf->end - buf->begin;
9ea47344
KZ
186 if (width)
187 *width = buf->begin && *buf->begin ? mbs_width(buf->begin) : 0;
0a993981
KZ
188 return buf->begin;
189}
190
f60dc888
KZ
191/* size of allocated area (!= size of stored data */
192size_t ul_buffer_get_bufsiz(struct ul_buffer *buf)
193{
194 return buf->sz;
195}
196
9ea47344
KZ
197/* encode data by mbs_safe_encode() to avoid control and non-printable chars */
198char *ul_buffer_get_safe_data(struct ul_buffer *buf, size_t *sz, size_t *width, const char *safechars)
199{
200 char *data = ul_buffer_get_data(buf, NULL, NULL);
201 size_t encsz, wsz = 0;
202 char *res = NULL;
203
204 if (!data)
205 goto nothing;
206
207 encsz = mbs_safe_encode_size(buf->sz) + 1;
208 if (encsz > buf->encoded_sz) {
209 char *tmp = realloc(buf->encoded, encsz);
210 if (!tmp)
211 goto nothing;
212 buf->encoded = tmp;
213 buf->encoded_sz = encsz;
214 }
215
216 res = mbs_safe_encode_to_buffer(data, &wsz, buf->encoded, safechars);
217 if (!res || !wsz || wsz == (size_t) -1)
218 goto nothing;
219
220 if (width)
221 *width = wsz;
222 if (sz)
223 *sz = strlen(res);
224 return res;
225nothing:
226 if (width)
227 *width = 0;
228 if (sz)
229 *sz = 0;
230 return NULL;
231}
232
f60dc888 233
0a993981 234#ifdef TEST_PROGRAM_BUFFER
f55be401
KZ
235
236enum {
237 PTR_AAA = 0,
238 PTR_BBB,
239};
240
0a993981
KZ
241int main(void)
242{
243 struct ul_buffer buf = UL_INIT_BUFFER;
244 char *str;
f60dc888 245 size_t sz = 0;
0a993981
KZ
246
247 ul_buffer_set_chunksize(&buf, 16);
248
249 ul_buffer_append_string(&buf, "AAA");
250 ul_buffer_append_data(&buf, "=", 1);
251 ul_buffer_append_string(&buf, "aaa");
f55be401
KZ
252 ul_buffer_save_pointer(&buf, PTR_AAA);
253
0a993981
KZ
254 ul_buffer_append_data(&buf, ",", 1);
255 ul_buffer_append_string(&buf, "BBB");
256 ul_buffer_append_string(&buf, "=");
257 ul_buffer_append_string(&buf, "bbb");
f55be401 258 ul_buffer_save_pointer(&buf, PTR_BBB);
0a993981 259
9ea47344 260 str = ul_buffer_get_data(&buf, &sz, NULL);
f60dc888 261 printf("data [%zu] '%s'\n", sz, str);
0a993981 262
f55be401
KZ
263 printf(" pointer data len: AAA=%zu, BBB=%zu\n",
264 ul_buffer_get_pointer_length(&buf, PTR_AAA),
265 ul_buffer_get_pointer_length(&buf, PTR_BBB));
9ea47344
KZ
266 printf(" pointer data width: AAA=%zu, BBB=%zu\n",
267 ul_buffer_get_safe_pointer_width(&buf, PTR_AAA),
268 ul_buffer_get_safe_pointer_width(&buf, PTR_BBB));
f55be401 269
0a993981
KZ
270 ul_buffer_reset_data(&buf);
271 ul_buffer_append_string(&buf, "This is really long string to test the buffer function.");
f55be401 272 ul_buffer_save_pointer(&buf, PTR_AAA);
0a993981 273 ul_buffer_append_string(&buf, " YES!");
9ea47344 274 str = ul_buffer_get_data(&buf, &sz, NULL);
f60dc888 275 printf("data [%zu] '%s'\n", sz, str);
f55be401 276 printf(" pointer data len: AAA=%zu\n", ul_buffer_get_pointer_length(&buf, PTR_AAA));
0a993981
KZ
277
278 ul_buffer_free_data(&buf);
279 str = strdup("foo");
280 ul_buffer_refer_string(&buf, str);
281 ul_buffer_append_data(&buf, ",", 1);
282 ul_buffer_append_string(&buf, "bar");
9ea47344 283 str = ul_buffer_get_data(&buf, &sz, NULL);
f60dc888 284 printf("data [%zu] '%s'\n", sz, str);
0a993981
KZ
285
286 ul_buffer_free_data(&buf);
740b6c73
AP
287
288 return EXIT_SUCCESS;
0a993981
KZ
289}
290#endif /* TEST_PROGRAM_BUFFER */