string.c revision 258945
1258945Sroberto/* 2258945Sroberto * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") 3258945Sroberto * Copyright (C) 1999-2001, 2003 Internet Software Consortium. 4258945Sroberto * 5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any 6258945Sroberto * purpose with or without fee is hereby granted, provided that the above 7258945Sroberto * copyright notice and this permission notice appear in all copies. 8258945Sroberto * 9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11258945Sroberto * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15258945Sroberto * PERFORMANCE OF THIS SOFTWARE. 16258945Sroberto */ 17258945Sroberto 18258945Sroberto/* $Id: string.c,v 1.20 2007/06/19 23:47:17 tbox Exp $ */ 19258945Sroberto 20258945Sroberto/*! \file */ 21258945Sroberto 22258945Sroberto#include <config.h> 23258945Sroberto 24258945Sroberto#include <ctype.h> 25258945Sroberto 26258945Sroberto#include <isc/mem.h> 27258945Sroberto#include <isc/print.h> 28258945Sroberto#include <isc/region.h> 29258945Sroberto#include <isc/string.h> 30258945Sroberto#include <isc/util.h> 31258945Sroberto 32258945Srobertostatic char digits[] = "0123456789abcdefghijklmnoprstuvwxyz"; 33258945Sroberto 34258945Srobertoisc_uint64_t 35258945Srobertoisc_string_touint64(char *source, char **end, int base) { 36258945Sroberto isc_uint64_t tmp; 37258945Sroberto isc_uint64_t overflow; 38258945Sroberto char *s = source; 39258945Sroberto char *o; 40258945Sroberto char c; 41258945Sroberto 42258945Sroberto if ((base < 0) || (base == 1) || (base > 36)) { 43258945Sroberto *end = source; 44258945Sroberto return (0); 45258945Sroberto } 46258945Sroberto 47258945Sroberto while (*s != 0 && isascii(*s&0xff) && isspace(*s&0xff)) 48258945Sroberto s++; 49258945Sroberto if (*s == '+' /* || *s == '-' */) 50258945Sroberto s++; 51258945Sroberto if (base == 0) { 52258945Sroberto if (*s == '0' && (*(s+1) == 'X' || *(s+1) == 'x')) { 53258945Sroberto s += 2; 54258945Sroberto base = 16; 55258945Sroberto } else if (*s == '0') 56258945Sroberto base = 8; 57258945Sroberto else 58258945Sroberto base = 10; 59258945Sroberto } 60258945Sroberto if (*s == 0) { 61258945Sroberto *end = source; 62258945Sroberto return (0); 63258945Sroberto } 64258945Sroberto overflow = ~0; 65258945Sroberto overflow /= base; 66258945Sroberto tmp = 0; 67258945Sroberto 68258945Sroberto while ((c = *s) != 0) { 69258945Sroberto c = tolower(c&0xff); 70258945Sroberto /* end ? */ 71258945Sroberto if ((o = strchr(digits, c)) == NULL) { 72258945Sroberto *end = s; 73258945Sroberto return (tmp); 74258945Sroberto } 75258945Sroberto /* end ? */ 76258945Sroberto if ((o - digits) >= base) { 77258945Sroberto *end = s; 78258945Sroberto return (tmp); 79258945Sroberto } 80258945Sroberto /* overflow ? */ 81258945Sroberto if (tmp > overflow) { 82258945Sroberto *end = source; 83258945Sroberto return (0); 84258945Sroberto } 85258945Sroberto tmp *= base; 86258945Sroberto /* overflow ? */ 87258945Sroberto if ((tmp + (o - digits)) < tmp) { 88258945Sroberto *end = source; 89258945Sroberto return (0); 90258945Sroberto } 91258945Sroberto tmp += o - digits; 92258945Sroberto s++; 93258945Sroberto } 94258945Sroberto *end = s; 95258945Sroberto return (tmp); 96258945Sroberto} 97258945Sroberto 98258945Srobertoisc_result_t 99258945Srobertoisc_string_copy(char *target, size_t size, const char *source) { 100258945Sroberto REQUIRE(size > 0U); 101258945Sroberto 102258945Sroberto if (strlcpy(target, source, size) >= size) { 103258945Sroberto memset(target, ISC_STRING_MAGIC, size); 104258945Sroberto return (ISC_R_NOSPACE); 105258945Sroberto } 106258945Sroberto 107258945Sroberto ENSURE(strlen(target) < size); 108258945Sroberto 109258945Sroberto return (ISC_R_SUCCESS); 110258945Sroberto} 111258945Sroberto 112258945Srobertovoid 113258945Srobertoisc_string_copy_truncate(char *target, size_t size, const char *source) { 114258945Sroberto REQUIRE(size > 0U); 115258945Sroberto 116258945Sroberto strlcpy(target, source, size); 117258945Sroberto 118258945Sroberto ENSURE(strlen(target) < size); 119258945Sroberto} 120258945Sroberto 121258945Srobertoisc_result_t 122258945Srobertoisc_string_append(char *target, size_t size, const char *source) { 123258945Sroberto REQUIRE(size > 0U); 124258945Sroberto REQUIRE(strlen(target) < size); 125258945Sroberto 126258945Sroberto if (strlcat(target, source, size) >= size) { 127258945Sroberto memset(target, ISC_STRING_MAGIC, size); 128258945Sroberto return (ISC_R_NOSPACE); 129258945Sroberto } 130258945Sroberto 131258945Sroberto ENSURE(strlen(target) < size); 132258945Sroberto 133258945Sroberto return (ISC_R_SUCCESS); 134258945Sroberto} 135258945Sroberto 136258945Srobertovoid 137258945Srobertoisc_string_append_truncate(char *target, size_t size, const char *source) { 138258945Sroberto REQUIRE(size > 0U); 139258945Sroberto REQUIRE(strlen(target) < size); 140258945Sroberto 141258945Sroberto strlcat(target, source, size); 142258945Sroberto 143258945Sroberto ENSURE(strlen(target) < size); 144258945Sroberto} 145258945Sroberto 146258945Srobertoisc_result_t 147258945Srobertoisc_string_printf(char *target, size_t size, const char *format, ...) { 148258945Sroberto va_list args; 149258945Sroberto size_t n; 150258945Sroberto 151258945Sroberto REQUIRE(size > 0U); 152258945Sroberto 153258945Sroberto va_start(args, format); 154258945Sroberto n = vsnprintf(target, size, format, args); 155258945Sroberto va_end(args); 156258945Sroberto 157258945Sroberto if (n >= size) { 158258945Sroberto memset(target, ISC_STRING_MAGIC, size); 159258945Sroberto return (ISC_R_NOSPACE); 160258945Sroberto } 161258945Sroberto 162258945Sroberto ENSURE(strlen(target) < size); 163258945Sroberto 164258945Sroberto return (ISC_R_SUCCESS); 165258945Sroberto} 166258945Sroberto 167258945Srobertovoid 168258945Srobertoisc_string_printf_truncate(char *target, size_t size, const char *format, ...) { 169258945Sroberto va_list args; 170258945Sroberto size_t n; 171258945Sroberto 172258945Sroberto REQUIRE(size > 0U); 173258945Sroberto 174258945Sroberto va_start(args, format); 175258945Sroberto n = vsnprintf(target, size, format, args); 176258945Sroberto va_end(args); 177258945Sroberto 178258945Sroberto ENSURE(strlen(target) < size); 179258945Sroberto} 180258945Sroberto 181258945Srobertochar * 182258945Srobertoisc_string_regiondup(isc_mem_t *mctx, const isc_region_t *source) { 183258945Sroberto char *target; 184258945Sroberto 185258945Sroberto REQUIRE(mctx != NULL); 186258945Sroberto REQUIRE(source != NULL); 187258945Sroberto 188258945Sroberto target = (char *) isc_mem_allocate(mctx, source->length + 1); 189258945Sroberto if (target != NULL) { 190258945Sroberto memcpy(source->base, target, source->length); 191258945Sroberto target[source->length] = '\0'; 192258945Sroberto } 193258945Sroberto 194258945Sroberto return (target); 195258945Sroberto} 196258945Sroberto 197258945Srobertochar * 198258945Srobertoisc_string_separate(char **stringp, const char *delim) { 199258945Sroberto char *string = *stringp; 200258945Sroberto char *s; 201258945Sroberto const char *d; 202258945Sroberto char sc, dc; 203258945Sroberto 204258945Sroberto if (string == NULL) 205258945Sroberto return (NULL); 206258945Sroberto 207258945Sroberto for (s = string; (sc = *s) != '\0'; s++) 208258945Sroberto for (d = delim; (dc = *d) != '\0'; d++) 209258945Sroberto if (sc == dc) { 210258945Sroberto *s++ = '\0'; 211258945Sroberto *stringp = s; 212258945Sroberto return (string); 213258945Sroberto } 214258945Sroberto *stringp = NULL; 215258945Sroberto return (string); 216258945Sroberto} 217258945Sroberto 218258945Srobertosize_t 219258945Srobertoisc_string_strlcpy(char *dst, const char *src, size_t size) 220258945Sroberto{ 221258945Sroberto char *d = dst; 222258945Sroberto const char *s = src; 223258945Sroberto size_t n = size; 224258945Sroberto 225258945Sroberto /* Copy as many bytes as will fit */ 226258945Sroberto if (n != 0U && --n != 0U) { 227258945Sroberto do { 228258945Sroberto if ((*d++ = *s++) == 0) 229258945Sroberto break; 230258945Sroberto } while (--n != 0U); 231258945Sroberto } 232258945Sroberto 233258945Sroberto /* Not enough room in dst, add NUL and traverse rest of src */ 234258945Sroberto if (n == 0U) { 235258945Sroberto if (size != 0U) 236258945Sroberto *d = '\0'; /* NUL-terminate dst */ 237258945Sroberto while (*s++) 238258945Sroberto ; 239258945Sroberto } 240258945Sroberto 241258945Sroberto return(s - src - 1); /* count does not include NUL */ 242258945Sroberto} 243258945Sroberto 244258945Srobertosize_t 245258945Srobertoisc_string_strlcat(char *dst, const char *src, size_t size) 246258945Sroberto{ 247258945Sroberto char *d = dst; 248258945Sroberto const char *s = src; 249258945Sroberto size_t n = size; 250258945Sroberto size_t dlen; 251258945Sroberto 252258945Sroberto /* Find the end of dst and adjust bytes left but don't go past end */ 253258945Sroberto while (n-- != 0U && *d != '\0') 254258945Sroberto d++; 255258945Sroberto dlen = d - dst; 256258945Sroberto n = size - dlen; 257258945Sroberto 258258945Sroberto if (n == 0U) 259258945Sroberto return(dlen + strlen(s)); 260258945Sroberto while (*s != '\0') { 261258945Sroberto if (n != 1U) { 262258945Sroberto *d++ = *s; 263258945Sroberto n--; 264258945Sroberto } 265258945Sroberto s++; 266258945Sroberto } 267258945Sroberto *d = '\0'; 268258945Sroberto 269258945Sroberto return(dlen + (s - src)); /* count does not include NUL */ 270258945Sroberto} 271