1 /* $NetBSD: string.c,v 1.6 2014/12/10 04:37:59 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2004-2007, 2011, 2012, 2014 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 /* 21 * Copyright (c) 1990, 1993 22 * The Regents of the University of California. All rights reserved. 23 * 24 * Redistribution and use in source and binary forms, with or without 25 * modification, are permitted provided that the following conditions 26 * are met: 27 * 1. Redistributions of source code must retain the above copyright 28 * notice, this list of conditions and the following disclaimer. 29 * 2. Redistributions in binary form must reproduce the above copyright 30 * notice, this list of conditions and the following disclaimer in the 31 * documentation and/or other materials provided with the distribution. 32 * 3. Neither the name of the University nor the names of its contributors 33 * may be used to endorse or promote products derived from this software 34 * without specific prior written permission. 35 * 36 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 37 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 39 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 40 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 41 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 42 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 44 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 45 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 46 * SUCH DAMAGE. 47 */ 48 49 /*! \file */ 50 51 #include <config.h> 52 53 #include <ctype.h> 54 55 #include <isc/mem.h> 56 #include <isc/print.h> 57 #include <isc/region.h> 58 #include <isc/string.h> 59 #include <isc/util.h> 60 61 static char digits[] = "0123456789abcdefghijklmnoprstuvwxyz"; 62 63 isc_uint64_t 64 isc_string_touint64(char *source, char **end, int base) { 65 isc_uint64_t tmp; 66 isc_uint64_t overflow; 67 char *s = source; 68 char *o; 69 char c; 70 71 if ((base < 0) || (base == 1) || (base > 36)) { 72 *end = source; 73 return (0); 74 } 75 76 while (*s != 0 && isascii(*s&0xff) && isspace(*s&0xff)) 77 s++; 78 if (*s == '+' /* || *s == '-' */) 79 s++; 80 if (base == 0) { 81 if (*s == '0' && (*(s+1) == 'X' || *(s+1) == 'x')) { 82 s += 2; 83 base = 16; 84 } else if (*s == '0') 85 base = 8; 86 else 87 base = 10; 88 } 89 if (*s == 0) { 90 *end = source; 91 return (0); 92 } 93 overflow = ~0; 94 overflow /= base; 95 tmp = 0; 96 97 while ((c = *s) != 0) { 98 c = tolower(c&0xff); 99 /* end ? */ 100 if ((o = strchr(digits, c)) == NULL) { 101 *end = s; 102 return (tmp); 103 } 104 /* end ? */ 105 if ((o - digits) >= base) { 106 *end = s; 107 return (tmp); 108 } 109 /* overflow ? */ 110 if (tmp > overflow) { 111 *end = source; 112 return (0); 113 } 114 tmp *= base; 115 /* overflow ? */ 116 if ((tmp + (o - digits)) < tmp) { 117 *end = source; 118 return (0); 119 } 120 tmp += o - digits; 121 s++; 122 } 123 *end = s; 124 return (tmp); 125 } 126 127 isc_result_t 128 isc_string_copy(char *target, size_t size, const char *source) { 129 REQUIRE(size > 0U); 130 131 if (strlcpy(target, source, size) >= size) { 132 memset(target, ISC_STRING_MAGIC, size); 133 return (ISC_R_NOSPACE); 134 } 135 136 ENSURE(strlen(target) < size); 137 138 return (ISC_R_SUCCESS); 139 } 140 141 void 142 isc_string_copy_truncate(char *target, size_t size, const char *source) { 143 REQUIRE(size > 0U); 144 145 strlcpy(target, source, size); 146 147 ENSURE(strlen(target) < size); 148 } 149 150 isc_result_t 151 isc_string_append(char *target, size_t size, const char *source) { 152 REQUIRE(size > 0U); 153 REQUIRE(strlen(target) < size); 154 155 if (strlcat(target, source, size) >= size) { 156 memset(target, ISC_STRING_MAGIC, size); 157 return (ISC_R_NOSPACE); 158 } 159 160 ENSURE(strlen(target) < size); 161 162 return (ISC_R_SUCCESS); 163 } 164 165 void 166 isc_string_append_truncate(char *target, size_t size, const char *source) { 167 REQUIRE(size > 0U); 168 REQUIRE(strlen(target) < size); 169 170 strlcat(target, source, size); 171 172 ENSURE(strlen(target) < size); 173 } 174 175 isc_result_t 176 isc_string_printf(char *target, size_t size, const char *format, ...) { 177 va_list args; 178 size_t n; 179 180 REQUIRE(size > 0U); 181 182 va_start(args, format); 183 n = vsnprintf(target, size, format, args); 184 va_end(args); 185 186 if (n >= size) { 187 memset(target, ISC_STRING_MAGIC, size); 188 return (ISC_R_NOSPACE); 189 } 190 191 ENSURE(strlen(target) < size); 192 193 return (ISC_R_SUCCESS); 194 } 195 196 void 197 isc_string_printf_truncate(char *target, size_t size, const char *format, ...) 198 { 199 va_list args; 200 201 REQUIRE(size > 0U); 202 203 va_start(args, format); 204 /* check return code? */ 205 (void)vsnprintf(target, size, format, args); 206 va_end(args); 207 208 ENSURE(strlen(target) < size); 209 } 210 211 char * 212 isc_string_regiondup(isc_mem_t *mctx, const isc_region_t *source) { 213 char *target; 214 215 REQUIRE(mctx != NULL); 216 REQUIRE(source != NULL); 217 218 target = (char *) isc_mem_allocate(mctx, source->length + 1); 219 if (target != NULL) { 220 memmove(source->base, target, source->length); 221 target[source->length] = '\0'; 222 } 223 224 return (target); 225 } 226 227 char * 228 isc_string_separate(char **stringp, const char *delim) { 229 char *string = *stringp; 230 char *s; 231 const char *d; 232 char sc, dc; 233 234 if (string == NULL) 235 return (NULL); 236 237 for (s = string; (sc = *s) != '\0'; s++) 238 for (d = delim; (dc = *d) != '\0'; d++) 239 if (sc == dc) { 240 *s++ = '\0'; 241 *stringp = s; 242 return (string); 243 } 244 *stringp = NULL; 245 return (string); 246 } 247 248 size_t 249 isc_string_strlcpy(char *dst, const char *src, size_t size) 250 { 251 char *d = dst; 252 const char *s = src; 253 size_t n = size; 254 255 /* Copy as many bytes as will fit */ 256 if (n != 0U && --n != 0U) { 257 do { 258 if ((*d++ = *s++) == 0) 259 break; 260 } while (--n != 0U); 261 } 262 263 /* Not enough room in dst, add NUL and traverse rest of src */ 264 if (n == 0U) { 265 if (size != 0U) 266 *d = '\0'; /* NUL-terminate dst */ 267 while (*s++) 268 ; 269 } 270 271 return(s - src - 1); /* count does not include NUL */ 272 } 273 274 size_t 275 isc_string_strlcat(char *dst, const char *src, size_t size) 276 { 277 char *d = dst; 278 const char *s = src; 279 size_t n = size; 280 size_t dlen; 281 282 /* Find the end of dst and adjust bytes left but don't go past end */ 283 while (n-- != 0U && *d != '\0') 284 d++; 285 dlen = d - dst; 286 n = size - dlen; 287 288 if (n == 0U) 289 return(dlen + strlen(s)); 290 while (*s != '\0') { 291 if (n != 1U) { 292 *d++ = *s; 293 n--; 294 } 295 s++; 296 } 297 *d = '\0'; 298 299 return(dlen + (s - src)); /* count does not include NUL */ 300 } 301 302 char * 303 isc_string_strcasestr(const char *str, const char *search) { 304 char c, sc, *s; 305 size_t len; 306 307 if ((c = *search++) != 0) { 308 c = tolower((unsigned char) c); 309 len = strlen(search); 310 do { 311 do { 312 if ((sc = *str++) == 0) 313 return (NULL); 314 } while ((char) tolower((unsigned char) sc) != c); 315 } while (strncasecmp(str, search, len) != 0); 316 str--; 317 } 318 DE_CONST(str, s); 319 return (s); 320 321 } 322