/* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2019 Joyent, Inc. */ #ifndef _LIBCUSTR_H #define _LIBCUSTR_H #include #include /* dynamic string utilities */ #ifdef __cplusplus extern "C" { #endif typedef struct custr custr_t; typedef struct custr_alloc_ops custr_alloc_ops_t; typedef struct custr_alloc custr_alloc_t; /* * A custom allocator instance. To use a custom allocator, the user provides * the memory for a given custr_alloc_t and calls custr_alloc_init() with the * address of the instance to initialize it. custr_alloc_init() will invoke * the init op (if defined) with any additional arguments. The user can then * save any desired state for the allocator instance in cua_arg. If a * custom allocator instance needs to do any cleanup after it's no longer * needed, it should also define the fini op and invoke custr_alloc_fini() to * do the cleanup. */ #define CUSTR_VERSION 1 struct custr_alloc { uint_t cua_version; const custr_alloc_ops_t *cua_ops; void *cua_arg; }; struct custr_alloc_ops { /* * Optional allocator constructor. Returns 0 on success, -1 * on failure (and should set errno on failure). */ int (*custr_ao_init)(custr_alloc_t *, va_list); /* * Optional allocator destructor. */ void (*custr_ao_fini)(custr_alloc_t *); /* * Returns at least size_t bytes of allocated memory, or NULL. * It should also set errno on failure. */ void *(*custr_ao_alloc)(custr_alloc_t *, size_t); /* * Free the memory previously allocated with custr_ao_alloc. */ void (*custr_ao_free)(custr_alloc_t *, void *, size_t); }; /* * Initializes a custr allocator. custr_alloc_t->cua_version should be set to * CUSTR_VERSION prior to calling custr_alloc_init(). Both the custr_ao_alloc * and custr_ao_free functions must be defined in custr_alloc_ops_t (the * init and fini functions are both optional). If an init function is * provided, it will be called with a va_list parameter initialized to * point to any arguments after the custr_alloc_ops_t * argument. * * If cua_version is not CUSTR_VERSION, or if the custr_ao_alloc or * custr_ao_free functions are missing, -1 is returned and errno is set to * EINVAL. If an init function was given and it fails (returns -1 -- see * the struct custr_alloc_ops definition aboive), -1 is returned and any * value of errno set by the init function is left unchanged. * * On success, 0 is returned. */ int custr_alloc_init(custr_alloc_t *, const custr_alloc_ops_t *, ...); /* * If a fini function was given in the custr_alloc_init() call that initalized * the given custr_alloc_t instance, it is called to perform any custom * cleanup needed. */ void custr_alloc_fini(custr_alloc_t *); /* * Allocate and free a "custr_t" dynamic string object. Returns 0 on success * and -1 otherwise. */ int custr_alloc(custr_t **); int custr_xalloc(custr_t **, custr_alloc_t *); void custr_free(custr_t *); /* * Allocate a "custr_t" dynamic string object that operates on a fixed external * buffer. */ int custr_alloc_buf(custr_t **, void *, size_t); /* * Like custr_alloc_buf(), except the given allocator is used to allocate * the custr_t * instance (but still uses a fixed external buffer for the * string contents). */ int custr_xalloc_buf(custr_t **, void *, size_t, custr_alloc_t *); /* * Append a single character, or a NUL-terminated string of characters, to a * dynamic string. Returns 0 on success and -1 otherwise. The dynamic string * will be unmodified if the function returns -1. */ int custr_appendc(custr_t *, char); int custr_append(custr_t *, const char *); /* * Append a format string and arguments as though the contents were being parsed * through snprintf. Returns 0 on success and -1 otherwise. The dynamic string * will be unmodified if the function returns -1. */ int custr_append_printf(custr_t *, const char *, ...); int custr_append_vprintf(custr_t *, const char *, va_list); /* * Determine the length in bytes, not including the NUL terminator, of the * dynamic string. */ size_t custr_len(custr_t *); /* * Clear the contents of a dynamic string. Does not free the underlying * memory. */ void custr_reset(custr_t *); /* * custr_remove(cus, idx, len) * * Remove len bytes from cus, starting at idx. * * Returns 0 on success or -1 on failure. On failure, errno will be set to: * EINVAL Either the idx or len parameter is invalid * */ int custr_remove(custr_t *, size_t, size_t); /* * custr_rremove(cus, idx, len) * * Remove len bytes from cus, starting at idx relative to the end of cus. * That is, 0 = last byte of cus, 1 = second to last byte of cus, ...). * The direction of removal is always towards the end of the string. I.e. * 'custr_rremove(cus, 1, 2)' removes the last two bytes of cus. * * Returns 0 on success or -1 on failure. On failure, errno will be set to: * EINVAL Either the idx or len parameter is invalid * */ int custr_rremove(custr_t *, size_t, size_t); /* * custr_trunc(cus, idx) * * Truncate cus starting at idx. * * Returns 0 on success or -1 on failure. On failure, errno is set to: * EINVAL The idx value was invalid. */ int custr_trunc(custr_t *, size_t); /* * custr_rtrunc(cus, idx) * * Truncate cus starting at idx relative to the end of cus (similar to how * the idx paramter is treated with custr_rremove()). * * Returns 0 on success or -1 on failure. On failure, errno is set to: * EINVAL The idx value was invalid. */ int custr_rtrunc(custr_t *, size_t); /* * Retrieve a const pointer to a NUL-terminated string version of the contents * of the dynamic string. Storage for this string should not be freed, and * the pointer will be invalidated by any mutations to the dynamic string. */ const char *custr_cstr(custr_t *str); #ifdef __cplusplus } #endif #endif /* _LIBCUSTR_H */