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