chiark / gitweb /
@@@ timeout wip
[mLib] / struct / buf.h
1 /* -*-c-*-
2  *
3  * Reading and writing packet buffers
4  *
5  * (c) 2001 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of the mLib utilities library.
11  *
12  * mLib is free software; you can redistribute it and/or modify
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.
16  *
17  * mLib is distributed in the hope that it will be useful,
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.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with mLib; if not, write to the Free
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 #ifndef MLIB_BUF_H
29 #define MLIB_BUF_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <stdarg.h>
38 #include <stddef.h>
39
40 #ifndef MLIB_BITS_H
41 #  include "bits.h"
42 #endif
43
44 #ifndef MLIB_CONTROL_H
45 #  include "control.h"
46 #endif
47
48 #ifndef MLIB_DSTR_H
49 #  include "dstr.h"
50 #endif
51
52 #ifndef MLIB_MACROS_H
53 #  include "macros.h"
54 #endif
55
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 */
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;
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
96 #define BENSURE(b, sz)                                          \
97      (BBAD(b) ? -1 : (sz) > BLEFT(b) ? buf_tryextend(b, sz) : 0)
98
99 #define DBBASE(db) BBASE(DBUF_BUF(db))
100 #define DBLIM(db) BLIM(DBUF_BUF(db))
101 #define DBCUR(db) BCUR(DBUF_BUF(db))
102 #define DBSZ(db) BSZ(DBUF_BUF(db))
103 #define DBLEN(db) BLEN(DBUF_BUF(db))
104 #define DBLEFT(db) BLEFT(DBUF_BUF(db))
105 #define DBSTEP(db, sz) BSTEP(DBUF_BUF(db), (sz))
106 #define DBBAD(db) BBAD(DBUF_BUF(db))
107 #define DBOK(db) BOK(DBUF_BUF(db))
108 #define DBENSURE(b, sz) BENSURE(DBUF_BUF(db), (sz))
109
110 #ifdef HAVE_UINT64
111 #  define BUF_DOKLUDGESUFFIXES(_)
112 #else
113 #  define BUF_DOKLUDGESUFFIXES(_)                                       \
114         _(64, 64, 64) _(64, 64_B, 64b) _(64, 64_L, 64l)
115 #endif
116
117 #define BUF_DOSUFFIXES(_) DOUINTCONV(_) BUF_DOKLUDGESUFFIXES(_) _(z, z, z)
118
119 /*----- Functions provided ------------------------------------------------*/
120
121 /* --- @buf_init@ --- *
122  *
123  * Arguments:   @buf *b@ = pointer to a buffer block
124  *              @void *p@ = pointer to a buffer
125  *              @size_t sz@ = size of the buffer
126  *
127  * Returns:     ---
128  *
129  * Use:         Initializes the buffer block appropriately.
130  */
131
132 extern void buf_init(buf */*b*/, void */*p*/, size_t /*sz*/);
133
134 /* --- @dbuf_create@ --- *
135  *
136  * Arguments:   @dbuf *db@ = pointer to a dynamic buffer block
137  *
138  * Returns:     ---
139  *
140  * Use:         Initializes a dynamic buffer.  The buffer is initially empty,
141  *              and ready for writing.
142  */
143
144 extern void dbuf_create(dbuf */*db*/);
145
146 /* --- @dbuf_reset@ --- *
147  *
148  * Arguments:   @dbuf *db@ = pointer to a buffer block
149  *
150  * Returns:     ---
151  *
152  * Use:         Resets a buffer so that it can be written again.
153  */
154
155 extern void dbuf_reset(dbuf */*db*/);
156
157 #define DBRESET(db) do {                                                \
158   (db)->_b.p = (db)->_b.base; (db)->_b.limit = (db)->_b.base + (db)->sz; \
159   (db)->_b.f = ((db)->_b.f&~BF_BROKEN) | BF_WRITE;                      \
160 } while (0)
161
162 /* --- @dbuf_destroy@ --- *
163  *
164  * Arguments:   @dbuf *db@ = pointer to a buffer block
165  *
166  * Returns:     ---
167  *
168  * Use:         Release all of the resources held by a dynamic buffer.
169  */
170
171 extern void dbuf_destroy(dbuf */*db*/);
172
173 /* --- @{,d}buf_break@ --- *
174  *
175  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
176  *
177  * Returns:     Some negative value.
178  *
179  * Use:         Marks a buffer as broken.
180  */
181
182 extern int buf_break(buf */*b*/);
183 extern int dbuf_break(dbuf */*db*/);
184 #define dbuf_break(db) (buf_break(DBUF_BUF(db)))
185
186 /* --- @{,d}buf_flip@ --- *
187  *
188  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
189  *
190  * Returns:     ---
191  *
192  * Use:         Flips a buffer so that if you've just been writing to it,
193  *              you can now read from the bit you've written.
194  */
195
196 extern void buf_flip(buf */*b*/);
197 extern void dbuf_flip(dbuf */*db*/);
198 #define dbuf_flip(db) (buf_flip(DBUF_BUF(db)))
199
200 #define BFLIP(b) do {                                                   \
201   (b)->limit = (b)->p; (b)->p = (b)->base;                              \
202   (b)->f &= ~BF_WRITE;                                                  \
203 } while (0)
204 #define DBFLIP(db) BFLIP(DBUF_BUF(db))
205
206 /* --- @{,d}buf_ensure@ --- *
207  *
208  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
209  *              @size_t sz@ = size of data wanted
210  *
211  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
212  *
213  * Use:         Ensures that there are @sz@ bytes still in the buffer.
214  */
215
216 extern int buf_ensure(buf */*b*/, size_t /*sz*/);
217 extern int dbuf_ensure(dbuf */*db*/, size_t /*sz*/);
218 #define dbuf_ensure(db, sz) (buf_ensure(DBUF_BUF(db), (sz)))
219
220 /* --- @{,d}buf_tryextend@ --- *
221  *
222  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
223  *              @size_t sz@ = size of data wanted
224  *
225  * Returns:     Zero if it worked, nonzero if the buffer won't grow.
226  *
227  * Use:         Extend the buffer so that at least @sz@ bytes are available.
228  *              This only works if the buffer is allocated.
229  */
230
231 extern int buf_tryextend(buf */*b*/, size_t /*sz*/);
232 extern int dbuf_tryextend(dbuf */*db*/, size_t /*sz*/);
233 #define dbuf_tryextend(db, sz) (buf_tryextend(DBUF_BUF(db), (sz)))
234
235 /* --- @{,d}buf_get@ --- *
236  *
237  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
238  *              @size_t sz@ = size of the buffer
239  *
240  * Returns:     Pointer to the place in the buffer.
241  *
242  * Use:         Reserves a space in the buffer of the requested size, and
243  *              returns its start address.
244  */
245
246 extern void *buf_get(buf */*b*/, size_t /*sz*/);
247 extern void *dbuf_get(dbuf */*db*/, size_t /*sz*/);
248 #define dbuf_get(db, sz) (buf_get(DBUF_BUF(db), (sz)))
249
250 /* --- @{,d}buf_put@ --- *
251  *
252  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
253  *              @const void *p@ = pointer to a buffer
254  *              @size_t sz@ = size of the buffer
255  *
256  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
257  *
258  * Use:         Fetches data from some place and puts it in the buffer
259  */
260
261 extern int buf_put(buf */*b*/, const void */*p*/, size_t /*sz*/);
262 extern int dbuf_put(dbuf */*db*/, const void */*p*/, size_t /*sz*/);
263 #define dbuf_put(db, p, sz) (buf_put(DBUF_BUF(db), (p), (sz)))
264
265 /* --- @{,d}buf_getbyte@ --- *
266  *
267  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
268  *
269  * Returns:     A byte, or less than zero if there wasn't a byte there.
270  *
271  * Use:         Gets a single byte from a buffer.
272  */
273
274 extern int buf_getbyte(buf */*b*/);
275 extern int dbuf_getbyte(dbuf */*db*/);
276 #define dbuf_getbyte(db) (buf_getbyte(DBUF_BUF(db)))
277
278 /* --- @{,d}buf_putbyte@ --- *
279  *
280  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
281  *              @int ch@ = byte to write
282  *
283  * Returns:     Zero if OK, nonzero if there wasn't enough space.
284  *
285  * Use:         Puts a single byte in a buffer.
286  */
287
288 extern int buf_putbyte(buf */*b*/, int /*ch*/);
289 extern int dbuf_putbyte(dbuf */*db*/, int /*ch*/);
290 #define dbuf_putbyte(db, ch) (buf_putbyte(DBUF_BUF(db), (ch)))
291
292 /* --- @{,d}buf_getu{8,{16,24,32,64}{,l,b}}@ --- *
293  *
294  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
295  *              @uintSZ *w@ = where to put the word
296  *
297  * Returns:     Zero if OK, or nonzero if there wasn't a word there.
298  *
299  * Use:         Gets a word of appropriate size and order from a buffer.
300  */
301
302 #define BUF_DECL_GETU_(n, W, w)                                         \
303   extern int buf_getu##w(buf */*b*/, uint##n */*w*/);                   \
304   extern int dbuf_getu##w(dbuf */*db*/, uint##n */*w*/);
305 DOUINTCONV(BUF_DECL_GETU_)
306 #define dbuf_getu8(db, w) (buf_getu8(DBUF_BUF(db), (w)))
307 #define dbuf_getu16(db, w) (buf_getu16(DBUF_BUF(db), (w)))
308 #define dbuf_getu16l(db, w) (buf_getu16l(DBUF_BUF(db), (w)))
309 #define dbuf_getu16b(db, w) (buf_getu16b(DBUF_BUF(db), (w)))
310 #define dbuf_getu24(db, w) (buf_getu24(DBUF_BUF(db), (w)))
311 #define dbuf_getu24l(db, w) (buf_getu24l(DBUF_BUF(db), (w)))
312 #define dbuf_getu24b(db, w) (buf_getu24b(DBUF_BUF(db), (w)))
313 #define dbuf_getu32(db, w) (buf_getu32(DBUF_BUF(db), (w)))
314 #define dbuf_getu32l(db, w) (buf_getu32l(DBUF_BUF(db), (w)))
315 #define dbuf_getu32b(db, w) (buf_getu32b(DBUF_BUF(db), (w)))
316 #ifdef HAVE_UINT64
317 #  define dbuf_getu64(db, w) (buf_getu64(DBUF_BUF(db), (w)))
318 #  define dbuf_getu64l(db, w) (buf_getu64l(DBUF_BUF(db), (w)))
319 #  define dbuf_getu64b(db, w) (buf_getu64b(DBUF_BUF(db), (w)))
320 #endif
321
322 /* --- @{,d}buf_getk64{,l,b}@ --- *
323  *
324  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
325  *              @kludge64 *w@ = where to put the word
326  *
327  * Returns:     Zero if OK, or nonzero if there wasn't a word there.
328  *
329  * Use:         Gets a word of appropriate size and order from a buffer.
330  */
331
332 extern int buf_getk64(buf */*b*/, kludge64 */*w*/);
333 extern int buf_getk64l(buf */*b*/, kludge64 */*w*/);
334 extern int buf_getk64b(buf */*b*/, kludge64 */*w*/);
335 extern int dbuf_getk64(dbuf */*db*/, kludge64 */*w*/);
336 extern int dbuf_getk64l(dbuf */*db*/, kludge64 */*w*/);
337 extern int dbuf_getk64b(dbuf */*db*/, kludge64 */*w*/);
338 #define dbuf_getk64(db, w) (buf_getk64(DBUF_BUF(db), (w)))
339 #define dbuf_getk64l(db, w) (buf_getk64l(DBUF_BUF(db), (w)))
340 #define dbuf_getk64b(db, w) (buf_getk64b(DBUF_BUF(db), (w)))
341
342 /* --- @{,d}buf_putu{8,{16,24,32,64}{,l,b}}@ --- *
343  *
344  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
345  *              @uintSZ w@ = word to write
346  *
347  * Returns:     Zero if OK, or nonzero if there wasn't enough space
348  *
349  * Use:         Puts a word into a buffer with appropriate size and order.
350  */
351
352 #define BUF_DECL_PUTU_(n, W, w)                                         \
353   extern int buf_putu##w(buf */*b*/, uint##n /*w*/);                    \
354   extern int dbuf_putu##w(dbuf */*db*/, uint##n /*w*/);
355 DOUINTCONV(BUF_DECL_PUTU_)
356 #define dbuf_putu8(db, w) (buf_putu8(DBUF_BUF(db), (w)))
357 #define dbuf_putu16(db, w) (buf_putu16(DBUF_BUF(db), (w)))
358 #define dbuf_putu16l(db, w) (buf_putu16l(DBUF_BUF(db), (w)))
359 #define dbuf_putu16b(db, w) (buf_putu16b(DBUF_BUF(db), (w)))
360 #define dbuf_putu24(db, w) (buf_putu24(DBUF_BUF(db), (w)))
361 #define dbuf_putu24l(db, w) (buf_putu24l(DBUF_BUF(db), (w)))
362 #define dbuf_putu24b(db, w) (buf_putu24b(DBUF_BUF(db), (w)))
363 #define dbuf_putu32(db, w) (buf_putu32(DBUF_BUF(db), (w)))
364 #define dbuf_putu32l(db, w) (buf_putu32l(DBUF_BUF(db), (w)))
365 #define dbuf_putu32b(db, w) (buf_putu32b(DBUF_BUF(db), (w)))
366 #ifdef HAVE_UINT64
367 #  define dbuf_putu64(db, w) (buf_putu64(DBUF_BUF(db), (w)))
368 #  define dbuf_putu64l(db, w) (buf_putu64l(DBUF_BUF(db), (w)))
369 #  define dbuf_putu64b(db, w) (buf_putu64b(DBUF_BUF(db), (w)))
370 #endif
371
372 /* --- @{,d}buf_putk64{,l,b}@ --- *
373  *
374  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
375  *              @kludge64 w@ = word to write
376  *
377  * Returns:     Zero if OK, or nonzero if there wasn't enough space
378  *
379  * Use:         Gets a word of appropriate size and order from a buffer.
380  */
381
382 extern int buf_putk64(buf */*b*/, kludge64 /*w*/);
383 extern int buf_putk64l(buf */*b*/, kludge64 /*w*/);
384 extern int buf_putk64b(buf */*b*/, kludge64 /*w*/);
385 extern int dbuf_putk64(dbuf */*db*/, kludge64 /*w*/);
386 extern int dbuf_putk64l(dbuf */*db*/, kludge64 /*w*/);
387 extern int dbuf_putk64b(dbuf */*db*/, kludge64 /*w*/);
388 #define dbuf_putk64(db, w) (buf_putk64(DBUF_BUF(db), (w)))
389 #define dbuf_putk64l(db, w) (buf_putk64l(DBUF_BUF(db), (w)))
390 #define dbuf_putk64b(db, w) (buf_putk64b(DBUF_BUF(db), (w)))
391
392 /* --- @{,d}buf_getmem{8,{16,24,32,64}{,l,b},z} --- *
393  *
394  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
395  *              @size_t *nn@ = where to put the length
396  *
397  * Returns:     Pointer to the buffer data, or null.
398  *
399  * Use:         Gets a chunk of memory from a buffer.  The suffix is the
400  *              width and byte order of the length; @z@ means null-
401  *              terminated.
402  */
403
404 #define BUF_DECL_GETMEM_(n, W, w)                                       \
405   extern void *buf_getmem##w(buf */*b*/, size_t */*nn*/);               \
406   extern void *dbuf_getmem##w(dbuf */*db*/, size_t */*nn*/);
407 BUF_DOSUFFIXES(BUF_DECL_GETMEM_)
408 #define dbuf_getmem8(db, nn) (buf_getmem8(DBUF_BUF(db), (nn)))
409 #define dbuf_getmem16(db, nn) (buf_getmem16(DBUF_BUF(db), (nn)))
410 #define dbuf_getmem16l(db, nn) (buf_getmem16l(DBUF_BUF(db), (nn)))
411 #define dbuf_getmem16b(db, nn) (buf_getmem16b(DBUF_BUF(db), (nn)))
412 #define dbuf_getmem24(db, nn) (buf_getmem24(DBUF_BUF(db), (nn)))
413 #define dbuf_getmem24l(db, nn) (buf_getmem24l(DBUF_BUF(db), (nn)))
414 #define dbuf_getmem24b(db, nn) (buf_getmem24b(DBUF_BUF(db), (nn)))
415 #define dbuf_getmem32(db, nn) (buf_getmem32(DBUF_BUF(db), (nn)))
416 #define dbuf_getmem32l(db, nn) (buf_getmem32l(DBUF_BUF(db), (nn)))
417 #define dbuf_getmem32b(db, nn) (buf_getmem32b(DBUF_BUF(db), (nn)))
418 #define dbuf_getmem64(db, nn) (buf_getmem64(DBUF_BUF(db), (nn)))
419 #define dbuf_getmem64l(db, nn) (buf_getmem64l(DBUF_BUF(db), (nn)))
420 #define dbuf_getmem64b(db, nn) (buf_getmem64b(DBUF_BUF(db), (nn)))
421 #define dbuf_getmemz(db, nn) (buf_getmemz(DBUF_BUF(db), (nn)))
422
423 /* --- @{,d}buf_putmem{8,{16,24,32,64}{,l,b},z} --- *
424  *
425  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
426  *              @const void *p@ = pointer to data to write
427  *              @size_t n@ = length to write
428  *
429  * Returns:     Zero if OK, nonzero if there wasn't enough space.
430  *
431  * Use:         Writes a chunk of data to a buffer.  The suffix is the
432  *              width and byte order of the length; @z@ means null-
433  *              terminated.
434  */
435
436 #define BUF_DECL_PUTMEM_(n, W, w)                                       \
437   extern int buf_putmem##w(buf */*b*/, const void */*p*/, size_t /*nn*/); \
438   extern int dbuf_putmem##w(dbuf */*db*/, const void */*p*/, size_t /*nn*/);
439 BUF_DOSUFFIXES(BUF_DECL_PUTMEM_)
440 #define dbuf_putmem8(db, p, nn) (buf_putmem8(DBUF_BUF(db), (p), (nn)))
441 #define dbuf_putmem16(db, p, nn) (buf_putmem16(DBUF_BUF(db), (p), (nn)))
442 #define dbuf_putmem16l(db, p, nn) (buf_putmem16l(DBUF_BUF(db), (p), (nn)))
443 #define dbuf_putmem16b(db, p, nn) (buf_putmem16b(DBUF_BUF(db), (p), (nn)))
444 #define dbuf_putmem24(db, p, nn) (buf_putmem24(DBUF_BUF(db), (p), (nn)))
445 #define dbuf_putmem24l(db, p, nn) (buf_putmem24l(DBUF_BUF(db), (p), (nn)))
446 #define dbuf_putmem24b(db, p, nn) (buf_putmem24b(DBUF_BUF(db), (p), (nn)))
447 #define dbuf_putmem32(db, p, nn) (buf_putmem32(DBUF_BUF(db), (p), (nn)))
448 #define dbuf_putmem32l(db, p, nn) (buf_putmem32l(DBUF_BUF(db), (p), (nn)))
449 #define dbuf_putmem32b(db, p, nn) (buf_putmem32b(DBUF_BUF(db), (p), (nn)))
450 #define dbuf_putmem64(db, p, nn) (buf_putmem64(DBUF_BUF(db), (p), (nn)))
451 #define dbuf_putmem64l(db, p, nn) (buf_putmem64l(DBUF_BUF(db), (p), (nn)))
452 #define dbuf_putmem64b(db, p, nn) (buf_putmem64b(DBUF_BUF(db), (p), (nn)))
453 #define dbuf_putmemz(db, p, nn) (buf_putmemz(DBUF_BUF(db), (p), (nn)))
454
455 /* --- @{,d}buf_getbuf{8,{16,24,32,64}{,l,b},z} --- *
456  *
457  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
458  *              @buf *bb@ = where to put the result
459  *
460  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
461  *
462  * Use:         Gets a block of data from a buffer, and writes its bounds to
463  *              another buffer.
464  */
465
466 #define BUF_DECL_GETBUF_(n, W, w)                                       \
467   extern int buf_getbuf##w(buf */*b*/, buf */*bb*/);                    \
468   extern int dbuf_getbuf##w(dbuf */*db*/, buf */*bb*/);
469 BUF_DOSUFFIXES(BUF_DECL_GETBUF_)
470 #define dbuf_getbuf8(db, bb) (buf_getbuf8(DBUF_BUF(db), (bb)))
471 #define dbuf_getbuf16(db, bb) (buf_getbuf16(DBUF_BUF(db), (bb)))
472 #define dbuf_getbuf16l(db, bb) (buf_getbuf16l(DBUF_BUF(db), (bb)))
473 #define dbuf_getbuf16b(db, bb) (buf_getbuf16b(DBUF_BUF(db), (bb)))
474 #define dbuf_getbuf24(db, bb) (buf_getbuf24(DBUF_BUF(db), (bb)))
475 #define dbuf_getbuf24l(db, bb) (buf_getbuf24l(DBUF_BUF(db), (bb)))
476 #define dbuf_getbuf24b(db, bb) (buf_getbuf24b(DBUF_BUF(db), (bb)))
477 #define dbuf_getbuf32(db, bb) (buf_getbuf32(DBUF_BUF(db), (bb)))
478 #define dbuf_getbuf32l(db, bb) (buf_getbuf32l(DBUF_BUF(db), (bb)))
479 #define dbuf_getbuf32b(db, bb) (buf_getbuf32b(DBUF_BUF(db), (bb)))
480 #define dbuf_getbuf64(db, bb) (buf_getbuf64(DBUF_BUF(db), (bb)))
481 #define dbuf_getbuf64l(db, bb) (buf_getbuf64l(DBUF_BUF(db), (bb)))
482 #define dbuf_getbuf64b(db, bb) (buf_getbuf64b(DBUF_BUF(db), (bb)))
483 #define dbuf_getbufz(db, bb) (buf_getbufz(DBUF_BUF(db), (bb)))
484
485 /* --- @{,d}buf_putbuf{8,{16,24,32,64}{,l,b},z} --- *
486  *
487  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
488  *              @buf *bb@ = buffer to write
489  *
490  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
491  *
492  * Use:         Puts the contents of a buffer to a buffer.
493  */
494
495 #define BUF_DECL_PUTBUF_(n, W, w)                                       \
496   extern int buf_putbuf##w(buf */*b*/, buf */*bb*/);                    \
497   extern int dbuf_putbuf##w(dbuf */*db*/, buf */*bb*/);
498 BUF_DOSUFFIXES(BUF_DECL_PUTBUF_)
499 #define dbuf_putbuf8(db, bb) (buf_putbuf8(DBUF_BUF(db), (bb)))
500 #define dbuf_putbuf16(db, bb) (buf_putbuf16(DBUF_BUF(db), (bb)))
501 #define dbuf_putbuf16l(db, bb) (buf_putbuf16l(DBUF_BUF(db), (bb)))
502 #define dbuf_putbuf16b(db, bb) (buf_putbuf16b(DBUF_BUF(db), (bb)))
503 #define dbuf_putbuf24(db, bb) (buf_putbuf24(DBUF_BUF(db), (bb)))
504 #define dbuf_putbuf24l(db, bb) (buf_putbuf24l(DBUF_BUF(db), (bb)))
505 #define dbuf_putbuf24b(db, bb) (buf_putbuf24b(DBUF_BUF(db), (bb)))
506 #define dbuf_putbuf32(db, bb) (buf_putbuf32(DBUF_BUF(db), (bb)))
507 #define dbuf_putbuf32l(db, bb) (buf_putbuf32l(DBUF_BUF(db), (bb)))
508 #define dbuf_putbuf32b(db, bb) (buf_putbuf32b(DBUF_BUF(db), (bb)))
509 #define dbuf_putbuf64(db, bb) (buf_putbuf64(DBUF_BUF(db), (bb)))
510 #define dbuf_putbuf64l(db, bb) (buf_putbuf64l(DBUF_BUF(db), (bb)))
511 #define dbuf_putbuf64b(db, bb) (buf_putbuf64b(DBUF_BUF(db), (bb)))
512 #define dbuf_putbufz(db, bb) (buf_putbufz(DBUF_BUF(db), (bb)))
513
514 /* --- @{,d}buf_getdstr{8,{16,24,32,64}{,l,b},z} --- *
515  *
516  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
517  *              @dstr *d@ = where to put the result
518  *
519  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
520  *
521  * Use:         Gets a block of data from a buffer, and writes its contents
522  *              to a string.
523  */
524
525 #define BUF_DECL_GETDSTR_(n, W, w)                                      \
526   extern int buf_getdstr##w(buf */*b*/, dstr */*d*/);                   \
527   extern int dbuf_getdstr##w(dbuf */*db*/, dstr */*d*/);
528 BUF_DOSUFFIXES(BUF_DECL_GETDSTR_)
529 #define dbuf_getdstr8(db, d) (buf_getdstr8(DBUF_BUF(db), (d)))
530 #define dbuf_getdstr16(db, d) (buf_getdstr16(DBUF_BUF(db), (d)))
531 #define dbuf_getdstr16l(db, d) (buf_getdstr16l(DBUF_BUF(db), (d)))
532 #define dbuf_getdstr16b(db, d) (buf_getdstr16b(DBUF_BUF(db), (d)))
533 #define dbuf_getdstr24(db, d) (buf_getdstr24(DBUF_BUF(db), (d)))
534 #define dbuf_getdstr24l(db, d) (buf_getdstr24l(DBUF_BUF(db), (d)))
535 #define dbuf_getdstr24b(db, d) (buf_getdstr24b(DBUF_BUF(db), (d)))
536 #define dbuf_getdstr32(db, d) (buf_getdstr32(DBUF_BUF(db), (d)))
537 #define dbuf_getdstr32l(db, d) (buf_getdstr32l(DBUF_BUF(db), (d)))
538 #define dbuf_getdstr32b(db, d) (buf_getdstr32b(DBUF_BUF(db), (d)))
539 #define dbuf_getdstr64(db, d) (buf_getdstr64(DBUF_BUF(db), (d)))
540 #define dbuf_getdstr64l(db, d) (buf_getdstr64l(DBUF_BUF(db), (d)))
541 #define dbuf_getdstr64b(db, d) (buf_getdstr64b(DBUF_BUF(db), (d)))
542 #define dbuf_getdstrz(db, d) (buf_getdstrz(DBUF_BUF(db), (d)))
543
544 /* --- @{,d}buf_putdstr{8,{16,24,32,64}{,l,b},z} --- *
545  *
546  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
547  *              @dstr *d@ = string to write
548  *
549  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
550  *
551  * Use:         Puts a dynamic string to a buffer.
552  */
553
554 #define BUF_DECL_PUTDSTR_(n, W, w)                                      \
555   extern int buf_putdstr##w(buf */*b*/, dstr */*d*/);                   \
556   extern int dbuf_putdstr##w(dbuf */*db*/, dstr */*d*/);
557 BUF_DOSUFFIXES(BUF_DECL_PUTDSTR_)
558 #define dbuf_putdstr8(db, d) (buf_putdstr8(DBUF_BUF(db), (d)))
559 #define dbuf_putdstr16(db, d) (buf_putdstr16(DBUF_BUF(db), (d)))
560 #define dbuf_putdstr16l(db, d) (buf_putdstr16l(DBUF_BUF(db), (d)))
561 #define dbuf_putdstr16b(db, d) (buf_putdstr16b(DBUF_BUF(db), (d)))
562 #define dbuf_putdstr24(db, d) (buf_putdstr24(DBUF_BUF(db), (d)))
563 #define dbuf_putdstr24l(db, d) (buf_putdstr24l(DBUF_BUF(db), (d)))
564 #define dbuf_putdstr24b(db, d) (buf_putdstr24b(DBUF_BUF(db), (d)))
565 #define dbuf_putdstr32(db, d) (buf_putdstr32(DBUF_BUF(db), (d)))
566 #define dbuf_putdstr32l(db, d) (buf_putdstr32l(DBUF_BUF(db), (d)))
567 #define dbuf_putdstr32b(db, d) (buf_putdstr32b(DBUF_BUF(db), (d)))
568 #define dbuf_putdstr64(db, d) (buf_putdstr64(DBUF_BUF(db), (d)))
569 #define dbuf_putdstr64l(db, d) (buf_putdstr64l(DBUF_BUF(db), (d)))
570 #define dbuf_putdstr64b(db, d) (buf_putdstr64b(DBUF_BUF(db), (d)))
571 #define dbuf_putdstrz(db, d) (buf_putdstrz(DBUF_BUF(db), (d)))
572
573 /* --- @{,d}buf_putstr{8,{16,24,32,64}{,l,b},z} --- *
574  *
575  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
576  *              @const char *p@ = string to write
577  *
578  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
579  *
580  * Use:         Puts a null-terminated string to a buffer.
581  */
582
583 #define BUF_DECL_PUTSTR_(n, W, w)                                       \
584   extern int buf_putstr##w(buf */*b*/, const char */*p*/);              \
585   extern int dbuf_putstr##w(dbuf */*db*/, const char */*p*/);
586 BUF_DOSUFFIXES(BUF_DECL_PUTSTR_)
587 #define dbuf_putstr8(db, p) (buf_putstr8(DBUF_BUF(db), (p)))
588 #define dbuf_putstr16(db, p) (buf_putstr16(DBUF_BUF(db), (p)))
589 #define dbuf_putstr16l(db, p) (buf_putstr16l(DBUF_BUF(db), (p)))
590 #define dbuf_putstr16b(db, p) (buf_putstr16b(DBUF_BUF(db), (p)))
591 #define dbuf_putstr24(db, p) (buf_putstr24(DBUF_BUF(db), (p)))
592 #define dbuf_putstr24l(db, p) (buf_putstr24l(DBUF_BUF(db), (p)))
593 #define dbuf_putstr24b(db, p) (buf_putstr24b(DBUF_BUF(db), (p)))
594 #define dbuf_putstr32(db, p) (buf_putstr32(DBUF_BUF(db), (p)))
595 #define dbuf_putstr32l(db, p) (buf_putstr32l(DBUF_BUF(db), (p)))
596 #define dbuf_putstr32b(db, p) (buf_putstr32b(DBUF_BUF(db), (p)))
597 #define dbuf_putstr64(db, p) (buf_putstr64(DBUF_BUF(db), (p)))
598 #define dbuf_putstr64l(db, p) (buf_putstr64l(DBUF_BUF(db), (p)))
599 #define dbuf_putstr64b(db, p) (buf_putstr64b(DBUF_BUF(db), (p)))
600 #define dbuf_putstrz(db, p) (buf_putstrz(DBUF_BUF(db), (p)))
601
602 /* --- @{,d}buf_getf64{,l,b} --- *
603  *
604  * Arguments:   @buf *b@ = pointer to a bfufer block
605  *              @double *x_out@ = where to put the result
606  *
607  * Returns:     Zero on success, @-1@ on failure (and the buffer is broken).
608  *
609  *              If the system supports NaNs, then any encoded NaN is returned
610  *              as the value of @NAN@ in @<math.h>@; otherwise, this function
611  *              reports failure.
612  *
613  *              In general, values are rounded to the nearest available
614  *              value, in the way that the system usually rounds.  If the
615  *              system doesn't support infinities, then any encoded infinity
616  *              is reported as the largest-possible-magnitude finite value
617  *              instead.
618  */
619
620 extern int buf_getf64(buf */*b*/, double */*x_out*/);
621 extern int buf_getf64l(buf */*b*/, double */*x_out*/);
622 extern int buf_getf64b(buf */*b*/, double */*x_out*/);
623 extern int dbuf_getf64(dbuf */*db*/, double */*x_out*/);
624 extern int dbuf_getf64l(dbuf */*db*/, double */*x_out*/);
625 extern int dbuf_getf64b(dbuf */*db*/, double */*x_out*/);
626 #define dbuf_getf64(db, x_out) (buf_getf64(DBUF_BUF(db), (x_out)))
627 #define dbuf_getf64l(db, x_out) (buf_getf64l(DBUF_BUF(db), (x_out)))
628 #define dbuf_getf64b(db, x_out) (buf_getf64b(DBUF_BUF(db), (x_out)))
629
630 /* --- @{,d}buf_putf64{,l,b} --- *
631  *
632  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
633  *              @double x@ = a number to write
634  *
635  * Returns:     Zero on success, @-1@ on failure (and the buffer is broken).
636  *
637  *              On C89, this function can't detect negative zero so these
638  *              will be silently written as positive zero.
639  *
640  *              This function doesn't distinguish NaNs.  Any NaN is written
641  *              as a quiet NaN with all payload bits zero.
642  *
643  *              A finite value with too large a magnitude to be represented
644  *              is rounded to the appropriate infinity.  Other finite values
645  *              are rounded as necessary, in the usual IEEE 754 round-to-
646  *              nearest-or-even way.
647  */
648
649 extern int buf_putf64(buf */*b*/, double /*x*/);
650 extern int buf_putf64l(buf */*b*/, double /*x*/);
651 extern int buf_putf64b(buf */*b*/, double /*x*/);
652 extern int dbuf_putf64(dbuf */*db*/, double /*x*/);
653 extern int dbuf_putf64l(dbuf */*db*/, double /*x*/);
654 extern int dbuf_putf64b(dbuf */*db*/, double /*x*/);
655 #define dbuf_putf64(db, x) (buf_putf64(DBUF_BUF(db), (x)))
656 #define dbuf_putf64l(db, x) (buf_putf64l(DBUF_BUF(db), (x)))
657 #define dbuf_putf64b(db, x) (buf_putf64b(DBUF_BUF(db), (x)))
658
659 /* --- @{,D}BUF_ENCLOSETAG@ --- *
660  *
661  * Arguments:   @tag@ = a control-structure macro tag
662  *              @buf *b@ or @dbuf *db@ = pointer to a buffer block
663  *              @size_t mk@ = temporary, used to stash starting offset
664  *              @check@ = expression which is true if the length @_delta@
665  *                      is representable
666  *              @poke@ = function or macro called as @poke(octet *, size_t)@
667  *                      to store the final size at the given address
668  *              @size_t lensz@ = space to leave for the length
669  *
670  * Use:         This is a statement head.  It ensures that there is enough
671  *              space in the buffer, saves the current output offset in @mk,
672  *              and reserves @lensz@ bytes for a length prefix.  It then
673  *              executes the @body@, which should contribute zero or more
674  *              further bytes to the buffer.  Finally, it invokes @poke@ to
675  *              store the length of the material written by @body@ in the
676  *              space reserved.
677  */
678
679 #define BUF_ENCLOSETAG(tag, b, mk, check, poke, lensz)                  \
680   MC_BEFORE(tag##__save, {                                              \
681     (mk) = BLEN(b);                                                     \
682     if (!BENSURE(b, lensz)) BSTEP(b, (lensz));                          \
683   })                                                                    \
684   MC_AFTER(tag##__poke, {                                               \
685     size_t _delta = BLEN(b) - (mk) - (lensz);                           \
686     assert(check);                                                      \
687     if (BOK(b)) poke(BBASE(b) + (mk), _delta);                          \
688   })
689
690 #define DBUF_ENCLOSETAG(tag, b, mk, check, poke, lensz)                 \
691   BUF_ENCLOSETAG(tag, DBUF_BUF(b), (mk), (check), poke, (lensz))
692
693 /* --- @{,D}BUF_ENCLOSE{I,K,Z}TAG@ --- *
694  *
695  * Arguments:   @tag@ = a control-structure macro tag
696  *              @buf *b@ or @dbuf *db@ = pointer to a buffer block
697  *              @size_t mk@ = temporary, used to stash starting offset
698  *              @W@ = word-size and -order suffix
699  *
700  * Use:         Specialized versions of @BUF_ENCLOSETAG@ above.
701  *
702  *              @BUF_ENCLOSEZTAG@ just writes a terminating zero byte.
703  *              @BUF_ENCLOSEITAG@ writes a word with the given size and
704  *              byte ordering.  @BUF_ENCLOSEKTAG@ does the same using the
705  *              @kludge64@ machinery.
706  */
707
708 #define BUF_STORESZK64(p, sz)                                           \
709   do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_((p), _k); } while (0)
710 #define BUF_STORESZK64_B(p, sz)                                         \
711   do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_B_((p), _k); } while (0)
712 #define BUF_STORESZK64_L(p, sz)                                         \
713   do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_L_((p), _k); } while (0)
714
715 #define BUF_ENCLOSEITAG(tag, b, mk, W)                                  \
716   BUF_ENCLOSETAG(tag, (b), (mk), (_delta <= MASK##W), STORE##W, SZ_##W)
717 #define BUF_ENCLOSEKTAG(tag, b, mk, W)                          \
718   BUF_ENCLOSE(tag, (b), (mk), 1, BUF_STORESZK##W, 8)
719 #define BUF_ENCLOSEZTAG(tag, b)                                         \
720   MC_AFTER(tag##__zero, { buf_putbyte((b), 0); })
721
722 #define DBUF_ENCLOSEITAG(tag, b, mk, W)                                 \
723   BUF_ENCLOSEITAG(tag, DBUF_BUF(b), (mk), W)
724 #define DBUF_ENCLOSEKTAG(tag, b, mk, W)                                 \
725   BUF_ENCLOSEKTAG(tag, DBUF_BUF(b), (mk), W)
726 #define DBUF_ENCLOSEZTAG(tag, b)                                        \
727   BUF_ENCLOSEZTAG(tag, DBUF_BUF(b))
728
729 /* --- @{,D}BUF_ENCLOSE{8,{16,24,32,64}{,_L,_B},Z}@ --- *
730  *
731  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
732  *              @size_t mk@ = temporary, used to stash starting offset
733  *              @W@ = word-size and -order suffix
734  *
735  * Use:         User versions of @BUF_ENCLOSETAG@; see that macro for
736  *              details.
737  *
738  *              These are statement heads.  They reserve space for a length
739  *              prefix and execute the statement.  When the statement
740  *              completes, they patch the length of material written by the
741  *              statement into the reserved space.
742  */
743
744 #define BUF_ENCLOSE8(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 8)
745 #define BUF_ENCLOSE16(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 16)
746 #define BUF_ENCLOSE16_B(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 16_B)
747 #define BUF_ENCLOSE16_L(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 16_L)
748 #define BUF_ENCLOSE24(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 24)
749 #define BUF_ENCLOSE24_B(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 24_B)
750 #define BUF_ENCLOSE24_L(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 24_L)
751 #define BUF_ENCLOSE32(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 32)
752 #define BUF_ENCLOSE32_B(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 32_B)
753 #define BUF_ENCLOSE32_L(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 32_L)
754 #ifdef HAVE_UINT64
755 #  define BUF_ENCLOSE64(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 64)
756 #  define BUF_ENCLOSE64_B(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 64_B)
757 #  define BUF_ENCLOSE64_L(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 64_L)
758 #else
759 #  define BUF_ENCLOSE64(b, mk) BUF_ENCLOSEKTAG(encl, (b), (mk), 64)
760 #  define BUF_ENCLOSE64_B(b, mk) BUF_ENCLOSEKTAG(encl, (b), (mk), 64_B)
761 #  define BUF_ENCLOSE64_L(b, mk) BUF_ENCLOSEKTAG(encl, (b), (mk), 64_L)
762 #endif
763 #define BUF_ENCLOSEZ(b) BUF_ENCLOSEZTAG(encl, (b))
764
765 #define DBUF_ENCLOSE8(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 8)
766 #define DBUF_ENCLOSE16(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 16)
767 #define DBUF_ENCLOSE16_B(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 16_B)
768 #define DBUF_ENCLOSE16_L(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 16_L)
769 #define DBUF_ENCLOSE24(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 24)
770 #define DBUF_ENCLOSE24_B(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 24_B)
771 #define DBUF_ENCLOSE24_L(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 24_L)
772 #define DBUF_ENCLOSE32(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 32)
773 #define DBUF_ENCLOSE32_B(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 32_B)
774 #define DBUF_ENCLOSE32_L(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 32_L)
775 #ifdef HAVE_UINT64
776 #  define DBUF_ENCLOSE64(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 64)
777 #  define DBUF_ENCLOSE64_B(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 64_B)
778 #  define DBUF_ENCLOSE64_L(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 64_L)
779 #else
780 #  define DBUF_ENCLOSE64(db, mk) DBUF_ENCLOSEKTAG(encl, (db), (mk), 64)
781 #  define DBUF_ENCLOSE64_B(db, mk) DBUF_ENCLOSEKTAG(encl, (db), (mk), 64_B)
782 #  define DBUF_ENCLOSE64_L(db, mk) DBUF_ENCLOSEKTAG(encl, (db), (mk), 64_L)
783 #endif
784 #define DBUF_ENCLOSEZ(db) DBUF_ENCLOSEZTAG(encl, (db))
785
786 /* --- @{,d}buf_putstrf@, @{,d}buf_vputstrf@ --- *
787  *
788  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
789  *              @const char *p@ = pointer to @printf@-style format string
790  *              @va_list *ap@ = argument handle
791  *
792  * Returns:     The number of characters written to the string, or @-1@ on
793  *              failure.
794  *
795  * Use:         Format a string to a buffer.  The resulting output is not
796  *              null-terminated.
797  */
798
799 extern PRINTF_LIKE(2, 3)
800   int buf_putstrf(buf */*b*/, const char */*p*/, ...);
801 extern PRINTF_LIKE(2, 3)
802   int dbuf_putstrf(dbuf */*db*/, const char */*p*/, ...);
803 #if __STDC__ >= 199901
804 #  define dbuf_putstrf(db, /*p*/...) (buf_putstr(DBUF_BUF(db), __VA_ARGS__))
805 #endif
806 extern int buf_vputstrf(buf */*b*/, const char */*p*/, va_list */*ap*/);
807 extern int dbuf_vputstrf(dbuf */*db*/, const char */*p*/, va_list */*ap*/);
808 #define dbuf_vputstrf(db, p, ap) (buf_vputstrf(DBUF_BUF(db), (p), (ap)))
809
810 /* --- @{,d}buf_{,v}putstrf{8,{16,24,32,64}{,b,l},z}@ --- *
811  *
812  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
813  *              @const char *p@ = pointer to @printf@-style format string
814  *              @va_list *ap@ = argument handle
815  *
816  * Returns:     The number of characters written to the string, or @-1@ on
817  *              failure.
818  *
819  * Use:         As for @buf_putstr@, but using a format string.
820  */
821
822 #define BUF_DECL_PUTSTRF_(n, W, w)                                      \
823   extern PRINTF_LIKE(2, 3)                                              \
824     int buf_putstrf##w(buf */*b*/, const char */*p*/, ...);             \
825   extern PRINTF_LIKE(2, 3)                                              \
826     int dbuf_putstrf##w(dbuf */*db*/, const char */*p*/, ...);          \
827   extern int buf_vputstrf##w(buf */*b*/,                                \
828                              const char */*p*/, va_list */*ap*/);       \
829   extern int dbuf_vputstrf##w(dbuf */*db*/,                             \
830                               const char */*p*/, va_list */*ap*/);
831 BUF_DOSUFFIXES(BUF_DECL_PUTSTRF_)
832 #if __STDC__ >= 199901
833 #  define dbuf_putstrf8(db, /*p*/...)                                   \
834      (buf_putstrf8(DBUF_BUF(db), __VA_ARGS__))
835 #  define dbuf_putstrf16(db, /*p*/...)                                  \
836      (buf_putstrf16(DBUF_BUF(db), __VA_ARGS__))
837 #  define dbuf_putstrf16l(db, /*p*/...)                                 \
838      (buf_putstrf16l(DBUF_BUF(db), __VA_ARGS__))
839 #  define dbuf_putstrf16b(db, /*p*/...)                                 \
840      (buf_putstrf16b(DBUF_BUF(db), __VA_ARGS__))
841 #  define dbuf_putstrf24(db, /*p*/...)                                  \
842      (buf_putstrf24(DBUF_BUF(db), __VA_ARGS__))
843 #  define dbuf_putstrf24l(db, /*p*/...)                                 \
844      (buf_putstrf24l(DBUF_BUF(db), __VA_ARGS__))
845 #  define dbuf_putstrf24b(db, /*p*/...)                                 \
846      (buf_putstrf24b(DBUF_BUF(db), __VA_ARGS__))
847 #  define dbuf_putstrf32(db, /*p*/...)                                  \
848      (buf_putstrf32(DBUF_BUF(db), __VA_ARGS__))
849 #  define dbuf_putstrf32l(db, /*p*/...)                                 \
850      (buf_putstrf32l(DBUF_BUF(db), __VA_ARGS__))
851 #  define dbuf_putstrf32b(db, /*p*/...)                                 \
852      (buf_putstrf32b(DBUF_BUF(db), __VA_ARGS__))
853 #  define dbuf_putstrf64(db, /*p*/...)                                  \
854      (buf_putstrf64(DBUF_BUF(db), __VA_ARGS__))
855 #  define dbuf_putstrf64l(db, /*p*/...)                                 \
856      (buf_putstrf64l(DBUF_BUF(db), __VA_ARGS__))
857 #  define dbuf_putstrf64b(db, /*p*/...)                                 \
858      (buf_putstrf64b(DBUF_BUF(db), __VA_ARGS__))
859 #  define dbuf_putstrfz(db, /*p*/...)                                   \
860      (buf_putstrfz(DBUF_BUF(db), __VA_ARGS__))
861 #endif
862 #define dbuf_vputstrf8(db, p, ap) (buf_vputstrf8(DBUF_BUF(db), (p), (ap)))
863 #define dbuf_vputstrf16(db, p, ap) (buf_vputstrf16(DBUF_BUF(db), (p), (ap)))
864 #define dbuf_vputstrf16l(db, p, ap) (buf_vputstrf16l(DBUF_BUF(db), (p), (ap)))
865 #define dbuf_vputstrf16b(db, p, ap) (buf_vputstrf16b(DBUF_BUF(db), (p), (ap)))
866 #define dbuf_vputstrf24(db, p, ap) (buf_vputstrf24(DBUF_BUF(db), (p), (ap)))
867 #define dbuf_vputstrf24l(db, p, ap) (buf_vputstrf24l(DBUF_BUF(db), (p), (ap)))
868 #define dbuf_vputstrf24b(db, p, ap) (buf_vputstrf24b(DBUF_BUF(db), (p), (ap)))
869 #define dbuf_vputstrf32(db, p, ap) (buf_vputstrf32(DBUF_BUF(db), (p), (ap)))
870 #define dbuf_vputstrf32l(db, p, ap) (buf_vputstrf32l(DBUF_BUF(db), (p), (ap)))
871 #define dbuf_vputstrf32b(db, p, ap) (buf_vputstrf32b(DBUF_BUF(db), (p), (ap)))
872 #define dbuf_vputstrf64(db, p, ap) (buf_vputstrf64(DBUF_BUF(db), (p), (ap)))
873 #define dbuf_vputstrf64l(db, p, ap) (buf_vputstrf64l(DBUF_BUF(db), (p), (ap)))
874 #define dbuf_vputstrf64b(db, p, ap) (buf_vputstrf64b(DBUF_BUF(db), (p), (ap)))
875 #define dbuf_vputstrfz(db, p, ap) (buf_vputstrfz(DBUF_BUF(db), (p), (ap)))
876
877 /*----- That's all, folks -------------------------------------------------*/
878
879 #ifdef __cplusplus
880   }
881 #endif
882
883 #endif