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