176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ----------------------------------------------------------------------- * 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright 2008 H. Peter Anvin - All Rights Reserved 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program is free software; you can redistribute it and/or modify 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * it under the terms of the GNU General Public License as published by 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Boston MA 02110-1301, USA; either version 2 of the License, or 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * (at your option) any later version; incorporated herein by reference. 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ----------------------------------------------------------------------- */ 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * refstr.c 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Simple reference-counted strings 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdlib.h> 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h> 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdio.h> 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "refstr.h" 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Allocate space for a refstring of len bytes, plus final null */ 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* The final null is inserted in the string; the rest is uninitialized. */ 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanchar *refstr_alloc(size_t len) 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char *r = malloc(sizeof(unsigned int) + len + 1); 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!r) 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return NULL; 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *(unsigned int *)r = 1; 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman r += sizeof(unsigned int); 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman r[len] = '\0'; 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return r; 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanconst char *refstrndup(const char *str, size_t len) 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char *r; 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!str) 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return NULL; 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len = strnlen(str, len); 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman r = refstr_alloc(len); 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (r) 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(r, str, len); 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return r; 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanconst char *refstrdup(const char *str) 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char *r; 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman size_t len; 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!str) 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return NULL; 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len = strlen(str); 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman r = refstr_alloc(len); 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (r) 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(r, str, len); 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return r; 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint vrsprintf(const char **bufp, const char *fmt, va_list ap) 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman va_list ap1; 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int len; 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char *p; 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman va_copy(ap1, ap); 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len = vsnprintf(NULL, 0, fmt, ap1); 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman va_end(ap1); 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *bufp = p = refstr_alloc(len); 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!p) 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return vsnprintf(p, len + 1, fmt, ap); 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint rsprintf(const char **bufp, const char *fmt, ...) 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int rv; 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman va_list ap; 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman va_start(ap, fmt); 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rv = vrsprintf(bufp, fmt, ap); 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman va_end(ap); 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return rv; 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid refstr_put(const char *r) 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int *ref; 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (r) { 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ref = (unsigned int *)r - 1; 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!--*ref) 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman free(ref); 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 106