2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * String utility functions with dynamic memory management.
17 * Copyright 2016 Joyent, Inc.
25 #include <sys/debug.h>
27 #include "libcmdutils.h"
37 custr_flags_t cus_flags
;
40 #define STRING_CHUNK_SIZE 64
43 custr_reset(custr_t
*cus
)
45 if (cus
->cus_data
== NULL
)
49 cus
->cus_data
[0] = '\0';
53 custr_len(custr_t
*cus
)
55 return (cus
->cus_strlen
);
59 custr_cstr(custr_t
*cus
)
61 if (cus
->cus_data
== NULL
) {
62 VERIFY(cus
->cus_strlen
== 0);
63 VERIFY(cus
->cus_datalen
== 0);
66 * This function should never return NULL. If no buffer has
67 * been allocated, return a pointer to a zero-length string.
71 return (cus
->cus_data
);
75 custr_append_vprintf(custr_t
*cus
, const char *fmt
, va_list ap
)
77 int len
= vsnprintf(NULL
, 0, fmt
, ap
);
78 size_t chunksz
= STRING_CHUNK_SIZE
;
83 while (chunksz
< len
) {
87 if (len
+ cus
->cus_strlen
+ 1 >= cus
->cus_datalen
) {
89 size_t new_datalen
= cus
->cus_datalen
+ chunksz
;
91 if (cus
->cus_flags
& CUSTR_FIXEDBUF
) {
97 * Allocate replacement memory:
99 if ((new_data
= malloc(new_datalen
)) == NULL
) {
104 * Copy existing data into replacement memory and free
107 if (cus
->cus_data
!= NULL
) {
108 (void) memcpy(new_data
, cus
->cus_data
,
109 cus
->cus_strlen
+ 1);
114 * Swap in the replacement buffer:
116 cus
->cus_data
= new_data
;
117 cus
->cus_datalen
= new_datalen
;
120 * Append new string to existing string:
122 len
= vsnprintf(cus
->cus_data
+ cus
->cus_strlen
,
123 (uintptr_t)cus
->cus_data
- (uintptr_t)cus
->cus_strlen
, fmt
, ap
);
126 cus
->cus_strlen
+= len
;
132 custr_appendc(custr_t
*cus
, char newc
)
134 return (custr_append_printf(cus
, "%c", newc
));
138 custr_append_printf(custr_t
*cus
, const char *fmt
, ...)
144 ret
= custr_append_vprintf(cus
, fmt
, ap
);
151 custr_append(custr_t
*cus
, const char *name
)
153 return (custr_append_printf(cus
, "%s", name
));
157 custr_alloc(custr_t
**cus
)
161 if ((t
= calloc(1, sizeof (*t
))) == NULL
) {
171 custr_alloc_buf(custr_t
**cus
, void *buf
, size_t buflen
)
175 if (buflen
== 0 || buf
== NULL
) {
180 if ((ret
= custr_alloc(cus
)) != 0)
183 (*cus
)->cus_data
= buf
;
184 (*cus
)->cus_datalen
= buflen
;
185 (*cus
)->cus_strlen
= 0;
186 (*cus
)->cus_flags
= CUSTR_FIXEDBUF
;
187 (*cus
)->cus_data
[0] = '\0';
193 custr_free(custr_t
*cus
)
198 if ((cus
->cus_flags
& CUSTR_FIXEDBUF
) == 0)