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 | ||
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 | ||
132 | extern 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 | 144 | extern 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 | ||
155 | extern 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 | ||
171 | extern 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 | ||
182 | extern int buf_break(buf */*b*/); | |
31d0247c MW |
183 | extern 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 | ||
196 | extern void buf_flip(buf */*b*/); | |
31d0247c MW |
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)) | |
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 | ||
216 | extern int buf_ensure(buf */*b*/, size_t /*sz*/); | |
31d0247c MW |
217 | extern 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 | ||
231 | extern int buf_tryextend(buf */*b*/, size_t /*sz*/); | |
31d0247c MW |
232 | extern 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 | ||
246 | extern void *buf_get(buf */*b*/, size_t /*sz*/); | |
31d0247c MW |
247 | extern 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 | ||
261 | extern int buf_put(buf */*b*/, const void */*p*/, size_t /*sz*/); | |
31d0247c MW |
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))) | |
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 | ||
274 | extern int buf_getbyte(buf */*b*/); | |
31d0247c MW |
275 | extern 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 | ||
288 | extern int buf_putbyte(buf */*b*/, int /*ch*/); | |
31d0247c MW |
289 | extern 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 | 305 | DOUINTCONV(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 | ||
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*/); | |
31d0247c MW |
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))) | |
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 | 355 | DOUINTCONV(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 | ||
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*/); | |
31d0247c MW |
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))) | |
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 | 407 | BUF_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 | 439 | BUF_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 | 469 | BUF_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 | 498 | BUF_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 | 528 | BUF_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 | 557 | BUF_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 | 586 | BUF_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 | ||
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))) | |
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 | ||
649 | extern int buf_putf64(buf */*b*/, double /*x*/); | |
e63124bc | 650 | extern int buf_putf64l(buf */*b*/, double /*x*/); |
31d0247c MW |
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. | |
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 |
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))) | |
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 | 831 | BUF_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 |