]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/lib/isc/string.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / ntp / lib / isc / string.c
1 /*
2  * Copyright (C) 2004-2007, 2011, 2012  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 /* $Id$ */
19
20 /*! \file */
21
22 #include <config.h>
23
24 #include <ctype.h>
25
26 #include <isc/mem.h>
27 #include <isc/print.h>
28 #include <isc/region.h>
29 #include <isc/string.h>
30 #include <isc/util.h>
31
32 static char digits[] = "0123456789abcdefghijklmnoprstuvwxyz";
33
34 isc_uint64_t
35 isc_string_touint64(char *source, char **end, int base) {
36         isc_uint64_t tmp;
37         isc_uint64_t overflow;
38         char *s = source;
39         char *o;
40         char c;
41
42         if ((base < 0) || (base == 1) || (base > 36)) {
43                 *end = source;
44                 return (0);
45         }
46
47         while (*s != 0 && isascii(*s&0xff) && isspace(*s&0xff))
48                 s++;
49         if (*s == '+' /* || *s == '-' */)
50                 s++;
51         if (base == 0) {
52                 if (*s == '0' && (*(s+1) == 'X' || *(s+1) == 'x')) {
53                         s += 2;
54                         base = 16;
55                 } else if (*s == '0')
56                         base = 8;
57                 else
58                         base = 10;
59         }
60         if (*s == 0) {
61                 *end = source;
62                 return (0);
63         }
64         overflow = ~0;
65         overflow /= base;
66         tmp = 0;
67
68         while ((c = *s) != 0) {
69                 c = tolower(c&0xff);
70                 /* end ? */
71                 if ((o = strchr(digits, c)) == NULL) {
72                         *end = s;
73                         return (tmp);
74                 }
75                 /* end ? */
76                 if ((o - digits) >= base) {
77                         *end = s;
78                         return (tmp);
79                 }
80                 /* overflow ? */
81                 if (tmp > overflow) {
82                         *end = source;
83                         return (0);
84                 }
85                 tmp *= base;
86                 /* overflow ? */
87                 if ((tmp + (o - digits)) < tmp) {
88                         *end = source;
89                         return (0);
90                 }
91                 tmp += o - digits;
92                 s++;
93         }
94         *end = s;
95         return (tmp);
96 }
97
98 isc_result_t
99 isc_string_copy(char *target, size_t size, const char *source) {
100         REQUIRE(size > 0U);
101
102         if (strlcpy(target, source, size) >= size) {
103                 memset(target, ISC_STRING_MAGIC, size);
104                 return (ISC_R_NOSPACE);
105         }
106
107         ENSURE(strlen(target) < size);
108
109         return (ISC_R_SUCCESS);
110 }
111
112 void
113 isc_string_copy_truncate(char *target, size_t size, const char *source) {
114         REQUIRE(size > 0U);
115
116         strlcpy(target, source, size);
117
118         ENSURE(strlen(target) < size);
119 }
120
121 isc_result_t
122 isc_string_append(char *target, size_t size, const char *source) {
123         REQUIRE(size > 0U);
124         REQUIRE(strlen(target) < size);
125
126         if (strlcat(target, source, size) >= size) {
127                 memset(target, ISC_STRING_MAGIC, size);
128                 return (ISC_R_NOSPACE);
129         }
130
131         ENSURE(strlen(target) < size);
132
133         return (ISC_R_SUCCESS);
134 }
135
136 void
137 isc_string_append_truncate(char *target, size_t size, const char *source) {
138         REQUIRE(size > 0U);
139         REQUIRE(strlen(target) < size);
140
141         strlcat(target, source, size);
142
143         ENSURE(strlen(target) < size);
144 }
145
146 isc_result_t
147 isc_string_printf(char *target, size_t size, const char *format, ...) {
148         va_list args;
149         size_t n;
150
151         REQUIRE(size > 0U);
152
153         va_start(args, format);
154         n = vsnprintf(target, size, format, args);
155         va_end(args);
156
157         if (n >= size) {
158                 memset(target, ISC_STRING_MAGIC, size);
159                 return (ISC_R_NOSPACE);
160         }
161
162         ENSURE(strlen(target) < size);
163
164         return (ISC_R_SUCCESS);
165 }
166
167 void
168 isc_string_printf_truncate(char *target, size_t size, const char *format, ...)
169 {
170         va_list args;
171
172         REQUIRE(size > 0U);
173
174         va_start(args, format);
175         /* check return code? */
176         (void)vsnprintf(target, size, format, args);
177         va_end(args);
178
179         ENSURE(strlen(target) < size);
180 }
181
182 char *
183 isc_string_regiondup(isc_mem_t *mctx, const isc_region_t *source) {
184         char *target;
185
186         REQUIRE(mctx != NULL);
187         REQUIRE(source != NULL);
188
189         target = (char *) isc_mem_allocate(mctx, source->length + 1);
190         if (target != NULL) {
191                 memcpy(source->base, target, source->length);
192                 target[source->length] = '\0';
193         }
194
195         return (target);
196 }
197
198 char *
199 isc_string_separate(char **stringp, const char *delim) {
200         char *string = *stringp;
201         char *s;
202         const char *d;
203         char sc, dc;
204
205         if (string == NULL)
206                 return (NULL);
207
208         for (s = string; (sc = *s) != '\0'; s++)
209                 for (d = delim; (dc = *d) != '\0'; d++)
210                         if (sc == dc) {
211                                 *s++ = '\0';
212                                 *stringp = s;
213                                 return (string);
214                         }
215         *stringp = NULL;
216         return (string);
217 }
218
219 size_t
220 isc_string_strlcpy(char *dst, const char *src, size_t size)
221 {
222         char *d = dst;
223         const char *s = src;
224         size_t n = size;
225
226         /* Copy as many bytes as will fit */
227         if (n != 0U && --n != 0U) {
228                 do {
229                         if ((*d++ = *s++) == 0)
230                                 break;
231                 } while (--n != 0U);
232         }
233
234         /* Not enough room in dst, add NUL and traverse rest of src */
235         if (n == 0U) {
236                 if (size != 0U)
237                         *d = '\0';              /* NUL-terminate dst */
238                 while (*s++)
239                         ;
240         }
241
242         return(s - src - 1);    /* count does not include NUL */
243 }
244
245 size_t
246 isc_string_strlcat(char *dst, const char *src, size_t size)
247 {
248         char *d = dst;
249         const char *s = src;
250         size_t n = size;
251         size_t dlen;
252
253         /* Find the end of dst and adjust bytes left but don't go past end */
254         while (n-- != 0U && *d != '\0')
255                 d++;
256         dlen = d - dst;
257         n = size - dlen;
258
259         if (n == 0U)
260                 return(dlen + strlen(s));
261         while (*s != '\0') {
262                 if (n != 1U) {
263                         *d++ = *s;
264                         n--;
265                 }
266                 s++;
267         }
268         *d = '\0';
269
270         return(dlen + (s - src));       /* count does not include NUL */
271 }