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);  } | 
