1258945Sroberto/* 2280849Scy * Copyright (C) 2004-2007, 2011, 2012 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 18280849Scy/* $Id$ */ 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 168280849Scyisc_string_printf_truncate(char *target, size_t size, const char *format, ...) 169280849Scy{ 170258945Sroberto va_list args; 171258945Sroberto 172258945Sroberto REQUIRE(size > 0U); 173258945Sroberto 174258945Sroberto va_start(args, format); 175280849Scy /* check return code? */ 176280849Scy (void)vsnprintf(target, size, format, args); 177258945Sroberto va_end(args); 178258945Sroberto 179258945Sroberto ENSURE(strlen(target) < size); 180258945Sroberto} 181258945Sroberto 182258945Srobertochar * 183258945Srobertoisc_string_regiondup(isc_mem_t *mctx, const isc_region_t *source) { 184258945Sroberto char *target; 185258945Sroberto 186258945Sroberto REQUIRE(mctx != NULL); 187258945Sroberto REQUIRE(source != NULL); 188258945Sroberto 189258945Sroberto target = (char *) isc_mem_allocate(mctx, source->length + 1); 190258945Sroberto if (target != NULL) { 191258945Sroberto memcpy(source->base, target, source->length); 192258945Sroberto target[source->length] = '\0'; 193258945Sroberto } 194258945Sroberto 195258945Sroberto return (target); 196258945Sroberto} 197258945Sroberto 198258945Srobertochar * 199258945Srobertoisc_string_separate(char **stringp, const char *delim) { 200258945Sroberto char *string = *stringp; 201258945Sroberto char *s; 202258945Sroberto const char *d; 203258945Sroberto char sc, dc; 204258945Sroberto 205258945Sroberto if (string == NULL) 206258945Sroberto return (NULL); 207258945Sroberto 208258945Sroberto for (s = string; (sc = *s) != '\0'; s++) 209258945Sroberto for (d = delim; (dc = *d) != '\0'; d++) 210258945Sroberto if (sc == dc) { 211258945Sroberto *s++ = '\0'; 212258945Sroberto *stringp = s; 213258945Sroberto return (string); 214258945Sroberto } 215258945Sroberto *stringp = NULL; 216258945Sroberto return (string); 217258945Sroberto} 218258945Sroberto 219258945Srobertosize_t 220258945Srobertoisc_string_strlcpy(char *dst, const char *src, size_t size) 221258945Sroberto{ 222258945Sroberto char *d = dst; 223258945Sroberto const char *s = src; 224258945Sroberto size_t n = size; 225258945Sroberto 226258945Sroberto /* Copy as many bytes as will fit */ 227258945Sroberto if (n != 0U && --n != 0U) { 228258945Sroberto do { 229258945Sroberto if ((*d++ = *s++) == 0) 230258945Sroberto break; 231258945Sroberto } while (--n != 0U); 232258945Sroberto } 233258945Sroberto 234258945Sroberto /* Not enough room in dst, add NUL and traverse rest of src */ 235258945Sroberto if (n == 0U) { 236258945Sroberto if (size != 0U) 237258945Sroberto *d = '\0'; /* NUL-terminate dst */ 238258945Sroberto while (*s++) 239258945Sroberto ; 240258945Sroberto } 241258945Sroberto 242258945Sroberto return(s - src - 1); /* count does not include NUL */ 243258945Sroberto} 244258945Sroberto 245258945Srobertosize_t 246258945Srobertoisc_string_strlcat(char *dst, const char *src, size_t size) 247258945Sroberto{ 248258945Sroberto char *d = dst; 249258945Sroberto const char *s = src; 250258945Sroberto size_t n = size; 251258945Sroberto size_t dlen; 252258945Sroberto 253258945Sroberto /* Find the end of dst and adjust bytes left but don't go past end */ 254258945Sroberto while (n-- != 0U && *d != '\0') 255258945Sroberto d++; 256258945Sroberto dlen = d - dst; 257258945Sroberto n = size - dlen; 258258945Sroberto 259258945Sroberto if (n == 0U) 260258945Sroberto return(dlen + strlen(s)); 261258945Sroberto while (*s != '\0') { 262258945Sroberto if (n != 1U) { 263258945Sroberto *d++ = *s; 264258945Sroberto n--; 265258945Sroberto } 266258945Sroberto s++; 267258945Sroberto } 268258945Sroberto *d = '\0'; 269258945Sroberto 270258945Sroberto return(dlen + (s - src)); /* count does not include NUL */ 271258945Sroberto} 272