Commit | Line | Data |
---|---|---|
800d4c59 | 1 | /* -*-c-*- |
2 | * | |
800d4c59 | 3 | * Buffer handling |
4 | * | |
5 | * (c) 2001 Straylight/Edgeware | |
6 | */ | |
7 | ||
d4efbcd9 | 8 | /*----- Licensing notice --------------------------------------------------* |
800d4c59 | 9 | * |
9b5ac6ff | 10 | * This file is part of the mLib utilities library. |
800d4c59 | 11 | * |
9b5ac6ff | 12 | * mLib is free software; you can redistribute it and/or modify |
800d4c59 | 13 | * it under the terms of the GNU Library General Public License as |
14 | * published by the Free Software Foundation; either version 2 of the | |
15 | * License, or (at your option) any later version. | |
d4efbcd9 | 16 | * |
9b5ac6ff | 17 | * mLib is distributed in the hope that it will be useful, |
800d4c59 | 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU Library General Public License for more details. | |
d4efbcd9 | 21 | * |
800d4c59 | 22 | * You should have received a copy of the GNU Library General Public |
9b5ac6ff | 23 | * License along with mLib; if not, write to the Free |
800d4c59 | 24 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
25 | * MA 02111-1307, USA. | |
26 | */ | |
27 | ||
28 | /*----- Header files ------------------------------------------------------*/ | |
29 | ||
9b5ac6ff | 30 | #include <assert.h> |
800d4c59 | 31 | #include <string.h> |
32 | ||
800d4c59 | 33 | #include "buf.h" |
34 | ||
35 | /*----- Main code ---------------------------------------------------------*/ | |
36 | ||
37 | /* --- @buf_init@ --- * | |
38 | * | |
39 | * Arguments: @buf *b@ = pointer to a buffer block | |
40 | * @void *p@ = pointer to a buffer | |
41 | * @size_t sz@ = size of the buffer | |
42 | * | |
43 | * Returns: --- | |
44 | * | |
45 | * Use: Initializes the buffer block appropriately. | |
46 | */ | |
47 | ||
48 | void buf_init(buf *b, void *p, size_t sz) | |
49 | { | |
50 | b->base = b->p = p; | |
51 | b->limit = b->p + sz; | |
52 | b->f = 0; | |
53 | } | |
54 | ||
55 | /* --- @buf_break@ --- * | |
56 | * | |
57 | * Arguments: @buf *b@ = pointer to a buffer block | |
58 | * | |
59 | * Returns: Some negative value. | |
60 | * | |
61 | * Use: Marks a buffer as broken. | |
62 | */ | |
63 | ||
64 | int buf_break(buf *b) { b->f |= BF_BROKEN; return (-1); } | |
65 | ||
66 | /* --- @buf_flip@ --- * | |
67 | * | |
68 | * Arguments: @buf *b@ = pointer to a buffer block | |
69 | * | |
70 | * Returns: --- | |
71 | * | |
72 | * Use: Flips a buffer so that if you've just been writing to it, | |
73 | * you can now read from the bit you've written. | |
74 | */ | |
75 | ||
76 | void buf_flip(buf *b) | |
77 | { | |
78 | b->limit = b->p; | |
79 | b->p = b->base; | |
80 | } | |
81 | ||
82 | /* --- @buf_ensure@ --- * | |
83 | * | |
84 | * Arguments: @buf *b@ = pointer to a buffer block | |
85 | * @size_t sz@ = size of data wanted | |
86 | * | |
87 | * Returns: Zero if it worked, nonzero if there wasn't enough space. | |
88 | * | |
89 | * Use: Ensures that there are @sz@ bytes still in the buffer. | |
90 | */ | |
91 | ||
92 | int buf_ensure(buf *b, size_t sz) { return (BENSURE(b, sz)); } | |
93 | ||
94 | /* --- @buf_get@ --- * | |
95 | * | |
96 | * Arguments: @buf *b@ = pointer to a buffer block | |
97 | * @size_t sz@ = size of the buffer | |
98 | * | |
99 | * Returns: Pointer to the place in the buffer. | |
100 | * | |
101 | * Use: Reserves a space in the buffer of the requested size, and | |
102 | * returns its start address. | |
103 | */ | |
104 | ||
105 | void *buf_get(buf *b, size_t sz) | |
106 | { | |
107 | void *p; | |
108 | if (BENSURE(b, sz)) | |
109 | return (0); | |
110 | p = BCUR(b); | |
111 | BSTEP(b, sz); | |
112 | return (p); | |
113 | } | |
114 | ||
115 | /* --- @buf_put@ --- * | |
116 | * | |
117 | * Arguments: @buf *b@ = pointer to a buffer block | |
118 | * @const void *p@ = pointer to a buffer | |
119 | * @size_t sz@ = size of the buffer | |
120 | * | |
121 | * Returns: Zero if it worked, nonzero if there wasn't enough space. | |
122 | * | |
123 | * Use: Fetches data from some place and puts it in the buffer | |
124 | */ | |
125 | ||
126 | int buf_put(buf *b, const void *p, size_t sz) | |
127 | { | |
128 | if (BENSURE(b, sz)) | |
129 | return (-1); | |
130 | memcpy(BCUR(b), p, sz); | |
131 | BSTEP(b, sz); | |
132 | return (0); | |
133 | } | |
134 | ||
135 | /* --- @buf_getbyte@ --- * | |
136 | * | |
137 | * Arguments: @buf *b@ = pointer to a buffer block | |
138 | * | |
139 | * Returns: A byte, or less than zero if there wasn't a byte there. | |
140 | * | |
141 | * Use: Gets a single byte from a buffer. | |
142 | */ | |
143 | ||
144 | int buf_getbyte(buf *b) | |
145 | { | |
146 | if (BENSURE(b, 1)) | |
147 | return (-1); | |
148 | return (*b->p++); | |
149 | } | |
150 | ||
151 | /* --- @buf_putbyte@ --- * | |
152 | * | |
153 | * Arguments: @buf *b@ = pointer to a buffer block | |
154 | * @int ch@ = byte to write | |
155 | * | |
156 | * Returns: Zero if OK, nonzero if there wasn't enough space. | |
157 | * | |
158 | * Use: Puts a single byte in a buffer. | |
159 | */ | |
160 | ||
161 | int buf_putbyte(buf *b, int ch) | |
162 | { | |
163 | if (BENSURE(b, 1)) | |
164 | return (-1); | |
165 | *b->p++ = ch; | |
166 | return (0); | |
167 | } | |
168 | ||
9b5ac6ff | 169 | /* --- @buf_getu{8,{16,24,32,64}{,l,b}}@ --- * |
800d4c59 | 170 | * |
171 | * Arguments: @buf *b@ = pointer to a buffer block | |
9b5ac6ff | 172 | * @uintSZ *w@ = where to put the word |
800d4c59 | 173 | * |
174 | * Returns: Zero if OK, or nonzero if there wasn't a word there. | |
175 | * | |
9b5ac6ff | 176 | * Use: Gets a word of appropriate size and order from a buffer. |
800d4c59 | 177 | */ |
178 | ||
9b5ac6ff | 179 | #define BUF_GETU_(n, W, w) \ |
180 | int buf_getu##w(buf *b, uint##n *ww) \ | |
181 | { \ | |
182 | if (BENSURE(b, SZ_##W)) return (-1); \ | |
183 | *ww = LOAD##W(b->p); \ | |
184 | BSTEP(b, SZ_##W); \ | |
185 | return (0); \ | |
186 | } | |
187 | DOUINTCONV(BUF_GETU_) | |
800d4c59 | 188 | |
9b5ac6ff | 189 | /* --- @buf_putu{8,{16,24,32,64}{,l,b}}@ --- * |
800d4c59 | 190 | * |
191 | * Arguments: @buf *b@ = pointer to a buffer block | |
9b5ac6ff | 192 | * @uintSZ w@ = word to write |
800d4c59 | 193 | * |
9b5ac6ff | 194 | * Returns: Zero if OK, or nonzero if there wasn't enough space |
800d4c59 | 195 | * |
9b5ac6ff | 196 | * Use: Puts a word into a buffer with appropriate size and order. |
800d4c59 | 197 | */ |
198 | ||
9b5ac6ff | 199 | #define BUF_PUTU_(n, W, w) \ |
200 | int buf_putu##w(buf *b, uint##n ww) \ | |
201 | { \ | |
202 | if (BENSURE(b, SZ_##W)) return (-1); \ | |
203 | STORE##W(b->p, ww); \ | |
204 | BSTEP(b, SZ_##W); \ | |
205 | return (0); \ | |
206 | } | |
207 | DOUINTCONV(BUF_PUTU_) | |
800d4c59 | 208 | |
209 | /* --- @findz@ --- * | |
210 | * | |
211 | * Arguments: @buf *b@ = pointer to a buffer block | |
212 | * @size_t *nn@ = where to put the length | |
213 | * | |
214 | * Returns: Zero if OK, nonzero if there wasn't a null byte to be found. | |
215 | * | |
95491579 MW |
216 | * Use: Finds a terminating null byte. The length includes this |
217 | * terminator. | |
800d4c59 | 218 | */ |
219 | ||
220 | static int findz(buf *b, size_t *nn) | |
221 | { | |
222 | octet *p; | |
223 | ||
a4589237 | 224 | if ((p = memchr(BCUR(b), 0, BLEFT(b))) == 0) { |
800d4c59 | 225 | buf_break(b); |
226 | return (-1); | |
227 | } | |
95491579 | 228 | *nn = p - BCUR(b) + 1; |
800d4c59 | 229 | return (0); |
230 | } | |
231 | ||
9b5ac6ff | 232 | /* --- @buf_getmem{8,{16,24,32,64}{,l,b},z} --- * |
800d4c59 | 233 | * |
234 | * Arguments: @buf *b@ = pointer to a buffer block | |
235 | * @size_t *nn@ = where to put the length | |
236 | * | |
237 | * Returns: Pointer to the buffer data, or null. | |
238 | * | |
9b5ac6ff | 239 | * Use: Gets a chunk of memory from a buffer. The suffix is the |
240 | * width and byte order of the length; @z@ means null- | |
241 | * terminated. | |
800d4c59 | 242 | */ |
243 | ||
9b5ac6ff | 244 | #define BUF_GETMEM_(n, W, w) \ |
245 | void *buf_getmem##w(buf *b, size_t *nn) \ | |
246 | { \ | |
247 | uint##n sz; \ | |
a4589237 | 248 | if (buf_getu##w(b, &sz)) return (0); \ |
9b5ac6ff | 249 | *nn = sz; \ |
250 | return (buf_get(b, sz)); \ | |
251 | } | |
252 | DOUINTCONV(BUF_GETMEM_) | |
800d4c59 | 253 | |
800d4c59 | 254 | void *buf_getmemz(buf *b, size_t *nn) |
255 | { | |
256 | if (findz(b, nn)) return (0); | |
257 | return (buf_get(b, *nn)); | |
258 | } | |
259 | ||
9b5ac6ff | 260 | /* --- @buf_putmem{8,{16,24,32,64}{,l,b},z} --- * |
800d4c59 | 261 | * |
262 | * Arguments: @buf *b@ = pointer to a buffer block | |
263 | * @const void *p@ = pointer to data to write | |
264 | * @size_t n@ = length to write | |
265 | * | |
266 | * Returns: Zero if OK, nonzero if there wasn't enough space. | |
267 | * | |
9b5ac6ff | 268 | * Use: Writes a chunk of data to a buffer. The suffix is the |
269 | * width and byte order of the length; @z@ means null- | |
270 | * terminated. | |
800d4c59 | 271 | */ |
272 | ||
9b5ac6ff | 273 | #define BUF_PUTMEM_(n, W, w) \ |
274 | int buf_putmem##w(buf *b, const void *p, size_t sz) \ | |
275 | { \ | |
276 | assert(sz <= MASK##W); \ | |
a4589237 | 277 | if (buf_putu##w(b, sz) || buf_put(b, p, sz)) \ |
9b5ac6ff | 278 | return (-1); \ |
279 | return (0); \ | |
280 | } | |
281 | DOUINTCONV(BUF_PUTMEM_) | |
800d4c59 | 282 | |
283 | int buf_putmemz(buf *b, const void *p, size_t n) | |
284 | { | |
285 | octet *q; | |
286 | ||
287 | assert(!memchr(p, 0, n)); | |
288 | if ((q = buf_get(b, n + 1)) == 0) | |
289 | return (-1); | |
290 | memcpy(q, p, n); | |
291 | q[n] = 0; | |
292 | return (0); | |
293 | } | |
294 | ||
9b5ac6ff | 295 | /* --- @buf_getbuf{8,{16,24,32,64}{,l,b},z} --- * |
800d4c59 | 296 | * |
297 | * Arguments: @buf *b@ = pointer to a buffer block | |
298 | * @buf *bb@ = where to put the result | |
299 | * | |
300 | * Returns: Zero if it worked, nonzero if there wasn't enough space. | |
301 | * | |
302 | * Use: Gets a block of data from a buffer, and writes its bounds to | |
9b5ac6ff | 303 | * another buffer. |
800d4c59 | 304 | */ |
305 | ||
9b5ac6ff | 306 | #define BUF_GETBUF_(n, W, w) \ |
307 | int buf_getbuf##w(buf *b, buf *bb) \ | |
308 | { \ | |
309 | void *p; \ | |
310 | size_t sz; \ | |
800d4c59 | 311 | \ |
9b5ac6ff | 312 | if ((p = buf_getmem##w(b, &sz)) == 0) \ |
313 | return (-1); \ | |
314 | buf_init(bb, p, sz); \ | |
315 | return (0); \ | |
800d4c59 | 316 | } |
9b5ac6ff | 317 | BUF_DOSUFFIXES(BUF_GETBUF_) |
800d4c59 | 318 | |
9b5ac6ff | 319 | /* --- @buf_putbuf{8,{16,24,32,64}{,l,b},z} --- * |
800d4c59 | 320 | * |
321 | * Arguments: @buf *b@ = pointer to a buffer block | |
9b5ac6ff | 322 | * @buf *bb@ = buffer to write |
800d4c59 | 323 | * |
324 | * Returns: Zero if it worked, nonzero if there wasn't enough space. | |
325 | * | |
9b5ac6ff | 326 | * Use: Puts the contents of a buffer to a buffer. |
800d4c59 | 327 | */ |
328 | ||
9b5ac6ff | 329 | #define BUF_PUTBUF_(n, W, w) \ |
330 | int buf_putbuf##w(buf *b, buf *bb) \ | |
331 | { return (buf_putmem##w(b, BBASE(bb), BLEN(bb))); } | |
332 | BUF_DOSUFFIXES(BUF_PUTBUF_) | |
800d4c59 | 333 | |
9b5ac6ff | 334 | /* --- @buf_putstr{8,{16,24,32,64}{,l,b},z} --- * |
800d4c59 | 335 | * |
336 | * Arguments: @buf *b@ = pointer to a buffer block | |
9b5ac6ff | 337 | * @const char *p@ = string to write |
800d4c59 | 338 | * |
339 | * Returns: Zero if it worked, nonzero if there wasn't enough space. | |
340 | * | |
9b5ac6ff | 341 | * Use: Puts a null-terminated string to a buffer. |
800d4c59 | 342 | */ |
343 | ||
9b5ac6ff | 344 | #define BUF_PUTSTR_(n, W, w) \ |
345 | int buf_putstr##w(buf *b, const char *p) \ | |
346 | { return (buf_putmem##w(b, p, strlen(p))); } | |
347 | BUF_DOSUFFIXES(BUF_PUTSTR_) | |
800d4c59 | 348 | |
349 | /*----- That's all, folks -------------------------------------------------*/ |