string.c revision 290001
1/* 2 * Copyright (C) 2004-2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2001, 2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id$ */ 19 20/*! \file */ 21 22#include <config.h> 23 24#include <ctype.h> 25 26#include <isc/mem.h> 27#include <isc/print.h> 28#include <isc/region.h> 29#include <isc/string.h> 30#include <isc/util.h> 31 32static char digits[] = "0123456789abcdefghijklmnoprstuvwxyz"; 33 34isc_uint64_t 35isc_string_touint64(char *source, char **end, int base) { 36 isc_uint64_t tmp; 37 isc_uint64_t overflow; 38 char *s = source; 39 char *o; 40 char c; 41 42 if ((base < 0) || (base == 1) || (base > 36)) { 43 *end = source; 44 return (0); 45 } 46 47 while (*s != 0 && isascii(*s&0xff) && isspace(*s&0xff)) 48 s++; 49 if (*s == '+' /* || *s == '-' */) 50 s++; 51 if (base == 0) { 52 if (*s == '0' && (*(s+1) == 'X' || *(s+1) == 'x')) { 53 s += 2; 54 base = 16; 55 } else if (*s == '0') 56 base = 8; 57 else 58 base = 10; 59 } 60 if (*s == 0) { 61 *end = source; 62 return (0); 63 } 64 overflow = ~0; 65 overflow /= base; 66 tmp = 0; 67 68 while ((c = *s) != 0) { 69 c = tolower(c&0xff); 70 /* end ? */ 71 if ((o = strchr(digits, c)) == NULL) { 72 *end = s; 73 return (tmp); 74 } 75 /* end ? */ 76 if ((o - digits) >= base) { 77 *end = s; 78 return (tmp); 79 } 80 /* overflow ? */ 81 if (tmp > overflow) { 82 *end = source; 83 return (0); 84 } 85 tmp *= base; 86 /* overflow ? */ 87 if ((tmp + (o - digits)) < tmp) { 88 *end = source; 89 return (0); 90 } 91 tmp += o - digits; 92 s++; 93 } 94 *end = s; 95 return (tmp); 96} 97 98isc_result_t 99isc_string_copy(char *target, size_t size, const char *source) { 100 REQUIRE(size > 0U); 101 102 if (strlcpy(target, source, size) >= size) { 103 memset(target, ISC_STRING_MAGIC, size); 104 return (ISC_R_NOSPACE); 105 } 106 107 ENSURE(strlen(target) < size); 108 109 return (ISC_R_SUCCESS); 110} 111 112void 113isc_string_copy_truncate(char *target, size_t size, const char *source) { 114 REQUIRE(size > 0U); 115 116 strlcpy(target, source, size); 117 118 ENSURE(strlen(target) < size); 119} 120 121isc_result_t 122isc_string_append(char *target, size_t size, const char *source) { 123 REQUIRE(size > 0U); 124 REQUIRE(strlen(target) < size); 125 126 if (strlcat(target, source, size) >= size) { 127 memset(target, ISC_STRING_MAGIC, size); 128 return (ISC_R_NOSPACE); 129 } 130 131 ENSURE(strlen(target) < size); 132 133 return (ISC_R_SUCCESS); 134} 135 136void 137isc_string_append_truncate(char *target, size_t size, const char *source) { 138 REQUIRE(size > 0U); 139 REQUIRE(strlen(target) < size); 140 141 strlcat(target, source, size); 142 143 ENSURE(strlen(target) < size); 144} 145 146isc_result_t 147isc_string_printf(char *target, size_t size, const char *format, ...) { 148 va_list args; 149 size_t n; 150 151 REQUIRE(size > 0U); 152 153 va_start(args, format); 154 n = vsnprintf(target, size, format, args); 155 va_end(args); 156 157 if (n >= size) { 158 memset(target, ISC_STRING_MAGIC, size); 159 return (ISC_R_NOSPACE); 160 } 161 162 ENSURE(strlen(target) < size); 163 164 return (ISC_R_SUCCESS); 165} 166 167void 168isc_string_printf_truncate(char *target, size_t size, const char *format, ...) 169{ 170 va_list args; 171 172 REQUIRE(size > 0U); 173 174 va_start(args, format); 175 /* check return code? */ 176 (void)vsnprintf(target, size, format, args); 177 va_end(args); 178 179 ENSURE(strlen(target) < size); 180} 181 182char * 183isc_string_regiondup(isc_mem_t *mctx, const isc_region_t *source) { 184 char *target; 185 186 REQUIRE(mctx != NULL); 187 REQUIRE(source != NULL); 188 189 target = (char *) isc_mem_allocate(mctx, source->length + 1); 190 if (target != NULL) { 191 memcpy(source->base, target, source->length); 192 target[source->length] = '\0'; 193 } 194 195 return (target); 196} 197 198char * 199isc_string_separate(char **stringp, const char *delim) { 200 char *string = *stringp; 201 char *s; 202 const char *d; 203 char sc, dc; 204 205 if (string == NULL) 206 return (NULL); 207 208 for (s = string; (sc = *s) != '\0'; s++) 209 for (d = delim; (dc = *d) != '\0'; d++) 210 if (sc == dc) { 211 *s++ = '\0'; 212 *stringp = s; 213 return (string); 214 } 215 *stringp = NULL; 216 return (string); 217} 218 219size_t 220isc_string_strlcpy(char *dst, const char *src, size_t size) 221{ 222 char *d = dst; 223 const char *s = src; 224 size_t n = size; 225 226 /* Copy as many bytes as will fit */ 227 if (n != 0U && --n != 0U) { 228 do { 229 if ((*d++ = *s++) == 0) 230 break; 231 } while (--n != 0U); 232 } 233 234 /* Not enough room in dst, add NUL and traverse rest of src */ 235 if (n == 0U) { 236 if (size != 0U) 237 *d = '\0'; /* NUL-terminate dst */ 238 while (*s++) 239 ; 240 } 241 242 return(s - src - 1); /* count does not include NUL */ 243} 244 245size_t 246isc_string_strlcat(char *dst, const char *src, size_t size) 247{ 248 char *d = dst; 249 const char *s = src; 250 size_t n = size; 251 size_t dlen; 252 253 /* Find the end of dst and adjust bytes left but don't go past end */ 254 while (n-- != 0U && *d != '\0') 255 d++; 256 dlen = d - dst; 257 n = size - dlen; 258 259 if (n == 0U) 260 return(dlen + strlen(s)); 261 while (*s != '\0') { 262 if (n != 1U) { 263 *d++ = *s; 264 n--; 265 } 266 s++; 267 } 268 *d = '\0'; 269 270 return(dlen + (s - src)); /* count does not include NUL */ 271} 272