/src/pjsip/pjlib/src/pj/string.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) |
3 | | * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> |
4 | | * |
5 | | * This program is free software; you can redistribute it and/or modify |
6 | | * it under the terms of the GNU General Public License as published by |
7 | | * the Free Software Foundation; either version 2 of the License, or |
8 | | * (at your option) any later version. |
9 | | * |
10 | | * This program is distributed in the hope that it will be useful, |
11 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | * GNU General Public License for more details. |
14 | | * |
15 | | * You should have received a copy of the GNU General Public License |
16 | | * along with this program; if not, write to the Free Software |
17 | | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | | */ |
19 | | #include <pj/string.h> |
20 | | #include <pj/assert.h> |
21 | | #include <pj/pool.h> |
22 | | #include <pj/ctype.h> |
23 | | #include <pj/rand.h> |
24 | | #include <pj/os.h> |
25 | | #include <pj/errno.h> |
26 | | #include <pj/limits.h> |
27 | | |
28 | | #if PJ_FUNCTIONS_ARE_INLINED==0 |
29 | | # include <pj/string_i.h> |
30 | | #endif |
31 | | |
32 | | |
33 | | PJ_DEF(pj_ssize_t) pj_strspn(const pj_str_t *str, const pj_str_t *set_char) |
34 | 0 | { |
35 | 0 | pj_ssize_t i, j, count = 0; |
36 | 0 | for (i = 0; i < str->slen; i++) { |
37 | 0 | if (count != i) |
38 | 0 | break; |
39 | | |
40 | 0 | for (j = 0; j < set_char->slen; j++) { |
41 | 0 | if (str->ptr[i] == set_char->ptr[j]) |
42 | 0 | count++; |
43 | 0 | } |
44 | 0 | } |
45 | 0 | return count; |
46 | 0 | } |
47 | | |
48 | | |
49 | | PJ_DEF(pj_ssize_t) pj_strspn2(const pj_str_t *str, const char *set_char) |
50 | 0 | { |
51 | 0 | pj_ssize_t i, j, count = 0; |
52 | 0 | for (i = 0; i < str->slen; i++) { |
53 | 0 | if (count != i) |
54 | 0 | break; |
55 | | |
56 | 0 | for (j = 0; set_char[j] != 0; j++) { |
57 | 0 | if (str->ptr[i] == set_char[j]) |
58 | 0 | count++; |
59 | 0 | } |
60 | 0 | } |
61 | 0 | return count; |
62 | 0 | } |
63 | | |
64 | | |
65 | | PJ_DEF(pj_ssize_t) pj_strcspn(const pj_str_t *str, const pj_str_t *set_char) |
66 | 0 | { |
67 | 0 | pj_ssize_t i, j; |
68 | 0 | for (i = 0; i < str->slen; i++) { |
69 | 0 | for (j = 0; j < set_char->slen; j++) { |
70 | 0 | if (str->ptr[i] == set_char->ptr[j]) |
71 | 0 | return i; |
72 | 0 | } |
73 | 0 | } |
74 | 0 | return i; |
75 | 0 | } |
76 | | |
77 | | |
78 | | PJ_DEF(pj_ssize_t) pj_strcspn2(const pj_str_t *str, const char *set_char) |
79 | 0 | { |
80 | 0 | pj_ssize_t i, j; |
81 | 0 | for (i = 0; i < str->slen; i++) { |
82 | 0 | for (j = 0; set_char[j] != 0; j++) { |
83 | 0 | if (str->ptr[i] == set_char[j]) |
84 | 0 | return i; |
85 | 0 | } |
86 | 0 | } |
87 | 0 | return i; |
88 | 0 | } |
89 | | |
90 | | |
91 | | PJ_DEF(pj_ssize_t) pj_strtok(const pj_str_t *str, const pj_str_t *delim, |
92 | | pj_str_t *tok, pj_size_t start_idx) |
93 | 0 | { |
94 | 0 | pj_ssize_t str_idx; |
95 | |
|
96 | 0 | pj_assert(str->slen >= 0); |
97 | 0 | pj_assert(delim->slen >= 0); |
98 | |
|
99 | 0 | tok->slen = 0; |
100 | 0 | if ((str->slen <= 0) || ((pj_size_t)str->slen < start_idx)) { |
101 | 0 | return str->slen; |
102 | 0 | } |
103 | | |
104 | 0 | tok->ptr = str->ptr + start_idx; |
105 | 0 | tok->slen = str->slen - start_idx; |
106 | |
|
107 | 0 | str_idx = pj_strspn(tok, delim); |
108 | 0 | if (start_idx+str_idx == (pj_size_t)str->slen) { |
109 | 0 | return str->slen; |
110 | 0 | } |
111 | 0 | tok->ptr += str_idx; |
112 | 0 | tok->slen -= str_idx; |
113 | |
|
114 | 0 | tok->slen = pj_strcspn(tok, delim); |
115 | 0 | return start_idx + str_idx; |
116 | 0 | } |
117 | | |
118 | | |
119 | | PJ_DEF(pj_ssize_t) pj_strtok2(const pj_str_t *str, const char *delim, |
120 | | pj_str_t *tok, pj_size_t start_idx) |
121 | 0 | { |
122 | 0 | pj_ssize_t str_idx; |
123 | |
|
124 | 0 | pj_assert(str->slen >= 0); |
125 | |
|
126 | 0 | tok->slen = 0; |
127 | 0 | if ((str->slen <= 0) || ((pj_size_t)str->slen < start_idx)) { |
128 | 0 | return str->slen; |
129 | 0 | } |
130 | | |
131 | 0 | tok->ptr = str->ptr + start_idx; |
132 | 0 | tok->slen = str->slen - start_idx; |
133 | |
|
134 | 0 | str_idx = pj_strspn2(tok, delim); |
135 | 0 | if (start_idx + str_idx == (pj_size_t)str->slen) { |
136 | 0 | return str->slen; |
137 | 0 | } |
138 | 0 | tok->ptr += str_idx; |
139 | 0 | tok->slen -= str_idx; |
140 | |
|
141 | 0 | tok->slen = pj_strcspn2(tok, delim); |
142 | 0 | return start_idx + str_idx; |
143 | 0 | } |
144 | | |
145 | | |
146 | | PJ_DEF(char*) pj_strstr(const pj_str_t *str, const pj_str_t *substr) |
147 | 0 | { |
148 | 0 | const char *s, *ends; |
149 | 0 | int first; |
150 | |
|
151 | 0 | PJ_ASSERT_RETURN(str->slen >= 0 && substr->slen >= 0, NULL); |
152 | | |
153 | | /* Check if the string is empty */ |
154 | 0 | if (str->slen <= 0) |
155 | 0 | return NULL; |
156 | | |
157 | | /* Special case when substr is empty */ |
158 | 0 | if (substr->slen <= 0) { |
159 | 0 | return (char*)str->ptr; |
160 | 0 | } |
161 | | |
162 | 0 | s = str->ptr; |
163 | 0 | ends = str->ptr + str->slen - substr->slen; |
164 | 0 | first = substr->ptr[0]; |
165 | 0 | for (; s<=ends; ++s) { |
166 | 0 | if (s[0] == first && pj_memcmp(s, substr->ptr, substr->slen) == 0) |
167 | 0 | return (char*)s; |
168 | 0 | } |
169 | 0 | return NULL; |
170 | 0 | } |
171 | | |
172 | | |
173 | | PJ_DEF(char*) pj_stristr(const pj_str_t *str, const pj_str_t *substr) |
174 | 0 | { |
175 | 0 | const char *s, *ends; |
176 | 0 | int first; |
177 | |
|
178 | 0 | PJ_ASSERT_RETURN(str->slen >= 0 && substr->slen >= 0, NULL); |
179 | | |
180 | | /* Check if the string is empty */ |
181 | 0 | if (str->slen <= 0) |
182 | 0 | return NULL; |
183 | | |
184 | | /* Special case when substr is empty */ |
185 | 0 | if (substr->slen == 0) { |
186 | 0 | return (char*)str->ptr; |
187 | 0 | } |
188 | | |
189 | 0 | s = str->ptr; |
190 | 0 | ends = str->ptr + str->slen - substr->slen; |
191 | 0 | first = pj_tolower(substr->ptr[0]); |
192 | 0 | for (; s<=ends; ++s) { |
193 | 0 | if (pj_tolower(s[0]) == first && pj_ansi_strnicmp(s, substr->ptr, substr->slen) == 0) |
194 | 0 | return (char*)s; |
195 | 0 | } |
196 | 0 | return NULL; |
197 | 0 | } |
198 | | |
199 | | |
200 | | PJ_DEF(pj_str_t*) pj_strltrim( pj_str_t *str ) |
201 | 0 | { |
202 | 0 | char *end = str->ptr + str->slen; |
203 | 0 | register char *p = str->ptr; |
204 | |
|
205 | 0 | pj_assert(str->slen >= 0); |
206 | |
|
207 | 0 | while (p < end && pj_isspace(*p)) |
208 | 0 | ++p; |
209 | 0 | str->slen -= (p - str->ptr); |
210 | 0 | str->ptr = p; |
211 | 0 | return str; |
212 | 0 | } |
213 | | |
214 | | PJ_DEF(pj_str_t*) pj_strrtrim( pj_str_t *str ) |
215 | 0 | { |
216 | 0 | char *end = str->ptr + str->slen; |
217 | 0 | register char *p = end - 1; |
218 | |
|
219 | 0 | pj_assert(str->slen >= 0); |
220 | |
|
221 | 0 | while (p >= str->ptr && pj_isspace(*p)) |
222 | 0 | --p; |
223 | 0 | str->slen -= ((end - p) - 1); |
224 | 0 | return str; |
225 | 0 | } |
226 | | |
227 | | PJ_DEF(char*) pj_create_random_string(char *str, pj_size_t len) |
228 | 0 | { |
229 | 0 | unsigned i; |
230 | 0 | char *p = str; |
231 | |
|
232 | 0 | PJ_CHECK_STACK(); |
233 | |
|
234 | 0 | for (i=0; i<len/8; ++i) { |
235 | 0 | pj_uint32_t val = pj_rand(); |
236 | 0 | pj_val_to_hex_digit( (val & 0xFF000000) >> 24, p+0 ); |
237 | 0 | pj_val_to_hex_digit( (val & 0x00FF0000) >> 16, p+2 ); |
238 | 0 | pj_val_to_hex_digit( (val & 0x0000FF00) >> 8, p+4 ); |
239 | 0 | pj_val_to_hex_digit( (val & 0x000000FF) >> 0, p+6 ); |
240 | 0 | p += 8; |
241 | 0 | } |
242 | 0 | for (i=i * 8; i<len; ++i) { |
243 | 0 | *p++ = pj_hex_digits[ pj_rand() & 0x0F ]; |
244 | 0 | } |
245 | 0 | return str; |
246 | 0 | } |
247 | | |
248 | | PJ_DEF(long) pj_strtol(const pj_str_t *str) |
249 | 3.49k | { |
250 | 3.49k | pj_bool_t is_negative = PJ_FALSE; |
251 | 3.49k | unsigned long uval; |
252 | 3.49k | long val; |
253 | | |
254 | 3.49k | PJ_CHECK_STACK(); |
255 | | |
256 | 3.49k | if (str->slen > 0 && (str->ptr[0] == '+' || str->ptr[0] == '-')) { |
257 | 0 | pj_str_t s; |
258 | 0 | s.ptr = str->ptr + 1; |
259 | 0 | s.slen = str->slen - 1; |
260 | 0 | uval = pj_strtoul(&s); |
261 | 0 | is_negative = (str->ptr[0] == '-'); |
262 | 0 | } else |
263 | 3.49k | uval = pj_strtoul(str); |
264 | | |
265 | 3.49k | if (is_negative) |
266 | 0 | val = uval > PJ_MAXLONG ? PJ_MINLONG : -(long)uval; |
267 | 3.49k | else |
268 | 3.49k | val = uval > PJ_MAXLONG ? PJ_MAXLONG : uval; |
269 | | |
270 | 3.49k | return val; |
271 | 3.49k | } |
272 | | |
273 | | PJ_DEF(pj_status_t) pj_strtol2(const pj_str_t *str, long *value) |
274 | 0 | { |
275 | 0 | pj_str_t s; |
276 | 0 | unsigned long retval = 0; |
277 | 0 | pj_bool_t is_negative = PJ_FALSE; |
278 | 0 | int rc = 0; |
279 | |
|
280 | 0 | PJ_CHECK_STACK(); |
281 | |
|
282 | 0 | if (!str || !value) { |
283 | 0 | return PJ_EINVAL; |
284 | 0 | } |
285 | 0 | PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL); |
286 | | |
287 | 0 | s = *str; |
288 | 0 | pj_strltrim(&s); |
289 | |
|
290 | 0 | if (s.slen == 0) |
291 | 0 | return PJ_EINVAL; |
292 | | |
293 | 0 | if (s.ptr[0] == '+' || s.ptr[0] == '-') { |
294 | 0 | is_negative = (s.ptr[0] == '-'); |
295 | 0 | s.ptr += 1; |
296 | 0 | s.slen -= 1; |
297 | 0 | } |
298 | |
|
299 | 0 | rc = pj_strtoul3(&s, &retval, 10); |
300 | 0 | if (rc == PJ_EINVAL) { |
301 | 0 | return rc; |
302 | 0 | } else if (rc != PJ_SUCCESS) { |
303 | 0 | *value = is_negative ? PJ_MINLONG : PJ_MAXLONG; |
304 | 0 | return is_negative ? PJ_ETOOSMALL : PJ_ETOOBIG; |
305 | 0 | } |
306 | | |
307 | 0 | if (retval > PJ_MAXLONG && !is_negative) { |
308 | 0 | *value = PJ_MAXLONG; |
309 | 0 | return PJ_ETOOBIG; |
310 | 0 | } |
311 | | |
312 | 0 | if (retval > (PJ_MAXLONG + 1UL) && is_negative) { |
313 | 0 | *value = PJ_MINLONG; |
314 | 0 | return PJ_ETOOSMALL; |
315 | 0 | } |
316 | | |
317 | 0 | if (is_negative && retval == PJ_MAXLONG + 1UL) { |
318 | 0 | *value = PJ_MINLONG; |
319 | 0 | return PJ_SUCCESS; |
320 | 0 | } |
321 | | |
322 | 0 | *value = is_negative ? -(long)retval : retval; |
323 | |
|
324 | 0 | return PJ_SUCCESS; |
325 | 0 | } |
326 | | |
327 | | PJ_DEF(unsigned long) pj_strtoul(const pj_str_t *str) |
328 | 3.49k | { |
329 | 3.49k | unsigned long value; |
330 | 3.49k | unsigned i; |
331 | | |
332 | 3.49k | PJ_CHECK_STACK(); |
333 | | |
334 | 3.49k | pj_assert(str->slen >= 0); |
335 | | |
336 | 3.49k | value = 0; |
337 | 22.4k | for (i=0; i<(unsigned)str->slen; ++i) { |
338 | 18.9k | if (!pj_isdigit(str->ptr[i])) |
339 | 0 | break; |
340 | 18.9k | value = value * 10 + (str->ptr[i] - '0'); |
341 | 18.9k | } |
342 | 3.49k | return value; |
343 | 3.49k | } |
344 | | |
345 | | PJ_DEF(unsigned long) pj_strtoul2(const pj_str_t *str, pj_str_t *endptr, |
346 | | unsigned base) |
347 | 646 | { |
348 | 646 | unsigned long value; |
349 | 646 | unsigned i; |
350 | | |
351 | 646 | PJ_CHECK_STACK(); |
352 | | |
353 | 646 | pj_assert(str->slen >= 0); |
354 | | |
355 | 646 | value = 0; |
356 | 646 | if (base <= 10) { |
357 | 9.90k | for (i=0; i<(unsigned)str->slen; ++i) { |
358 | 9.47k | unsigned c = (str->ptr[i] - '0'); |
359 | 9.47k | if (c >= base) |
360 | 215 | break; |
361 | 9.25k | value = value * base + c; |
362 | 9.25k | } |
363 | 646 | } else if (base == 16) { |
364 | 0 | for (i=0; i<(unsigned)str->slen; ++i) { |
365 | 0 | if (!pj_isxdigit(str->ptr[i])) |
366 | 0 | break; |
367 | 0 | value = value * 16 + pj_hex_digit_to_val(str->ptr[i]); |
368 | 0 | } |
369 | 0 | } else { |
370 | 0 | pj_assert(!"Unsupported base"); |
371 | 0 | i = 0; |
372 | 0 | value = 0xFFFFFFFFUL; |
373 | 0 | } |
374 | | |
375 | 646 | if (endptr) { |
376 | 646 | endptr->ptr = str->ptr + i; |
377 | 646 | endptr->slen = (str->slen < 0)? 0: (str->slen - i); |
378 | 646 | } |
379 | | |
380 | 646 | return value; |
381 | 646 | } |
382 | | |
383 | | PJ_DEF(pj_status_t) pj_strtoul3(const pj_str_t *str, unsigned long *value, |
384 | | unsigned base) |
385 | 0 | { |
386 | 0 | pj_str_t s; |
387 | 0 | unsigned i; |
388 | |
|
389 | 0 | PJ_CHECK_STACK(); |
390 | |
|
391 | 0 | if (!str || !value) { |
392 | 0 | return PJ_EINVAL; |
393 | 0 | } |
394 | 0 | PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL); |
395 | | |
396 | 0 | s = *str; |
397 | 0 | pj_strltrim(&s); |
398 | |
|
399 | 0 | if (s.slen == 0 || s.ptr[0] < '0' || |
400 | 0 | (base <= 10 && (unsigned)s.ptr[0] > ('0' - 1) + base) || |
401 | 0 | (base == 16 && !pj_isxdigit(s.ptr[0]))) |
402 | 0 | { |
403 | 0 | return PJ_EINVAL; |
404 | 0 | } |
405 | | |
406 | 0 | *value = 0; |
407 | 0 | if (base <= 10) { |
408 | 0 | for (i=0; i<(unsigned)s.slen; ++i) { |
409 | 0 | unsigned c = s.ptr[i] - '0'; |
410 | 0 | if (s.ptr[i] < '0' || (unsigned)s.ptr[i] > ('0' - 1) + base) { |
411 | 0 | break; |
412 | 0 | } |
413 | 0 | if (*value > PJ_MAXULONG / base) { |
414 | 0 | *value = PJ_MAXULONG; |
415 | 0 | return PJ_ETOOBIG; |
416 | 0 | } |
417 | | |
418 | 0 | *value *= base; |
419 | 0 | if ((PJ_MAXULONG - *value) < c) { |
420 | 0 | *value = PJ_MAXULONG; |
421 | 0 | return PJ_ETOOBIG; |
422 | 0 | } |
423 | 0 | *value += c; |
424 | 0 | } |
425 | 0 | } else if (base == 16) { |
426 | 0 | for (i=0; i<(unsigned)s.slen; ++i) { |
427 | 0 | unsigned c = pj_hex_digit_to_val(s.ptr[i]); |
428 | 0 | if (!pj_isxdigit(s.ptr[i])) |
429 | 0 | break; |
430 | | |
431 | 0 | if (*value > PJ_MAXULONG / base) { |
432 | 0 | *value = PJ_MAXULONG; |
433 | 0 | return PJ_ETOOBIG; |
434 | 0 | } |
435 | 0 | *value *= base; |
436 | 0 | if ((PJ_MAXULONG - *value) < c) { |
437 | 0 | *value = PJ_MAXULONG; |
438 | 0 | return PJ_ETOOBIG; |
439 | 0 | } |
440 | 0 | *value += c; |
441 | 0 | } |
442 | 0 | } else { |
443 | 0 | pj_assert(!"Unsupported base"); |
444 | 0 | return PJ_EINVAL; |
445 | 0 | } |
446 | 0 | return PJ_SUCCESS; |
447 | 0 | } |
448 | | |
449 | | PJ_DEF(pj_status_t) pj_strtoul4(const pj_str_t *str, pj_uint_t *value, |
450 | | unsigned base) |
451 | 0 | { |
452 | 0 | pj_str_t s; |
453 | 0 | unsigned i; |
454 | |
|
455 | 0 | PJ_CHECK_STACK(); |
456 | |
|
457 | 0 | if (!str || !value) { |
458 | 0 | return PJ_EINVAL; |
459 | 0 | } |
460 | 0 | PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL); |
461 | | |
462 | 0 | s = *str; |
463 | 0 | pj_strltrim(&s); |
464 | |
|
465 | 0 | if (s.slen == 0 || s.ptr[0] < '0' || |
466 | 0 | (base <= 10 && (unsigned)s.ptr[0] > ('0' - 1) + base) || |
467 | 0 | (base == 16 && !pj_isxdigit(s.ptr[0]))) |
468 | 0 | { |
469 | 0 | return PJ_EINVAL; |
470 | 0 | } |
471 | | |
472 | 0 | *value = 0; |
473 | 0 | if (base <= 10) { |
474 | 0 | for (i=0; i<(unsigned)s.slen; ++i) { |
475 | 0 | unsigned c = s.ptr[i] - '0'; |
476 | 0 | if (s.ptr[i] < '0' || (unsigned)s.ptr[i] > ('0' - 1) + base) { |
477 | 0 | break; |
478 | 0 | } |
479 | 0 | if (*value > PJ_MAXUINT / base) { |
480 | 0 | *value = PJ_MAXUINT; |
481 | 0 | return PJ_ETOOBIG; |
482 | 0 | } |
483 | | |
484 | 0 | *value *= base; |
485 | 0 | if ((PJ_MAXUINT - *value) < c) { |
486 | 0 | *value = PJ_MAXUINT; |
487 | 0 | return PJ_ETOOBIG; |
488 | 0 | } |
489 | 0 | *value += c; |
490 | 0 | } |
491 | 0 | } else if (base == 16) { |
492 | 0 | for (i=0; i<(unsigned)s.slen; ++i) { |
493 | 0 | unsigned c = pj_hex_digit_to_val(s.ptr[i]); |
494 | 0 | if (!pj_isxdigit(s.ptr[i])) |
495 | 0 | break; |
496 | | |
497 | 0 | if (*value > PJ_MAXUINT / base) { |
498 | 0 | *value = PJ_MAXUINT; |
499 | 0 | return PJ_ETOOBIG; |
500 | 0 | } |
501 | 0 | *value *= base; |
502 | 0 | if ((PJ_MAXUINT - *value) < c) { |
503 | 0 | *value = PJ_MAXUINT; |
504 | 0 | return PJ_ETOOBIG; |
505 | 0 | } |
506 | 0 | *value += c; |
507 | 0 | } |
508 | 0 | } else { |
509 | 0 | pj_assert(!"Unsupported base"); |
510 | 0 | return PJ_EINVAL; |
511 | 0 | } |
512 | 0 | return PJ_SUCCESS; |
513 | 0 | } |
514 | | |
515 | | PJ_DEF(float) pj_strtof(const pj_str_t *str) |
516 | 6.17k | { |
517 | 6.17k | pj_str_t part; |
518 | 6.17k | char *pdot; |
519 | 6.17k | float val; |
520 | | |
521 | 6.17k | pj_assert(str->slen >= 0); |
522 | | |
523 | 6.17k | if (str->slen <= 0) |
524 | 0 | return 0; |
525 | | |
526 | 6.17k | pdot = (char*)pj_memchr(str->ptr, '.', str->slen); |
527 | 6.17k | part.ptr = str->ptr; |
528 | 6.17k | part.slen = pdot ? pdot - str->ptr : str->slen; |
529 | | |
530 | 6.17k | if (part.slen) |
531 | 3.49k | val = (float)pj_strtol(&part); |
532 | 2.67k | else |
533 | 2.67k | val = 0; |
534 | | |
535 | 6.17k | if (pdot) { |
536 | 2.70k | part.ptr = pdot + 1; |
537 | 2.70k | part.slen = (str->ptr + str->slen - pdot - 1); |
538 | 2.70k | if (part.slen) { |
539 | 646 | pj_str_t endptr; |
540 | 646 | float fpart, fdiv; |
541 | 646 | int i; |
542 | 646 | fpart = (float)pj_strtoul2(&part, &endptr, 10); |
543 | 646 | fdiv = 1.0; |
544 | 9.90k | for (i=0; i<(part.slen - endptr.slen); ++i) |
545 | 9.25k | fdiv = fdiv * 10; |
546 | 646 | if (val >= 0) |
547 | 646 | val += (fpart / fdiv); |
548 | 0 | else |
549 | 0 | val -= (fpart / fdiv); |
550 | 646 | } |
551 | 2.70k | } |
552 | 6.17k | return val; |
553 | 6.17k | } |
554 | | |
555 | | PJ_DEF(int) pj_utoa(unsigned long val, char *buf) |
556 | 0 | { |
557 | 0 | return pj_utoa_pad(val, buf, 0, 0); |
558 | 0 | } |
559 | | |
560 | | PJ_DEF(int) pj_utoa_pad( unsigned long val, char *buf, int min_dig, int pad) |
561 | 4 | { |
562 | 4 | char *p; |
563 | 4 | int len; |
564 | | |
565 | 4 | PJ_CHECK_STACK(); |
566 | | |
567 | 4 | p = buf; |
568 | 8 | do { |
569 | 8 | unsigned long digval = (unsigned long) (val % 10); |
570 | 8 | val /= 10; |
571 | 8 | *p++ = (char) (digval + '0'); |
572 | 8 | } while (val > 0); |
573 | | |
574 | 4 | len = (int)(p-buf); |
575 | 5 | while (len < min_dig) { |
576 | 1 | *p++ = (char)pad; |
577 | 1 | ++len; |
578 | 1 | } |
579 | 4 | *p-- = '\0'; |
580 | | |
581 | 4 | do { |
582 | 4 | char temp = *p; |
583 | 4 | *p = *buf; |
584 | 4 | *buf = temp; |
585 | 4 | --p; |
586 | 4 | ++buf; |
587 | 4 | } while (buf < p); |
588 | | |
589 | 4 | return len; |
590 | 4 | } |
591 | | |
592 | | PJ_DEF(int) pj_utoa2(pj_uint_t val, char *buf) |
593 | 0 | { |
594 | 0 | return pj_utoa_pad2(val, buf, 0, 0); |
595 | 0 | } |
596 | | |
597 | | PJ_DEF(int) pj_utoa_pad2(pj_uint_t val, char *buf, int min_dig, int pad) |
598 | 0 | { |
599 | 0 | char *p; |
600 | 0 | int len; |
601 | |
|
602 | 0 | PJ_CHECK_STACK(); |
603 | |
|
604 | 0 | p = buf; |
605 | 0 | do { |
606 | 0 | pj_uint_t digval = (pj_uint_t) (val % 10); |
607 | 0 | val /= 10; |
608 | 0 | *p++ = (char) (digval + '0'); |
609 | 0 | } while (val > 0); |
610 | |
|
611 | 0 | len = (int)(p-buf); |
612 | 0 | while (len < min_dig) { |
613 | 0 | *p++ = (char)pad; |
614 | 0 | ++len; |
615 | 0 | } |
616 | 0 | *p-- = '\0'; |
617 | |
|
618 | 0 | do { |
619 | 0 | char temp = *p; |
620 | 0 | *p = *buf; |
621 | 0 | *buf = temp; |
622 | 0 | --p; |
623 | 0 | ++buf; |
624 | 0 | } while (buf < p); |
625 | |
|
626 | 0 | return len; |
627 | 0 | } |
628 | | |
629 | | PJ_DEF(int) pj_ansi_strxcpy(char *dst, const char *src, |
630 | | pj_size_t dst_size) |
631 | 6.83k | { |
632 | 6.83k | char *odst = dst; |
633 | | |
634 | 6.83k | PJ_ASSERT_RETURN(dst && src, -PJ_EINVAL); |
635 | | |
636 | 6.83k | if (dst_size==0) |
637 | 0 | return -PJ_ETOOBIG; |
638 | | |
639 | 88.8k | while (--dst_size && (*dst=*src) != 0) { |
640 | 82.0k | ++dst; |
641 | 82.0k | ++src; |
642 | 82.0k | } |
643 | | |
644 | 6.83k | if (!*dst && !*src) { |
645 | 6.83k | return (int)(dst-odst); |
646 | 6.83k | } else { |
647 | 0 | *dst = '\0'; |
648 | 0 | return *src? -PJ_ETOOBIG : (int)(dst-odst); |
649 | 0 | } |
650 | 6.83k | } |
651 | | |
652 | | PJ_DEF(int) pj_ansi_strxcpy2(char *dst, const pj_str_t *src, |
653 | | pj_size_t dst_size) |
654 | 0 | { |
655 | 0 | char *odst = dst; |
656 | 0 | const char *ssrc, *esrc; |
657 | |
|
658 | 0 | PJ_ASSERT_RETURN(dst && src && src->slen >= 0, -PJ_EINVAL); |
659 | 0 | if (dst_size==0) |
660 | 0 | return -PJ_ETOOBIG; |
661 | | |
662 | 0 | ssrc = src->ptr; |
663 | 0 | esrc = ssrc + src->slen; |
664 | |
|
665 | 0 | while (ssrc < esrc && --dst_size && (*dst = *ssrc)!= 0) { |
666 | 0 | dst++; |
667 | 0 | ssrc++; |
668 | 0 | } |
669 | |
|
670 | 0 | *dst = '\0'; |
671 | 0 | if (ssrc==esrc || !*ssrc) { |
672 | 0 | return (int)(dst-odst); |
673 | 0 | } else { |
674 | 0 | return -PJ_ETOOBIG; |
675 | 0 | } |
676 | 0 | } |
677 | | |
678 | | PJ_DEF(int) pj_ansi_strxcat(char *dst, const char *src, pj_size_t dst_size) |
679 | 0 | { |
680 | 0 | pj_size_t dst_len; |
681 | |
|
682 | 0 | PJ_ASSERT_RETURN(dst && src, -PJ_EINVAL); |
683 | | |
684 | 0 | if (dst_size==0) |
685 | 0 | return -PJ_ETOOBIG; |
686 | | |
687 | 0 | dst_len = pj_ansi_strlen(dst); |
688 | 0 | if (dst_len < dst_size) { |
689 | 0 | int rc = pj_ansi_strxcpy(dst+dst_len, src, dst_size-dst_len); |
690 | 0 | if (rc < 0) |
691 | 0 | return rc; |
692 | 0 | return (int)dst_len + rc; |
693 | 0 | } else |
694 | 0 | return -PJ_ETOOBIG; |
695 | 0 | } |