1135446Strhodes/*
2262706Serwin * Copyright (C) 2004-2007, 2011, 2012, 2014  Internet Systems Consortium, Inc. ("ISC")
3135446Strhodes * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
4135446Strhodes *
5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any
6135446Strhodes * purpose with or without fee is hereby granted, provided that the above
7135446Strhodes * copyright notice and this permission notice appear in all copies.
8135446Strhodes *
9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11135446Strhodes * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15135446Strhodes * PERFORMANCE OF THIS SOFTWARE.
16135446Strhodes */
17135446Strhodes
18262706Serwin/*
19262706Serwin * Copyright (c) 1990, 1993
20262706Serwin *	The Regents of the University of California.  All rights reserved.
21262706Serwin *
22262706Serwin * Redistribution and use in source and binary forms, with or without
23262706Serwin * modification, are permitted provided that the following conditions
24262706Serwin * are met:
25262706Serwin * 1. Redistributions of source code must retain the above copyright
26262706Serwin *    notice, this list of conditions and the following disclaimer.
27262706Serwin * 2. Redistributions in binary form must reproduce the above copyright
28262706Serwin *    notice, this list of conditions and the following disclaimer in the
29262706Serwin *    documentation and/or other materials provided with the distribution.
30262706Serwin * 3. Neither the name of the University nor the names of its contributors
31262706Serwin *    may be used to endorse or promote products derived from this software
32262706Serwin *    without specific prior written permission.
33262706Serwin *
34262706Serwin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
35262706Serwin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36262706Serwin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37262706Serwin * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38262706Serwin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39262706Serwin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40262706Serwin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41262706Serwin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42262706Serwin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43262706Serwin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44262706Serwin * SUCH DAMAGE.
45262706Serwin */
46135446Strhodes
47170222Sdougb/*! \file */
48170222Sdougb
49135446Strhodes#include <config.h>
50135446Strhodes
51135446Strhodes#include <ctype.h>
52135446Strhodes
53170222Sdougb#include <isc/mem.h>
54170222Sdougb#include <isc/print.h>
55170222Sdougb#include <isc/region.h>
56135446Strhodes#include <isc/string.h>
57170222Sdougb#include <isc/util.h>
58135446Strhodes
59135446Strhodesstatic char digits[] = "0123456789abcdefghijklmnoprstuvwxyz";
60135446Strhodes
61135446Strhodesisc_uint64_t
62135446Strhodesisc_string_touint64(char *source, char **end, int base) {
63135446Strhodes	isc_uint64_t tmp;
64135446Strhodes	isc_uint64_t overflow;
65135446Strhodes	char *s = source;
66135446Strhodes	char *o;
67135446Strhodes	char c;
68135446Strhodes
69135446Strhodes	if ((base < 0) || (base == 1) || (base > 36)) {
70135446Strhodes		*end = source;
71135446Strhodes		return (0);
72135446Strhodes	}
73135446Strhodes
74135446Strhodes	while (*s != 0 && isascii(*s&0xff) && isspace(*s&0xff))
75135446Strhodes		s++;
76135446Strhodes	if (*s == '+' /* || *s == '-' */)
77135446Strhodes		s++;
78135446Strhodes	if (base == 0) {
79135446Strhodes		if (*s == '0' && (*(s+1) == 'X' || *(s+1) == 'x')) {
80135446Strhodes			s += 2;
81135446Strhodes			base = 16;
82135446Strhodes		} else if (*s == '0')
83135446Strhodes			base = 8;
84135446Strhodes		else
85135446Strhodes			base = 10;
86135446Strhodes	}
87135446Strhodes	if (*s == 0) {
88135446Strhodes		*end = source;
89135446Strhodes		return (0);
90135446Strhodes	}
91135446Strhodes	overflow = ~0;
92135446Strhodes	overflow /= base;
93135446Strhodes	tmp = 0;
94135446Strhodes
95135446Strhodes	while ((c = *s) != 0) {
96143731Sdougb		c = tolower(c&0xff);
97135446Strhodes		/* end ? */
98135446Strhodes		if ((o = strchr(digits, c)) == NULL) {
99135446Strhodes			*end = s;
100135446Strhodes			return (tmp);
101135446Strhodes		}
102135446Strhodes		/* end ? */
103135446Strhodes		if ((o - digits) >= base) {
104135446Strhodes			*end = s;
105135446Strhodes			return (tmp);
106135446Strhodes		}
107135446Strhodes		/* overflow ? */
108135446Strhodes		if (tmp > overflow) {
109135446Strhodes			*end = source;
110135446Strhodes			return (0);
111135446Strhodes		}
112135446Strhodes		tmp *= base;
113135446Strhodes		/* overflow ? */
114135446Strhodes		if ((tmp + (o - digits)) < tmp) {
115135446Strhodes			*end = source;
116135446Strhodes			return (0);
117135446Strhodes		}
118135446Strhodes		tmp += o - digits;
119135446Strhodes		s++;
120135446Strhodes	}
121135446Strhodes	*end = s;
122135446Strhodes	return (tmp);
123135446Strhodes}
124135446Strhodes
125170222Sdougbisc_result_t
126170222Sdougbisc_string_copy(char *target, size_t size, const char *source) {
127170222Sdougb	REQUIRE(size > 0U);
128170222Sdougb
129170222Sdougb	if (strlcpy(target, source, size) >= size) {
130170222Sdougb		memset(target, ISC_STRING_MAGIC, size);
131170222Sdougb		return (ISC_R_NOSPACE);
132170222Sdougb	}
133170222Sdougb
134170222Sdougb	ENSURE(strlen(target) < size);
135170222Sdougb
136170222Sdougb	return (ISC_R_SUCCESS);
137170222Sdougb}
138170222Sdougb
139170222Sdougbvoid
140170222Sdougbisc_string_copy_truncate(char *target, size_t size, const char *source) {
141170222Sdougb	REQUIRE(size > 0U);
142170222Sdougb
143170222Sdougb	strlcpy(target, source, size);
144170222Sdougb
145170222Sdougb	ENSURE(strlen(target) < size);
146170222Sdougb}
147170222Sdougb
148170222Sdougbisc_result_t
149170222Sdougbisc_string_append(char *target, size_t size, const char *source) {
150170222Sdougb	REQUIRE(size > 0U);
151170222Sdougb	REQUIRE(strlen(target) < size);
152170222Sdougb
153170222Sdougb	if (strlcat(target, source, size) >= size) {
154170222Sdougb		memset(target, ISC_STRING_MAGIC, size);
155170222Sdougb		return (ISC_R_NOSPACE);
156170222Sdougb	}
157170222Sdougb
158170222Sdougb	ENSURE(strlen(target) < size);
159170222Sdougb
160170222Sdougb	return (ISC_R_SUCCESS);
161170222Sdougb}
162170222Sdougb
163170222Sdougbvoid
164170222Sdougbisc_string_append_truncate(char *target, size_t size, const char *source) {
165170222Sdougb	REQUIRE(size > 0U);
166170222Sdougb	REQUIRE(strlen(target) < size);
167170222Sdougb
168170222Sdougb	strlcat(target, source, size);
169170222Sdougb
170170222Sdougb	ENSURE(strlen(target) < size);
171170222Sdougb}
172170222Sdougb
173170222Sdougbisc_result_t
174170222Sdougbisc_string_printf(char *target, size_t size, const char *format, ...) {
175170222Sdougb	va_list args;
176170222Sdougb	size_t n;
177170222Sdougb
178170222Sdougb	REQUIRE(size > 0U);
179170222Sdougb
180170222Sdougb	va_start(args, format);
181170222Sdougb	n = vsnprintf(target, size, format, args);
182170222Sdougb	va_end(args);
183170222Sdougb
184170222Sdougb	if (n >= size) {
185170222Sdougb		memset(target, ISC_STRING_MAGIC, size);
186170222Sdougb		return (ISC_R_NOSPACE);
187170222Sdougb	}
188170222Sdougb
189170222Sdougb	ENSURE(strlen(target) < size);
190170222Sdougb
191170222Sdougb	return (ISC_R_SUCCESS);
192170222Sdougb}
193170222Sdougb
194170222Sdougbvoid
195225361Sdougbisc_string_printf_truncate(char *target, size_t size, const char *format, ...)
196225361Sdougb{
197170222Sdougb	va_list args;
198170222Sdougb
199170222Sdougb	REQUIRE(size > 0U);
200170222Sdougb
201170222Sdougb	va_start(args, format);
202225361Sdougb	/* check return code? */
203225361Sdougb	(void)vsnprintf(target, size, format, args);
204170222Sdougb	va_end(args);
205170222Sdougb
206170222Sdougb	ENSURE(strlen(target) < size);
207170222Sdougb}
208170222Sdougb
209135446Strhodeschar *
210170222Sdougbisc_string_regiondup(isc_mem_t *mctx, const isc_region_t *source) {
211170222Sdougb	char *target;
212170222Sdougb
213170222Sdougb	REQUIRE(mctx != NULL);
214170222Sdougb	REQUIRE(source != NULL);
215170222Sdougb
216170222Sdougb	target = (char *) isc_mem_allocate(mctx, source->length + 1);
217170222Sdougb	if (target != NULL) {
218262706Serwin		memmove(source->base, target, source->length);
219170222Sdougb		target[source->length] = '\0';
220170222Sdougb	}
221170222Sdougb
222170222Sdougb	return (target);
223170222Sdougb}
224170222Sdougb
225170222Sdougbchar *
226135446Strhodesisc_string_separate(char **stringp, const char *delim) {
227135446Strhodes	char *string = *stringp;
228135446Strhodes	char *s;
229135446Strhodes	const char *d;
230135446Strhodes	char sc, dc;
231135446Strhodes
232135446Strhodes	if (string == NULL)
233135446Strhodes		return (NULL);
234135446Strhodes
235135446Strhodes	for (s = string; (sc = *s) != '\0'; s++)
236135446Strhodes		for (d = delim; (dc = *d) != '\0'; d++)
237135446Strhodes			if (sc == dc) {
238135446Strhodes				*s++ = '\0';
239135446Strhodes				*stringp = s;
240135446Strhodes				return (string);
241135446Strhodes			}
242135446Strhodes	*stringp = NULL;
243135446Strhodes	return (string);
244135446Strhodes}
245135446Strhodes
246135446Strhodessize_t
247135446Strhodesisc_string_strlcpy(char *dst, const char *src, size_t size)
248135446Strhodes{
249135446Strhodes	char *d = dst;
250135446Strhodes	const char *s = src;
251135446Strhodes	size_t n = size;
252135446Strhodes
253135446Strhodes	/* Copy as many bytes as will fit */
254135446Strhodes	if (n != 0U && --n != 0U) {
255135446Strhodes		do {
256135446Strhodes			if ((*d++ = *s++) == 0)
257135446Strhodes				break;
258135446Strhodes		} while (--n != 0U);
259135446Strhodes	}
260135446Strhodes
261135446Strhodes	/* Not enough room in dst, add NUL and traverse rest of src */
262135446Strhodes	if (n == 0U) {
263135446Strhodes		if (size != 0U)
264135446Strhodes			*d = '\0';		/* NUL-terminate dst */
265135446Strhodes		while (*s++)
266135446Strhodes			;
267135446Strhodes	}
268135446Strhodes
269135446Strhodes	return(s - src - 1);	/* count does not include NUL */
270135446Strhodes}
271135446Strhodes
272135446Strhodessize_t
273135446Strhodesisc_string_strlcat(char *dst, const char *src, size_t size)
274135446Strhodes{
275135446Strhodes	char *d = dst;
276135446Strhodes	const char *s = src;
277135446Strhodes	size_t n = size;
278135446Strhodes	size_t dlen;
279135446Strhodes
280135446Strhodes	/* Find the end of dst and adjust bytes left but don't go past end */
281135446Strhodes	while (n-- != 0U && *d != '\0')
282135446Strhodes		d++;
283135446Strhodes	dlen = d - dst;
284135446Strhodes	n = size - dlen;
285135446Strhodes
286135446Strhodes	if (n == 0U)
287135446Strhodes		return(dlen + strlen(s));
288135446Strhodes	while (*s != '\0') {
289135446Strhodes		if (n != 1U) {
290135446Strhodes			*d++ = *s;
291135446Strhodes			n--;
292135446Strhodes		}
293135446Strhodes		s++;
294135446Strhodes	}
295135446Strhodes	*d = '\0';
296135446Strhodes
297135446Strhodes	return(dlen + (s - src));	/* count does not include NUL */
298135446Strhodes}
299262706Serwin
300262706Serwinchar *
301262706Serwinisc_string_strcasestr(const char *str, const char *search) {
302262706Serwin	char c, sc, *s;
303262706Serwin	size_t len;
304262706Serwin
305262706Serwin	if ((c = *search++) != 0) {
306262706Serwin		c = tolower((unsigned char) c);
307262706Serwin		len = strlen(search);
308262706Serwin		do {
309262706Serwin			do {
310262706Serwin				if ((sc = *str++) == 0)
311262706Serwin					return (NULL);
312262706Serwin			} while ((char) tolower((unsigned char) sc) != c);
313262706Serwin		} while (strncasecmp(str, search, len) != 0);
314262706Serwin		str--;
315262706Serwin	}
316262706Serwin	DE_CONST(str, s);
317262706Serwin	return (s);
318262706Serwin
319262706Serwin}
320