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
isc_string_touint64(char * source,char ** end,int base)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
isc_string_copy(char * target,size_t size,const char * source)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
isc_string_copy_truncate(char * target,size_t size,const char * source)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
isc_string_append(char * target,size_t size,const char * source)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
isc_string_append_truncate(char * target,size_t size,const char * source)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
isc_string_printf(char * target,size_t size,const char * format,...)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
isc_string_printf_truncate(char * target,size_t size,const char * format,...)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 *
isc_string_regiondup(isc_mem_t * mctx,const isc_region_t * source)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 *
isc_string_separate(char ** stringp,const char * delim)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
isc_string_strlcpy(char * dst,const char * src,size_t size)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
isc_string_strlcat(char * dst,const char * src,size_t size)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 *
isc_string_strcasestr(const char * str,const char * search)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