2  * Copyright (c) 2020 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  28 #include <kern/kalloc.h> 
  29 #include <libkern/libkern.h> 
  31 #include <os/overflow.h> 
  32 #include <sys/param.h> 
  36 #if DEBUG || DEVELOPMENT 
  37 #include <kern/macro_help.h> 
  38 #include <sys/errno.h> 
  39 #include <sys/sysctl.h> 
  40 #endif /* DEBUG || DEVELOPMENT */ 
  42 #define SBUF_ISSET(s, f)        ((s)->s_flags & (f)) 
  43 #define SBUF_SETFLAG(s, f)      do { (s)->s_flags |= (f); } while (0) 
  44 #define SBUF_CLEARFLAG(s, f)    do { (s)->s_flags &= ~(f); } while (0) 
  46 #define SBUF_CANEXTEND(s)       SBUF_ISSET(s, SBUF_AUTOEXTEND) 
  47 #define SBUF_HASOVERFLOWED(s)   SBUF_ISSET(s, SBUF_OVERFLOWED) 
  48 #define SBUF_ISDYNAMIC(s)       SBUF_ISSET(s, SBUF_DYNAMIC) 
  49 #define SBUF_ISDYNSTRUCT(s)     SBUF_ISSET(s, SBUF_DYNSTRUCT) 
  50 #define SBUF_ISFINISHED(s)      SBUF_ISSET(s, SBUF_FINISHED) 
  52 #define SBUF_MINEXTENDSIZE      16 
  53 #define SBUF_MAXEXTENDSIZE      PAGE_SIZE 
  54 #define SBUF_MAXEXTENDINCR      PAGE_SIZE 
  57  * @function sbuf_delete 
  60  * Destroys an sbuf.  Frees the underlying buffer if it's allocated on the heap 
  61  * (indicated by SBUF_ISDYNAMIC) and frees the sbuf if it itself is allocated 
  62  * on the heap (SBUF_ISDYNSTRUCT). 
  65  * The sbuf to destroy. 
  68 sbuf_delete(struct sbuf 
*s
) 
  70         if (SBUF_ISDYNAMIC(s
) && s
->s_buf
) { 
  71                 kheap_free(KHEAP_DATA_BUFFERS
, s
->s_buf
, s
->s_size
); 
  75         if (SBUF_ISDYNSTRUCT(s
)) { 
  76                 kheap_free(KHEAP_DEFAULT
, s
, sizeof(*s
)); 
  81  * @function sbuf_extendsize 
  84  * Attempts to extend the size of an sbuf to the value pointed to by size. 
  87  * Points to a size_t containing the desired size for input and receives the 
  88  * actual new size on success (which will be greater than or equal to the 
  92  * 0 on success, -1 on failure. 
  95 sbuf_extendsize(size_t *size
) 
  97         size_t target_size 
= *size
; 
 100         if (target_size 
> INT_MAX
) { 
 104         if (target_size 
< SBUF_MAXEXTENDSIZE
) { 
 105                 new_size 
= SBUF_MINEXTENDSIZE
; 
 106                 while (new_size 
< target_size
) { 
 110                 /* round up to nearest page: */ 
 111                 new_size 
= (target_size 
+ PAGE_SIZE 
- 1) & ~PAGE_MASK
; 
 114         if (new_size 
> INT_MAX
) { 
 126  * Allocates and/or initializes an sbuf. 
 129  * An optional existing sbuf to initialize.  If NULL, a new one is allocated on 
 133  * An optional existing backing buffer to assign to the sbuf.  If NULL, a new 
 134  * one is allocated on the heap. 
 137  * The initial size of the sbuf.  The actual size may be greater than this 
 141  * The flags to set on the sbuf.  Accepted values are: 
 143  *   - SBUF_FIXEDLEN:   Do not allow the backing buffer to dynamically expand 
 144  *                      to accommodate appended data. 
 145  *   - SBUF_AUTOEXPAND: Automatically reallocate the backing buffer using the 
 149  * The new and/or initialized sbuf on success, or NULL on failure. 
 152 sbuf_new(struct sbuf 
*s
, char *buf
, int length_
, int flags
) 
 154         size_t length 
= (size_t)length_
; 
 156         if (length 
> INT_MAX 
|| flags 
& ~SBUF_USRFLAGMSK
) { 
 161                 s 
= (struct sbuf 
*)kheap_alloc(KHEAP_DEFAULT
, sizeof(*s
), Z_WAITOK
); 
 166                 bzero(s
, sizeof(*s
)); 
 168                 SBUF_SETFLAG(s
, SBUF_DYNSTRUCT
); 
 170                 bzero(s
, sizeof(*s
)); 
 175                 s
->s_size 
= (int)length
; 
 180         if (SBUF_CANEXTEND(s
) && (-1 == sbuf_extendsize(&length
))) { 
 185          * we always need at least 1 byte for \0, so s_size of 0 will cause an 
 186          * underflow in sbuf_capacity. 
 192         s
->s_buf 
= (char *)kheap_alloc(KHEAP_DATA_BUFFERS
, length
, Z_WAITOK
); 
 193         if (NULL 
== s
->s_buf
) { 
 196         bzero(s
->s_buf
, length
); 
 197         s
->s_size 
= (int)length
; 
 199         SBUF_SETFLAG(s
, SBUF_DYNAMIC
); 
 208  * @function sbuf_setpos 
 211  * Set the current position of the sbuf. 
 214  * The sbuf to modify. 
 217  * The new position to set.  Must be less than or equal to the current position. 
 220  * 0 on success, -1 on failure. 
 223 sbuf_setpos(struct sbuf 
*s
, int pos
) 
 225         if (pos 
< 0 || pos 
> s
->s_len
) { 
 234  * @function sbuf_clear 
 237  * Resets the position/length of the sbuf data to zero and clears the finished 
 238  * and overflow flags. 
 244 sbuf_clear(struct sbuf 
*s
) 
 246         SBUF_CLEARFLAG(s
, SBUF_FINISHED
); 
 247         SBUF_CLEARFLAG(s
, SBUF_OVERFLOWED
); 
 252  * @function sbuf_extend 
 255  * Attempt to extend the size of an sbuf's backing buffer by @a addlen bytes. 
 258  * The sbuf to extend. 
 261  * How many bytes to increase the size by. 
 264  * 0 on success, -1 on failure. 
 266 static int OS_WARN_RESULT
 
 267 sbuf_extend(struct sbuf 
*s
, size_t addlen
) 
 276         if (!SBUF_CANEXTEND(s
)) { 
 280         if (os_add_overflow((size_t)s
->s_size
, addlen
, &new_size
)) { 
 284         if (-1 == sbuf_extendsize(&new_size
)) { 
 288         new_buf 
= (char *)kheap_alloc(KHEAP_DATA_BUFFERS
, new_size
, Z_WAITOK
); 
 289         if (NULL 
== new_buf
) { 
 293         bcopy(s
->s_buf
, new_buf
, (size_t)s
->s_size
); 
 294         if (SBUF_ISDYNAMIC(s
)) { 
 295                 kheap_free(KHEAP_DATA_BUFFERS
, s
->s_buf
, (size_t)s
->s_size
); 
 297                 SBUF_SETFLAG(s
, SBUF_DYNAMIC
); 
 301         s
->s_size 
= (int)new_size
; 
 306  * @function sbuf_capacity 
 309  * Get the current capacity of an sbuf: how many more bytes we can append given 
 310  * the current size and position. 
 313  * The sbuf to get the capacity of. 
 316  * The current sbuf capacity. 
 319 sbuf_capacity(const struct sbuf 
*s
) 
 321         /* 1 byte reserved for \0: */ 
 322         return (size_t)(s
->s_size 
- s
->s_len 
- 1); 
 326  * @function sbuf_ensure_capacity 
 329  * Ensure that an sbuf can accommodate @a add_len bytes, reallocating the 
 330  * backing buffer if necessary. 
 336  * The minimum capacity to ensure @a s has. 
 339  * 0 if the minimum capacity is met by @a s, or -1 on error. 
 342 sbuf_ensure_capacity(struct sbuf 
*s
, size_t wanted
) 
 346         size 
= sbuf_capacity(s
); 
 347         if (size 
>= wanted
) { 
 351         return sbuf_extend(s
, wanted 
- size
); 
 355  * @function sbuf_bcat 
 358  * Append data to an sbuf. 
 364  * The data to append. 
 367  * The length of the data. 
 370  * 0 on success, -1 on failure.  Will always fail if the sbuf is marked as 
 374 sbuf_bcat(struct sbuf 
*s
, const void *data
, size_t len
) 
 376         if (SBUF_HASOVERFLOWED(s
)) { 
 380         if (-1 == sbuf_ensure_capacity(s
, len
)) { 
 381                 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
); 
 385         bcopy(data
, s
->s_buf 
+ s
->s_len
, len
); 
 386         s
->s_len 
+= (int)len
; /* safe */ 
 392  * @function sbuf_bcpy 
 395  * Set the entire sbuf data, possibly reallocating the backing buffer to 
 405  * The length of the data to set. 
 408  * 0 on success or -1 on failure.  Will clear the finished/overflowed flags. 
 411 sbuf_bcpy(struct sbuf 
*s
, const void *data
, size_t len
) 
 414         return sbuf_bcat(s
, data
, len
); 
 421  * Append a string to an sbuf, possibly expanding the backing buffer to 
 428  * The string to append. 
 431  * 0 on success, -1 on failure.  Always fails if the sbuf is marked as 
 435 sbuf_cat(struct sbuf 
*s
, const char *str
) 
 437         return sbuf_bcat(s
, str
, strlen(str
)); 
 444  * Set the entire sbuf data to the given nul-terminated string, possibly 
 445  * expanding the backing buffer to accommodate it if necessary. 
 451  * The string to set the sbuf data to. 
 454  * 0 on success, -1 on failure.  Clears and resets the sbuf first. 
 457 sbuf_cpy(struct sbuf 
*s
, const char *str
) 
 460         return sbuf_cat(s
, str
); 
 464  * @function sbuf_vprintf 
 467  * Formatted-print into an sbuf using a va_list. 
 476  * The format string argument data. 
 479  * 0 on success, -1 on failure.  Always fails if the sbuf is marked as 
 483 sbuf_vprintf(struct sbuf 
*s
, const char *fmt
, va_list ap
) 
 490         if (SBUF_HASOVERFLOWED(s
)) { 
 495                 capacity 
= sbuf_capacity(s
); 
 497                 va_copy(ap_copy
, ap
); 
 498                 /* +1 for \0.  safe because we already accommodate this. */ 
 499                 result 
= vsnprintf(&s
->s_buf
[s
->s_len
], capacity 
+ 1, fmt
, ap_copy
); 
 506                 len 
= (size_t)result
; 
 507                 if (len 
<= capacity
) { 
 508                         s
->s_len 
+= (int)len
; 
 511         } while (-1 != sbuf_ensure_capacity(s
, len
)); 
 513         SBUF_SETFLAG(s
, SBUF_OVERFLOWED
); 
 518  * @function sbuf_printf 
 521  * Formatted-print into an sbuf using variadic arguments. 
 530  * 0 on success, -1 on failure.  Always fails if the sbuf is marked as 
 534 sbuf_printf(struct sbuf 
*s
, const char *fmt
, ...) 
 540         result 
= sbuf_vprintf(s
, fmt
, ap
); 
 546  * @function sbuf_putc 
 549  * Append a single character to an sbuf.  Ignores '\0'. 
 555  * The character to append. 
 558  * 0 on success, -1 on failure.  This function will always fail if the sbuf is 
 559  * marked as overflowed. 
 562 sbuf_putc(struct sbuf 
*s
, int c_
) 
 566         if (SBUF_HASOVERFLOWED(s
)) { 
 570         if (-1 == sbuf_ensure_capacity(s
, 1)) { 
 571                 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
); 
 576                 s
->s_buf
[s
->s_len
++] = c
; 
 585         return ch 
== ' ' || ch 
== '\n' || ch 
== '\t'; 
 589  * @function sbuf_trim 
 592  * Removes whitespace from the end of an sbuf. 
 598  * 0 on success or -1 if the sbuf is marked as overflowed. 
 601 sbuf_trim(struct sbuf 
*s
) 
 603         if (SBUF_HASOVERFLOWED(s
)) { 
 607         while (s
->s_len 
> 0 && isspace(s
->s_buf
[s
->s_len 
- 1])) { 
 615  * @function sbuf_overflowed 
 618  * Indicates whether the sbuf is marked as overflowed. 
 624  * 1 if the sbuf has overflowed or 0 otherwise. 
 627 sbuf_overflowed(struct sbuf 
*s
) 
 629         return !!SBUF_HASOVERFLOWED(s
); 
 633  * @function sbuf_finish 
 636  * Puts a trailing nul byte onto the sbuf data. 
 642 sbuf_finish(struct sbuf 
*s
) 
 644         /* safe because we always reserve a byte at the end for \0: */ 
 645         s
->s_buf
[s
->s_len
] = '\0'; 
 646         SBUF_CLEARFLAG(s
, SBUF_OVERFLOWED
); 
 647         SBUF_SETFLAG(s
, SBUF_FINISHED
); 
 651  * @function sbuf_data 
 654  * Gets a pointer to the sbuf backing data. 
 660  * A pointer to the sbuf data. 
 663 sbuf_data(struct sbuf 
*s
) 
 672  * Retrieves the current length of the sbuf data. 
 678  * The length of the sbuf data or -1 if the sbuf is marked as overflowed. 
 681 sbuf_len(struct sbuf 
*s
) 
 683         if (SBUF_HASOVERFLOWED(s
)) { 
 691  * @function sbuf_done 
 694  * Tests if the sbuf is marked as finished. 
 700  * 1 if the sbuf is marked as finished or 0 if not. 
 703 sbuf_done(struct sbuf 
*s
) 
 705         return !!SBUF_ISFINISHED(s
); 
 708 #if DEBUG || DEVELOPMENT 
 711  * a = assertion string 
 713 #define SBUF_FAIL(a)                                                             \ 
 715         printf("sbuf_tests: failed assertion: %s\n", a);                         \ 
 716         if (what != NULL && should != NULL) {                                    \ 
 717             printf("sbuf_tests: while testing: %s should %s\n", what, should);   \ 
 728 #define SBUF_ASSERT(x)     \ 
 737 #define SBUF_ASSERT_NOT(x) \ 
 745 #define SBUF_ASSERT_CMP(e, a, c)         \ 
 750             SBUF_FAIL(#a " " #c " " #e); \ 
 754 #define SBUF_ASSERT_EQ(e, a)    SBUF_ASSERT_CMP(e, a, ==) 
 755 #define SBUF_ASSERT_NE(e, a)    SBUF_ASSERT_CMP(e, a, !=) 
 756 #define SBUF_ASSERT_GT(e, a)    SBUF_ASSERT_CMP(e, a, >) 
 757 #define SBUF_ASSERT_GTE(e, a)   SBUF_ASSERT_CMP(e, a, >=) 
 758 #define SBUF_ASSERT_LT(e, a)    SBUF_ASSERT_CMP(e, a, <) 
 759 #define SBUF_ASSERT_LTE(e, a)   SBUF_ASSERT_CMP(e, a, <=) 
 761 #define SBUF_TEST_BEGIN      \ 
 763     const char *what = NULL; \ 
 764     const char *should = NULL; 
 767  * include the trailing semi-colons here intentionally to allow for block-like 
 770 #define SBUF_TESTING(f) \ 
 775 #define SBUF_SHOULD(s) \ 
 780 #define SBUF_TEST_END                                      \ 
 781     printf("sbuf_tests: %zu assertions passed\n", passed); \ 
 784     return ENOTRECOVERABLE; 
 787 sysctl_sbuf_tests SYSCTL_HANDLER_ARGS
 
 789 #pragma unused(arg1, arg2) 
 791         char str
[32] = { 'o', 'k', 0 }; 
 793         rval 
= sysctl_handle_string(oidp
, str
, sizeof(str
), req
); 
 794         if (rval 
!= 0 || req
->newptr 
== 0 || req
->newlen 
< 1) { 
 800         SBUF_TESTING("sbuf_new") 
 802                 SBUF_SHOULD("fail to allocate >INT_MAX") 
 804                         struct sbuf 
*s 
= NULL
; 
 806                         s 
= sbuf_new(NULL
, NULL
, INT_MAX 
+ 1, 0); 
 807                         SBUF_ASSERT_EQ(NULL
, s
); 
 810                 SBUF_SHOULD("fail when claiming a backing buffer >INT_MAX") 
 812                         struct sbuf 
*s 
= NULL
; 
 815                         s 
= sbuf_new(NULL
, buf
, INT_MAX 
+ 1, 0); 
 816                         SBUF_ASSERT_EQ(NULL
, s
); 
 819                 SBUF_SHOULD("fail to allocate a zero-length sbuf") 
 821                         struct sbuf 
*s 
= NULL
; 
 823                         s 
= sbuf_new(NULL
, NULL
, 0, 0); 
 824                         SBUF_ASSERT_EQ(NULL
, s
); 
 827                 SBUF_SHOULD("not accept invalid flags") 
 829                         struct sbuf 
*s 
= NULL
; 
 831                         s 
= sbuf_new(NULL
, NULL
, 16, 0x10000); 
 832                         SBUF_ASSERT_EQ(NULL
, s
); 
 835                 SBUF_SHOULD("succeed when passed an existing sbuf") 
 837                         struct sbuf 
*s 
= NULL
; 
 838                         struct sbuf existing
; 
 840                         memset(&existing
, 0x41, sizeof(existing
)); 
 841                         s 
= sbuf_new(&existing
, NULL
, 16, SBUF_AUTOEXTEND
); 
 842                         SBUF_ASSERT_EQ(&existing
, s
); 
 843                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_AUTOEXTEND
)); 
 844                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_DYNAMIC
)); 
 845                         SBUF_ASSERT_NE(NULL
, s
->s_buf
); 
 846                         SBUF_ASSERT_NE(0, s
->s_size
); 
 847                         SBUF_ASSERT_EQ(0, s
->s_len
); 
 852                 SBUF_SHOULD("succeed when passed an existing sbuf and buffer") 
 854                         struct sbuf 
*s 
= NULL
; 
 855                         struct sbuf existing
; 
 858                         memset(&existing
, 0x41, sizeof(existing
)); 
 859                         s 
= sbuf_new(&existing
, buf
, sizeof(buf
), 0); 
 860                         SBUF_ASSERT_EQ(&existing
, s
); 
 861                         SBUF_ASSERT_EQ(buf
, s
->s_buf
); 
 862                         SBUF_ASSERT_EQ(4, s
->s_size
); 
 863                         SBUF_ASSERT_EQ(0, s
->s_len
); 
 868                 SBUF_SHOULD("succeed without an existing sbuf or buffer") 
 870                         struct sbuf 
*s 
= NULL
; 
 872                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
 873                         SBUF_ASSERT_NE(NULL
, s
); 
 874                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_DYNAMIC
)); 
 875                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_DYNSTRUCT
)); 
 876                         SBUF_ASSERT_NE(NULL
, s
->s_buf
); 
 877                         SBUF_ASSERT_NE(0, s
->s_size
); 
 878                         SBUF_ASSERT_EQ(0, s
->s_len
); 
 883                 SBUF_SHOULD("succeed without an existing sbuf, but with a buffer") 
 885                         struct sbuf 
*s 
= NULL
; 
 888                         s 
= sbuf_new(NULL
, buf
, sizeof(buf
), 0); 
 889                         SBUF_ASSERT_NE(NULL
, s
); 
 890                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_DYNSTRUCT
)); 
 891                         SBUF_ASSERT_EQ(buf
, s
->s_buf
); 
 892                         SBUF_ASSERT_EQ(4, s
->s_size
); 
 893                         SBUF_ASSERT_EQ(0, s
->s_len
); 
 898                 SBUF_SHOULD("round up the requested size if SBUF_AUTOEXTEND") 
 900                         struct sbuf 
*s 
= NULL
; 
 902                         s 
= sbuf_new(NULL
, NULL
, 1, SBUF_AUTOEXTEND
); 
 903                         SBUF_ASSERT_GT(1, s
->s_size
); 
 909         SBUF_TESTING("sbuf_clear") 
 911                 SBUF_SHOULD("clear the overflowed and finished flags") 
 913                         struct sbuf 
*s 
= NULL
; 
 915                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
 917                         SBUF_SETFLAG(s
, SBUF_OVERFLOWED
); 
 918                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
)); 
 919                         SBUF_SETFLAG(s
, SBUF_FINISHED
); 
 920                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_FINISHED
)); 
 922                         SBUF_ASSERT_NOT(SBUF_ISSET(s
, SBUF_OVERFLOWED
)); 
 923                         SBUF_ASSERT_NOT(SBUF_ISSET(s
, SBUF_FINISHED
)); 
 928                 SBUF_SHOULD("reset the position to zero") 
 930                         struct sbuf 
*s 
= NULL
; 
 932                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
 936                         SBUF_ASSERT_EQ(0, s
->s_len
); 
 942         SBUF_TESTING("sbuf_extend") 
 944                 SBUF_SHOULD("allow zero") 
 946                         struct sbuf 
*s 
= NULL
; 
 949                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
 950                         size_before 
= s
->s_size
; 
 951                         SBUF_ASSERT_EQ(0, sbuf_extend(s
, 0)); 
 952                         SBUF_ASSERT_EQ(size_before
, s
->s_size
); 
 957                 SBUF_SHOULD("fail for sbuf not marked as SBUF_AUTOEXTEND") 
 959                         struct sbuf 
*s 
= NULL
; 
 961                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
 962                         SBUF_ASSERT_EQ(-1, sbuf_extend(s
, 10)); 
 967                 SBUF_SHOULD("accommodate reasonable requests") 
 969                         struct sbuf 
*s 
= NULL
; 
 972                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
 973                         size_before 
= s
->s_size
; 
 975                         SBUF_ASSERT_EQ(0, sbuf_extend(s
, 10)); 
 976                         SBUF_ASSERT_GTE(10, s
->s_size 
- size_before
); 
 981                 SBUF_SHOULD("reject requests that cause overflows") 
 983                         struct sbuf 
*s 
= NULL
; 
 985                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
 986                         SBUF_ASSERT_EQ(-1, sbuf_extend(s
, SIZE_MAX
)); 
 987                         SBUF_ASSERT_EQ(-1, sbuf_extend(s
, INT_MAX
)); 
 992                 SBUF_SHOULD("transform the sbuf into an SBUF_DYNAMIC one") 
 994                         struct sbuf 
*s 
= NULL
; 
 997                         s 
= sbuf_new(NULL
, buf
, sizeof(buf
), SBUF_AUTOEXTEND
); 
 998                         SBUF_ASSERT_NOT(SBUF_ISSET(s
, SBUF_DYNAMIC
)); 
 999                         SBUF_ASSERT_EQ(0, sbuf_extend(s
, 10)); 
1000                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_DYNAMIC
)); 
1006         SBUF_TESTING("sbuf_capacity") 
1008                 SBUF_SHOULD("account for the trailing nul byte") 
1010                         struct sbuf 
*s 
= NULL
; 
1012                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1013                         SBUF_ASSERT_EQ(s
->s_size 
- s
->s_len 
- 1, sbuf_capacity(s
)); 
1019         SBUF_TESTING("sbuf_ensure_capacity") 
1021                 SBUF_SHOULD("return 0 if the sbuf already has enough capacity") 
1023                         struct sbuf 
*s 
= NULL
; 
1026                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1027                         size_before 
= s
->s_size
; 
1028                         SBUF_ASSERT_EQ(0, sbuf_ensure_capacity(s
, 5)); 
1029                         SBUF_ASSERT_EQ(size_before
, s
->s_size
); 
1034                 SBUF_SHOULD("extend the buffer as needed") 
1036                         struct sbuf 
*s 
= NULL
; 
1039                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1040                         size_before 
= s
->s_size
; 
1041                         SBUF_ASSERT_EQ(0, sbuf_ensure_capacity(s
, 30)); 
1042                         SBUF_ASSERT_GT(size_before
, s
->s_size
); 
1048         SBUF_TESTING("sbuf_bcat") 
1050                 SBUF_SHOULD("fail if the sbuf is marked as overflowed") 
1052                         struct sbuf 
*s 
= NULL
; 
1054                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1055                         SBUF_SETFLAG(s
, SBUF_OVERFLOWED
); 
1056                         SBUF_ASSERT_EQ(-1, sbuf_bcat(s
, "A", 1)); 
1061                 SBUF_SHOULD("fail if len is too big") 
1063                         struct sbuf 
*s 
= NULL
; 
1065                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1066                         SBUF_ASSERT_EQ(-1, sbuf_bcat(s
, "A", INT_MAX
)); 
1067                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
)); 
1072                 SBUF_SHOULD("succeed for a fixed buf within limits") 
1074                         struct sbuf 
*s 
= NULL
; 
1076                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1077                         SBUF_ASSERT_EQ(0, sbuf_bcat(s
, "ABC", 3)); 
1078                         SBUF_ASSERT_EQ(3, s
->s_len
); 
1079                         SBUF_ASSERT_EQ('A', s
->s_buf
[0]); 
1080                         SBUF_ASSERT_EQ('B', s
->s_buf
[1]); 
1081                         SBUF_ASSERT_EQ('C', s
->s_buf
[2]); 
1086                 SBUF_SHOULD("succeed for binary data, even with nul bytes") 
1088                         struct sbuf 
*s 
= NULL
; 
1090                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1091                         SBUF_ASSERT_EQ(0, sbuf_bcat(s
, "A\0C", 3)); 
1092                         SBUF_ASSERT_EQ(3, s
->s_len
); 
1093                         SBUF_ASSERT_EQ('A', s
->s_buf
[0]); 
1094                         SBUF_ASSERT_EQ('\0', s
->s_buf
[1]); 
1095                         SBUF_ASSERT_EQ('C', s
->s_buf
[2]); 
1100                 SBUF_SHOULD("append to existing data") 
1102                         struct sbuf 
*s 
= NULL
; 
1104                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1105                         SBUF_ASSERT_EQ(0, sbuf_bcat(s
, "ABC", 3)); 
1106                         SBUF_ASSERT_EQ(3, s
->s_len
); 
1107                         SBUF_ASSERT_EQ('A', s
->s_buf
[0]); 
1108                         SBUF_ASSERT_EQ('B', s
->s_buf
[1]); 
1109                         SBUF_ASSERT_EQ('C', s
->s_buf
[2]); 
1111                         SBUF_ASSERT_EQ(0, sbuf_bcat(s
, "DEF", 3)); 
1112                         SBUF_ASSERT_EQ(6, s
->s_len
); 
1113                         SBUF_ASSERT_EQ('D', s
->s_buf
[3]); 
1114                         SBUF_ASSERT_EQ('E', s
->s_buf
[4]); 
1115                         SBUF_ASSERT_EQ('F', s
->s_buf
[5]); 
1120                 SBUF_SHOULD("succeed for a fixed buf right up to the limit") 
1122                         struct sbuf 
*s 
= NULL
; 
1124                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1125                         SBUF_ASSERT_EQ(0, sbuf_bcat(s
, "0123456789abcde", 15)); 
1126                         SBUF_ASSERT_EQ(15, s
->s_len
); 
1131                 SBUF_SHOULD("fail for a fixed buf if too big") 
1133                         struct sbuf 
*s 
= NULL
; 
1135                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1136                         SBUF_ASSERT_EQ(-1, sbuf_bcat(s
, "0123456789abcdef", 16)); 
1137                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
)); 
1142                 SBUF_SHOULD("expand the backing buffer as needed") 
1144                         struct sbuf 
*s 
= NULL
; 
1147                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1148                         size_before 
= s
->s_size
; 
1149                         SBUF_ASSERT_EQ(0, sbuf_bcat(s
, "0123456789abcdef", 16)); 
1150                         SBUF_ASSERT_GT(size_before
, s
->s_size
); 
1151                         SBUF_ASSERT_EQ(16, s
->s_len
); 
1157         SBUF_TESTING("sbuf_bcpy") 
1159                 SBUF_SHOULD("overwrite any existing data") 
1161                         struct sbuf 
*s 
= NULL
; 
1163                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1164                         SBUF_ASSERT_EQ(0, sbuf_bcpy(s
, "ABC", 3)); 
1165                         SBUF_ASSERT_EQ(3, s
->s_len
); 
1166                         SBUF_ASSERT_EQ('A', s
->s_buf
[0]); 
1167                         SBUF_ASSERT_EQ('B', s
->s_buf
[1]); 
1168                         SBUF_ASSERT_EQ('C', s
->s_buf
[2]); 
1170                         SBUF_ASSERT_EQ(0, sbuf_bcpy(s
, "XYZ123", 6)); 
1171                         SBUF_ASSERT_EQ(6, s
->s_len
); 
1172                         SBUF_ASSERT_EQ('X', s
->s_buf
[0]); 
1173                         SBUF_ASSERT_EQ('Y', s
->s_buf
[1]); 
1174                         SBUF_ASSERT_EQ('Z', s
->s_buf
[2]); 
1175                         SBUF_ASSERT_EQ('1', s
->s_buf
[3]); 
1176                         SBUF_ASSERT_EQ('2', s
->s_buf
[4]); 
1177                         SBUF_ASSERT_EQ('3', s
->s_buf
[5]); 
1182                 SBUF_SHOULD("succeed if the sbuf is marked as overflowed, but there is space") 
1184                         struct sbuf 
*s 
= NULL
; 
1186                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1187                         SBUF_SETFLAG(s
, SBUF_OVERFLOWED
); 
1188                         SBUF_ASSERT_EQ(0, sbuf_bcpy(s
, "A", 1)); 
1193                 SBUF_SHOULD("fail if len is too big") 
1195                         struct sbuf 
*s 
= NULL
; 
1197                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1198                         SBUF_ASSERT_EQ(-1, sbuf_bcpy(s
, "A", INT_MAX
)); 
1199                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
)); 
1204                 SBUF_SHOULD("succeed for a fixed buf within limits") 
1206                         struct sbuf 
*s 
= NULL
; 
1208                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1209                         SBUF_ASSERT_EQ(0, sbuf_bcpy(s
, "ABC", 3)); 
1210                         SBUF_ASSERT_EQ(3, s
->s_len
); 
1211                         SBUF_ASSERT_EQ('A', s
->s_buf
[0]); 
1212                         SBUF_ASSERT_EQ('B', s
->s_buf
[1]); 
1213                         SBUF_ASSERT_EQ('C', s
->s_buf
[2]); 
1218                 SBUF_SHOULD("succeed for a fixed buf right up to the limit") 
1220                         struct sbuf 
*s 
= NULL
; 
1222                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1223                         SBUF_ASSERT_EQ(0, sbuf_bcpy(s
, "0123456789abcde", 15)); 
1224                         SBUF_ASSERT_EQ(15, s
->s_len
); 
1229                 SBUF_SHOULD("fail for a fixed buf if too big") 
1231                         struct sbuf 
*s 
= NULL
; 
1233                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1234                         SBUF_ASSERT_EQ(-1, sbuf_bcpy(s
, "0123456789abcdef", 16)); 
1235                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
)); 
1240                 SBUF_SHOULD("expand the backing buffer as needed") 
1242                         struct sbuf 
*s 
= NULL
; 
1245                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1246                         size_before 
= s
->s_size
; 
1247                         SBUF_ASSERT_EQ(0, sbuf_bcpy(s
, "0123456789abcdef", 16)); 
1248                         SBUF_ASSERT_GT(size_before
, s
->s_size
); 
1249                         SBUF_ASSERT_EQ(16, s
->s_len
); 
1255         SBUF_TESTING("sbuf_cat") 
1257                 SBUF_SHOULD("fail if the sbuf is marked as overflowed") 
1259                         struct sbuf 
*s 
= NULL
; 
1261                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1262                         SBUF_SETFLAG(s
, SBUF_OVERFLOWED
); 
1263                         SBUF_ASSERT_EQ(-1, sbuf_cat(s
, "A")); 
1268                 SBUF_SHOULD("succeed for a fixed buf within limits") 
1270                         struct sbuf 
*s 
= NULL
; 
1272                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1273                         SBUF_ASSERT_EQ(0, sbuf_cat(s
, "ABC")); 
1274                         SBUF_ASSERT_EQ(3, s
->s_len
); 
1275                         SBUF_ASSERT_EQ('A', s
->s_buf
[0]); 
1276                         SBUF_ASSERT_EQ('B', s
->s_buf
[1]); 
1277                         SBUF_ASSERT_EQ('C', s
->s_buf
[2]); 
1282                 SBUF_SHOULD("only copy up to a nul byte") 
1284                         struct sbuf 
*s 
= NULL
; 
1286                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1287                         SBUF_ASSERT_EQ(0, sbuf_cat(s
, "A\0C")); 
1288                         SBUF_ASSERT_EQ(1, s
->s_len
); 
1289                         SBUF_ASSERT_EQ('A', s
->s_buf
[0]); 
1294                 SBUF_SHOULD("append to existing data") 
1296                         struct sbuf 
*s 
= NULL
; 
1298                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1299                         SBUF_ASSERT_EQ(0, sbuf_cat(s
, "ABC")); 
1300                         SBUF_ASSERT_EQ(3, s
->s_len
); 
1301                         SBUF_ASSERT_EQ('A', s
->s_buf
[0]); 
1302                         SBUF_ASSERT_EQ('B', s
->s_buf
[1]); 
1303                         SBUF_ASSERT_EQ('C', s
->s_buf
[2]); 
1305                         SBUF_ASSERT_EQ(0, sbuf_cat(s
, "DEF")); 
1306                         SBUF_ASSERT_EQ(6, s
->s_len
); 
1307                         SBUF_ASSERT_EQ('D', s
->s_buf
[3]); 
1308                         SBUF_ASSERT_EQ('E', s
->s_buf
[4]); 
1309                         SBUF_ASSERT_EQ('F', s
->s_buf
[5]); 
1314                 SBUF_SHOULD("succeed for a fixed buf right up to the limit") 
1316                         struct sbuf 
*s 
= NULL
; 
1318                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1319                         SBUF_ASSERT_EQ(0, sbuf_cat(s
, "0123456789abcde")); 
1320                         SBUF_ASSERT_EQ(15, s
->s_len
); 
1325                 SBUF_SHOULD("fail for a fixed buf if too big") 
1327                         struct sbuf 
*s 
= NULL
; 
1329                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1330                         SBUF_ASSERT_EQ(-1, sbuf_cat(s
, "0123456789abcdef")); 
1331                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
)); 
1336                 SBUF_SHOULD("expand the backing buffer as needed") 
1338                         struct sbuf 
*s 
= NULL
; 
1341                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1342                         size_before 
= s
->s_size
; 
1343                         SBUF_ASSERT_EQ(0, sbuf_cat(s
, "0123456789abcdef")); 
1344                         SBUF_ASSERT_GT(size_before
, s
->s_size
); 
1345                         SBUF_ASSERT_EQ(16, s
->s_len
); 
1351         SBUF_TESTING("sbuf_cpy") 
1353                 SBUF_SHOULD("overwrite any existing data") 
1355                         struct sbuf 
*s 
= NULL
; 
1357                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1358                         SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "ABC")); 
1359                         SBUF_ASSERT_EQ(3, s
->s_len
); 
1360                         SBUF_ASSERT_EQ('A', s
->s_buf
[0]); 
1361                         SBUF_ASSERT_EQ('B', s
->s_buf
[1]); 
1362                         SBUF_ASSERT_EQ('C', s
->s_buf
[2]); 
1364                         SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "XYZ123")); 
1365                         SBUF_ASSERT_EQ(6, s
->s_len
); 
1366                         SBUF_ASSERT_EQ('X', s
->s_buf
[0]); 
1367                         SBUF_ASSERT_EQ('Y', s
->s_buf
[1]); 
1368                         SBUF_ASSERT_EQ('Z', s
->s_buf
[2]); 
1369                         SBUF_ASSERT_EQ('1', s
->s_buf
[3]); 
1370                         SBUF_ASSERT_EQ('2', s
->s_buf
[4]); 
1371                         SBUF_ASSERT_EQ('3', s
->s_buf
[5]); 
1376                 SBUF_SHOULD("succeed if the sbuf is marked as overflowed, but there is space") 
1378                         struct sbuf 
*s 
= NULL
; 
1380                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1381                         SBUF_SETFLAG(s
, SBUF_OVERFLOWED
); 
1382                         SBUF_ASSERT_EQ(0, sbuf_bcpy(s
, "A", 1)); 
1387                 SBUF_SHOULD("succeed for a fixed buf within limits") 
1389                         struct sbuf 
*s 
= NULL
; 
1391                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1392                         SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "ABC")); 
1393                         SBUF_ASSERT_EQ(3, s
->s_len
); 
1394                         SBUF_ASSERT_EQ('A', s
->s_buf
[0]); 
1395                         SBUF_ASSERT_EQ('B', s
->s_buf
[1]); 
1396                         SBUF_ASSERT_EQ('C', s
->s_buf
[2]); 
1401                 SBUF_SHOULD("succeed for a fixed buf right up to the limit") 
1403                         struct sbuf 
*s 
= NULL
; 
1405                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1406                         SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "0123456789abcde")); 
1407                         SBUF_ASSERT_EQ(15, s
->s_len
); 
1412                 SBUF_SHOULD("fail for a fixed buf if too big") 
1414                         struct sbuf 
*s 
= NULL
; 
1416                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1417                         SBUF_ASSERT_EQ(-1, sbuf_cpy(s
, "0123456789abcdef")); 
1418                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
)); 
1423                 SBUF_SHOULD("expand the backing buffer as needed") 
1425                         struct sbuf 
*s 
= NULL
; 
1428                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1429                         size_before 
= s
->s_size
; 
1430                         SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "0123456789abcdef")); 
1431                         SBUF_ASSERT_GT(size_before
, s
->s_size
); 
1432                         SBUF_ASSERT_EQ(16, s
->s_len
); 
1438         /* also tests sbuf_vprintf: */ 
1439         SBUF_TESTING("sbuf_printf") 
1441                 SBUF_SHOULD("support simple printing") 
1443                         struct sbuf 
*s 
= NULL
; 
1445                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1446                         SBUF_ASSERT_EQ(0, sbuf_printf(s
, "hello")); 
1447                         SBUF_ASSERT_EQ(5, s
->s_len
); 
1448                         SBUF_ASSERT_EQ('h', s
->s_buf
[0]); 
1449                         SBUF_ASSERT_EQ('e', s
->s_buf
[1]); 
1450                         SBUF_ASSERT_EQ('l', s
->s_buf
[2]); 
1451                         SBUF_ASSERT_EQ('l', s
->s_buf
[3]); 
1452                         SBUF_ASSERT_EQ('o', s
->s_buf
[4]); 
1457                 SBUF_SHOULD("support format strings") 
1459                         struct sbuf 
*s 
= NULL
; 
1462                         const char *data3 
= "foo"; 
1464                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1465                         SBUF_ASSERT_EQ(0, sbuf_printf(s
, "%c %d %s", data1
, data2
, data3
)); 
1466                         SBUF_ASSERT_EQ(9, s
->s_len
); 
1467                         SBUF_ASSERT_EQ('A', s
->s_buf
[0]); 
1468                         SBUF_ASSERT_EQ(' ', s
->s_buf
[1]); 
1469                         SBUF_ASSERT_EQ('1', s
->s_buf
[2]); 
1470                         SBUF_ASSERT_EQ('2', s
->s_buf
[3]); 
1471                         SBUF_ASSERT_EQ('3', s
->s_buf
[4]); 
1472                         SBUF_ASSERT_EQ(' ', s
->s_buf
[5]); 
1473                         SBUF_ASSERT_EQ('f', s
->s_buf
[6]); 
1474                         SBUF_ASSERT_EQ('o', s
->s_buf
[7]); 
1475                         SBUF_ASSERT_EQ('o', s
->s_buf
[8]); 
1480                 SBUF_SHOULD("work with the fact we reserve a nul byte at the end") 
1482                         struct sbuf 
*s 
= NULL
; 
1484                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1485                         SBUF_ASSERT_EQ(0, sbuf_printf(s
, "0123456789abcde")); 
1486                         SBUF_ASSERT_NOT(SBUF_ISSET(s
, SBUF_OVERFLOWED
)); 
1491                 SBUF_SHOULD("mark the sbuf as overflowed if we try to write too much") 
1493                         struct sbuf 
*s 
= NULL
; 
1495                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1496                         SBUF_ASSERT_EQ(-1, sbuf_printf(s
, "0123456789abcdef")); 
1497                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
)); 
1502                 SBUF_SHOULD("auto-extend as necessary") 
1504                         struct sbuf 
*s 
= NULL
; 
1505                         const char *data 
= "0123456789abcdef"; 
1509                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1510                         size_before 
= s
->s_size
; 
1511                         SBUF_ASSERT_EQ(0, sbuf_printf(s
, "%s", data
)); 
1512                         SBUF_ASSERT_GT(size_before
, s
->s_size
); 
1514                         for (n 
= 0; n 
< strlen(data
); ++n
) { 
1515                                 SBUF_ASSERT_EQ(data
[n
], s
->s_buf
[n
]); 
1521                 SBUF_SHOULD("fail if the sbuf is marked as overflowed") 
1523                         struct sbuf 
*s 
= NULL
; 
1525                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1526                         SBUF_SETFLAG(s
, SBUF_OVERFLOWED
); 
1527                         SBUF_ASSERT_EQ(-1, sbuf_printf(s
, "A")); 
1533         SBUF_TESTING("sbuf_putc") 
1535                 SBUF_SHOULD("work where we have capacity") 
1537                         struct sbuf 
*s 
= NULL
; 
1539                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1540                         SBUF_ASSERT_EQ(0, sbuf_putc(s
, 'a')); 
1541                         SBUF_ASSERT_EQ(1, s
->s_len
); 
1542                         SBUF_ASSERT_EQ('a', s
->s_buf
[0]); 
1547                 SBUF_SHOULD("fail if we have a full, fixedlen sbuf") 
1549                         struct sbuf 
*s 
= NULL
; 
1551                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
); 
1552                         SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "0123456789abcd")); 
1553                         SBUF_ASSERT_EQ(0, sbuf_putc(s
, 'e')); 
1554                         SBUF_ASSERT_EQ(-1, sbuf_putc(s
, 'f')); 
1555                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
)); 
1560                 SBUF_SHOULD("ignore nul") 
1562                         struct sbuf 
*s 
= NULL
; 
1564                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1565                         SBUF_ASSERT_EQ(0, sbuf_putc(s
, '\0')); 
1566                         SBUF_ASSERT_EQ(0, s
->s_len
); 
1571                 SBUF_SHOULD("auto-extend if necessary") 
1573                         struct sbuf 
*s 
= NULL
; 
1577                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1578                         SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "0123456789abcde")); 
1579                         len_before 
= s
->s_len
; 
1580                         size_before 
= s
->s_size
; 
1581                         SBUF_ASSERT_EQ(0, sbuf_putc(s
, 'f')); 
1582                         SBUF_ASSERT_EQ(len_before 
+ 1, s
->s_len
); 
1583                         SBUF_ASSERT_GT(size_before
, s
->s_size
); 
1584                         SBUF_ASSERT_EQ('f', s
->s_buf
[s
->s_len 
- 1]); 
1589                 SBUF_SHOULD("fail if the sbuf is overflowed") 
1591                         struct sbuf 
*s 
= NULL
; 
1593                         s 
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
); 
1594                         SBUF_SETFLAG(s
, SBUF_OVERFLOWED
); 
1595                         SBUF_ASSERT_EQ(-1, sbuf_putc(s
, 'a')); 
1601         SBUF_TESTING("sbuf_trim") 
1603                 SBUF_SHOULD("remove trailing spaces, tabs and newlines") 
1605                         struct sbuf 
*s 
= NULL
; 
1606                         const char *test 
= "foo    \t\t\n\t"; 
1608                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1609                         SBUF_ASSERT_EQ(0, sbuf_cpy(s
, test
)); 
1610                         SBUF_ASSERT_EQ(strlen(test
), s
->s_len
); 
1611                         SBUF_ASSERT_EQ(0, sbuf_trim(s
)); 
1612                         SBUF_ASSERT_EQ(3, s
->s_len
); 
1617                 SBUF_SHOULD("do nothing if there is no trailing whitespace") 
1619                         struct sbuf 
*s 
= NULL
; 
1620                         const char *test 
= "foo"; 
1622                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1623                         SBUF_ASSERT_EQ(0, sbuf_cpy(s
, test
)); 
1624                         SBUF_ASSERT_EQ(strlen(test
), s
->s_len
); 
1625                         SBUF_ASSERT_EQ(0, sbuf_trim(s
)); 
1626                         SBUF_ASSERT_EQ(strlen(test
), s
->s_len
); 
1631                 SBUF_SHOULD("fail if the sbuf is overflowed") 
1633                         struct sbuf 
*s 
= NULL
; 
1634                         const char *test 
= "foo   "; 
1636                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1637                         SBUF_ASSERT_EQ(0, sbuf_cpy(s
, test
)); 
1638                         SBUF_SETFLAG(s
, SBUF_OVERFLOWED
); 
1639                         SBUF_ASSERT_EQ(-1, sbuf_trim(s
)); 
1640                         SBUF_ASSERT_EQ(strlen(test
), s
->s_len
); 
1645                 SBUF_SHOULD("work on empty strings") 
1647                         struct sbuf 
*s 
= NULL
; 
1649                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1650                         SBUF_ASSERT_EQ(0, sbuf_trim(s
)); 
1651                         SBUF_ASSERT_EQ(0, s
->s_len
); 
1657         SBUF_TESTING("sbuf_overflowed") 
1659                 SBUF_SHOULD("return false if it hasn't overflowed") 
1661                         struct sbuf 
*s 
= NULL
; 
1663                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1664                         SBUF_ASSERT_NOT(sbuf_overflowed(s
)); 
1669                 SBUF_SHOULD("return true if it has overflowed") 
1671                         struct sbuf 
*s 
= NULL
; 
1673                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1674                         SBUF_SETFLAG(s
, SBUF_OVERFLOWED
); 
1675                         SBUF_ASSERT(sbuf_overflowed(s
)); 
1681         SBUF_TESTING("sbuf_finish") 
1683                 SBUF_SHOULD("insert a nul byte, clear the overflowed flag and set the finished flag") 
1685                         struct sbuf 
*s 
= NULL
; 
1687                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1688                         SBUF_ASSERT_EQ(0, sbuf_putc(s
, 'A')); 
1689                         s
->s_buf
[s
->s_len
] = 'x'; 
1690                         SBUF_SETFLAG(s
, SBUF_OVERFLOWED
); 
1691                         SBUF_ASSERT_NOT(SBUF_ISSET(s
, SBUF_FINISHED
)); 
1695                         SBUF_ASSERT_EQ(0, s
->s_buf
[s
->s_len
]); 
1696                         SBUF_ASSERT_NOT(SBUF_ISSET(s
, SBUF_OVERFLOWED
)); 
1697                         SBUF_ASSERT(SBUF_ISSET(s
, SBUF_FINISHED
)); 
1703         SBUF_TESTING("sbuf_data") 
1705                 SBUF_SHOULD("return the s_buf pointer") 
1707                         struct sbuf 
*s 
= NULL
; 
1709                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1710                         SBUF_ASSERT_EQ(s
->s_buf
, sbuf_data(s
)); 
1715                 SBUF_SHOULD("return the buffer we gave it") 
1717                         struct sbuf 
*s 
= NULL
; 
1718                         char buf
[4] = { 0 }; 
1720                         s 
= sbuf_new(NULL
, buf
, sizeof(buf
), 0); 
1721                         SBUF_ASSERT_EQ(buf
, sbuf_data(s
)); 
1727         SBUF_TESTING("sbuf_len") 
1729                 SBUF_SHOULD("return the length of the sbuf data") 
1731                         struct sbuf 
*s 
= NULL
; 
1733                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1734                         SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "hello")); 
1735                         SBUF_ASSERT_EQ(5, sbuf_len(s
)); 
1740                 SBUF_SHOULD("return -1 if the sbuf is overflowed") 
1742                         struct sbuf 
*s 
= NULL
; 
1744                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1745                         SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "hello")); 
1746                         SBUF_ASSERT_EQ(5, sbuf_len(s
)); 
1747                         SBUF_SETFLAG(s
, SBUF_OVERFLOWED
); 
1748                         SBUF_ASSERT_EQ(-1, sbuf_len(s
)); 
1754         SBUF_TESTING("sbuf_done") 
1756                 SBUF_SHOULD("return false if the sbuf isn't finished") 
1758                         struct sbuf 
*s 
= NULL
; 
1760                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1761                         SBUF_ASSERT_NOT(sbuf_done(s
)); 
1766                 SBUF_SHOULD("return true if the sbuf has finished") 
1768                         struct sbuf 
*s 
= NULL
; 
1770                         s 
= sbuf_new(NULL
, NULL
, 16, 0); 
1771                         SBUF_ASSERT_NOT(sbuf_done(s
)); 
1772                         SBUF_SETFLAG(s
, SBUF_FINISHED
); 
1773                         SBUF_ASSERT(sbuf_done(s
)); 
1779         SBUF_TESTING("sbuf_delete") 
1781                 SBUF_SHOULD("just free the backing buffer if we supplied an sbuf") 
1783                         struct sbuf 
*s 
= NULL
; 
1784                         struct sbuf existing 
= {}; 
1786                         s 
= sbuf_new(&existing
, NULL
, 16, 0); 
1787                         SBUF_ASSERT_NE(NULL
, s
->s_buf
); 
1790                         SBUF_ASSERT_EQ(NULL
, s
->s_buf
); 
1797 SYSCTL_PROC(_kern
, OID_AUTO
, sbuf_test
, CTLTYPE_STRING 
| CTLFLAG_RW 
| CTLFLAG_KERN 
| CTLFLAG_MASKED
, 0, 0, sysctl_sbuf_tests
, "A", "sbuf tests"); 
1799 #endif /* DEBUG || DEVELOPMENT */