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
);
709 * @function sbuf_uionew
712 * Create a new sbuf and initialize its buffer with data from the given uio.
715 * An optional existing sbuf to initialize, or NULL to allocate a new one.
718 * The uio describing the data to populate the sbuf with.
721 * An output parameter to report any error to.
724 * The new and/or initialized sbuf, or NULL on error. The error code is
725 * reported back via @a error.
728 sbuf_uionew(struct sbuf
*s
, struct uio
*uio
, int *error
)
732 if ((user_size_t
)uio_resid(uio
) > INT_MAX
- 1) {
737 size
= (int)uio_resid(uio
);
738 s
= sbuf_new(s
, NULL
, size
+ 1, 0);
744 *error
= uiomove(s
->s_buf
, size
, uio
);
757 * @function sbuf_bcopyin
760 * Append userland data to an sbuf.
766 * The userland address of data to append to the sbuf.
769 * The length of the data to copy from userland.
772 * 0 on success or -1 on error. Always returns -1 if the sbuf is marked as
776 sbuf_bcopyin(struct sbuf
*s
, const void *uaddr
, size_t len
)
778 if (SBUF_HASOVERFLOWED(s
)) {
786 if (-1 == sbuf_ensure_capacity(s
, len
)) {
787 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
791 if (copyin(CAST_USER_ADDR_T(uaddr
), &s
->s_buf
[s
->s_len
], len
) != 0) {
795 s
->s_len
+= (int)len
;
800 * @function sbuf_copyin
803 * Append a userland string to an sbuf.
809 * The userland address of the string to append to the sbuf.
812 * The maximum length of the string to copy. If zero, the current capacity of
816 * The number of bytes copied or -1 if an error occurred. Always returns -1 if
817 * the sbuf is marked as overflowed.
820 sbuf_copyin(struct sbuf
*s
, const void *uaddr
, size_t len
)
824 if (SBUF_HASOVERFLOWED(s
)) {
829 len
= sbuf_capacity(s
);
830 } else if (-1 == sbuf_ensure_capacity(s
, len
)) {
834 switch (copyinstr(CAST_USER_ADDR_T(uaddr
), &s
->s_buf
[s
->s_len
], len
+ 1, &done
)) {
836 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
840 s
->s_len
+= done
- 1;
849 #if DEBUG || DEVELOPMENT
852 * a = assertion string
854 #define SBUF_FAIL(a) \
856 printf("sbuf_tests: failed assertion: %s\n", a); \
857 if (what != NULL && should != NULL) { \
858 printf("sbuf_tests: while testing: %s should %s\n", what, should); \
869 #define SBUF_ASSERT(x) \
878 #define SBUF_ASSERT_NOT(x) \
886 #define SBUF_ASSERT_CMP(e, a, c) \
891 SBUF_FAIL(#a " " #c " " #e); \
895 #define SBUF_ASSERT_EQ(e, a) SBUF_ASSERT_CMP(e, a, ==)
896 #define SBUF_ASSERT_NE(e, a) SBUF_ASSERT_CMP(e, a, !=)
897 #define SBUF_ASSERT_GT(e, a) SBUF_ASSERT_CMP(e, a, >)
898 #define SBUF_ASSERT_GTE(e, a) SBUF_ASSERT_CMP(e, a, >=)
899 #define SBUF_ASSERT_LT(e, a) SBUF_ASSERT_CMP(e, a, <)
900 #define SBUF_ASSERT_LTE(e, a) SBUF_ASSERT_CMP(e, a, <=)
902 #define SBUF_TEST_BEGIN \
904 const char *what = NULL; \
905 const char *should = NULL;
908 * include the trailing semi-colons here intentionally to allow for block-like
911 #define SBUF_TESTING(f) \
916 #define SBUF_SHOULD(s) \
921 #define SBUF_TEST_END \
922 printf("sbuf_tests: %zu assertions passed\n", passed); \
925 return ENOTRECOVERABLE;
928 sysctl_sbuf_tests SYSCTL_HANDLER_ARGS
930 #pragma unused(arg1, arg2)
932 char str
[32] = { 'o', 'k', 0 };
934 rval
= sysctl_handle_string(oidp
, str
, sizeof(str
), req
);
935 if (rval
!= 0 || req
->newptr
== 0 || req
->newlen
< 1) {
941 SBUF_TESTING("sbuf_new")
943 SBUF_SHOULD("fail to allocate >INT_MAX")
945 struct sbuf
*s
= NULL
;
947 s
= sbuf_new(NULL
, NULL
, INT_MAX
+ 1, 0);
948 SBUF_ASSERT_EQ(NULL
, s
);
951 SBUF_SHOULD("fail when claiming a backing buffer >INT_MAX")
953 struct sbuf
*s
= NULL
;
956 s
= sbuf_new(NULL
, buf
, INT_MAX
+ 1, 0);
957 SBUF_ASSERT_EQ(NULL
, s
);
960 SBUF_SHOULD("fail to allocate a zero-length sbuf")
962 struct sbuf
*s
= NULL
;
964 s
= sbuf_new(NULL
, NULL
, 0, 0);
965 SBUF_ASSERT_EQ(NULL
, s
);
968 SBUF_SHOULD("not accept invalid flags")
970 struct sbuf
*s
= NULL
;
972 s
= sbuf_new(NULL
, NULL
, 16, 0x10000);
973 SBUF_ASSERT_EQ(NULL
, s
);
976 SBUF_SHOULD("succeed when passed an existing sbuf")
978 struct sbuf
*s
= NULL
;
979 struct sbuf existing
;
981 memset(&existing
, 0x41, sizeof(existing
));
982 s
= sbuf_new(&existing
, NULL
, 16, SBUF_AUTOEXTEND
);
983 SBUF_ASSERT_EQ(&existing
, s
);
984 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_AUTOEXTEND
));
985 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_DYNAMIC
));
986 SBUF_ASSERT_NE(NULL
, s
->s_buf
);
987 SBUF_ASSERT_NE(0, s
->s_size
);
988 SBUF_ASSERT_EQ(0, s
->s_len
);
993 SBUF_SHOULD("succeed when passed an existing sbuf and buffer")
995 struct sbuf
*s
= NULL
;
996 struct sbuf existing
;
999 memset(&existing
, 0x41, sizeof(existing
));
1000 s
= sbuf_new(&existing
, buf
, sizeof(buf
), 0);
1001 SBUF_ASSERT_EQ(&existing
, s
);
1002 SBUF_ASSERT_EQ(buf
, s
->s_buf
);
1003 SBUF_ASSERT_EQ(4, s
->s_size
);
1004 SBUF_ASSERT_EQ(0, s
->s_len
);
1009 SBUF_SHOULD("succeed without an existing sbuf or buffer")
1011 struct sbuf
*s
= NULL
;
1013 s
= sbuf_new(NULL
, NULL
, 16, 0);
1014 SBUF_ASSERT_NE(NULL
, s
);
1015 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_DYNAMIC
));
1016 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_DYNSTRUCT
));
1017 SBUF_ASSERT_NE(NULL
, s
->s_buf
);
1018 SBUF_ASSERT_NE(0, s
->s_size
);
1019 SBUF_ASSERT_EQ(0, s
->s_len
);
1024 SBUF_SHOULD("succeed without an existing sbuf, but with a buffer")
1026 struct sbuf
*s
= NULL
;
1027 char buf
[4] = { 0 };
1029 s
= sbuf_new(NULL
, buf
, sizeof(buf
), 0);
1030 SBUF_ASSERT_NE(NULL
, s
);
1031 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_DYNSTRUCT
));
1032 SBUF_ASSERT_EQ(buf
, s
->s_buf
);
1033 SBUF_ASSERT_EQ(4, s
->s_size
);
1034 SBUF_ASSERT_EQ(0, s
->s_len
);
1039 SBUF_SHOULD("round up the requested size if SBUF_AUTOEXTEND")
1041 struct sbuf
*s
= NULL
;
1043 s
= sbuf_new(NULL
, NULL
, 1, SBUF_AUTOEXTEND
);
1044 SBUF_ASSERT_GT(1, s
->s_size
);
1050 SBUF_TESTING("sbuf_clear")
1052 SBUF_SHOULD("clear the overflowed and finished flags")
1054 struct sbuf
*s
= NULL
;
1056 s
= sbuf_new(NULL
, NULL
, 16, 0);
1058 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
1059 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
));
1060 SBUF_SETFLAG(s
, SBUF_FINISHED
);
1061 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_FINISHED
));
1063 SBUF_ASSERT_NOT(SBUF_ISSET(s
, SBUF_OVERFLOWED
));
1064 SBUF_ASSERT_NOT(SBUF_ISSET(s
, SBUF_FINISHED
));
1069 SBUF_SHOULD("reset the position to zero")
1071 struct sbuf
*s
= NULL
;
1073 s
= sbuf_new(NULL
, NULL
, 16, 0);
1077 SBUF_ASSERT_EQ(0, s
->s_len
);
1083 SBUF_TESTING("sbuf_extend")
1085 SBUF_SHOULD("allow zero")
1087 struct sbuf
*s
= NULL
;
1090 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1091 size_before
= s
->s_size
;
1092 SBUF_ASSERT_EQ(0, sbuf_extend(s
, 0));
1093 SBUF_ASSERT_EQ(size_before
, s
->s_size
);
1098 SBUF_SHOULD("fail for sbuf not marked as SBUF_AUTOEXTEND")
1100 struct sbuf
*s
= NULL
;
1102 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1103 SBUF_ASSERT_EQ(-1, sbuf_extend(s
, 10));
1108 SBUF_SHOULD("accommodate reasonable requests")
1110 struct sbuf
*s
= NULL
;
1113 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1114 size_before
= s
->s_size
;
1116 SBUF_ASSERT_EQ(0, sbuf_extend(s
, 10));
1117 SBUF_ASSERT_GTE(10, s
->s_size
- size_before
);
1122 SBUF_SHOULD("reject requests that cause overflows")
1124 struct sbuf
*s
= NULL
;
1126 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1127 SBUF_ASSERT_EQ(-1, sbuf_extend(s
, SIZE_MAX
));
1128 SBUF_ASSERT_EQ(-1, sbuf_extend(s
, INT_MAX
));
1133 SBUF_SHOULD("transform the sbuf into an SBUF_DYNAMIC one")
1135 struct sbuf
*s
= NULL
;
1136 char buf
[4] = { 0 };
1138 s
= sbuf_new(NULL
, buf
, sizeof(buf
), SBUF_AUTOEXTEND
);
1139 SBUF_ASSERT_NOT(SBUF_ISSET(s
, SBUF_DYNAMIC
));
1140 SBUF_ASSERT_EQ(0, sbuf_extend(s
, 10));
1141 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_DYNAMIC
));
1147 SBUF_TESTING("sbuf_capacity")
1149 SBUF_SHOULD("account for the trailing nul byte")
1151 struct sbuf
*s
= NULL
;
1153 s
= sbuf_new(NULL
, NULL
, 16, 0);
1154 SBUF_ASSERT_EQ(s
->s_size
- s
->s_len
- 1, sbuf_capacity(s
));
1160 SBUF_TESTING("sbuf_ensure_capacity")
1162 SBUF_SHOULD("return 0 if the sbuf already has enough capacity")
1164 struct sbuf
*s
= NULL
;
1167 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1168 size_before
= s
->s_size
;
1169 SBUF_ASSERT_EQ(0, sbuf_ensure_capacity(s
, 5));
1170 SBUF_ASSERT_EQ(size_before
, s
->s_size
);
1175 SBUF_SHOULD("extend the buffer as needed")
1177 struct sbuf
*s
= NULL
;
1180 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1181 size_before
= s
->s_size
;
1182 SBUF_ASSERT_EQ(0, sbuf_ensure_capacity(s
, 30));
1183 SBUF_ASSERT_GT(size_before
, s
->s_size
);
1189 SBUF_TESTING("sbuf_bcat")
1191 SBUF_SHOULD("fail if the sbuf is marked as overflowed")
1193 struct sbuf
*s
= NULL
;
1195 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1196 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
1197 SBUF_ASSERT_EQ(-1, sbuf_bcat(s
, "A", 1));
1202 SBUF_SHOULD("fail if len is too big")
1204 struct sbuf
*s
= NULL
;
1206 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1207 SBUF_ASSERT_EQ(-1, sbuf_bcat(s
, "A", INT_MAX
));
1208 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
));
1213 SBUF_SHOULD("succeed for a fixed buf within limits")
1215 struct sbuf
*s
= NULL
;
1217 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1218 SBUF_ASSERT_EQ(0, sbuf_bcat(s
, "ABC", 3));
1219 SBUF_ASSERT_EQ(3, s
->s_len
);
1220 SBUF_ASSERT_EQ('A', s
->s_buf
[0]);
1221 SBUF_ASSERT_EQ('B', s
->s_buf
[1]);
1222 SBUF_ASSERT_EQ('C', s
->s_buf
[2]);
1227 SBUF_SHOULD("succeed for binary data, even with nul bytes")
1229 struct sbuf
*s
= NULL
;
1231 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1232 SBUF_ASSERT_EQ(0, sbuf_bcat(s
, "A\0C", 3));
1233 SBUF_ASSERT_EQ(3, s
->s_len
);
1234 SBUF_ASSERT_EQ('A', s
->s_buf
[0]);
1235 SBUF_ASSERT_EQ('\0', s
->s_buf
[1]);
1236 SBUF_ASSERT_EQ('C', s
->s_buf
[2]);
1241 SBUF_SHOULD("append to existing data")
1243 struct sbuf
*s
= NULL
;
1245 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1246 SBUF_ASSERT_EQ(0, sbuf_bcat(s
, "ABC", 3));
1247 SBUF_ASSERT_EQ(3, s
->s_len
);
1248 SBUF_ASSERT_EQ('A', s
->s_buf
[0]);
1249 SBUF_ASSERT_EQ('B', s
->s_buf
[1]);
1250 SBUF_ASSERT_EQ('C', s
->s_buf
[2]);
1252 SBUF_ASSERT_EQ(0, sbuf_bcat(s
, "DEF", 3));
1253 SBUF_ASSERT_EQ(6, s
->s_len
);
1254 SBUF_ASSERT_EQ('D', s
->s_buf
[3]);
1255 SBUF_ASSERT_EQ('E', s
->s_buf
[4]);
1256 SBUF_ASSERT_EQ('F', s
->s_buf
[5]);
1261 SBUF_SHOULD("succeed for a fixed buf right up to the limit")
1263 struct sbuf
*s
= NULL
;
1265 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1266 SBUF_ASSERT_EQ(0, sbuf_bcat(s
, "0123456789abcde", 15));
1267 SBUF_ASSERT_EQ(15, s
->s_len
);
1272 SBUF_SHOULD("fail for a fixed buf if too big")
1274 struct sbuf
*s
= NULL
;
1276 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1277 SBUF_ASSERT_EQ(-1, sbuf_bcat(s
, "0123456789abcdef", 16));
1278 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
));
1283 SBUF_SHOULD("expand the backing buffer as needed")
1285 struct sbuf
*s
= NULL
;
1288 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1289 size_before
= s
->s_size
;
1290 SBUF_ASSERT_EQ(0, sbuf_bcat(s
, "0123456789abcdef", 16));
1291 SBUF_ASSERT_GT(size_before
, s
->s_size
);
1292 SBUF_ASSERT_EQ(16, s
->s_len
);
1298 SBUF_TESTING("sbuf_bcpy")
1300 SBUF_SHOULD("overwrite any existing data")
1302 struct sbuf
*s
= NULL
;
1304 s
= sbuf_new(NULL
, NULL
, 16, 0);
1305 SBUF_ASSERT_EQ(0, sbuf_bcpy(s
, "ABC", 3));
1306 SBUF_ASSERT_EQ(3, s
->s_len
);
1307 SBUF_ASSERT_EQ('A', s
->s_buf
[0]);
1308 SBUF_ASSERT_EQ('B', s
->s_buf
[1]);
1309 SBUF_ASSERT_EQ('C', s
->s_buf
[2]);
1311 SBUF_ASSERT_EQ(0, sbuf_bcpy(s
, "XYZ123", 6));
1312 SBUF_ASSERT_EQ(6, s
->s_len
);
1313 SBUF_ASSERT_EQ('X', s
->s_buf
[0]);
1314 SBUF_ASSERT_EQ('Y', s
->s_buf
[1]);
1315 SBUF_ASSERT_EQ('Z', s
->s_buf
[2]);
1316 SBUF_ASSERT_EQ('1', s
->s_buf
[3]);
1317 SBUF_ASSERT_EQ('2', s
->s_buf
[4]);
1318 SBUF_ASSERT_EQ('3', s
->s_buf
[5]);
1323 SBUF_SHOULD("succeed if the sbuf is marked as overflowed, but there is space")
1325 struct sbuf
*s
= NULL
;
1327 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1328 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
1329 SBUF_ASSERT_EQ(0, sbuf_bcpy(s
, "A", 1));
1334 SBUF_SHOULD("fail if len is too big")
1336 struct sbuf
*s
= NULL
;
1338 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1339 SBUF_ASSERT_EQ(-1, sbuf_bcpy(s
, "A", INT_MAX
));
1340 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
));
1345 SBUF_SHOULD("succeed for a fixed buf within limits")
1347 struct sbuf
*s
= NULL
;
1349 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1350 SBUF_ASSERT_EQ(0, sbuf_bcpy(s
, "ABC", 3));
1351 SBUF_ASSERT_EQ(3, s
->s_len
);
1352 SBUF_ASSERT_EQ('A', s
->s_buf
[0]);
1353 SBUF_ASSERT_EQ('B', s
->s_buf
[1]);
1354 SBUF_ASSERT_EQ('C', s
->s_buf
[2]);
1359 SBUF_SHOULD("succeed for a fixed buf right up to the limit")
1361 struct sbuf
*s
= NULL
;
1363 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1364 SBUF_ASSERT_EQ(0, sbuf_bcpy(s
, "0123456789abcde", 15));
1365 SBUF_ASSERT_EQ(15, s
->s_len
);
1370 SBUF_SHOULD("fail for a fixed buf if too big")
1372 struct sbuf
*s
= NULL
;
1374 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1375 SBUF_ASSERT_EQ(-1, sbuf_bcpy(s
, "0123456789abcdef", 16));
1376 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
));
1381 SBUF_SHOULD("expand the backing buffer as needed")
1383 struct sbuf
*s
= NULL
;
1386 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1387 size_before
= s
->s_size
;
1388 SBUF_ASSERT_EQ(0, sbuf_bcpy(s
, "0123456789abcdef", 16));
1389 SBUF_ASSERT_GT(size_before
, s
->s_size
);
1390 SBUF_ASSERT_EQ(16, s
->s_len
);
1396 SBUF_TESTING("sbuf_cat")
1398 SBUF_SHOULD("fail if the sbuf is marked as overflowed")
1400 struct sbuf
*s
= NULL
;
1402 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1403 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
1404 SBUF_ASSERT_EQ(-1, sbuf_cat(s
, "A"));
1409 SBUF_SHOULD("succeed for a fixed buf within limits")
1411 struct sbuf
*s
= NULL
;
1413 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1414 SBUF_ASSERT_EQ(0, sbuf_cat(s
, "ABC"));
1415 SBUF_ASSERT_EQ(3, s
->s_len
);
1416 SBUF_ASSERT_EQ('A', s
->s_buf
[0]);
1417 SBUF_ASSERT_EQ('B', s
->s_buf
[1]);
1418 SBUF_ASSERT_EQ('C', s
->s_buf
[2]);
1423 SBUF_SHOULD("only copy up to a nul byte")
1425 struct sbuf
*s
= NULL
;
1427 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1428 SBUF_ASSERT_EQ(0, sbuf_cat(s
, "A\0C"));
1429 SBUF_ASSERT_EQ(1, s
->s_len
);
1430 SBUF_ASSERT_EQ('A', s
->s_buf
[0]);
1435 SBUF_SHOULD("append to existing data")
1437 struct sbuf
*s
= NULL
;
1439 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1440 SBUF_ASSERT_EQ(0, sbuf_cat(s
, "ABC"));
1441 SBUF_ASSERT_EQ(3, s
->s_len
);
1442 SBUF_ASSERT_EQ('A', s
->s_buf
[0]);
1443 SBUF_ASSERT_EQ('B', s
->s_buf
[1]);
1444 SBUF_ASSERT_EQ('C', s
->s_buf
[2]);
1446 SBUF_ASSERT_EQ(0, sbuf_cat(s
, "DEF"));
1447 SBUF_ASSERT_EQ(6, s
->s_len
);
1448 SBUF_ASSERT_EQ('D', s
->s_buf
[3]);
1449 SBUF_ASSERT_EQ('E', s
->s_buf
[4]);
1450 SBUF_ASSERT_EQ('F', s
->s_buf
[5]);
1455 SBUF_SHOULD("succeed for a fixed buf right up to the limit")
1457 struct sbuf
*s
= NULL
;
1459 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1460 SBUF_ASSERT_EQ(0, sbuf_cat(s
, "0123456789abcde"));
1461 SBUF_ASSERT_EQ(15, s
->s_len
);
1466 SBUF_SHOULD("fail for a fixed buf if too big")
1468 struct sbuf
*s
= NULL
;
1470 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1471 SBUF_ASSERT_EQ(-1, sbuf_cat(s
, "0123456789abcdef"));
1472 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
));
1477 SBUF_SHOULD("expand the backing buffer as needed")
1479 struct sbuf
*s
= NULL
;
1482 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1483 size_before
= s
->s_size
;
1484 SBUF_ASSERT_EQ(0, sbuf_cat(s
, "0123456789abcdef"));
1485 SBUF_ASSERT_GT(size_before
, s
->s_size
);
1486 SBUF_ASSERT_EQ(16, s
->s_len
);
1492 SBUF_TESTING("sbuf_cpy")
1494 SBUF_SHOULD("overwrite any existing data")
1496 struct sbuf
*s
= NULL
;
1498 s
= sbuf_new(NULL
, NULL
, 16, 0);
1499 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "ABC"));
1500 SBUF_ASSERT_EQ(3, s
->s_len
);
1501 SBUF_ASSERT_EQ('A', s
->s_buf
[0]);
1502 SBUF_ASSERT_EQ('B', s
->s_buf
[1]);
1503 SBUF_ASSERT_EQ('C', s
->s_buf
[2]);
1505 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "XYZ123"));
1506 SBUF_ASSERT_EQ(6, s
->s_len
);
1507 SBUF_ASSERT_EQ('X', s
->s_buf
[0]);
1508 SBUF_ASSERT_EQ('Y', s
->s_buf
[1]);
1509 SBUF_ASSERT_EQ('Z', s
->s_buf
[2]);
1510 SBUF_ASSERT_EQ('1', s
->s_buf
[3]);
1511 SBUF_ASSERT_EQ('2', s
->s_buf
[4]);
1512 SBUF_ASSERT_EQ('3', s
->s_buf
[5]);
1517 SBUF_SHOULD("succeed if the sbuf is marked as overflowed, but there is space")
1519 struct sbuf
*s
= NULL
;
1521 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1522 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
1523 SBUF_ASSERT_EQ(0, sbuf_bcpy(s
, "A", 1));
1528 SBUF_SHOULD("succeed for a fixed buf within limits")
1530 struct sbuf
*s
= NULL
;
1532 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1533 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "ABC"));
1534 SBUF_ASSERT_EQ(3, s
->s_len
);
1535 SBUF_ASSERT_EQ('A', s
->s_buf
[0]);
1536 SBUF_ASSERT_EQ('B', s
->s_buf
[1]);
1537 SBUF_ASSERT_EQ('C', s
->s_buf
[2]);
1542 SBUF_SHOULD("succeed for a fixed buf right up to the limit")
1544 struct sbuf
*s
= NULL
;
1546 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1547 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "0123456789abcde"));
1548 SBUF_ASSERT_EQ(15, s
->s_len
);
1553 SBUF_SHOULD("fail for a fixed buf if too big")
1555 struct sbuf
*s
= NULL
;
1557 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1558 SBUF_ASSERT_EQ(-1, sbuf_cpy(s
, "0123456789abcdef"));
1559 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
));
1564 SBUF_SHOULD("expand the backing buffer as needed")
1566 struct sbuf
*s
= NULL
;
1569 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1570 size_before
= s
->s_size
;
1571 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "0123456789abcdef"));
1572 SBUF_ASSERT_GT(size_before
, s
->s_size
);
1573 SBUF_ASSERT_EQ(16, s
->s_len
);
1579 /* also tests sbuf_vprintf: */
1580 SBUF_TESTING("sbuf_printf")
1582 SBUF_SHOULD("support simple printing")
1584 struct sbuf
*s
= NULL
;
1586 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1587 SBUF_ASSERT_EQ(0, sbuf_printf(s
, "hello"));
1588 SBUF_ASSERT_EQ(5, s
->s_len
);
1589 SBUF_ASSERT_EQ('h', s
->s_buf
[0]);
1590 SBUF_ASSERT_EQ('e', s
->s_buf
[1]);
1591 SBUF_ASSERT_EQ('l', s
->s_buf
[2]);
1592 SBUF_ASSERT_EQ('l', s
->s_buf
[3]);
1593 SBUF_ASSERT_EQ('o', s
->s_buf
[4]);
1598 SBUF_SHOULD("support format strings")
1600 struct sbuf
*s
= NULL
;
1603 const char *data3
= "foo";
1605 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1606 SBUF_ASSERT_EQ(0, sbuf_printf(s
, "%c %d %s", data1
, data2
, data3
));
1607 SBUF_ASSERT_EQ(9, s
->s_len
);
1608 SBUF_ASSERT_EQ('A', s
->s_buf
[0]);
1609 SBUF_ASSERT_EQ(' ', s
->s_buf
[1]);
1610 SBUF_ASSERT_EQ('1', s
->s_buf
[2]);
1611 SBUF_ASSERT_EQ('2', s
->s_buf
[3]);
1612 SBUF_ASSERT_EQ('3', s
->s_buf
[4]);
1613 SBUF_ASSERT_EQ(' ', s
->s_buf
[5]);
1614 SBUF_ASSERT_EQ('f', s
->s_buf
[6]);
1615 SBUF_ASSERT_EQ('o', s
->s_buf
[7]);
1616 SBUF_ASSERT_EQ('o', s
->s_buf
[8]);
1621 SBUF_SHOULD("work with the fact we reserve a nul byte at the end")
1623 struct sbuf
*s
= NULL
;
1625 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1626 SBUF_ASSERT_EQ(0, sbuf_printf(s
, "0123456789abcde"));
1627 SBUF_ASSERT_NOT(SBUF_ISSET(s
, SBUF_OVERFLOWED
));
1632 SBUF_SHOULD("mark the sbuf as overflowed if we try to write too much")
1634 struct sbuf
*s
= NULL
;
1636 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1637 SBUF_ASSERT_EQ(-1, sbuf_printf(s
, "0123456789abcdef"));
1638 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
));
1643 SBUF_SHOULD("auto-extend as necessary")
1645 struct sbuf
*s
= NULL
;
1646 const char *data
= "0123456789abcdef";
1650 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1651 size_before
= s
->s_size
;
1652 SBUF_ASSERT_EQ(0, sbuf_printf(s
, "%s", data
));
1653 SBUF_ASSERT_GT(size_before
, s
->s_size
);
1655 for (n
= 0; n
< strlen(data
); ++n
) {
1656 SBUF_ASSERT_EQ(data
[n
], s
->s_buf
[n
]);
1662 SBUF_SHOULD("fail if the sbuf is marked as overflowed")
1664 struct sbuf
*s
= NULL
;
1666 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1667 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
1668 SBUF_ASSERT_EQ(-1, sbuf_printf(s
, "A"));
1674 SBUF_TESTING("sbuf_putc")
1676 SBUF_SHOULD("work where we have capacity")
1678 struct sbuf
*s
= NULL
;
1680 s
= sbuf_new(NULL
, NULL
, 16, 0);
1681 SBUF_ASSERT_EQ(0, sbuf_putc(s
, 'a'));
1682 SBUF_ASSERT_EQ(1, s
->s_len
);
1683 SBUF_ASSERT_EQ('a', s
->s_buf
[0]);
1688 SBUF_SHOULD("fail if we have a full, fixedlen sbuf")
1690 struct sbuf
*s
= NULL
;
1692 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
1693 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "0123456789abcd"));
1694 SBUF_ASSERT_EQ(0, sbuf_putc(s
, 'e'));
1695 SBUF_ASSERT_EQ(-1, sbuf_putc(s
, 'f'));
1696 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
));
1701 SBUF_SHOULD("ignore nul")
1703 struct sbuf
*s
= NULL
;
1705 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1706 SBUF_ASSERT_EQ(0, sbuf_putc(s
, '\0'));
1707 SBUF_ASSERT_EQ(0, s
->s_len
);
1712 SBUF_SHOULD("auto-extend if necessary")
1714 struct sbuf
*s
= NULL
;
1718 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1719 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "0123456789abcde"));
1720 len_before
= s
->s_len
;
1721 size_before
= s
->s_size
;
1722 SBUF_ASSERT_EQ(0, sbuf_putc(s
, 'f'));
1723 SBUF_ASSERT_EQ(len_before
+ 1, s
->s_len
);
1724 SBUF_ASSERT_GT(size_before
, s
->s_size
);
1725 SBUF_ASSERT_EQ('f', s
->s_buf
[s
->s_len
- 1]);
1730 SBUF_SHOULD("fail if the sbuf is overflowed")
1732 struct sbuf
*s
= NULL
;
1734 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
1735 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
1736 SBUF_ASSERT_EQ(-1, sbuf_putc(s
, 'a'));
1742 SBUF_TESTING("sbuf_trim")
1744 SBUF_SHOULD("remove trailing spaces, tabs and newlines")
1746 struct sbuf
*s
= NULL
;
1747 const char *test
= "foo \t\t\n\t";
1749 s
= sbuf_new(NULL
, NULL
, 16, 0);
1750 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, test
));
1751 SBUF_ASSERT_EQ(strlen(test
), s
->s_len
);
1752 SBUF_ASSERT_EQ(0, sbuf_trim(s
));
1753 SBUF_ASSERT_EQ(3, s
->s_len
);
1758 SBUF_SHOULD("do nothing if there is no trailing whitespace")
1760 struct sbuf
*s
= NULL
;
1761 const char *test
= "foo";
1763 s
= sbuf_new(NULL
, NULL
, 16, 0);
1764 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, test
));
1765 SBUF_ASSERT_EQ(strlen(test
), s
->s_len
);
1766 SBUF_ASSERT_EQ(0, sbuf_trim(s
));
1767 SBUF_ASSERT_EQ(strlen(test
), s
->s_len
);
1772 SBUF_SHOULD("fail if the sbuf is overflowed")
1774 struct sbuf
*s
= NULL
;
1775 const char *test
= "foo ";
1777 s
= sbuf_new(NULL
, NULL
, 16, 0);
1778 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, test
));
1779 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
1780 SBUF_ASSERT_EQ(-1, sbuf_trim(s
));
1781 SBUF_ASSERT_EQ(strlen(test
), s
->s_len
);
1786 SBUF_SHOULD("work on empty strings")
1788 struct sbuf
*s
= NULL
;
1790 s
= sbuf_new(NULL
, NULL
, 16, 0);
1791 SBUF_ASSERT_EQ(0, sbuf_trim(s
));
1792 SBUF_ASSERT_EQ(0, s
->s_len
);
1798 SBUF_TESTING("sbuf_overflowed")
1800 SBUF_SHOULD("return false if it hasn't overflowed")
1802 struct sbuf
*s
= NULL
;
1804 s
= sbuf_new(NULL
, NULL
, 16, 0);
1805 SBUF_ASSERT_NOT(sbuf_overflowed(s
));
1810 SBUF_SHOULD("return true if it has overflowed")
1812 struct sbuf
*s
= NULL
;
1814 s
= sbuf_new(NULL
, NULL
, 16, 0);
1815 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
1816 SBUF_ASSERT(sbuf_overflowed(s
));
1822 SBUF_TESTING("sbuf_finish")
1824 SBUF_SHOULD("insert a nul byte, clear the overflowed flag and set the finished flag")
1826 struct sbuf
*s
= NULL
;
1828 s
= sbuf_new(NULL
, NULL
, 16, 0);
1829 SBUF_ASSERT_EQ(0, sbuf_putc(s
, 'A'));
1830 s
->s_buf
[s
->s_len
] = 'x';
1831 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
1832 SBUF_ASSERT_NOT(SBUF_ISSET(s
, SBUF_FINISHED
));
1836 SBUF_ASSERT_EQ(0, s
->s_buf
[s
->s_len
]);
1837 SBUF_ASSERT_NOT(SBUF_ISSET(s
, SBUF_OVERFLOWED
));
1838 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_FINISHED
));
1844 SBUF_TESTING("sbuf_data")
1846 SBUF_SHOULD("return the s_buf pointer")
1848 struct sbuf
*s
= NULL
;
1850 s
= sbuf_new(NULL
, NULL
, 16, 0);
1851 SBUF_ASSERT_EQ(s
->s_buf
, sbuf_data(s
));
1856 SBUF_SHOULD("return the buffer we gave it")
1858 struct sbuf
*s
= NULL
;
1859 char buf
[4] = { 0 };
1861 s
= sbuf_new(NULL
, buf
, sizeof(buf
), 0);
1862 SBUF_ASSERT_EQ(buf
, sbuf_data(s
));
1868 SBUF_TESTING("sbuf_len")
1870 SBUF_SHOULD("return the length of the sbuf data")
1872 struct sbuf
*s
= NULL
;
1874 s
= sbuf_new(NULL
, NULL
, 16, 0);
1875 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "hello"));
1876 SBUF_ASSERT_EQ(5, sbuf_len(s
));
1881 SBUF_SHOULD("return -1 if the sbuf is overflowed")
1883 struct sbuf
*s
= NULL
;
1885 s
= sbuf_new(NULL
, NULL
, 16, 0);
1886 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "hello"));
1887 SBUF_ASSERT_EQ(5, sbuf_len(s
));
1888 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
1889 SBUF_ASSERT_EQ(-1, sbuf_len(s
));
1895 SBUF_TESTING("sbuf_done")
1897 SBUF_SHOULD("return false if the sbuf isn't finished")
1899 struct sbuf
*s
= NULL
;
1901 s
= sbuf_new(NULL
, NULL
, 16, 0);
1902 SBUF_ASSERT_NOT(sbuf_done(s
));
1907 SBUF_SHOULD("return true if the sbuf has finished")
1909 struct sbuf
*s
= NULL
;
1911 s
= sbuf_new(NULL
, NULL
, 16, 0);
1912 SBUF_ASSERT_NOT(sbuf_done(s
));
1913 SBUF_SETFLAG(s
, SBUF_FINISHED
);
1914 SBUF_ASSERT(sbuf_done(s
));
1920 SBUF_TESTING("sbuf_delete")
1922 SBUF_SHOULD("just free the backing buffer if we supplied an sbuf")
1924 struct sbuf
*s
= NULL
;
1925 struct sbuf existing
= {};
1927 s
= sbuf_new(&existing
, NULL
, 16, 0);
1928 SBUF_ASSERT_NE(NULL
, s
->s_buf
);
1931 SBUF_ASSERT_EQ(NULL
, s
->s_buf
);
1935 SBUF_TESTING("sbuf_uionew")
1937 SBUF_SHOULD("reject residuals that are too large")
1939 struct sbuf
*s
= NULL
;
1949 auio
= uio_create(1, 0, UIO_SYSSPACE
, UIO_READ
);
1950 uio_addiov(auio
, (user_addr_t
)buf
, INT_MAX
);
1952 s
= sbuf_uionew(NULL
, auio
, &error
);
1953 SBUF_ASSERT_EQ(NULL
, s
);
1954 SBUF_ASSERT_EQ(EINVAL
, error
);
1959 SBUF_SHOULD("initialize using data described by the uio")
1961 struct sbuf
*s
= NULL
;
1971 auio
= uio_create(1, 0, UIO_SYSSPACE
, UIO_WRITE
);
1972 uio_addiov(auio
, (user_addr_t
)buf
, sizeof(buf
));
1974 s
= sbuf_uionew(NULL
, auio
, &error
);
1975 SBUF_ASSERT_NE(NULL
, s
);
1976 SBUF_ASSERT_EQ(0, error
);
1977 SBUF_ASSERT_EQ(4, s
->s_len
);
1978 SBUF_ASSERT_EQ('A', s
->s_buf
[0]);
1979 SBUF_ASSERT_EQ('B', s
->s_buf
[1]);
1980 SBUF_ASSERT_EQ('C', s
->s_buf
[2]);
1981 SBUF_ASSERT_EQ('D', s
->s_buf
[3]);
1987 SBUF_SHOULD("fail gracefully for bad addresses")
1989 struct sbuf
*s
= NULL
;
1993 auio
= uio_create(1, 0, UIO_USERSPACE
, UIO_WRITE
);
1994 uio_addiov(auio
, (user_addr_t
)0xdeadUL
, 123);
1996 s
= sbuf_uionew(NULL
, auio
, &error
);
1997 SBUF_ASSERT_EQ(NULL
, s
);
1998 SBUF_ASSERT_NE(0, error
);
2004 SBUF_TESTING("sbuf_bcopyin")
2006 SBUF_SHOULD("succeed when len is zero")
2008 struct sbuf
*s
= NULL
;
2009 const void *uptr
= (const void *)req
->newptr
;
2011 s
= sbuf_new(NULL
, NULL
, 16, 0);
2012 SBUF_ASSERT_EQ(0, sbuf_bcopyin(s
, uptr
, 0));
2013 SBUF_ASSERT_EQ(0, s
->s_len
);
2018 SBUF_SHOULD("succeed in the simple case")
2020 struct sbuf
*s
= NULL
;
2021 const void *uptr
= (const void *)req
->newptr
;
2022 size_t ulen
= req
->newlen
;
2024 s
= sbuf_new(NULL
, NULL
, 16, 0);
2025 SBUF_ASSERT_EQ(0, sbuf_bcopyin(s
, uptr
, ulen
));
2026 SBUF_ASSERT_EQ(ulen
, (size_t)s
->s_len
);
2031 SBUF_SHOULD("fail for invalid userland addresses")
2033 struct sbuf
*s
= NULL
;
2034 const void *uptr
= (const void *)0xdeadUL
;
2035 size_t ulen
= req
->newlen
;
2037 s
= sbuf_new(NULL
, NULL
, 16, 0);
2038 SBUF_ASSERT_EQ(-1, sbuf_bcopyin(s
, uptr
, ulen
));
2039 SBUF_ASSERT_EQ(0, s
->s_len
);
2044 SBUF_SHOULD("fail for kernel addresses")
2046 struct sbuf
*s
= NULL
;
2047 const void *uptr
= "abcd";
2050 s
= sbuf_new(NULL
, NULL
, 16, 0);
2051 SBUF_ASSERT_EQ(-1, sbuf_bcopyin(s
, uptr
, ulen
));
2052 SBUF_ASSERT_EQ(0, s
->s_len
);
2057 SBUF_SHOULD("fail if we don't have capacity for a fixed-len sbuf")
2059 struct sbuf
*s
= NULL
;
2060 const void *uptr
= (const void *)req
->newptr
;
2061 size_t ulen
= req
->newlen
;
2064 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
2065 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "0123456789abcde"));
2066 len_before
= s
->s_len
;
2067 SBUF_ASSERT_EQ(-1, sbuf_bcopyin(s
, uptr
, ulen
));
2068 SBUF_ASSERT_EQ(len_before
, s
->s_len
);
2069 SBUF_ASSERT(SBUF_ISSET(s
, SBUF_OVERFLOWED
));
2074 SBUF_SHOULD("auto-extend if we don't have capacity for an auto-extend sbuf")
2076 struct sbuf
*s
= NULL
;
2077 const void *uptr
= (const void *)req
->newptr
;
2078 size_t ulen
= req
->newlen
;
2081 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
2082 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "0123456789abcde"));
2083 len_before
= s
->s_len
;
2084 SBUF_ASSERT_EQ(0, sbuf_bcopyin(s
, uptr
, ulen
));
2085 SBUF_ASSERT_EQ(len_before
+ (int)ulen
, s
->s_len
);
2086 SBUF_ASSERT_NOT(SBUF_ISSET(s
, SBUF_OVERFLOWED
));
2091 SBUF_SHOULD("fail if overflowed")
2093 struct sbuf
*s
= NULL
;
2094 const void *uptr
= (const void *)req
->newptr
;
2095 size_t ulen
= req
->newlen
;
2097 s
= sbuf_new(NULL
, NULL
, 16, 0);
2098 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
2099 SBUF_ASSERT_EQ(-1, sbuf_bcopyin(s
, uptr
, ulen
));
2105 SBUF_TESTING("sbuf_copyin")
2107 SBUF_SHOULD("succeed in the simple case")
2109 struct sbuf
*s
= NULL
;
2111 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
2112 SBUF_ASSERT_EQ(req
->newlen
+ 1, sbuf_copyin(s
, (const void *)req
->newptr
, req
->newlen
));
2113 SBUF_ASSERT_EQ(req
->newlen
, s
->s_len
);
2118 SBUF_SHOULD("use the sbuf capacity if len is zero")
2120 struct sbuf
*s
= NULL
;
2122 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
2123 SBUF_ASSERT_EQ(req
->newlen
+ 1, sbuf_copyin(s
, (const void *)req
->newptr
, 0));
2124 SBUF_ASSERT_EQ(req
->newlen
, s
->s_len
);
2129 SBUF_SHOULD("fail if we can't extend the sbuf to accommodate")
2131 struct sbuf
*s
= NULL
;
2133 s
= sbuf_new(NULL
, NULL
, 16, SBUF_FIXEDLEN
);
2134 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "0123456789abcde"));
2135 SBUF_ASSERT_EQ(-1, sbuf_copyin(s
, (const void *)req
->newptr
, req
->newlen
));
2140 SBUF_SHOULD("auto-extend the buffer if necessary")
2142 struct sbuf
*s
= NULL
;
2145 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
2146 SBUF_ASSERT_EQ(0, sbuf_cpy(s
, "0123456789abcde"));
2147 len_before
= s
->s_len
;
2148 SBUF_ASSERT_NE(-1, sbuf_copyin(s
, (const void *)req
->newptr
, req
->newlen
));
2149 SBUF_ASSERT_GT(len_before
, s
->s_len
);
2154 SBUF_SHOULD("fail if the sbuf is overflowed")
2156 struct sbuf
*s
= NULL
;
2158 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
2159 SBUF_SETFLAG(s
, SBUF_OVERFLOWED
);
2160 SBUF_ASSERT_EQ(-1, sbuf_copyin(s
, (const void *)req
->newptr
, req
->newlen
));
2165 SBUF_SHOULD("fail gracefully for an invalid address")
2167 struct sbuf
*s
= NULL
;
2169 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
2170 SBUF_ASSERT_EQ(-1, sbuf_copyin(s
, (void *)0xdeadUL
, req
->newlen
));
2175 SBUF_SHOULD("fail gracefully for a kernel address")
2177 struct sbuf
*s
= NULL
;
2178 const char *ptr
= "abcd";
2180 s
= sbuf_new(NULL
, NULL
, 16, SBUF_AUTOEXTEND
);
2181 SBUF_ASSERT_EQ(-1, sbuf_copyin(s
, ptr
, strlen(ptr
)));
2190 SYSCTL_PROC(_kern
, OID_AUTO
, sbuf_test
, CTLTYPE_STRING
| CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_MASKED
, 0, 0, sysctl_sbuf_tests
, "A", "sbuf tests");
2192 #endif /* DEBUG || DEVELOPMENT */