Commit | Line | Data |
---|---|---|
800d4c59 | 1 | /* -*-c-*- |
2 | * | |
800d4c59 | 3 | * Reading and writing packet buffers |
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 | ||
9b5ac6ff | 28 | #ifndef MLIB_BUF_H |
29 | #define MLIB_BUF_H | |
800d4c59 | 30 | |
31 | #ifdef __cplusplus | |
32 | extern "C" { | |
33 | #endif | |
34 | ||
35 | /*----- Header files ------------------------------------------------------*/ | |
36 | ||
e63124bc | 37 | #include <stdarg.h> |
800d4c59 | 38 | #include <stddef.h> |
39 | ||
9b5ac6ff | 40 | #ifndef MLIB_BITS_H |
41 | # include "bits.h" | |
800d4c59 | 42 | #endif |
43 | ||
e63124bc MW |
44 | #ifndef MLIB_CONTROL_H |
45 | # include "control.h" | |
46 | #endif | |
47 | ||
9b5ac6ff | 48 | #ifndef MLIB_DSTR_H |
49 | # include "dstr.h" | |
800d4c59 | 50 | #endif |
51 | ||
4debfda5 MW |
52 | #ifndef MLIB_MACROS_H |
53 | # include "macros.h" | |
54 | #endif | |
55 | ||
800d4c59 | 56 | /*----- Data structures ---------------------------------------------------*/ |
57 | ||
58 | /* --- Buffers --- * | |
59 | * | |
60 | * Buffers provide a simple stream-like interface for building and parsing | |
61 | * packets. | |
62 | */ | |
63 | ||
64 | typedef struct buf { | |
65 | octet *base, *p, *limit; /* Pointers to the buffer */ | |
66 | unsigned f; /* Various flags */ | |
67 | } buf; | |
68 | ||
69 | #define BF_BROKEN 1u /* Buffer is broken */ | |
e63124bc MW |
70 | #define BF_ALLOC 2u /* Buffer is dynamic */ |
71 | #define BF_WRITE 4u /* Currently writing to buffer */ | |
72 | ||
73 | typedef struct dbuf { | |
74 | buf _b; | |
75 | arena *a; /* Allocation arena */ | |
76 | size_t sz; /* Allocated size */ | |
77 | } dbuf; | |
78 | ||
79 | #define DBUF_INIT { { 0, 0, 0, BF_ALLOC | BF_WRITE}, &arena_stdlib, 0 } | |
80 | #define DBUF_BUF(db) (&(db)->_b) | |
81 | ||
82 | extern const struct gprintf_ops buf_printops; | |
800d4c59 | 83 | |
84 | /*----- Useful macros -----------------------------------------------------*/ | |
85 | ||
86 | #define BBASE(b) ((b)->base) | |
87 | #define BLIM(b) ((b)->limit) | |
88 | #define BCUR(b) ((b)->p) | |
89 | #define BSZ(b) ((b)->limit - (b)->base) | |
90 | #define BLEN(b) ((b)->p - (b)->base) | |
91 | #define BLEFT(b) ((b)->limit - (b)->p) | |
92 | #define BSTEP(b, sz) ((b)->p += (sz)) | |
93 | #define BBAD(b) ((b)->f & BF_BROKEN) | |
94 | #define BOK(b) (!BBAD(b)) | |
95 | ||
4debfda5 MW |
96 | #if GCC_VERSION_P(8, 0) |
97 | # define BENSURE(b, sz) \ | |
98 | MUFFLE_WARNINGS_EXPR(GCC_WARNING("-Wint-in-bool-context"), \ | |
e63124bc | 99 | (BBAD(b) ? -1 : (sz) > BLEFT(b) ? buf_tryextend(b, sz) : 0)) |
4debfda5 MW |
100 | #else |
101 | # define BENSURE(b, sz) \ | |
e63124bc | 102 | (BBAD(b) ? -1 : (sz) > BLEFT(b) ? buf_tryextend(b, sz) : 0) |
4debfda5 | 103 | #endif |
800d4c59 | 104 | |
e63124bc MW |
105 | #define DBBASE(db) BBASE(DBUF_BUF(db)) |
106 | #define DBLIM(db) BLIM(DBUF_BUF(db)) | |
107 | #define DBCUR(db) BCUR(DBUF_BUF(db)) | |
108 | #define DBSZ(db) BSZ(DBUF_BUF(db)) | |
109 | #define DBLEN(db) BLEN(DBUF_BUF(db)) | |
110 | #define DBLEFT(db) BLEFT(DBUF_BUF(db)) | |
111 | #define DBSTEP(db, sz) BSTEP(DBUF_BUF(db), (sz)) | |
112 | #define DBBAD(db) BBAD(DBUF_BUF(db)) | |
113 | #define DBOK(db) BOK(DBUF_BUF(db)) | |
114 | #define DBENSURE(b, sz) BENSURE(DBUF_BUF(db), (sz)) | |
115 | ||
116 | #ifdef HAVE_UINT64 | |
117 | # define BUF_DOKLUDGESUFFIXES(_) | |
118 | #else | |
119 | # define BUF_DOKLUDGESUFFIXES(_) \ | |
120 | _(64, 64, 64) _(64, 64_B, 64b) _(64, 64_L, 64l) | |
121 | #endif | |
122 | ||
123 | #define BUF_DOSUFFIXES(_) DOUINTCONV(_) BUF_DOKLUDGESUFFIXES(_) _(z, z, z) | |
9b5ac6ff | 124 | |
800d4c59 | 125 | /*----- Functions provided ------------------------------------------------*/ |
126 | ||
127 | /* --- @buf_init@ --- * | |
128 | * | |
129 | * Arguments: @buf *b@ = pointer to a buffer block | |
130 | * @void *p@ = pointer to a buffer | |
131 | * @size_t sz@ = size of the buffer | |
132 | * | |
133 | * Returns: --- | |
134 | * | |
135 | * Use: Initializes the buffer block appropriately. | |
136 | */ | |
137 | ||
138 | extern void buf_init(buf */*b*/, void */*p*/, size_t /*sz*/); | |
139 | ||
c91413e6 | 140 | /* --- @dbuf_create@ --- * |
e63124bc MW |
141 | * |
142 | * Arguments: @dbuf *db@ = pointer to a dynamic buffer block | |
143 | * | |
144 | * Returns: --- | |
145 | * | |
146 | * Use: Initializes a dynamic buffer. The buffer is initially empty, | |
147 | * and ready for writing. | |
148 | */ | |
149 | ||
c91413e6 | 150 | extern void dbuf_create(dbuf */*db*/); |
e63124bc MW |
151 | |
152 | /* --- @dbuf_reset@ --- * | |
153 | * | |
154 | * Arguments: @dbuf *db@ = pointer to a buffer block | |
155 | * | |
156 | * Returns: --- | |
157 | * | |
158 | * Use: Resets a buffer so that it can be written again. | |
159 | */ | |
160 | ||
161 | extern void dbuf_reset(dbuf */*db*/); | |
162 | ||
163 | /* --- @dbuf_destroy@ --- * | |
164 | * | |
165 | * Arguments: @dbuf *db@ = pointer to a buffer block | |
166 | * | |
167 | * Returns: --- | |
168 | * | |
169 | * Use: Release all of the resources held by a dynamic buffer. | |
170 | */ | |
171 | ||
172 | extern void dbuf_destroy(dbuf */*db*/); | |
173 | ||
800d4c59 | 174 | /* --- @buf_break@ --- * |
175 | * | |
176 | * Arguments: @buf *b@ = pointer to a buffer block | |
177 | * | |
178 | * Returns: Some negative value. | |
179 | * | |
180 | * Use: Marks a buffer as broken. | |
181 | */ | |
182 | ||
183 | extern int buf_break(buf */*b*/); | |
184 | ||
185 | /* --- @buf_flip@ --- * | |
186 | * | |
187 | * Arguments: @buf *b@ = pointer to a buffer block | |
188 | * | |
189 | * Returns: --- | |
190 | * | |
191 | * Use: Flips a buffer so that if you've just been writing to it, | |
192 | * you can now read from the bit you've written. | |
193 | */ | |
194 | ||
195 | extern void buf_flip(buf */*b*/); | |
196 | ||
197 | /* --- @buf_ensure@ --- * | |
198 | * | |
199 | * Arguments: @buf *b@ = pointer to a buffer block | |
200 | * @size_t sz@ = size of data wanted | |
201 | * | |
202 | * Returns: Zero if it worked, nonzero if there wasn't enough space. | |
203 | * | |
204 | * Use: Ensures that there are @sz@ bytes still in the buffer. | |
205 | */ | |
206 | ||
207 | extern int buf_ensure(buf */*b*/, size_t /*sz*/); | |
208 | ||
e63124bc MW |
209 | /* --- @buf_tryextend@ --- * |
210 | * | |
211 | * Arguments: @buf *b@ = pointer to a buffer block | |
212 | * @size_t sz@ = size of data wanted | |
213 | * | |
214 | * Returns: Zero if it worked, nonzero if the buffer won't grow. | |
215 | * | |
216 | * Use: Extend the buffer so that at least @sz@ bytes are available. | |
217 | * This only works if the buffer is allocated. | |
218 | */ | |
219 | ||
220 | extern int buf_tryextend(buf */*b*/, size_t /*sz*/); | |
221 | ||
800d4c59 | 222 | /* --- @buf_get@ --- * |
223 | * | |
224 | * Arguments: @buf *b@ = pointer to a buffer block | |
225 | * @size_t sz@ = size of the buffer | |
226 | * | |
227 | * Returns: Pointer to the place in the buffer. | |
228 | * | |
229 | * Use: Reserves a space in the buffer of the requested size, and | |
230 | * returns its start address. | |
231 | */ | |
232 | ||
233 | extern void *buf_get(buf */*b*/, size_t /*sz*/); | |
234 | ||
235 | /* --- @buf_put@ --- * | |
236 | * | |
237 | * Arguments: @buf *b@ = pointer to a buffer block | |
238 | * @const void *p@ = pointer to a buffer | |
239 | * @size_t sz@ = size of the buffer | |
240 | * | |
241 | * Returns: Zero if it worked, nonzero if there wasn't enough space. | |
242 | * | |
243 | * Use: Fetches data from some place and puts it in the buffer | |
244 | */ | |
245 | ||
246 | extern int buf_put(buf */*b*/, const void */*p*/, size_t /*sz*/); | |
247 | ||
248 | /* --- @buf_getbyte@ --- * | |
249 | * | |
250 | * Arguments: @buf *b@ = pointer to a buffer block | |
251 | * | |
252 | * Returns: A byte, or less than zero if there wasn't a byte there. | |
253 | * | |
254 | * Use: Gets a single byte from a buffer. | |
255 | */ | |
256 | ||
257 | extern int buf_getbyte(buf */*b*/); | |
258 | ||
259 | /* --- @buf_putbyte@ --- * | |
260 | * | |
261 | * Arguments: @buf *b@ = pointer to a buffer block | |
262 | * @int ch@ = byte to write | |
263 | * | |
264 | * Returns: Zero if OK, nonzero if there wasn't enough space. | |
265 | * | |
266 | * Use: Puts a single byte in a buffer. | |
267 | */ | |
268 | ||
269 | extern int buf_putbyte(buf */*b*/, int /*ch*/); | |
270 | ||
9b5ac6ff | 271 | /* --- @buf_getu{8,{16,24,32,64}{,l,b}}@ --- * |
800d4c59 | 272 | * |
273 | * Arguments: @buf *b@ = pointer to a buffer block | |
9b5ac6ff | 274 | * @uintSZ *w@ = where to put the word |
800d4c59 | 275 | * |
276 | * Returns: Zero if OK, or nonzero if there wasn't a word there. | |
277 | * | |
9b5ac6ff | 278 | * Use: Gets a word of appropriate size and order from a buffer. |
800d4c59 | 279 | */ |
280 | ||
9b5ac6ff | 281 | #define BUF_DECL_GETU_(n, W, w) \ |
282 | extern int buf_getu##w(buf */*b*/, uint##n */*w*/); | |
283 | DOUINTCONV(BUF_DECL_GETU_) | |
800d4c59 | 284 | |
b64eb60f MW |
285 | /* --- @buf_getk64{,l,b}@ --- * |
286 | * | |
287 | * Arguments: @buf *b@ = pointer to a buffer block | |
288 | * @kludge64 *w@ = where to put the word | |
289 | * | |
290 | * Returns: Zero if OK, or nonzero if there wasn't a word there. | |
291 | * | |
292 | * Use: Gets a word of appropriate size and order from a buffer. | |
293 | */ | |
294 | ||
295 | extern int buf_getk64(buf */*b*/, kludge64 */*w*/); | |
296 | extern int buf_getk64l(buf */*b*/, kludge64 */*w*/); | |
297 | extern int buf_getk64b(buf */*b*/, kludge64 */*w*/); | |
298 | ||
9b5ac6ff | 299 | /* --- @buf_putu{8,{16,24,32,64}{,l,b}}@ --- * |
800d4c59 | 300 | * |
301 | * Arguments: @buf *b@ = pointer to a buffer block | |
9b5ac6ff | 302 | * @uintSZ w@ = word to write |
800d4c59 | 303 | * |
9b5ac6ff | 304 | * Returns: Zero if OK, or nonzero if there wasn't enough space |
800d4c59 | 305 | * |
9b5ac6ff | 306 | * Use: Puts a word into a buffer with appropriate size and order. |
800d4c59 | 307 | */ |
308 | ||
9b5ac6ff | 309 | #define BUF_DECL_PUTU_(n, W, w) \ |
310 | extern int buf_putu##w(buf */*b*/, uint##n /*w*/); | |
311 | DOUINTCONV(BUF_DECL_PUTU_) | |
800d4c59 | 312 | |
b64eb60f MW |
313 | /* --- @buf_putk64{,l,b}@ --- * |
314 | * | |
315 | * Arguments: @buf *b@ = pointer to a buffer block | |
316 | * @kludge64 w@ = word to write | |
317 | * | |
318 | * Returns: Zero if OK, or nonzero if there wasn't enough space | |
319 | * | |
320 | * Use: Gets a word of appropriate size and order from a buffer. | |
321 | */ | |
322 | ||
323 | extern int buf_putk64(buf */*b*/, kludge64 /*w*/); | |
324 | extern int buf_putk64l(buf */*b*/, kludge64 /*w*/); | |
325 | extern int buf_putk64b(buf */*b*/, kludge64 /*w*/); | |
326 | ||
9b5ac6ff | 327 | /* --- @buf_getmem{8,{16,24,32,64}{,l,b},z} --- * |
800d4c59 | 328 | * |
329 | * Arguments: @buf *b@ = pointer to a buffer block | |
330 | * @size_t *nn@ = where to put the length | |
331 | * | |
332 | * Returns: Pointer to the buffer data, or null. | |
333 | * | |
9b5ac6ff | 334 | * Use: Gets a chunk of memory from a buffer. The suffix is the |
335 | * width and byte order of the length; @z@ means null- | |
336 | * terminated. | |
800d4c59 | 337 | */ |
338 | ||
9b5ac6ff | 339 | #define BUF_DECL_GETMEM_(n, W, w) \ |
340 | extern void *buf_getmem##w(buf */*b*/, size_t */*nn*/); | |
341 | BUF_DOSUFFIXES(BUF_DECL_GETMEM_) | |
800d4c59 | 342 | |
9b5ac6ff | 343 | /* --- @buf_putmem{8,{16,24,32,64}{,l,b},z} --- * |
800d4c59 | 344 | * |
345 | * Arguments: @buf *b@ = pointer to a buffer block | |
346 | * @const void *p@ = pointer to data to write | |
347 | * @size_t n@ = length to write | |
348 | * | |
349 | * Returns: Zero if OK, nonzero if there wasn't enough space. | |
350 | * | |
9b5ac6ff | 351 | * Use: Writes a chunk of data to a buffer. The suffix is the |
352 | * width and byte order of the length; @z@ means null- | |
353 | * terminated. | |
800d4c59 | 354 | */ |
355 | ||
9b5ac6ff | 356 | #define BUF_DECL_PUTMEM_(n, W, w) \ |
357 | extern int buf_putmem##w(buf */*b*/, const void */*p*/, size_t /*nn*/); | |
358 | BUF_DOSUFFIXES(BUF_DECL_PUTMEM_) | |
800d4c59 | 359 | |
9b5ac6ff | 360 | /* --- @buf_getbuf{8,{16,24,32,64}{,l,b},z} --- * |
800d4c59 | 361 | * |
362 | * Arguments: @buf *b@ = pointer to a buffer block | |
363 | * @buf *bb@ = where to put the result | |
364 | * | |
365 | * Returns: Zero if it worked, nonzero if there wasn't enough space. | |
366 | * | |
367 | * Use: Gets a block of data from a buffer, and writes its bounds to | |
9b5ac6ff | 368 | * another buffer. |
800d4c59 | 369 | */ |
370 | ||
9b5ac6ff | 371 | #define BUF_DECL_GETBUF_(n, W, w) \ |
372 | extern int buf_getbuf##w(buf */*b*/, buf */*bb*/); | |
373 | BUF_DOSUFFIXES(BUF_DECL_GETBUF_) | |
800d4c59 | 374 | |
9b5ac6ff | 375 | /* --- @buf_putbuf{8,{16,24,32,64}{,l,b},z} --- * |
800d4c59 | 376 | * |
377 | * Arguments: @buf *b@ = pointer to a buffer block | |
378 | * @buf *bb@ = buffer to write | |
379 | * | |
380 | * Returns: Zero if it worked, nonzero if there wasn't enough space. | |
381 | * | |
9b5ac6ff | 382 | * Use: Puts the contents of a buffer to a buffer. |
800d4c59 | 383 | */ |
384 | ||
9b5ac6ff | 385 | #define BUF_DECL_PUTBUF_(n, W, w) \ |
386 | extern int buf_putbuf##w(buf */*b*/, buf */*bb*/); | |
387 | BUF_DOSUFFIXES(BUF_DECL_PUTBUF_) | |
800d4c59 | 388 | |
9b5ac6ff | 389 | /* --- @buf_getdstr{8,{16,24,32,64}{,l,b},z} --- * |
800d4c59 | 390 | * |
391 | * Arguments: @buf *b@ = pointer to a buffer block | |
392 | * @dstr *d@ = where to put the result | |
393 | * | |
394 | * Returns: Zero if it worked, nonzero if there wasn't enough space. | |
395 | * | |
396 | * Use: Gets a block of data from a buffer, and writes its contents | |
9b5ac6ff | 397 | * to a string. |
800d4c59 | 398 | */ |
399 | ||
9b5ac6ff | 400 | #define BUF_DECL_GETDSTR_(n, W, w) \ |
401 | extern int buf_getdstr##w(buf */*b*/, dstr */*d*/); | |
402 | BUF_DOSUFFIXES(BUF_DECL_GETDSTR_) | |
800d4c59 | 403 | |
9b5ac6ff | 404 | /* --- @buf_putdstr{8,{16,24,32,64}{,l,b},z} --- * |
800d4c59 | 405 | * |
406 | * Arguments: @buf *b@ = pointer to a buffer block | |
407 | * @dstr *d@ = string to write | |
408 | * | |
409 | * Returns: Zero if it worked, nonzero if there wasn't enough space. | |
410 | * | |
9b5ac6ff | 411 | * Use: Puts a dynamic string to a buffer. |
800d4c59 | 412 | */ |
413 | ||
9b5ac6ff | 414 | #define BUF_DECL_PUTDSTR_(n, W, w) \ |
415 | extern int buf_putdstr##w(buf */*b*/, dstr */*d*/); | |
416 | BUF_DOSUFFIXES(BUF_DECL_PUTDSTR_) | |
800d4c59 | 417 | |
9b5ac6ff | 418 | /* --- @buf_putstr{8,{16,24,32,64}{,l,b},z} --- * |
800d4c59 | 419 | * |
420 | * Arguments: @buf *b@ = pointer to a buffer block | |
9b5ac6ff | 421 | * @const char *p@ = string to write |
800d4c59 | 422 | * |
423 | * Returns: Zero if it worked, nonzero if there wasn't enough space. | |
424 | * | |
9b5ac6ff | 425 | * Use: Puts a null-terminated string to a buffer. |
800d4c59 | 426 | */ |
427 | ||
9b5ac6ff | 428 | #define BUF_DECL_PUTSTR_(n, W, w) \ |
b3027790 | 429 | extern int buf_putstr##w(buf */*b*/, const char */*p*/); |
9b5ac6ff | 430 | BUF_DOSUFFIXES(BUF_DECL_PUTSTR_) |
d4efbcd9 | 431 | |
e63124bc MW |
432 | /* --- @buf_putf64{,b,l} --- * |
433 | * | |
434 | * Arguments: @buf *b@ = a buffer to write to | |
435 | * @double x@ = a number to write | |
436 | * | |
437 | * Returns: Zero on success, @-1@ on failure (and the buffer is broken). | |
438 | * | |
439 | * On C89, this function can't detect negative zero so these | |
440 | * will be silently written as positive zero. | |
441 | * | |
442 | * This function doesn't distinguish NaNs. Any NaN is written | |
443 | * as a quiet NaN with all payload bits zero. | |
444 | * | |
445 | * A finite value with too large a magnitude to be represented | |
446 | * is rounded to the appropriate infinity. Other finite values | |
447 | * are rounded as necessary, in the usual IEEE 754 round-to- | |
448 | * nearest-or-even way. | |
449 | */ | |
450 | ||
451 | extern int buf_putf64(buf */*b*/, double /*x*/); | |
452 | extern int buf_putf64b(buf */*b*/, double /*x*/); | |
453 | extern int buf_putf64l(buf */*b*/, double /*x*/); | |
454 | ||
455 | /* --- @buf_getf64{,b,l} --- * | |
456 | * | |
457 | * Arguments: @buf *b@ = a buffer to read from | |
458 | * @double *x_out@ = where to put the result | |
459 | * | |
460 | * Returns: Zero on success, @-1@ on failure (and the buffer is broken). | |
461 | * | |
462 | * If the system supports NaNs, then any encoded NaN is returned | |
463 | * as the value of @NAN@ in @<math.h>@; otherwise, this function | |
464 | * reports failure. | |
465 | * | |
466 | * In general, values are rounded to the nearest available | |
467 | * value, in the way that the system usually rounds. If the | |
468 | * system doesn't support infinities, then any encoded infinity | |
469 | * is reported as the largest-possible-magnitude finite value | |
470 | * instead. | |
471 | */ | |
472 | ||
473 | extern int buf_getf64(buf */*b*/, double *x_/*out*/); | |
474 | extern int buf_getf64b(buf */*b*/, double *x_/*out*/); | |
475 | extern int buf_getf64l(buf */*b*/, double *x_/*out*/); | |
476 | ||
477 | #define BUF_ENCLOSETAG(tag, buf, mk, check, poke, lensz) \ | |
478 | MC_BEFORE(tag##__save, \ | |
479 | { (mk) = BLEN(buf); \ | |
480 | if (!BENSURE(buf, lensz)) (buf)->p += (lensz); }) \ | |
481 | MC_AFTER(tag##__poke, \ | |
482 | { size_t _delta = BLEN(buf) - (mk) + (lensz); \ | |
483 | assert(check); \ | |
484 | if (BOK(buf)) poke((buf)->base + (mk), _delta); }) | |
485 | ||
486 | #define BUF_ENCLOSEZTAG(tag, buf) \ | |
487 | MC_AFTER(tag##__zero, { buf_putbyte(buf, 0); }) | |
488 | ||
489 | #define BUF_ENCLOSENATIVETAG(tag, buf, mk, W) \ | |
490 | BUF_ENCLOSETAG(tag, buf, mk, (_delta <= MASK##W), STORE##W, SZ_##W) | |
491 | ||
492 | #define BUF_STORESZK64(p, sz) \ | |
493 | do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_((p), _k); } while (0) | |
494 | #define BUF_STORESZK64_B(p, sz) \ | |
495 | do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_B_((p), _k); } while (0) | |
496 | #define BUF_STORESZK64_L(p, sz) \ | |
497 | do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_L_((p), _k); } while (0) | |
498 | #define BUF_ENCLOSEK64TAG(tag, buf, mk, W) \ | |
499 | BUF_ENCLOSE(tag, buf, mk, 1, BUF_STORESZK##W, 8) | |
500 | ||
501 | #define BUF_ENCLOSE8(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 8) | |
502 | #define BUF_ENCLOSE16(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 16) | |
503 | #define BUF_ENCLOSE16_B(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 16_B) | |
504 | #define BUF_ENCLOSE16_L(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 16_L) | |
505 | #define BUF_ENCLOSE24(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 24) | |
506 | #define BUF_ENCLOSE24_B(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 24_B) | |
507 | #define BUF_ENCLOSE24_L(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 24_L) | |
508 | #define BUF_ENCLOSE32(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 32) | |
509 | #define BUF_ENCLOSE32_B(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 32_B) | |
510 | #define BUF_ENCLOSE32_L(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 32_L) | |
511 | #ifdef HAVE_UINT64 | |
512 | # define BUF_ENCLOSE64(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 64) | |
513 | # define BUF_ENCLOSE64_B(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 64_B) | |
514 | # define BUF_ENCLOSE64_L(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 64_L) | |
515 | #else | |
516 | # define BUF_ENCLOSE64(buf, mk) BUF_ENCLOSEK64TAG(encl, buf, mk, 64) | |
517 | # define BUF_ENCLOSE64_B(buf, mk) BUF_ENCLOSEK64TAG(encl, buf, mk, 64_B) | |
518 | # define BUF_ENCLOSE64_L(buf, mk) BUF_ENCLOSEK64TAG(encl, buf, mk, 64_L) | |
519 | #endif | |
520 | #define BUF_ENCLOSEZ(buf) BUF_ENCLOSEZTAG(encl, buf) | |
521 | ||
522 | /* --- @buf_vputstrf@ --- * | |
523 | * | |
524 | * Arguments: @buf *b@ = pointer to a buffer | |
525 | * @const char *p@ = pointer to @printf@-style format string | |
526 | * @va_list *ap@ = argument handle | |
527 | * | |
528 | * Returns: The number of characters written to the string, or @-1@ on | |
529 | * failure. | |
530 | * | |
531 | * Use: As for @buf_putstrf@, but may be used as a back-end to user- | |
532 | * supplied functions with @printf@-style interfaces. | |
533 | */ | |
534 | ||
535 | extern int buf_vputstrf(buf */*b*/, const char */*p*/, va_list */*ap*/); | |
536 | ||
537 | /* --- @buf_putstrf@ --- * | |
538 | * | |
539 | * Arguments: @buf *b@ = pointer to a buffer | |
540 | * @const char *p@ = pointer to @printf@-style format string | |
541 | * @...@ = argument handle | |
542 | * | |
543 | * Returns: The number of characters written to the string, or @-1@ on | |
544 | * failure. | |
545 | * | |
546 | * Use: Format a string to a buffer. The resulting output is not | |
547 | * null-terminated. | |
548 | */ | |
549 | ||
550 | extern PRINTF_LIKE(2, 3) int buf_putstrf(buf */*b*/, const char */*p*/, ...); | |
551 | ||
552 | /* --- @buf_{,v}putstrf{8,{16,24,32,64}{,b,l},z}@ --- * | |
553 | * | |
554 | * Arguments: @buf *b@ = pointer to a buffer | |
555 | * @const char *p@ = pointer to @printf@-style format string | |
556 | * @va_list *ap@ = argument handle | |
557 | * | |
558 | * Returns: The number of characters written to the string, or @-1@ on | |
559 | * failure. | |
560 | * | |
561 | * Use: As for @buf_putstr@, but using a format string. | |
562 | */ | |
563 | ||
564 | #define BUF_DECL_PUTSTRF_(n, W, w) \ | |
565 | extern int buf_vputstrf##w(buf */*b*/, \ | |
566 | const char */*p*/, va_list */*ap*/); \ | |
567 | extern PRINTF_LIKE(2, 3) \ | |
568 | int buf_putstrf##w(buf */*b*/, const char */*p*/, ...); | |
569 | BUF_DOSUFFIXES(BUF_DECL_PUTSTRF_) | |
570 | #undef BUF_DECL_PUTSTRF_ | |
571 | ||
800d4c59 | 572 | /*----- That's all, folks -------------------------------------------------*/ |
573 | ||
574 | #ifdef __cplusplus | |
575 | } | |
576 | #endif | |
577 | ||
578 | #endif |