1 /* 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 5 * 1.0 of the CDDL. 6 * 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. 10 */ 11 12 /* 13 * Copyright 2019 Joyent, Inc. 14 */ 15 16 #ifndef _LIBCUSTR_H 17 #define _LIBCUSTR_H 18 19 #include <stdarg.h> 20 #include <sys/types.h> 21 22 /* dynamic string utilities */ 23 24 #ifdef __cplusplus 25 extern "C" { 26 #endif 27 28 typedef struct custr custr_t; 29 typedef struct custr_alloc_ops custr_alloc_ops_t; 30 typedef struct custr_alloc custr_alloc_t; 31 32 /* 33 * A custom allocator instance. To use a custom allocator, the user provides 34 * the memory for a given custr_alloc_t and calls custr_alloc_init() with the 35 * address of the instance to initialize it. custr_alloc_init() will invoke 36 * the init op (if defined) with any additional arguments. The user can then 37 * save any desired state for the allocator instance in cua_arg. If a 38 * custom allocator instance needs to do any cleanup after it's no longer 39 * needed, it should also define the fini op and invoke custr_alloc_fini() to 40 * do the cleanup. 41 */ 42 #define CUSTR_VERSION 1 43 struct custr_alloc { 44 uint_t cua_version; 45 const custr_alloc_ops_t *cua_ops; 46 void *cua_arg; 47 }; 48 49 struct custr_alloc_ops { 50 /* 51 * Optional allocator constructor. Returns 0 on success, -1 52 * on failure (and should set errno on failure). 53 */ 54 int (*custr_ao_init)(custr_alloc_t *, va_list); 55 /* 56 * Optional allocator destructor. 57 */ 58 void (*custr_ao_fini)(custr_alloc_t *); 59 /* 60 * Returns at least size_t bytes of allocated memory, or NULL. 61 * It should also set errno on failure. 62 */ 63 void *(*custr_ao_alloc)(custr_alloc_t *, size_t); 64 /* 65 * Free the memory previously allocated with custr_ao_alloc. 66 */ 67 void (*custr_ao_free)(custr_alloc_t *, void *, size_t); 68 }; 69 70 /* 71 * Initializes a custr allocator. custr_alloc_t->cua_version should be set to 72 * CUSTR_VERSION prior to calling custr_alloc_init(). Both the custr_ao_alloc 73 * and custr_ao_free functions must be defined in custr_alloc_ops_t (the 74 * init and fini functions are both optional). If an init function is 75 * provided, it will be called with a va_list parameter initialized to 76 * point to any arguments after the custr_alloc_ops_t * argument. 77 * 78 * If cua_version is not CUSTR_VERSION, or if the custr_ao_alloc or 79 * custr_ao_free functions are missing, -1 is returned and errno is set to 80 * EINVAL. If an init function was given and it fails (returns -1 -- see 81 * the struct custr_alloc_ops definition aboive), -1 is returned and any 82 * value of errno set by the init function is left unchanged. 83 * 84 * On success, 0 is returned. 85 */ 86 int custr_alloc_init(custr_alloc_t *, const custr_alloc_ops_t *, ...); 87 88 /* 89 * If a fini function was given in the custr_alloc_init() call that initalized 90 * the given custr_alloc_t instance, it is called to perform any custom 91 * cleanup needed. 92 */ 93 void custr_alloc_fini(custr_alloc_t *); 94 95 /* 96 * Allocate and free a "custr_t" dynamic string object. Returns 0 on success 97 * and -1 otherwise. 98 */ 99 int custr_alloc(custr_t **); 100 int custr_xalloc(custr_t **, custr_alloc_t *); 101 void custr_free(custr_t *); 102 103 /* 104 * Allocate a "custr_t" dynamic string object that operates on a fixed external 105 * buffer. 106 */ 107 int custr_alloc_buf(custr_t **, void *, size_t); 108 109 /* 110 * Like custr_alloc_buf(), except the given allocator is used to allocate 111 * the custr_t * instance (but still uses a fixed external buffer for the 112 * string contents). 113 */ 114 int custr_xalloc_buf(custr_t **, void *, size_t, custr_alloc_t *); 115 116 /* 117 * Append a single character, or a NUL-terminated string of characters, to a 118 * dynamic string. Returns 0 on success and -1 otherwise. The dynamic string 119 * will be unmodified if the function returns -1. 120 */ 121 int custr_appendc(custr_t *, char); 122 int custr_append(custr_t *, const char *); 123 124 /* 125 * Append a format string and arguments as though the contents were being parsed 126 * through snprintf. Returns 0 on success and -1 otherwise. The dynamic string 127 * will be unmodified if the function returns -1. 128 */ 129 int custr_append_printf(custr_t *, const char *, ...); 130 int custr_append_vprintf(custr_t *, const char *, va_list); 131 132 /* 133 * Determine the length in bytes, not including the NUL terminator, of the 134 * dynamic string. 135 */ 136 size_t custr_len(custr_t *); 137 138 /* 139 * Clear the contents of a dynamic string. Does not free the underlying 140 * memory. 141 */ 142 void custr_reset(custr_t *); 143 144 /* 145 * custr_remove(cus, idx, len) 146 * 147 * Remove len bytes from cus, starting at idx. 148 * 149 * Returns 0 on success or -1 on failure. On failure, errno will be set to: 150 * EINVAL Either the idx or len parameter is invalid 151 * 152 */ 153 int custr_remove(custr_t *, size_t, size_t); 154 155 /* 156 * custr_rremove(cus, idx, len) 157 * 158 * Remove len bytes from cus, starting at idx relative to the end of cus. 159 * That is, 0 = last byte of cus, 1 = second to last byte of cus, ...). 160 * The direction of removal is always towards the end of the string. I.e. 161 * 'custr_rremove(cus, 1, 2)' removes the last two bytes of cus. 162 * 163 * Returns 0 on success or -1 on failure. On failure, errno will be set to: 164 * EINVAL Either the idx or len parameter is invalid 165 * 166 */ 167 int custr_rremove(custr_t *, size_t, size_t); 168 169 /* 170 * custr_trunc(cus, idx) 171 * 172 * Truncate cus starting at idx. 173 * 174 * Returns 0 on success or -1 on failure. On failure, errno is set to: 175 * EINVAL The idx value was invalid. 176 */ 177 int custr_trunc(custr_t *, size_t); 178 179 /* 180 * custr_rtrunc(cus, idx) 181 * 182 * Truncate cus starting at idx relative to the end of cus (similar to how 183 * the idx paramter is treated with custr_rremove()). 184 * 185 * Returns 0 on success or -1 on failure. On failure, errno is set to: 186 * EINVAL The idx value was invalid. 187 */ 188 int custr_rtrunc(custr_t *, size_t); 189 190 /* 191 * Retrieve a const pointer to a NUL-terminated string version of the contents 192 * of the dynamic string. Storage for this string should not be freed, and 193 * the pointer will be invalidated by any mutations to the dynamic string. 194 */ 195 const char *custr_cstr(custr_t *str); 196 197 #ifdef __cplusplus 198 } 199 #endif 200 201 #endif /* _LIBCUSTR_H */ 202