buf.c (3709B)
1 /*
2 * Copyright (c) 2013-2022 Joris Vink <joris@coders.se>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <sys/types.h>
18
19 #include <string.h>
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <stdlib.h>
23
24 #include "kore.h"
25
26 struct kore_buf *
27 kore_buf_alloc(size_t initial)
28 {
29 struct kore_buf *buf;
30
31 buf = kore_malloc(sizeof(*buf));
32 kore_buf_init(buf, initial);
33 buf->flags = KORE_BUF_OWNER_API;
34
35 return (buf);
36 }
37
38 void
39 kore_buf_init(struct kore_buf *buf, size_t initial)
40 {
41 if (initial > 0)
42 buf->data = kore_malloc(initial);
43 else
44 buf->data = NULL;
45
46 buf->length = initial;
47 buf->offset = 0;
48 buf->flags = 0;
49 }
50
51 void
52 kore_buf_cleanup(struct kore_buf *buf)
53 {
54 kore_free(buf->data);
55 buf->data = NULL;
56 buf->offset = 0;
57 buf->length = 0;
58 }
59
60 void
61 kore_buf_free(struct kore_buf *buf)
62 {
63 kore_buf_cleanup(buf);
64 if (buf->flags & KORE_BUF_OWNER_API)
65 kore_free(buf);
66 }
67
68 void
69 kore_buf_append(struct kore_buf *buf, const void *data, size_t len)
70 {
71 if ((buf->offset + len) < len)
72 fatal("overflow in kore_buf_append");
73
74 if ((buf->offset + len) > buf->length) {
75 buf->length += len;
76 buf->data = kore_realloc(buf->data, buf->length);
77 }
78
79 memcpy((buf->data + buf->offset), data, len);
80 buf->offset += len;
81 }
82
83 void
84 kore_buf_appendv(struct kore_buf *buf, const char *fmt, va_list args)
85 {
86 int l;
87 va_list copy;
88 char *b, sb[BUFSIZ];
89
90 va_copy(copy, args);
91
92 l = vsnprintf(sb, sizeof(sb), fmt, args);
93 if (l == -1)
94 fatal("kore_buf_appendv(): vsnprintf error");
95
96 if ((size_t)l >= sizeof(sb)) {
97 l = vasprintf(&b, fmt, copy);
98 if (l == -1)
99 fatal("kore_buf_appendv(): error or truncation");
100 } else {
101 b = sb;
102 }
103
104 kore_buf_append(buf, b, l);
105 if (b != sb)
106 free(b);
107
108 va_end(copy);
109 }
110
111 void
112 kore_buf_appendf(struct kore_buf *buf, const char *fmt, ...)
113 {
114 va_list args;
115
116 va_start(args, fmt);
117 kore_buf_appendv(buf, fmt, args);
118 va_end(args);
119 }
120
121 char *
122 kore_buf_stringify(struct kore_buf *buf, size_t *len)
123 {
124 char c;
125
126 if (len != NULL)
127 *len = buf->offset;
128
129 c = '\0';
130 kore_buf_append(buf, &c, sizeof(c));
131
132 return ((char *)buf->data);
133 }
134
135 u_int8_t *
136 kore_buf_release(struct kore_buf *buf, size_t *len)
137 {
138 u_int8_t *p;
139
140 p = buf->data;
141 *len = buf->offset;
142
143 buf->data = NULL;
144 kore_buf_free(buf);
145
146 return (p);
147 }
148
149 void
150 kore_buf_replace_string(struct kore_buf *b, const char *src,
151 const void *dst, size_t len)
152 {
153 char *key, *end, *tmp, *p;
154 size_t blen, off, off2, nlen, klen;
155
156 off = 0;
157 klen = strlen(src);
158 for (;;) {
159 blen = b->offset;
160 nlen = blen + len;
161 p = (char *)b->data;
162
163 key = kore_mem_find(p + off, b->offset - off, src, klen);
164 if (key == NULL)
165 break;
166
167 end = key + klen;
168 off = key - p;
169 off2 = ((char *)(b->data + b->offset) - end);
170
171 tmp = kore_malloc(nlen);
172 memcpy(tmp, p, off);
173 if (dst != NULL)
174 memcpy((tmp + off), dst, len);
175 memcpy((tmp + off + len), end, off2);
176
177 kore_free(b->data);
178 b->data = (u_int8_t *)tmp;
179 b->offset = off + len + off2;
180 b->length = nlen;
181
182 off = off + len;
183 }
184 }
185
186 void
187 kore_buf_reset(struct kore_buf *buf)
188 {
189 buf->offset = 0;
190 }