diff options
Diffstat (limited to 'usr/src/lib/libcustr/common/custr.c')
-rw-r--r-- | usr/src/lib/libcustr/common/custr.c | 120 |
1 files changed, 111 insertions, 9 deletions
diff --git a/usr/src/lib/libcustr/common/custr.c b/usr/src/lib/libcustr/common/custr.c index 5c5b0e370a..6d3a003e6b 100644 --- a/usr/src/lib/libcustr/common/custr.c +++ b/usr/src/lib/libcustr/common/custr.c @@ -14,7 +14,7 @@ */ /* - * Copyright 2018 Joyent, Inc. + * Copyright 2019 Joyent, Inc. */ #include <stdlib.h> @@ -27,6 +27,19 @@ #include "libcustr.h" +/* + * libcustr is used by some things in usr/src/tools. If we are building + * on an older platform, __unused might not be defined on the build host. + * We define it here if needed. + */ +#ifndef __unused +#if __GNUC_VERSION >= 20700 +#define __unused __attribute__((_unused__)) +#else +#define __unused +#endif /* __GNUC_VERSION */ +#endif /* __unused */ + typedef enum { CUSTR_FIXEDBUF = 0x01 } custr_flags_t; @@ -36,10 +49,32 @@ struct custr { size_t cus_datalen; char *cus_data; custr_flags_t cus_flags; + custr_alloc_t *cus_alloc; }; +#define CUSTR_ALLOC(_cus, _len) \ + (_cus)->cus_alloc->cua_ops->custr_ao_alloc((_cus)->cus_alloc, (_len)) +#define CUSTR_FREE(_cus, _p, _len) \ + (_cus)->cus_alloc->cua_ops->custr_ao_free((_cus)->cus_alloc, \ + (_p), (_len)) #define STRING_CHUNK_SIZE 64 +static void *custr_def_alloc(custr_alloc_t *, size_t); +static void custr_def_free(custr_alloc_t *, void *, size_t); + +static custr_alloc_ops_t custr_alloc_ops_default = { + NULL, /* custr_ao_init */ + NULL, /* custr_ao_fini */ + custr_def_alloc, /* custr_ao_alloc */ + custr_def_free /* custr_ao_free */ +}; + +static custr_alloc_t custr_alloc_default = { + CUSTR_VERSION, /* cua_version */ + &custr_alloc_ops_default, /* cua_ops */ + NULL /* cua_arg */ +}; + void custr_reset(custr_t *cus) { @@ -97,7 +132,7 @@ custr_append_vprintf(custr_t *cus, const char *fmt, va_list ap) /* * Allocate replacement memory: */ - if ((new_data = malloc(new_datalen)) == NULL) { + if ((new_data = CUSTR_ALLOC(cus, new_datalen)) == NULL) { return (-1); } @@ -108,7 +143,7 @@ custr_append_vprintf(custr_t *cus, const char *fmt, va_list ap) if (cus->cus_data != NULL) { (void) memcpy(new_data, cus->cus_data, cus->cus_strlen + 1); - free(cus->cus_data); + CUSTR_FREE(cus, cus->cus_data, cus->cus_datalen); } /* @@ -155,21 +190,64 @@ custr_append(custr_t *cus, const char *name) } int -custr_alloc(custr_t **cus) +custr_alloc_init(custr_alloc_t *cua, const custr_alloc_ops_t *ops, ...) +{ + int ret = 0; + + if (cua->cua_version != CUSTR_VERSION || ops->custr_ao_alloc == NULL || + ops->custr_ao_free == NULL) { + errno = EINVAL; + return (-1); + } + + cua->cua_ops = ops; + cua->cua_arg = NULL; + + if (ops->custr_ao_init != NULL) { + va_list ap; + + va_start(ap, ops); + ret = ops->custr_ao_init(cua, ap); + va_end(ap); + } + + return ((ret == 0) ? 0 : -1); +} + +void +custr_alloc_fini(custr_alloc_t *cua) +{ + if (cua->cua_ops->custr_ao_fini != NULL) + cua->cua_ops->custr_ao_fini(cua); +} + +int +custr_xalloc(custr_t **cus, custr_alloc_t *cao) { custr_t *t; - if ((t = calloc(1, sizeof (*t))) == NULL) { + if (cao == NULL) + cao = &custr_alloc_default; + + if ((t = cao->cua_ops->custr_ao_alloc(cao, sizeof (*t))) == NULL) { *cus = NULL; return (-1); } + (void) memset(t, 0, sizeof (*t)); + t->cus_alloc = cao; *cus = t; return (0); } int -custr_alloc_buf(custr_t **cus, void *buf, size_t buflen) +custr_alloc(custr_t **cus) +{ + return (custr_xalloc(cus, NULL)); +} + +int +custr_xalloc_buf(custr_t **cus, void *buf, size_t buflen, custr_alloc_t *cao) { int ret; @@ -178,7 +256,7 @@ custr_alloc_buf(custr_t **cus, void *buf, size_t buflen) return (-1); } - if ((ret = custr_alloc(cus)) != 0) + if ((ret = custr_xalloc(cus, cao)) != 0) return (ret); (*cus)->cus_data = buf; @@ -190,13 +268,37 @@ custr_alloc_buf(custr_t **cus, void *buf, size_t buflen) return (0); } +int +custr_alloc_buf(custr_t **cus, void *buf, size_t buflen) +{ + return (custr_xalloc_buf(cus, buf, buflen, NULL)); +} + void custr_free(custr_t *cus) { + custr_alloc_t *cao; + if (cus == NULL) return; if ((cus->cus_flags & CUSTR_FIXEDBUF) == 0) - free(cus->cus_data); - free(cus); + CUSTR_FREE(cus, cus->cus_data, cus->cus_datalen); + + cao = cus->cus_alloc; + cao->cua_ops->custr_ao_free(cao, cus, sizeof (*cus)); +} + +/*ARGSUSED*/ +static void * +custr_def_alloc(custr_alloc_t *cao __unused, size_t len) +{ + return (malloc(len)); +} + +/*ARGSUSED*/ +static void +custr_def_free(custr_alloc_t *cao __unused, void *p, size_t len __unused) +{ + free(p); } |