@@@ timeout wip
[mLib] / struct / buf.c
CommitLineData
800d4c59 1/* -*-c-*-
2 *
800d4c59 3 * Buffer handling
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
28/*----- Header files ------------------------------------------------------*/
29
9b5ac6ff 30#include <assert.h>
800d4c59 31#include <string.h>
32
800d4c59 33#include "buf.h"
0d61a23c 34#include "macros.h"
800d4c59 35
36/*----- Main code ---------------------------------------------------------*/
37
38/* --- @buf_init@ --- *
39 *
31d0247c 40 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 41 * @void *p@ = pointer to a buffer
42 * @size_t sz@ = size of the buffer
43 *
44 * Returns: ---
45 *
46 * Use: Initializes the buffer block appropriately.
47 */
48
49void buf_init(buf *b, void *p, size_t sz)
50{
51 b->base = b->p = p;
52 b->limit = b->p + sz;
53 b->f = 0;
54}
55
c91413e6 56/* --- @dbuf_create@ --- *
e63124bc
MW
57 *
58 * Arguments: @dbuf *db@ = pointer to a dynamic buffer block
59 *
60 * Returns: ---
61 *
62 * Use: Initializes a dynamic buffer. The buffer is initially empty,
63 * and ready for writing.
64 */
65
c91413e6 66void dbuf_create(dbuf *db)
e63124bc
MW
67{
68 db->_b.base = db->_b.p = db->_b.limit = 0; db->_b.f = BF_ALLOC | BF_WRITE;
69 db->a = &arena_stdlib; db->sz = 0;
70}
71
72/* --- @dbuf_reset@ --- *
73 *
74 * Arguments: @dbuf *db@ = pointer to a buffer block
75 *
76 * Returns: ---
77 *
78 * Use: Resets a buffer so that it can be written again.
79 */
80
31d0247c 81void dbuf_reset(dbuf *db) { DBRESET(db); }
e63124bc
MW
82
83/* --- @dbuf_destroy@ --- *
84 *
85 * Arguments: @dbuf *db@ = pointer to a buffer block
86 *
87 * Returns: ---
88 *
89 * Use: Release all of the resources held by a dynamic buffer.
90 */
91
92void dbuf_destroy(dbuf *db)
93{
94 if (db->_b.base) x_free(db->a, db->_b.base);
c91413e6 95 dbuf_create(db);
e63124bc
MW
96}
97
31d0247c 98/* --- @{,d}buf_break@ --- *
800d4c59 99 *
31d0247c 100 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 101 *
102 * Returns: Some negative value.
103 *
104 * Use: Marks a buffer as broken.
105 */
106
107int buf_break(buf *b) { b->f |= BF_BROKEN; return (-1); }
31d0247c 108int (dbuf_break)(dbuf *db) { return (dbuf_break(db)); }
800d4c59 109
31d0247c 110/* --- @{,d}buf_flip@ --- *
800d4c59 111 *
31d0247c 112 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 113 *
114 * Returns: ---
115 *
116 * Use: Flips a buffer so that if you've just been writing to it,
117 * you can now read from the bit you've written.
118 */
119
31d0247c
MW
120void buf_flip(buf *b) { BFLIP(b); }
121void (dbuf_flip)(dbuf *db) { dbuf_flip(db); }
800d4c59 122
31d0247c 123/* --- @{,d}buf_ensure@ --- *
800d4c59 124 *
31d0247c 125 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 126 * @size_t sz@ = size of data wanted
127 *
128 * Returns: Zero if it worked, nonzero if there wasn't enough space.
129 *
130 * Use: Ensures that there are @sz@ bytes still in the buffer.
131 */
132
133int buf_ensure(buf *b, size_t sz) { return (BENSURE(b, sz)); }
31d0247c 134int (dbuf_ensure)(dbuf *db, size_t sz) { return (dbuf_ensure(db, sz)); }
800d4c59 135
31d0247c 136/* --- @{,d}buf_tryextend@ --- *
e63124bc 137 *
31d0247c 138 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
e63124bc
MW
139 * @size_t sz@ = size of data wanted
140 *
141 * Returns: Zero if it worked, nonzero if the buffer won't grow.
142 *
143 * Use: Extend the buffer so that at least @sz@ bytes are available.
144 * This only works if the buffer is allocated.
145 */
146
147int buf_tryextend(buf *b, size_t sz)
148{
149 dbuf *db;
150 size_t newsz, len;
151
152 if (~b->f&(BF_ALLOC | BF_WRITE))
153 { b->f |= BF_BROKEN; return (-1); }
154 db = (dbuf *)b;
155 len = BLEN(&db->_b); sz += len;
156 if (db->sz >= sz)
157 newsz = db->sz;
158 else {
159 newsz = db->sz ? 2*db->sz : 64;
160 while (newsz < sz) { assert(newsz < ((size_t)-1)/2); newsz *= 2; }
161 if (!db->_b.base) db->_b.base = x_alloc(db->a, newsz);
162 else db->_b.base = x_realloc(db->a, db->_b.base, newsz, db->sz);
163 db->_b.p = db->_b.base + len; db->sz = newsz;
164 }
165 db->_b.limit = db->_b.base + newsz;
166 return (0);
167}
31d0247c
MW
168int (dbuf_tryextend)(dbuf *db, size_t sz)
169 { return (dbuf_tryextend(db, sz)); }
e63124bc 170
31d0247c 171/* --- @{,d}buf_get@ --- *
800d4c59 172 *
31d0247c 173 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 174 * @size_t sz@ = size of the buffer
175 *
176 * Returns: Pointer to the place in the buffer.
177 *
178 * Use: Reserves a space in the buffer of the requested size, and
179 * returns its start address.
180 */
181
182void *buf_get(buf *b, size_t sz)
183{
184 void *p;
185 if (BENSURE(b, sz))
186 return (0);
187 p = BCUR(b);
188 BSTEP(b, sz);
189 return (p);
190}
31d0247c
MW
191void *(dbuf_get)(dbuf *db, size_t sz)
192 { return (dbuf_get(db, sz)); }
800d4c59 193
31d0247c 194/* --- @{,d}buf_put@ --- *
800d4c59 195 *
31d0247c 196 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 197 * @const void *p@ = pointer to a buffer
198 * @size_t sz@ = size of the buffer
199 *
200 * Returns: Zero if it worked, nonzero if there wasn't enough space.
201 *
202 * Use: Fetches data from some place and puts it in the buffer
203 */
204
205int buf_put(buf *b, const void *p, size_t sz)
206{
207 if (BENSURE(b, sz))
208 return (-1);
209 memcpy(BCUR(b), p, sz);
210 BSTEP(b, sz);
211 return (0);
212}
31d0247c
MW
213int (dbuf_put)(dbuf *db, const void *p, size_t sz)
214 { return (dbuf_put(db, p, sz)); }
800d4c59 215
31d0247c 216/* --- @{,d}buf_getbyte@ --- *
800d4c59 217 *
31d0247c 218 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 219 *
220 * Returns: A byte, or less than zero if there wasn't a byte there.
221 *
222 * Use: Gets a single byte from a buffer.
223 */
224
225int buf_getbyte(buf *b)
226{
227 if (BENSURE(b, 1))
228 return (-1);
229 return (*b->p++);
230}
31d0247c
MW
231int (dbuf_getbyte)(dbuf *db)
232 { return (dbuf_getbyte(db)); }
800d4c59 233
31d0247c 234/* --- @{,d}buf_putbyte@ --- *
800d4c59 235 *
31d0247c 236 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 237 * @int ch@ = byte to write
238 *
239 * Returns: Zero if OK, nonzero if there wasn't enough space.
240 *
241 * Use: Puts a single byte in a buffer.
242 */
243
244int buf_putbyte(buf *b, int ch)
245{
246 if (BENSURE(b, 1))
247 return (-1);
248 *b->p++ = ch;
249 return (0);
250}
31d0247c
MW
251int (dbuf_putbyte)(dbuf *db, int ch)
252 { return (dbuf_putbyte(db, ch)); }
800d4c59 253
31d0247c 254/* --- @{,d}buf_getu{8,{16,24,32,64}{,l,b}}@ --- *
800d4c59 255 *
31d0247c 256 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
9b5ac6ff 257 * @uintSZ *w@ = where to put the word
800d4c59 258 *
259 * Returns: Zero if OK, or nonzero if there wasn't a word there.
260 *
9b5ac6ff 261 * Use: Gets a word of appropriate size and order from a buffer.
800d4c59 262 */
263
9b5ac6ff 264#define BUF_GETU_(n, W, w) \
265 int buf_getu##w(buf *b, uint##n *ww) \
266 { \
267 if (BENSURE(b, SZ_##W)) return (-1); \
268 *ww = LOAD##W(b->p); \
269 BSTEP(b, SZ_##W); \
270 return (0); \
31d0247c
MW
271 } \
272 int (dbuf_getu##w)(dbuf *db, uint##n *ww) \
273 { return (dbuf_getu##w(db, ww)); }
9b5ac6ff 274DOUINTCONV(BUF_GETU_)
800d4c59 275
31d0247c 276/* --- @{,d}buf_getk64{,l,b}@ --- *
b64eb60f 277 *
31d0247c 278 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
b64eb60f
MW
279 * @kludge64 *w@ = where to put the word
280 *
281 * Returns: Zero if OK, or nonzero if there wasn't a word there.
282 *
283 * Use: Gets a word of appropriate size and order from a buffer.
284 */
285
286int buf_getk64(buf *b, kludge64 *w)
287{
288 if (BENSURE(b, 8)) return (-1);
289 LOAD64_(*w, b->p); BSTEP(b, 8); return (0);
290}
291
292int buf_getk64l(buf *b, kludge64 *w)
293{
294 if (BENSURE(b, 8)) return (-1);
295 LOAD64_L_(*w, b->p); BSTEP(b, 8); return (0);
296}
297
298int buf_getk64b(buf *b, kludge64 *w)
299{
300 if (BENSURE(b, 8)) return (-1);
301 LOAD64_B_(*w, b->p); BSTEP(b, 8); return (0);
302}
303
31d0247c
MW
304int (dbuf_getk64)(dbuf *db, kludge64 *w) { return (dbuf_getk64(db, w)); }
305int (dbuf_getk64l)(dbuf *db, kludge64 *w) { return (dbuf_getk64l(db, w)); }
306int (dbuf_getk64b)(dbuf *db, kludge64 *w) { return (dbuf_getk64b(db, w)); }
307
308/* --- @{,d}buf_putu{8,{16,24,32,64}{,l,b}}@ --- *
800d4c59 309 *
31d0247c 310 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
9b5ac6ff 311 * @uintSZ w@ = word to write
800d4c59 312 *
9b5ac6ff 313 * Returns: Zero if OK, or nonzero if there wasn't enough space
800d4c59 314 *
9b5ac6ff 315 * Use: Puts a word into a buffer with appropriate size and order.
800d4c59 316 */
317
9b5ac6ff 318#define BUF_PUTU_(n, W, w) \
319 int buf_putu##w(buf *b, uint##n ww) \
320 { \
321 if (BENSURE(b, SZ_##W)) return (-1); \
322 STORE##W(b->p, ww); \
323 BSTEP(b, SZ_##W); \
324 return (0); \
31d0247c
MW
325 } \
326 int (dbuf_putu##w)(dbuf *db, uint##n ww) \
327 { return (dbuf_putu##w(db, ww)); }
9b5ac6ff 328DOUINTCONV(BUF_PUTU_)
800d4c59 329
31d0247c 330/* --- @{,d}buf_putk64{,l,b}@ --- *
b64eb60f 331 *
31d0247c 332 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
b64eb60f
MW
333 * @kludge64 w@ = word to write
334 *
335 * Returns: Zero if OK, or nonzero if there wasn't enough space
336 *
337 * Use: Gets a word of appropriate size and order from a buffer.
338 */
339
340int buf_putk64(buf *b, kludge64 w)
341{
342 if (BENSURE(b, 8)) return (-1);
343 STORE64_(b->p, w); BSTEP(b, 8); return (0);
344}
345
346int buf_putk64l(buf *b, kludge64 w)
347{
348 if (BENSURE(b, 8)) return (-1);
349 STORE64_L_(b->p, w); BSTEP(b, 8); return (0);
350}
351
352int buf_putk64b(buf *b, kludge64 w)
353{
354 if (BENSURE(b, 8)) return (-1);
355 STORE64_B_(b->p, w); BSTEP(b, 8); return (0);
356}
357
31d0247c
MW
358int (dbuf_putk64)(dbuf *db, kludge64 w) { return (dbuf_putk64(db, w)); }
359int (dbuf_putk64l)(dbuf *db, kludge64 w) { return (dbuf_putk64l(db, w)); }
360int (dbuf_putk64b)(dbuf *db, kludge64 w) { return (dbuf_putk64b(db, w)); }
361
800d4c59 362/* --- @findz@ --- *
363 *
31d0247c 364 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 365 * @size_t *nn@ = where to put the length
366 *
367 * Returns: Zero if OK, nonzero if there wasn't a null byte to be found.
368 *
95491579
MW
369 * Use: Finds a terminating null byte. The length includes this
370 * terminator.
800d4c59 371 */
372
373static int findz(buf *b, size_t *nn)
374{
375 octet *p;
376
a4589237 377 if ((p = memchr(BCUR(b), 0, BLEFT(b))) == 0) {
800d4c59 378 buf_break(b);
379 return (-1);
380 }
95491579 381 *nn = p - BCUR(b) + 1;
800d4c59 382 return (0);
383}
384
31d0247c 385/* --- @{,d}buf_getmem{8,{16,24,32,64}{,l,b},z} --- *
800d4c59 386 *
31d0247c 387 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 388 * @size_t *nn@ = where to put the length
389 *
390 * Returns: Pointer to the buffer data, or null.
391 *
9b5ac6ff 392 * Use: Gets a chunk of memory from a buffer. The suffix is the
393 * width and byte order of the length; @z@ means null-
394 * terminated.
800d4c59 395 */
396
9b5ac6ff 397#define BUF_GETMEM_(n, W, w) \
398 void *buf_getmem##w(buf *b, size_t *nn) \
399 { \
400 uint##n sz; \
a4589237 401 if (buf_getu##w(b, &sz)) return (0); \
f868c432 402 if (BENSURE(b, sz)) return (0); \
9b5ac6ff 403 *nn = sz; \
404 return (buf_get(b, sz)); \
31d0247c
MW
405 } \
406 void *(dbuf_getmem##w)(dbuf *db, size_t *nn) \
407 { return (dbuf_getmem##w(db, nn)); }
9b5ac6ff 408DOUINTCONV(BUF_GETMEM_)
800d4c59 409
800d4c59 410void *buf_getmemz(buf *b, size_t *nn)
411{
412 if (findz(b, nn)) return (0);
413 return (buf_get(b, *nn));
414}
31d0247c
MW
415void *(dbuf_getmemz)(dbuf *db, size_t *nn)
416 { return (dbuf_getmemz(db, nn)); }
800d4c59 417
e63124bc
MW
418#ifndef HAVE_UINT64
419
420static void *getmem_k64(buf *b, size_t *nn_out, kludge64 k)
421{
422 kludge64 szmax;
423 size_t n;
424
425 ASSIGN64(szmax, (size_t)-1);
426 if (CMP64(k, >, szmax)) { buf_break(b); return (-1); }
427 n = GET64(size_t, k); *nn_out = n; return (buf_get(b, n));
428}
429
430void *buf_getmem64(buf *b, size_t *nn)
431{
432 kludge64 k;
433
434 if (buf_getk64(b, &k)) return (-1);
435 return (getmem_k64(b, nn, k));
436}
437
31d0247c 438void *buf_getmem64l(buf *b, size_t *nn)
e63124bc
MW
439{
440 kludge64 k;
441
31d0247c 442 if (buf_getk64l(b, &k)) return (-1);
e63124bc
MW
443 return (getmem_k64(b, nn, k));
444}
445
31d0247c 446void *buf_getmem64b(buf *b, size_t *nn)
e63124bc
MW
447{
448 kludge64 k;
449
31d0247c 450 if (buf_getk64b(b, &k)) return (-1);
e63124bc
MW
451 return (getmem_k64(b, nn, k));
452}
453
31d0247c
MW
454void *(dbuf_getmem64)(dbuf *db, size_t *nn)
455 { return (dbuf_getmem64(db, nn)); }
456void *(dbuf_getmem64l)(dbuf *db, size_t *nn)
457 { return (dbuf_getmem64l(db, nn)); }
458void *(dbuf_getmem64b)(dbuf *db, size_t *nn)
459 { return (dbuf_getmem64b(db, nn)); }
460
e63124bc
MW
461#endif
462
31d0247c 463/* --- @{,d}buf_putmem{8,{16,24,32,64}{,l,b},z} --- *
800d4c59 464 *
31d0247c 465 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 466 * @const void *p@ = pointer to data to write
467 * @size_t n@ = length to write
468 *
469 * Returns: Zero if OK, nonzero if there wasn't enough space.
470 *
9b5ac6ff 471 * Use: Writes a chunk of data to a buffer. The suffix is the
472 * width and byte order of the length; @z@ means null-
473 * terminated.
800d4c59 474 */
475
9b5ac6ff 476#define BUF_PUTMEM_(n, W, w) \
477 int buf_putmem##w(buf *b, const void *p, size_t sz) \
478 { \
0d61a23c
MW
479 MUFFLE_WARNINGS_STMT \
480 (CLANG_WARNING("-Wtautological-constant-out-of-range-compare"), \
481 { assert(sz <= MASK##W); }); \
a4589237 482 if (buf_putu##w(b, sz) || buf_put(b, p, sz)) \
9b5ac6ff 483 return (-1); \
484 return (0); \
31d0247c
MW
485 } \
486 int (dbuf_putmem##w)(dbuf *db, const void *p, size_t sz) \
487 { return (dbuf_putmem##w(db, p, sz)); }
9b5ac6ff 488DOUINTCONV(BUF_PUTMEM_)
800d4c59 489
e63124bc
MW
490#ifndef HAVE_UINT64
491
492void *buf_putmem64(buf *b, const void *p, size_t n)
493{
494 kludge64 k;
495
496 ASSIGN64(k, n); if (buf_putk64(b, k) || buf_put(b, p, n)) return (-1);
497 return (0);
498}
499
31d0247c 500void *buf_putmem64l(buf *b, const void *p, size_t n)
e63124bc
MW
501{
502 kludge64 k;
503
31d0247c 504 ASSIGN64(k, n); if (buf_putk64l(b, k) || buf_put(b, p, n)) return (-1);
e63124bc
MW
505 return (0);
506}
507
31d0247c 508void *buf_putmem64b(buf *b, const void *p, size_t n)
e63124bc
MW
509{
510 kludge64 k;
511
31d0247c 512 ASSIGN64(k, n); if (buf_putk64b(b, k) || buf_put(b, p, n)) return (-1);
e63124bc
MW
513 return (0);
514}
515
31d0247c
MW
516int (dbuf_putmem64)(dbuf *db, const void *p, size_t n)
517 { return (dbuf_putmem64(db, p, n)); }
518int (dbuf_putmem64l)(dbuf *db, const void *p, size_t n)
519 { return (dbuf_putmem64l(db, p, n)); }
520int (dbuf_putmem64b)(dbuf *db, const void *p, size_t n)
521 { return (dbuf_putmem64b(db, p, n)); }
522
e63124bc
MW
523#endif
524
800d4c59 525int buf_putmemz(buf *b, const void *p, size_t n)
526{
527 octet *q;
528
529 assert(!memchr(p, 0, n));
530 if ((q = buf_get(b, n + 1)) == 0)
531 return (-1);
532 memcpy(q, p, n);
533 q[n] = 0;
534 return (0);
535}
31d0247c
MW
536int (dbuf_putmemz)(dbuf *db, const void *p, size_t n)
537 { return (dbuf_putmemz(db, p, n)); }
800d4c59 538
31d0247c 539/* --- @{,d}buf_getbuf{8,{16,24,32,64}{,l,b},z} --- *
800d4c59 540 *
31d0247c 541 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
800d4c59 542 * @buf *bb@ = where to put the result
543 *
544 * Returns: Zero if it worked, nonzero if there wasn't enough space.
545 *
546 * Use: Gets a block of data from a buffer, and writes its bounds to
9b5ac6ff 547 * another buffer.
800d4c59 548 */
549
9b5ac6ff 550#define BUF_GETBUF_(n, W, w) \
551 int buf_getbuf##w(buf *b, buf *bb) \
552 { \
553 void *p; \
554 size_t sz; \
800d4c59 555 \
9b5ac6ff 556 if ((p = buf_getmem##w(b, &sz)) == 0) \
557 return (-1); \
558 buf_init(bb, p, sz); \
559 return (0); \
31d0247c
MW
560 } \
561 int (dbuf_getbuf##w)(dbuf *db, buf *bb) \
562 { return (dbuf_getbuf##w(db, bb)); }
9b5ac6ff 563BUF_DOSUFFIXES(BUF_GETBUF_)
800d4c59 564
31d0247c 565/* --- @{,d}buf_putbuf{8,{16,24,32,64}{,l,b},z} --- *
800d4c59 566 *
31d0247c 567 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
9b5ac6ff 568 * @buf *bb@ = buffer to write
800d4c59 569 *
570 * Returns: Zero if it worked, nonzero if there wasn't enough space.
571 *
9b5ac6ff 572 * Use: Puts the contents of a buffer to a buffer.
800d4c59 573 */
574
9b5ac6ff 575#define BUF_PUTBUF_(n, W, w) \
576 int buf_putbuf##w(buf *b, buf *bb) \
31d0247c
MW
577 { return (buf_putmem##w(b, BBASE(bb), BLEN(bb))); } \
578 int (dbuf_putbuf##w)(dbuf *db, buf *bb) \
579 { return (dbuf_putbuf##w(db, bb)); }
9b5ac6ff 580BUF_DOSUFFIXES(BUF_PUTBUF_)
800d4c59 581
31d0247c 582/* --- @{,d}buf_putstr{8,{16,24,32,64}{,l,b},z} --- *
800d4c59 583 *
31d0247c 584 * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
9b5ac6ff 585 * @const char *p@ = string to write
800d4c59 586 *
587 * Returns: Zero if it worked, nonzero if there wasn't enough space.
588 *
9b5ac6ff 589 * Use: Puts a null-terminated string to a buffer.
800d4c59 590 */
591
9b5ac6ff 592#define BUF_PUTSTR_(n, W, w) \
593 int buf_putstr##w(buf *b, const char *p) \
31d0247c
MW
594 { return (buf_putmem##w(b, p, strlen(p))); } \
595 int (dbuf_putstr##w)(dbuf *db, const char *p) \
596 { return (dbuf_putstr##w(db, p)); }
9b5ac6ff 597BUF_DOSUFFIXES(BUF_PUTSTR_)
800d4c59 598
599/*----- That's all, folks -------------------------------------------------*/