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