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 = &copy1;
173     }
174 
175     if (len < (unsigned)str2->slen) {
176 	copy2.ptr = str2->ptr;
177 	copy2.slen = len;
178 	str2 = &copy2;
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, &copy2, 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, &copy2);
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, &copy2);
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 = &copy1;
327     }
328 
329     if (len < (unsigned)str2->slen) {
330 	copy2.ptr = str2->ptr;
331 	copy2.slen = len;
332 	str2 = &copy2;
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, &copy2, 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