blob: d62b674a40a81fbc45fd2357db3c57211eaeebe7 [file] [log] [blame]
Alexandre Lision67916dd2014-01-24 13:33:04 -05001/* $Id$ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <pj/string.h>
21#include <pj/assert.h>
22#include <pj/pool.h>
23#include <pj/ctype.h>
24#include <pj/rand.h>
25#include <pj/os.h>
26
27#if PJ_FUNCTIONS_ARE_INLINED==0
28# include <pj/string_i.h>
29#endif
30
31
32PJ_DEF(char*) pj_strstr(const pj_str_t *str, const pj_str_t *substr)
33{
34 const char *s, *ends;
35
36 /* Special case when substr is zero */
37 if (substr->slen == 0) {
38 return (char*)str->ptr;
39 }
40
41 s = str->ptr;
42 ends = str->ptr + str->slen - substr->slen;
43 for (; s<=ends; ++s) {
44 if (pj_ansi_strncmp(s, substr->ptr, substr->slen)==0)
45 return (char*)s;
46 }
47 return NULL;
48}
49
50
51PJ_DEF(char*) pj_stristr(const pj_str_t *str, const pj_str_t *substr)
52{
53 const char *s, *ends;
54
55 /* Special case when substr is zero */
56 if (substr->slen == 0) {
57 return (char*)str->ptr;
58 }
59
60 s = str->ptr;
61 ends = str->ptr + str->slen - substr->slen;
62 for (; s<=ends; ++s) {
63 if (pj_ansi_strnicmp(s, substr->ptr, substr->slen)==0)
64 return (char*)s;
65 }
66 return NULL;
67}
68
69
70PJ_DEF(pj_str_t*) pj_strltrim( pj_str_t *str )
71{
72 char *end = str->ptr + str->slen;
73 register char *p = str->ptr;
74 while (p < end && pj_isspace(*p))
75 ++p;
76 str->slen -= (p - str->ptr);
77 str->ptr = p;
78 return str;
79}
80
81PJ_DEF(pj_str_t*) pj_strrtrim( pj_str_t *str )
82{
83 char *end = str->ptr + str->slen;
84 register char *p = end - 1;
85 while (p >= str->ptr && pj_isspace(*p))
86 --p;
87 str->slen -= ((end - p) - 1);
88 return str;
89}
90
91PJ_DEF(char*) pj_create_random_string(char *str, pj_size_t len)
92{
93 unsigned i;
94 char *p = str;
95
96 PJ_CHECK_STACK();
97
98 for (i=0; i<len/8; ++i) {
99 pj_uint32_t val = pj_rand();
100 pj_val_to_hex_digit( (val & 0xFF000000) >> 24, p+0 );
101 pj_val_to_hex_digit( (val & 0x00FF0000) >> 16, p+2 );
102 pj_val_to_hex_digit( (val & 0x0000FF00) >> 8, p+4 );
103 pj_val_to_hex_digit( (val & 0x000000FF) >> 0, p+6 );
104 p += 8;
105 }
106 for (i=i * 8; i<len; ++i) {
107 *p++ = pj_hex_digits[ pj_rand() & 0x0F ];
108 }
109 return str;
110}
111
112PJ_DEF(long) pj_strtol(const pj_str_t *str)
113{
114 PJ_CHECK_STACK();
115
116 if (str->slen > 0 && (str->ptr[0] == '+' || str->ptr[0] == '-')) {
117 pj_str_t s;
118
119 s.ptr = str->ptr + 1;
120 s.slen = str->slen - 1;
121 return (str->ptr[0] == '-'? -(long)pj_strtoul(&s) : pj_strtoul(&s));
122 } else
123 return pj_strtoul(str);
124}
125
126PJ_DEF(unsigned long) pj_strtoul(const pj_str_t *str)
127{
128 unsigned long value;
129 unsigned i;
130
131 PJ_CHECK_STACK();
132
133 value = 0;
134 for (i=0; i<(unsigned)str->slen; ++i) {
135 if (!pj_isdigit(str->ptr[i]))
136 break;
137 value = value * 10 + (str->ptr[i] - '0');
138 }
139 return value;
140}
141
142PJ_DEF(unsigned long) pj_strtoul2(const pj_str_t *str, pj_str_t *endptr,
143 unsigned base)
144{
145 unsigned long value;
146 unsigned i;
147
148 PJ_CHECK_STACK();
149
150 value = 0;
151 if (base <= 10) {
152 for (i=0; i<(unsigned)str->slen; ++i) {
153 unsigned c = (str->ptr[i] - '0');
154 if (c >= base)
155 break;
156 value = value * base + c;
157 }
158 } else if (base == 16) {
159 for (i=0; i<(unsigned)str->slen; ++i) {
160 if (!pj_isxdigit(str->ptr[i]))
161 break;
162 value = value * 16 + pj_hex_digit_to_val(str->ptr[i]);
163 }
164 } else {
165 pj_assert(!"Unsupported base");
166 i = 0;
167 value = 0xFFFFFFFFUL;
168 }
169
170 if (endptr) {
171 endptr->ptr = str->ptr + i;
172 endptr->slen = str->slen - i;
173 }
174
175 return value;
176}
177
178PJ_DEF(float) pj_strtof(const pj_str_t *str)
179{
180 pj_str_t part;
181 char *pdot;
182 float val;
183
184 if (str->slen == 0)
185 return 0;
186
187 pdot = (char*)pj_memchr(str->ptr, '.', str->slen);
188 part.ptr = str->ptr;
189 part.slen = pdot ? pdot - str->ptr : str->slen;
190
191 if (part.slen)
192 val = (float)pj_strtol(&part);
193 else
194 val = 0;
195
196 if (pdot) {
197 part.ptr = pdot + 1;
198 part.slen = (str->ptr + str->slen - pdot - 1);
199 if (part.slen) {
200 pj_str_t endptr;
201 float fpart, fdiv;
202 int i;
203 fpart = (float)pj_strtoul2(&part, &endptr, 10);
204 fdiv = 1.0;
205 for (i=0; i<(part.slen - endptr.slen); ++i)
206 fdiv = fdiv * 10;
207 if (val >= 0)
208 val += (fpart / fdiv);
209 else
210 val -= (fpart / fdiv);
211 }
212 }
213 return val;
214}
215
216PJ_DEF(int) pj_utoa(unsigned long val, char *buf)
217{
218 return pj_utoa_pad(val, buf, 0, 0);
219}
220
221PJ_DEF(int) pj_utoa_pad( unsigned long val, char *buf, int min_dig, int pad)
222{
223 char *p;
224 int len;
225
226 PJ_CHECK_STACK();
227
228 p = buf;
229 do {
230 unsigned long digval = (unsigned long) (val % 10);
231 val /= 10;
232 *p++ = (char) (digval + '0');
233 } while (val > 0);
234
235 len = (int)(p-buf);
236 while (len < min_dig) {
237 *p++ = (char)pad;
238 ++len;
239 }
240 *p-- = '\0';
241
242 do {
243 char temp = *p;
244 *p = *buf;
245 *buf = temp;
246 --p;
247 ++buf;
248 } while (buf < p);
249
250 return len;
251}
252
253