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