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 * String utility functions with dynamic memory management. 14 */ 15 16 /* 17 * Copyright 2014, Joyent, Inc. 18 */ 19 20 #include <stdlib.h> 21 #include <err.h> 22 #include <string.h> 23 24 #include "libcmdutils.h" 25 26 struct custr { 27 size_t cus_strlen; 28 size_t cus_datalen; 29 char *cus_data; 30 }; 31 32 #define STRING_CHUNK_SIZE 64 33 34 void 35 custr_reset(custr_t *cus) 36 { 37 if (cus->cus_data == NULL) 38 return; 39 40 cus->cus_strlen = 0; 41 cus->cus_data[0] = '\0'; 42 } 43 44 size_t 45 custr_len(custr_t *cus) 46 { 47 return (cus->cus_strlen); 48 } 49 50 const char * 51 custr_cstr(custr_t *cus) 52 { 53 return (cus->cus_data); 54 } 55 56 int 57 custr_appendc(custr_t *cus, char newc) 58 { 59 char news[2]; 60 61 news[0] = newc; 62 news[1] = '\0'; 63 64 return (custr_append(cus, news)); 65 } 66 67 int 68 custr_append(custr_t *cus, const char *news) 69 { 70 size_t len = strlen(news); 71 size_t chunksz = STRING_CHUNK_SIZE; 72 73 while (chunksz < len) { 74 chunksz *= 2; 75 } 76 77 if (len + cus->cus_strlen + 1 >= cus->cus_datalen) { 78 char *new_data; 79 size_t new_datalen = cus->cus_datalen + chunksz; 80 81 /* 82 * Allocate replacement memory: 83 */ 84 if ((new_data = malloc(new_datalen)) == NULL) { 85 return (-1); 86 } 87 88 /* 89 * Copy existing data into replacement memory and free 90 * the old memory. 91 */ 92 if (cus->cus_data != NULL) { 93 (void) memcpy(new_data, cus->cus_data, 94 cus->cus_strlen + 1); 95 free(cus->cus_data); 96 } 97 98 /* 99 * Swap in the replacement buffer: 100 */ 101 cus->cus_data = new_data; 102 cus->cus_datalen = new_datalen; 103 } 104 /* 105 * Append new string to existing string: 106 */ 107 (void) memcpy(cus->cus_data + cus->cus_strlen, news, len + 1); 108 cus->cus_strlen += len; 109 110 return (0); 111 } 112 113 int 114 custr_alloc(custr_t **cus) 115 { 116 custr_t *t; 117 118 if ((t = calloc(1, sizeof (*t))) == NULL) { 119 *cus = NULL; 120 return (-1); 121 } 122 123 *cus = t; 124 return (0); 125 } 126 127 void 128 custr_free(custr_t *cus) 129 { 130 if (cus == NULL) 131 return; 132 133 free(cus->cus_data); 134 free(cus); 135 } 136