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