1 /* $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
21 #include <pj/assert.h>
22 #include <pj/pool.h>
23
pj_str(char * str)24 PJ_IDEF(pj_str_t) pj_str(char *str)
25 {
26 pj_str_t dst;
27 dst.ptr = str;
28 dst.slen = str ? pj_ansi_strlen(str) : 0;
29 return dst;
30 }
31
pj_strdup(pj_pool_t * pool,pj_str_t * dst,const pj_str_t * src)32 PJ_IDEF(pj_str_t*) pj_strdup(pj_pool_t *pool,
33 pj_str_t *dst,
34 const pj_str_t *src)
35 {
36 /* Without this, destination will be corrupted */
37 if (dst == src)
38 return dst;
39
40 if (src->slen) {
41 dst->ptr = (char*)pj_pool_alloc(pool, src->slen);
42 pj_memcpy(dst->ptr, src->ptr, src->slen);
43 }
44 dst->slen = src->slen;
45 return dst;
46 }
47
pj_strdup_with_null(pj_pool_t * pool,pj_str_t * dst,const pj_str_t * src)48 PJ_IDEF(pj_str_t*) pj_strdup_with_null( pj_pool_t *pool,
49 pj_str_t *dst,
50 const pj_str_t *src)
51 {
52 dst->ptr = (char*)pj_pool_alloc(pool, src->slen+1);
53 if (src->slen) {
54 pj_memcpy(dst->ptr, src->ptr, src->slen);
55 }
56 dst->slen = src->slen;
57 dst->ptr[dst->slen] = '\0';
58 return dst;
59 }
60
pj_strdup2(pj_pool_t * pool,pj_str_t * dst,const char * src)61 PJ_IDEF(pj_str_t*) pj_strdup2(pj_pool_t *pool,
62 pj_str_t *dst,
63 const char *src)
64 {
65 dst->slen = src ? pj_ansi_strlen(src) : 0;
66 if (dst->slen) {
67 dst->ptr = (char*)pj_pool_alloc(pool, dst->slen);
68 pj_memcpy(dst->ptr, src, dst->slen);
69 } else {
70 dst->ptr = NULL;
71 }
72 return dst;
73 }
74
pj_strdup2_with_null(pj_pool_t * pool,pj_str_t * dst,const char * src)75 PJ_IDEF(pj_str_t*) pj_strdup2_with_null( pj_pool_t *pool,
76 pj_str_t *dst,
77 const char *src)
78 {
79 dst->slen = src ? pj_ansi_strlen(src) : 0;
80 dst->ptr = (char*)pj_pool_alloc(pool, dst->slen+1);
81 if (dst->slen) {
82 pj_memcpy(dst->ptr, src, dst->slen);
83 }
84 dst->ptr[dst->slen] = '\0';
85 return dst;
86 }
87
pj_strdup3(pj_pool_t * pool,const char * src)88 PJ_IDEF(pj_str_t) pj_strdup3(pj_pool_t *pool, const char *src)
89 {
90 pj_str_t temp;
91 pj_strdup2(pool, &temp, src);
92 return temp;
93 }
94
pj_strassign(pj_str_t * dst,pj_str_t * src)95 PJ_IDEF(pj_str_t*) pj_strassign( pj_str_t *dst, pj_str_t *src )
96 {
97 dst->ptr = src->ptr;
98 dst->slen = src->slen;
99 return dst;
100 }
101
pj_strcpy(pj_str_t * dst,const pj_str_t * src)102 PJ_IDEF(pj_str_t*) pj_strcpy(pj_str_t *dst, const pj_str_t *src)
103 {
104 dst->slen = src->slen;
105 if (src->slen > 0)
106 pj_memcpy(dst->ptr, src->ptr, src->slen);
107 return dst;
108 }
109
pj_strcpy2(pj_str_t * dst,const char * src)110 PJ_IDEF(pj_str_t*) pj_strcpy2(pj_str_t *dst, const char *src)
111 {
112 dst->slen = src ? pj_ansi_strlen(src) : 0;
113 if (dst->slen > 0)
114 pj_memcpy(dst->ptr, src, dst->slen);
115 return dst;
116 }
117
pj_strncpy(pj_str_t * dst,const pj_str_t * src,pj_ssize_t max)118 PJ_IDEF(pj_str_t*) pj_strncpy( pj_str_t *dst, const pj_str_t *src,
119 pj_ssize_t max)
120 {
121 pj_assert(max >= 0);
122 if (max > src->slen) max = src->slen;
123 if (max > 0)
124 pj_memcpy(dst->ptr, src->ptr, max);
125 dst->slen = max;
126 return dst;
127 }
128
pj_strncpy_with_null(pj_str_t * dst,const pj_str_t * src,pj_ssize_t max)129 PJ_IDEF(pj_str_t*) pj_strncpy_with_null( pj_str_t *dst, const pj_str_t *src,
130 pj_ssize_t max)
131 {
132 pj_assert(max > 0);
133
134 if (max <= src->slen)
135 max = max-1;
136 else
137 max = src->slen;
138
139 pj_memcpy(dst->ptr, src->ptr, max);
140 dst->ptr[max] = '\0';
141 dst->slen = max;
142 return dst;
143 }
144
145
pj_strcmp(const pj_str_t * str1,const pj_str_t * str2)146 PJ_IDEF(int) pj_strcmp( const pj_str_t *str1, const pj_str_t *str2)
147 {
148 if (str1->slen == 0) {
149 return str2->slen==0 ? 0 : -1;
150 } else if (str2->slen == 0) {
151 return 1;
152 } else {
153 pj_size_t min = (str1->slen < str2->slen)? str1->slen : str2->slen;
154 int res = pj_memcmp(str1->ptr, str2->ptr, min);
155 if (res == 0) {
156 return (str1->slen < str2->slen) ? -1 :
157 (str1->slen == str2->slen ? 0 : 1);
158 } else {
159 return res;
160 }
161 }
162 }
163
pj_strncmp(const pj_str_t * str1,const pj_str_t * str2,pj_size_t len)164 PJ_IDEF(int) pj_strncmp( const pj_str_t *str1, const pj_str_t *str2,
165 pj_size_t len)
166 {
167 pj_str_t copy1, copy2;
168
169 if (len < (unsigned)str1->slen) {
170 copy1.ptr = str1->ptr;
171 copy1.slen = len;
172 str1 = ©1;
173 }
174
175 if (len < (unsigned)str2->slen) {
176 copy2.ptr = str2->ptr;
177 copy2.slen = len;
178 str2 = ©2;
179 }
180
181 return pj_strcmp(str1, str2);
182 }
183
pj_strncmp2(const pj_str_t * str1,const char * str2,pj_size_t len)184 PJ_IDEF(int) pj_strncmp2( const pj_str_t *str1, const char *str2,
185 pj_size_t len)
186 {
187 pj_str_t copy2;
188
189 if (str2) {
190 copy2.ptr = (char*)str2;
191 copy2.slen = pj_ansi_strlen(str2);
192 } else {
193 copy2.slen = 0;
194 }
195
196 return pj_strncmp(str1, ©2, len);
197 }
198
pj_strcmp2(const pj_str_t * str1,const char * str2)199 PJ_IDEF(int) pj_strcmp2( const pj_str_t *str1, const char *str2 )
200 {
201 pj_str_t copy2;
202
203 if (str2) {
204 copy2.ptr = (char*)str2;
205 copy2.slen = pj_ansi_strlen(str2);
206 } else {
207 copy2.ptr = NULL;
208 copy2.slen = 0;
209 }
210
211 return pj_strcmp(str1, ©2);
212 }
213
pj_stricmp(const pj_str_t * str1,const pj_str_t * str2)214 PJ_IDEF(int) pj_stricmp( const pj_str_t *str1, const pj_str_t *str2)
215 {
216 if (str1->slen == 0) {
217 return str2->slen==0 ? 0 : -1;
218 } else if (str2->slen == 0) {
219 return 1;
220 } else {
221 pj_size_t min = (str1->slen < str2->slen)? str1->slen : str2->slen;
222 int res = pj_ansi_strnicmp(str1->ptr, str2->ptr, min);
223 if (res == 0) {
224 return (str1->slen < str2->slen) ? -1 :
225 (str1->slen == str2->slen ? 0 : 1);
226 } else {
227 return res;
228 }
229 }
230 }
231
232 #if defined(PJ_HAS_STRICMP_ALNUM) && PJ_HAS_STRICMP_ALNUM!=0
strnicmp_alnum(const char * str1,const char * str2,int len)233 PJ_IDEF(int) strnicmp_alnum( const char *str1, const char *str2,
234 int len)
235 {
236 if (len==0)
237 return 0;
238 else {
239 register const pj_uint32_t *p1 = (pj_uint32_t*)str1,
240 *p2 = (pj_uint32_t*)str2;
241 while (len > 3 && (*p1 & 0x5F5F5F5F)==(*p2 & 0x5F5F5F5F))
242 ++p1, ++p2, len-=4;
243
244 if (len > 3)
245 return -1;
246 #if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN!=0
247 else if (len==3)
248 return ((*p1 & 0x005F5F5F)==(*p2 & 0x005F5F5F)) ? 0 : -1;
249 else if (len==2)
250 return ((*p1 & 0x00005F5F)==(*p2 & 0x00005F5F)) ? 0 : -1;
251 else if (len==1)
252 return ((*p1 & 0x0000005F)==(*p2 & 0x0000005F)) ? 0 : -1;
253 #else
254 else if (len==3)
255 return ((*p1 & 0x5F5F5F00)==(*p2 & 0x5F5F5F00)) ? 0 : -1;
256 else if (len==2)
257 return ((*p1 & 0x5F5F0000)==(*p2 & 0x5F5F0000)) ? 0 : -1;
258 else if (len==1)
259 return ((*p1 & 0x5F000000)==(*p2 & 0x5F000000)) ? 0 : -1;
260 #endif
261 else
262 return 0;
263 }
264 }
265
pj_stricmp_alnum(const pj_str_t * str1,const pj_str_t * str2)266 PJ_IDEF(int) pj_stricmp_alnum(const pj_str_t *str1, const pj_str_t *str2)
267 {
268 register int len = str1->slen;
269
270 if (len != str2->slen) {
271 return (len < str2->slen) ? -1 : 1;
272 } else if (len == 0) {
273 return 0;
274 } else {
275 register const pj_uint32_t *p1 = (pj_uint32_t*)str1->ptr,
276 *p2 = (pj_uint32_t*)str2->ptr;
277 while (len > 3 && (*p1 & 0x5F5F5F5F)==(*p2 & 0x5F5F5F5F))
278 ++p1, ++p2, len-=4;
279
280 if (len > 3)
281 return -1;
282 #if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN!=0
283 else if (len==3)
284 return ((*p1 & 0x005F5F5F)==(*p2 & 0x005F5F5F)) ? 0 : -1;
285 else if (len==2)
286 return ((*p1 & 0x00005F5F)==(*p2 & 0x00005F5F)) ? 0 : -1;
287 else if (len==1)
288 return ((*p1 & 0x0000005F)==(*p2 & 0x0000005F)) ? 0 : -1;
289 #else
290 else if (len==3)
291 return ((*p1 & 0x5F5F5F00)==(*p2 & 0x5F5F5F00)) ? 0 : -1;
292 else if (len==2)
293 return ((*p1 & 0x5F5F0000)==(*p2 & 0x5F5F0000)) ? 0 : -1;
294 else if (len==1)
295 return ((*p1 & 0x5F000000)==(*p2 & 0x5F000000)) ? 0 : -1;
296 #endif
297 else
298 return 0;
299 }
300 }
301 #endif /* PJ_HAS_STRICMP_ALNUM */
302
pj_stricmp2(const pj_str_t * str1,const char * str2)303 PJ_IDEF(int) pj_stricmp2( const pj_str_t *str1, const char *str2)
304 {
305 pj_str_t copy2;
306
307 if (str2) {
308 copy2.ptr = (char*)str2;
309 copy2.slen = pj_ansi_strlen(str2);
310 } else {
311 copy2.ptr = NULL;
312 copy2.slen = 0;
313 }
314
315 return pj_stricmp(str1, ©2);
316 }
317
pj_strnicmp(const pj_str_t * str1,const pj_str_t * str2,pj_size_t len)318 PJ_IDEF(int) pj_strnicmp( const pj_str_t *str1, const pj_str_t *str2,
319 pj_size_t len)
320 {
321 pj_str_t copy1, copy2;
322
323 if (len < (unsigned)str1->slen) {
324 copy1.ptr = str1->ptr;
325 copy1.slen = len;
326 str1 = ©1;
327 }
328
329 if (len < (unsigned)str2->slen) {
330 copy2.ptr = str2->ptr;
331 copy2.slen = len;
332 str2 = ©2;
333 }
334
335 return pj_stricmp(str1, str2);
336 }
337
pj_strnicmp2(const pj_str_t * str1,const char * str2,pj_size_t len)338 PJ_IDEF(int) pj_strnicmp2( const pj_str_t *str1, const char *str2,
339 pj_size_t len)
340 {
341 pj_str_t copy2;
342
343 if (str2) {
344 copy2.ptr = (char*)str2;
345 copy2.slen = pj_ansi_strlen(str2);
346 } else {
347 copy2.slen = 0;
348 }
349
350 return pj_strnicmp(str1, ©2, len);
351 }
352
pj_strcat(pj_str_t * dst,const pj_str_t * src)353 PJ_IDEF(void) pj_strcat(pj_str_t *dst, const pj_str_t *src)
354 {
355 if (src->slen) {
356 pj_memcpy(dst->ptr + dst->slen, src->ptr, src->slen);
357 dst->slen += src->slen;
358 }
359 }
360
pj_strcat2(pj_str_t * dst,const char * str)361 PJ_IDEF(void) pj_strcat2(pj_str_t *dst, const char *str)
362 {
363 pj_size_t len = str? pj_ansi_strlen(str) : 0;
364 if (len) {
365 pj_memcpy(dst->ptr + dst->slen, str, len);
366 dst->slen += len;
367 }
368 }
369
pj_strtrim(pj_str_t * str)370 PJ_IDEF(pj_str_t*) pj_strtrim( pj_str_t *str )
371 {
372 pj_strltrim(str);
373 pj_strrtrim(str);
374 return str;
375 }
376
377