]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/lib/isc/string.c
MFV r306384:
[FreeBSD/stable/9.git] / contrib / bind9 / lib / isc / string.c
1 /*
2  * Copyright (C) 2004-2007, 2011, 2012, 2014, 2015  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /*
19  * Copyright (c) 1990, 1993
20  *      The Regents of the University of California.  All rights reserved.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the above copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. Neither the name of the University nor the names of its contributors
31  *    may be used to endorse or promote products derived from this software
32  *    without specific prior written permission.
33  *
34  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
35  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44  * SUCH DAMAGE.
45  */
46
47 /*! \file */
48
49 #include <config.h>
50
51 #include <ctype.h>
52
53 #include <isc/mem.h>
54 #include <isc/print.h>
55 #include <isc/region.h>
56 #include <isc/string.h>
57 #include <isc/util.h>
58
59 static const char digits[] = "0123456789abcdefghijklmnoprstuvwxyz";
60
61 isc_uint64_t
62 isc_string_touint64(char *source, char **end, int base) {
63         isc_uint64_t tmp;
64         isc_uint64_t overflow;
65         char *s = source;
66         const char *o;
67         char c;
68
69         if ((base < 0) || (base == 1) || (base > 36)) {
70                 *end = source;
71                 return (0);
72         }
73
74         while (*s != 0 && isascii(*s&0xff) && isspace(*s&0xff))
75                 s++;
76         if (*s == '+' /* || *s == '-' */)
77                 s++;
78         if (base == 0) {
79                 if (*s == '0' && (*(s+1) == 'X' || *(s+1) == 'x')) {
80                         s += 2;
81                         base = 16;
82                 } else if (*s == '0')
83                         base = 8;
84                 else
85                         base = 10;
86         }
87         if (*s == 0) {
88                 *end = source;
89                 return (0);
90         }
91         overflow = ~0;
92         overflow /= base;
93         tmp = 0;
94
95         while ((c = *s) != 0) {
96                 c = tolower(c&0xff);
97                 /* end ? */
98                 if ((o = strchr(digits, c)) == NULL) {
99                         *end = s;
100                         return (tmp);
101                 }
102                 /* end ? */
103                 if ((o - digits) >= base) {
104                         *end = s;
105                         return (tmp);
106                 }
107                 /* overflow ? */
108                 if (tmp > overflow) {
109                         *end = source;
110                         return (0);
111                 }
112                 tmp *= base;
113                 /* overflow ? */
114                 if ((tmp + (o - digits)) < tmp) {
115                         *end = source;
116                         return (0);
117                 }
118                 tmp += o - digits;
119                 s++;
120         }
121         *end = s;
122         return (tmp);
123 }
124
125 isc_result_t
126 isc_string_copy(char *target, size_t size, const char *source) {
127         REQUIRE(size > 0U);
128
129         if (strlcpy(target, source, size) >= size) {
130                 memset(target, ISC_STRING_MAGIC, size);
131                 return (ISC_R_NOSPACE);
132         }
133
134         ENSURE(strlen(target) < size);
135
136         return (ISC_R_SUCCESS);
137 }
138
139 void
140 isc_string_copy_truncate(char *target, size_t size, const char *source) {
141         REQUIRE(size > 0U);
142
143         strlcpy(target, source, size);
144
145         ENSURE(strlen(target) < size);
146 }
147
148 isc_result_t
149 isc_string_append(char *target, size_t size, const char *source) {
150         REQUIRE(size > 0U);
151         REQUIRE(strlen(target) < size);
152
153         if (strlcat(target, source, size) >= size) {
154                 memset(target, ISC_STRING_MAGIC, size);
155                 return (ISC_R_NOSPACE);
156         }
157
158         ENSURE(strlen(target) < size);
159
160         return (ISC_R_SUCCESS);
161 }
162
163 void
164 isc_string_append_truncate(char *target, size_t size, const char *source) {
165         REQUIRE(size > 0U);
166         REQUIRE(strlen(target) < size);
167
168         strlcat(target, source, size);
169
170         ENSURE(strlen(target) < size);
171 }
172
173 isc_result_t
174 isc_string_printf(char *target, size_t size, const char *format, ...) {
175         va_list args;
176         size_t n;
177
178         REQUIRE(size > 0U);
179
180         va_start(args, format);
181         n = vsnprintf(target, size, format, args);
182         va_end(args);
183
184         if (n >= size) {
185                 memset(target, ISC_STRING_MAGIC, size);
186                 return (ISC_R_NOSPACE);
187         }
188
189         ENSURE(strlen(target) < size);
190
191         return (ISC_R_SUCCESS);
192 }
193
194 void
195 isc_string_printf_truncate(char *target, size_t size, const char *format, ...)
196 {
197         va_list args;
198
199         REQUIRE(size > 0U);
200
201         va_start(args, format);
202         /* check return code? */
203         (void)vsnprintf(target, size, format, args);
204         va_end(args);
205
206         ENSURE(strlen(target) < size);
207 }
208
209 char *
210 isc_string_regiondup(isc_mem_t *mctx, const isc_region_t *source) {
211         char *target;
212
213         REQUIRE(mctx != NULL);
214         REQUIRE(source != NULL);
215
216         target = (char *) isc_mem_allocate(mctx, source->length + 1);
217         if (target != NULL) {
218                 memmove(source->base, target, source->length);
219                 target[source->length] = '\0';
220         }
221
222         return (target);
223 }
224
225 char *
226 isc_string_separate(char **stringp, const char *delim) {
227         char *string = *stringp;
228         char *s;
229         const char *d;
230         char sc, dc;
231
232         if (string == NULL)
233                 return (NULL);
234
235         for (s = string; (sc = *s) != '\0'; s++)
236                 for (d = delim; (dc = *d) != '\0'; d++)
237                         if (sc == dc) {
238                                 *s++ = '\0';
239                                 *stringp = s;
240                                 return (string);
241                         }
242         *stringp = NULL;
243         return (string);
244 }
245
246 size_t
247 isc_string_strlcpy(char *dst, const char *src, size_t size)
248 {
249         char *d = dst;
250         const char *s = src;
251         size_t n = size;
252
253         /* Copy as many bytes as will fit */
254         if (n != 0U && --n != 0U) {
255                 do {
256                         if ((*d++ = *s++) == 0)
257                                 break;
258                 } while (--n != 0U);
259         }
260
261         /* Not enough room in dst, add NUL and traverse rest of src */
262         if (n == 0U) {
263                 if (size != 0U)
264                         *d = '\0';              /* NUL-terminate dst */
265                 while (*s++)
266                         ;
267         }
268
269         return(s - src - 1);    /* count does not include NUL */
270 }
271
272 size_t
273 isc_string_strlcat(char *dst, const char *src, size_t size)
274 {
275         char *d = dst;
276         const char *s = src;
277         size_t n = size;
278         size_t dlen;
279
280         /* Find the end of dst and adjust bytes left but don't go past end */
281         while (n-- != 0U && *d != '\0')
282                 d++;
283         dlen = d - dst;
284         n = size - dlen;
285
286         if (n == 0U)
287                 return(dlen + strlen(s));
288         while (*s != '\0') {
289                 if (n != 1U) {
290                         *d++ = *s;
291                         n--;
292                 }
293                 s++;
294         }
295         *d = '\0';
296
297         return(dlen + (s - src));       /* count does not include NUL */
298 }
299
300 char *
301 isc_string_strcasestr(const char *str, const char *search) {
302         char c, sc, *s;
303         size_t len;
304
305         if ((c = *search++) != 0) {
306                 c = tolower((unsigned char) c);
307                 len = strlen(search);
308                 do {
309                         do {
310                                 if ((sc = *str++) == 0)
311                                         return (NULL);
312                         } while ((char) tolower((unsigned char) sc) != c);
313                 } while (strncasecmp(str, search, len) != 0);
314                 str--;
315         }
316         DE_CONST(str, s);
317         return (s);
318
319 }