@@@ timeout wip
[mLib] / struct / buf.h
CommitLineData
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
64typedef 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
73typedef 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
82extern 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
31d0247c 96#define BENSURE(b, sz) \
e63124bc 97 (BBAD(b) ? -1 : (sz) > BLEFT(b) ? buf_tryextend(b, sz) : 0)
800d4c59 98
e63124bc
MW
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)
9b5ac6ff 118
800d4c59 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
132extern void buf_init(buf */*b*/, void */*p*/, size_t /*sz*/);
133
c91413e6 134/* --- @dbuf_create@ --- *
e63124bc
MW
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
c91413e6 144extern void dbuf_create(dbuf */*db*/);
e63124bc
MW
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
155extern void dbuf_reset(dbuf */*db*/);
156
31d0247c
MW
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
e63124bc
MW
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
171extern void dbuf_destroy(dbuf */*db*/);
172
31d0247c 173/* --- @{,d}buf_break@ --- *
800d4c59 174 *
31d0247c 175 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 176 *
177 * Returns: Some negative value.
178 *
179 * Use: Marks a buffer as broken.
180 */
181
182extern int buf_break(buf */*b*/);
31d0247c
MW
183extern int dbuf_break(dbuf */*db*/);
184#define dbuf_break(db) (buf_break(DBUF_BUF(db)))
800d4c59 185
31d0247c 186/* --- @{,d}buf_flip@ --- *
800d4c59 187 *
31d0247c 188 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 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
196extern void buf_flip(buf */*b*/);
31d0247c
MW
197extern 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))
800d4c59 205
31d0247c 206/* --- @{,d}buf_ensure@ --- *
800d4c59 207 *
31d0247c 208 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 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
216extern int buf_ensure(buf */*b*/, size_t /*sz*/);
31d0247c
MW
217extern int dbuf_ensure(dbuf */*db*/, size_t /*sz*/);
218#define dbuf_ensure(db, sz) (buf_ensure(DBUF_BUF(db), (sz)))
800d4c59 219
31d0247c 220/* --- @{,d}buf_tryextend@ --- *
e63124bc 221 *
31d0247c 222 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
e63124bc
MW
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
231extern int buf_tryextend(buf */*b*/, size_t /*sz*/);
31d0247c
MW
232extern int dbuf_tryextend(dbuf */*db*/, size_t /*sz*/);
233#define dbuf_tryextend(db, sz) (buf_tryextend(DBUF_BUF(db), (sz)))
e63124bc 234
31d0247c 235/* --- @{,d}buf_get@ --- *
800d4c59 236 *
31d0247c 237 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 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
246extern void *buf_get(buf */*b*/, size_t /*sz*/);
31d0247c
MW
247extern void *dbuf_get(dbuf */*db*/, size_t /*sz*/);
248#define dbuf_get(db, sz) (buf_get(DBUF_BUF(db), (sz)))
800d4c59 249
31d0247c 250/* --- @{,d}buf_put@ --- *
800d4c59 251 *
31d0247c 252 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 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
261extern int buf_put(buf */*b*/, const void */*p*/, size_t /*sz*/);
31d0247c
MW
262extern 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)))
800d4c59 264
31d0247c 265/* --- @{,d}buf_getbyte@ --- *
800d4c59 266 *
31d0247c 267 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 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
274extern int buf_getbyte(buf */*b*/);
31d0247c
MW
275extern int dbuf_getbyte(dbuf */*db*/);
276#define dbuf_getbyte(db) (buf_getbyte(DBUF_BUF(db)))
800d4c59 277
31d0247c 278/* --- @{,d}buf_putbyte@ --- *
800d4c59 279 *
31d0247c 280 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 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
288extern int buf_putbyte(buf */*b*/, int /*ch*/);
31d0247c
MW
289extern int dbuf_putbyte(dbuf */*db*/, int /*ch*/);
290#define dbuf_putbyte(db, ch) (buf_putbyte(DBUF_BUF(db), (ch)))
800d4c59 291
31d0247c 292/* --- @{,d}buf_getu{8,{16,24,32,64}{,l,b}}@ --- *
800d4c59 293 *
31d0247c 294 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
9b5ac6ff 295 * @uintSZ *w@ = where to put the word
800d4c59 296 *
297 * Returns: Zero if OK, or nonzero if there wasn't a word there.
298 *
9b5ac6ff 299 * Use: Gets a word of appropriate size and order from a buffer.
800d4c59 300 */
301
9b5ac6ff 302#define BUF_DECL_GETU_(n, W, w) \
31d0247c
MW
303 extern int buf_getu##w(buf */*b*/, uint##n */*w*/); \
304 extern int dbuf_getu##w(dbuf */*db*/, uint##n */*w*/);
9b5ac6ff 305DOUINTCONV(BUF_DECL_GETU_)
31d0247c
MW
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
800d4c59 321
31d0247c 322/* --- @{,d}buf_getk64{,l,b}@ --- *
b64eb60f 323 *
31d0247c 324 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
b64eb60f
MW
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
332extern int buf_getk64(buf */*b*/, kludge64 */*w*/);
333extern int buf_getk64l(buf */*b*/, kludge64 */*w*/);
334extern int buf_getk64b(buf */*b*/, kludge64 */*w*/);
31d0247c
MW
335extern int dbuf_getk64(dbuf */*db*/, kludge64 */*w*/);
336extern int dbuf_getk64l(dbuf */*db*/, kludge64 */*w*/);
337extern 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)))
b64eb60f 341
31d0247c 342/* --- @{,d}buf_putu{8,{16,24,32,64}{,l,b}}@ --- *
800d4c59 343 *
31d0247c 344 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
9b5ac6ff 345 * @uintSZ w@ = word to write
800d4c59 346 *
9b5ac6ff 347 * Returns: Zero if OK, or nonzero if there wasn't enough space
800d4c59 348 *
9b5ac6ff 349 * Use: Puts a word into a buffer with appropriate size and order.
800d4c59 350 */
351
9b5ac6ff 352#define BUF_DECL_PUTU_(n, W, w) \
31d0247c
MW
353 extern int buf_putu##w(buf */*b*/, uint##n /*w*/); \
354 extern int dbuf_putu##w(dbuf */*db*/, uint##n /*w*/);
9b5ac6ff 355DOUINTCONV(BUF_DECL_PUTU_)
31d0247c
MW
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
800d4c59 371
31d0247c 372/* --- @{,d}buf_putk64{,l,b}@ --- *
b64eb60f 373 *
31d0247c 374 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
b64eb60f
MW
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
382extern int buf_putk64(buf */*b*/, kludge64 /*w*/);
383extern int buf_putk64l(buf */*b*/, kludge64 /*w*/);
384extern int buf_putk64b(buf */*b*/, kludge64 /*w*/);
31d0247c
MW
385extern int dbuf_putk64(dbuf */*db*/, kludge64 /*w*/);
386extern int dbuf_putk64l(dbuf */*db*/, kludge64 /*w*/);
387extern 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)))
b64eb60f 391
31d0247c 392/* --- @{,d}buf_getmem{8,{16,24,32,64}{,l,b},z} --- *
800d4c59 393 *
31d0247c 394 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 395 * @size_t *nn@ = where to put the length
396 *
397 * Returns: Pointer to the buffer data, or null.
398 *
9b5ac6ff 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.
800d4c59 402 */
403
9b5ac6ff 404#define BUF_DECL_GETMEM_(n, W, w) \
31d0247c
MW
405 extern void *buf_getmem##w(buf */*b*/, size_t */*nn*/); \
406 extern void *dbuf_getmem##w(dbuf */*db*/, size_t */*nn*/);
9b5ac6ff 407BUF_DOSUFFIXES(BUF_DECL_GETMEM_)
31d0247c
MW
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
800d4c59 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 *
9b5ac6ff 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.
800d4c59 434 */
435
9b5ac6ff 436#define BUF_DECL_PUTMEM_(n, W, w) \
31d0247c
MW
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*/);
9b5ac6ff 439BUF_DOSUFFIXES(BUF_DECL_PUTMEM_)
31d0247c
MW
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
800d4c59 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
9b5ac6ff 463 * another buffer.
800d4c59 464 */
465
9b5ac6ff 466#define BUF_DECL_GETBUF_(n, W, w) \
31d0247c
MW
467 extern int buf_getbuf##w(buf */*b*/, buf */*bb*/); \
468 extern int dbuf_getbuf##w(dbuf */*db*/, buf */*bb*/);
9b5ac6ff 469BUF_DOSUFFIXES(BUF_DECL_GETBUF_)
31d0247c
MW
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
800d4c59 488 * @buf *bb@ = buffer to write
489 *
490 * Returns: Zero if it worked, nonzero if there wasn't enough space.
491 *
9b5ac6ff 492 * Use: Puts the contents of a buffer to a buffer.
800d4c59 493 */
494
9b5ac6ff 495#define BUF_DECL_PUTBUF_(n, W, w) \
31d0247c
MW
496 extern int buf_putbuf##w(buf */*b*/, buf */*bb*/); \
497 extern int dbuf_putbuf##w(dbuf */*db*/, buf */*bb*/);
9b5ac6ff 498BUF_DOSUFFIXES(BUF_DECL_PUTBUF_)
31d0247c
MW
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
800d4c59 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
9b5ac6ff 522 * to a string.
800d4c59 523 */
524
9b5ac6ff 525#define BUF_DECL_GETDSTR_(n, W, w) \
31d0247c
MW
526 extern int buf_getdstr##w(buf */*b*/, dstr */*d*/); \
527 extern int dbuf_getdstr##w(dbuf */*db*/, dstr */*d*/);
9b5ac6ff 528BUF_DOSUFFIXES(BUF_DECL_GETDSTR_)
31d0247c
MW
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
800d4c59 547 * @dstr *d@ = string to write
548 *
549 * Returns: Zero if it worked, nonzero if there wasn't enough space.
550 *
9b5ac6ff 551 * Use: Puts a dynamic string to a buffer.
800d4c59 552 */
553
9b5ac6ff 554#define BUF_DECL_PUTDSTR_(n, W, w) \
31d0247c
MW
555 extern int buf_putdstr##w(buf */*b*/, dstr */*d*/); \
556 extern int dbuf_putdstr##w(dbuf */*db*/, dstr */*d*/);
9b5ac6ff 557BUF_DOSUFFIXES(BUF_DECL_PUTDSTR_)
31d0247c
MW
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
9b5ac6ff 576 * @const char *p@ = string to write
800d4c59 577 *
578 * Returns: Zero if it worked, nonzero if there wasn't enough space.
579 *
9b5ac6ff 580 * Use: Puts a null-terminated string to a buffer.
800d4c59 581 */
582
9b5ac6ff 583#define BUF_DECL_PUTSTR_(n, W, w) \
31d0247c
MW
584 extern int buf_putstr##w(buf */*b*/, const char */*p*/); \
585 extern int dbuf_putstr##w(dbuf */*db*/, const char */*p*/);
9b5ac6ff 586BUF_DOSUFFIXES(BUF_DECL_PUTSTR_)
31d0247c
MW
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
620extern int buf_getf64(buf */*b*/, double */*x_out*/);
621extern int buf_getf64l(buf */*b*/, double */*x_out*/);
622extern int buf_getf64b(buf */*b*/, double */*x_out*/);
623extern int dbuf_getf64(dbuf */*db*/, double */*x_out*/);
624extern int dbuf_getf64l(dbuf */*db*/, double */*x_out*/);
625extern 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)))
d4efbcd9 629
31d0247c 630/* --- @{,d}buf_putf64{,l,b} --- *
e63124bc 631 *
31d0247c 632 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
e63124bc
MW
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
649extern int buf_putf64(buf */*b*/, double /*x*/);
e63124bc 650extern int buf_putf64l(buf */*b*/, double /*x*/);
31d0247c
MW
651extern int buf_putf64b(buf */*b*/, double /*x*/);
652extern int dbuf_putf64(dbuf */*db*/, double /*x*/);
653extern int dbuf_putf64l(dbuf */*db*/, double /*x*/);
654extern 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.
e63124bc
MW
677 */
678
31d0247c
MW
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 */
e63124bc
MW
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)
31d0247c
MW
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)
e63124bc 775#ifdef HAVE_UINT64
31d0247c
MW
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)
e63124bc 779#else
31d0247c
MW
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)
e63124bc 783#endif
31d0247c 784#define DBUF_ENCLOSEZ(db) DBUF_ENCLOSEZTAG(encl, (db))
e63124bc 785
31d0247c 786/* --- @{,d}buf_putstrf@, @{,d}buf_vputstrf@ --- *
e63124bc 787 *
31d0247c 788 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
e63124bc
MW
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 *
e63124bc
MW
795 * Use: Format a string to a buffer. The resulting output is not
796 * null-terminated.
797 */
798
31d0247c
MW
799extern PRINTF_LIKE(2, 3)
800 int buf_putstrf(buf */*b*/, const char */*p*/, ...);
801extern 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
806extern int buf_vputstrf(buf */*b*/, const char */*p*/, va_list */*ap*/);
807extern 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)))
e63124bc 809
31d0247c 810/* --- @{,d}buf_{,v}putstrf{8,{16,24,32,64}{,b,l},z}@ --- *
e63124bc 811 *
31d0247c 812 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
e63124bc
MW
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) \
31d0247c
MW
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*/, ...); \
e63124bc
MW
827 extern int buf_vputstrf##w(buf */*b*/, \
828 const char */*p*/, va_list */*ap*/); \
31d0247c
MW
829 extern int dbuf_vputstrf##w(dbuf */*db*/, \
830 const char */*p*/, va_list */*ap*/);
e63124bc 831BUF_DOSUFFIXES(BUF_DECL_PUTSTRF_)
31d0247c
MW
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)))
e63124bc 876
800d4c59 877/*----- That's all, folks -------------------------------------------------*/
878
879#ifdef __cplusplus
880 }
881#endif
882
883#endif