xref: /unit/src/nxt_string.c (revision 0)
1*0Sigor@sysoev.ru 
2*0Sigor@sysoev.ru /*
3*0Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
4*0Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
5*0Sigor@sysoev.ru  */
6*0Sigor@sysoev.ru 
7*0Sigor@sysoev.ru #include <nxt_main.h>
8*0Sigor@sysoev.ru 
9*0Sigor@sysoev.ru 
10*0Sigor@sysoev.ru nxt_str_t *
11*0Sigor@sysoev.ru nxt_str_alloc(nxt_mem_pool_t *mp, size_t len)
12*0Sigor@sysoev.ru {
13*0Sigor@sysoev.ru     nxt_str_t  *s;
14*0Sigor@sysoev.ru 
15*0Sigor@sysoev.ru     /* The string data is allocated aligned to be close to nxt_str_t. */
16*0Sigor@sysoev.ru     s = nxt_mem_alloc(mp, sizeof(nxt_str_t) + len);
17*0Sigor@sysoev.ru 
18*0Sigor@sysoev.ru     if (nxt_fast_path(s != NULL)) {
19*0Sigor@sysoev.ru         s->len = len;
20*0Sigor@sysoev.ru         s->data = (u_char *) s + sizeof(nxt_str_t);
21*0Sigor@sysoev.ru     }
22*0Sigor@sysoev.ru 
23*0Sigor@sysoev.ru     return s;
24*0Sigor@sysoev.ru }
25*0Sigor@sysoev.ru 
26*0Sigor@sysoev.ru 
27*0Sigor@sysoev.ru /*
28*0Sigor@sysoev.ru  * nxt_str_dup() creates a new string with a copy of a source string.
29*0Sigor@sysoev.ru  * If length of the source string is zero, then the new string anyway
30*0Sigor@sysoev.ru  * gets a pointer somewhere in mem_pool.
31*0Sigor@sysoev.ru  */
32*0Sigor@sysoev.ru 
33*0Sigor@sysoev.ru nxt_str_t *
34*0Sigor@sysoev.ru nxt_str_dup(nxt_mem_pool_t *mp, nxt_str_t *dst, const nxt_str_t *src)
35*0Sigor@sysoev.ru {
36*0Sigor@sysoev.ru     u_char  *p;
37*0Sigor@sysoev.ru 
38*0Sigor@sysoev.ru     if (dst == NULL) {
39*0Sigor@sysoev.ru         /* The string data is allocated aligned to be close to nxt_str_t. */
40*0Sigor@sysoev.ru         dst = nxt_mem_alloc(mp, sizeof(nxt_str_t) + src->len);
41*0Sigor@sysoev.ru         if (nxt_slow_path(dst == NULL)) {
42*0Sigor@sysoev.ru             return NULL;
43*0Sigor@sysoev.ru         }
44*0Sigor@sysoev.ru 
45*0Sigor@sysoev.ru         p = (u_char *) dst;
46*0Sigor@sysoev.ru         p += sizeof(nxt_str_t);
47*0Sigor@sysoev.ru         dst->data = p;
48*0Sigor@sysoev.ru 
49*0Sigor@sysoev.ru     } else {
50*0Sigor@sysoev.ru         dst->data = nxt_mem_nalloc(mp, src->len);
51*0Sigor@sysoev.ru         if (nxt_slow_path(dst->data == NULL)) {
52*0Sigor@sysoev.ru             return NULL;
53*0Sigor@sysoev.ru         }
54*0Sigor@sysoev.ru     }
55*0Sigor@sysoev.ru 
56*0Sigor@sysoev.ru     nxt_memcpy(dst->data, src->data, src->len);
57*0Sigor@sysoev.ru     dst->len = src->len;
58*0Sigor@sysoev.ru 
59*0Sigor@sysoev.ru     return dst;
60*0Sigor@sysoev.ru }
61*0Sigor@sysoev.ru 
62*0Sigor@sysoev.ru 
63*0Sigor@sysoev.ru /*
64*0Sigor@sysoev.ru  * nxt_str_copy() creates a C style zero-terminated copy of a source
65*0Sigor@sysoev.ru  * nxt_str_t.  The function is intended to create strings suitable
66*0Sigor@sysoev.ru  * for libc and kernel interfaces so result is pointer to char instead
67*0Sigor@sysoev.ru  * of u_char to minimize casts.  The copy is aligned to 2 bytes thus
68*0Sigor@sysoev.ru  * the lowest bit may be used as marker.
69*0Sigor@sysoev.ru  */
70*0Sigor@sysoev.ru 
71*0Sigor@sysoev.ru char *
72*0Sigor@sysoev.ru nxt_str_copy(nxt_mem_pool_t *mp, const nxt_str_t *src)
73*0Sigor@sysoev.ru {
74*0Sigor@sysoev.ru     char  *p, *dst;
75*0Sigor@sysoev.ru 
76*0Sigor@sysoev.ru     dst = nxt_mem_align(mp, 2, src->len + 1);
77*0Sigor@sysoev.ru 
78*0Sigor@sysoev.ru     if (nxt_fast_path(dst != NULL)) {
79*0Sigor@sysoev.ru         p = nxt_cpymem(dst, src->data, src->len);
80*0Sigor@sysoev.ru         *p = '\0';
81*0Sigor@sysoev.ru     }
82*0Sigor@sysoev.ru 
83*0Sigor@sysoev.ru     return dst;
84*0Sigor@sysoev.ru }
85*0Sigor@sysoev.ru 
86*0Sigor@sysoev.ru 
87*0Sigor@sysoev.ru void
88*0Sigor@sysoev.ru nxt_memcpy_lowcase(u_char *dst, const u_char *src, size_t len)
89*0Sigor@sysoev.ru {
90*0Sigor@sysoev.ru     u_char  c;
91*0Sigor@sysoev.ru 
92*0Sigor@sysoev.ru     while (len != 0) {
93*0Sigor@sysoev.ru         c = *src++;
94*0Sigor@sysoev.ru         *dst++ = nxt_lowcase(c);
95*0Sigor@sysoev.ru         len--;
96*0Sigor@sysoev.ru     }
97*0Sigor@sysoev.ru }
98*0Sigor@sysoev.ru 
99*0Sigor@sysoev.ru 
100*0Sigor@sysoev.ru u_char *
101*0Sigor@sysoev.ru nxt_cpystrn(u_char *dst, const u_char *src, size_t len)
102*0Sigor@sysoev.ru {
103*0Sigor@sysoev.ru     if (len == 0) {
104*0Sigor@sysoev.ru         return dst;
105*0Sigor@sysoev.ru     }
106*0Sigor@sysoev.ru 
107*0Sigor@sysoev.ru     while (--len != 0) {
108*0Sigor@sysoev.ru         *dst = *src;
109*0Sigor@sysoev.ru 
110*0Sigor@sysoev.ru         if (*dst == '\0') {
111*0Sigor@sysoev.ru             return dst;
112*0Sigor@sysoev.ru         }
113*0Sigor@sysoev.ru 
114*0Sigor@sysoev.ru         dst++;
115*0Sigor@sysoev.ru         src++;
116*0Sigor@sysoev.ru     }
117*0Sigor@sysoev.ru 
118*0Sigor@sysoev.ru     *dst = '\0';
119*0Sigor@sysoev.ru 
120*0Sigor@sysoev.ru     return dst;
121*0Sigor@sysoev.ru }
122*0Sigor@sysoev.ru 
123*0Sigor@sysoev.ru 
124*0Sigor@sysoev.ru nxt_int_t
125*0Sigor@sysoev.ru nxt_strcasecmp(const u_char *s1, const u_char *s2)
126*0Sigor@sysoev.ru {
127*0Sigor@sysoev.ru     u_char     c1, c2;
128*0Sigor@sysoev.ru     nxt_int_t  n;
129*0Sigor@sysoev.ru 
130*0Sigor@sysoev.ru     for ( ;; ) {
131*0Sigor@sysoev.ru         c1 = *s1++;
132*0Sigor@sysoev.ru         c2 = *s2++;
133*0Sigor@sysoev.ru 
134*0Sigor@sysoev.ru         c1 = nxt_lowcase(c1);
135*0Sigor@sysoev.ru         c2 = nxt_lowcase(c2);
136*0Sigor@sysoev.ru 
137*0Sigor@sysoev.ru         n = c1 - c2;
138*0Sigor@sysoev.ru 
139*0Sigor@sysoev.ru         if (n != 0) {
140*0Sigor@sysoev.ru             return n;
141*0Sigor@sysoev.ru         }
142*0Sigor@sysoev.ru 
143*0Sigor@sysoev.ru         if (c1 == 0) {
144*0Sigor@sysoev.ru             return 0;
145*0Sigor@sysoev.ru         }
146*0Sigor@sysoev.ru     }
147*0Sigor@sysoev.ru }
148*0Sigor@sysoev.ru 
149*0Sigor@sysoev.ru 
150*0Sigor@sysoev.ru nxt_int_t
151*0Sigor@sysoev.ru nxt_strncasecmp(const u_char *s1, const u_char *s2, size_t len)
152*0Sigor@sysoev.ru {
153*0Sigor@sysoev.ru     u_char     c1, c2;
154*0Sigor@sysoev.ru     nxt_int_t  n;
155*0Sigor@sysoev.ru 
156*0Sigor@sysoev.ru     while (len-- != 0) {
157*0Sigor@sysoev.ru         c1 = *s1++;
158*0Sigor@sysoev.ru         c2 = *s2++;
159*0Sigor@sysoev.ru 
160*0Sigor@sysoev.ru         c1 = nxt_lowcase(c1);
161*0Sigor@sysoev.ru         c2 = nxt_lowcase(c2);
162*0Sigor@sysoev.ru 
163*0Sigor@sysoev.ru         n = c1 - c2;
164*0Sigor@sysoev.ru 
165*0Sigor@sysoev.ru         if (n != 0) {
166*0Sigor@sysoev.ru             return n;
167*0Sigor@sysoev.ru         }
168*0Sigor@sysoev.ru 
169*0Sigor@sysoev.ru         if (c1 == 0) {
170*0Sigor@sysoev.ru             return 0;
171*0Sigor@sysoev.ru         }
172*0Sigor@sysoev.ru     }
173*0Sigor@sysoev.ru 
174*0Sigor@sysoev.ru     return 0;
175*0Sigor@sysoev.ru }
176*0Sigor@sysoev.ru 
177*0Sigor@sysoev.ru 
178*0Sigor@sysoev.ru nxt_int_t
179*0Sigor@sysoev.ru nxt_memcasecmp(const u_char *s1, const u_char *s2, size_t len)
180*0Sigor@sysoev.ru {
181*0Sigor@sysoev.ru     u_char     c1, c2;
182*0Sigor@sysoev.ru     nxt_int_t  n;
183*0Sigor@sysoev.ru 
184*0Sigor@sysoev.ru     while (len-- != 0) {
185*0Sigor@sysoev.ru         c1 = *s1++;
186*0Sigor@sysoev.ru         c2 = *s2++;
187*0Sigor@sysoev.ru 
188*0Sigor@sysoev.ru         c1 = nxt_lowcase(c1);
189*0Sigor@sysoev.ru         c2 = nxt_lowcase(c2);
190*0Sigor@sysoev.ru 
191*0Sigor@sysoev.ru         n = c1 - c2;
192*0Sigor@sysoev.ru 
193*0Sigor@sysoev.ru         if (n != 0) {
194*0Sigor@sysoev.ru             return n;
195*0Sigor@sysoev.ru         }
196*0Sigor@sysoev.ru     }
197*0Sigor@sysoev.ru 
198*0Sigor@sysoev.ru     return 0;
199*0Sigor@sysoev.ru }
200*0Sigor@sysoev.ru 
201*0Sigor@sysoev.ru 
202*0Sigor@sysoev.ru /*
203*0Sigor@sysoev.ru  * nxt_memstrn() is intended for search of static substring "ss"
204*0Sigor@sysoev.ru  * with known length "len" in string "s" limited by parameter "end".
205*0Sigor@sysoev.ru  * Zeros are ignored in both strings.
206*0Sigor@sysoev.ru  */
207*0Sigor@sysoev.ru 
208*0Sigor@sysoev.ru u_char *
209*0Sigor@sysoev.ru nxt_memstrn(const u_char *s, const u_char *end, const char *ss, size_t len)
210*0Sigor@sysoev.ru {
211*0Sigor@sysoev.ru     u_char  c1, c2, *s2;
212*0Sigor@sysoev.ru 
213*0Sigor@sysoev.ru     s2 = (u_char *) ss;
214*0Sigor@sysoev.ru     c2 = *s2++;
215*0Sigor@sysoev.ru     len--;
216*0Sigor@sysoev.ru 
217*0Sigor@sysoev.ru     while (s < end) {
218*0Sigor@sysoev.ru         c1 = *s++;
219*0Sigor@sysoev.ru 
220*0Sigor@sysoev.ru         if (c1 == c2) {
221*0Sigor@sysoev.ru 
222*0Sigor@sysoev.ru             if (s + len > end) {
223*0Sigor@sysoev.ru                 return NULL;
224*0Sigor@sysoev.ru             }
225*0Sigor@sysoev.ru 
226*0Sigor@sysoev.ru             if (nxt_memcmp(s, s2, len) == 0) {
227*0Sigor@sysoev.ru                 return (u_char *) s - 1;
228*0Sigor@sysoev.ru             }
229*0Sigor@sysoev.ru         }
230*0Sigor@sysoev.ru     }
231*0Sigor@sysoev.ru 
232*0Sigor@sysoev.ru     return NULL;
233*0Sigor@sysoev.ru }
234*0Sigor@sysoev.ru 
235*0Sigor@sysoev.ru 
236*0Sigor@sysoev.ru /*
237*0Sigor@sysoev.ru  * nxt_strcasestrn() is intended for caseless search of static substring
238*0Sigor@sysoev.ru  * "ss" with known length "len" in string "s" limited by parameter "end".
239*0Sigor@sysoev.ru  * Zeros are ignored in both strings.
240*0Sigor@sysoev.ru  */
241*0Sigor@sysoev.ru 
242*0Sigor@sysoev.ru u_char *
243*0Sigor@sysoev.ru nxt_memcasestrn(const u_char *s, const u_char *end, const char *ss, size_t len)
244*0Sigor@sysoev.ru {
245*0Sigor@sysoev.ru     u_char  c1, c2, *s2;
246*0Sigor@sysoev.ru 
247*0Sigor@sysoev.ru     s2 = (u_char *) ss;
248*0Sigor@sysoev.ru     c2 = *s2++;
249*0Sigor@sysoev.ru     c2 = nxt_lowcase(c2);
250*0Sigor@sysoev.ru     len--;
251*0Sigor@sysoev.ru 
252*0Sigor@sysoev.ru     while (s < end) {
253*0Sigor@sysoev.ru         c1 = *s++;
254*0Sigor@sysoev.ru         c1 = nxt_lowcase(c1);
255*0Sigor@sysoev.ru 
256*0Sigor@sysoev.ru         if (c1 == c2) {
257*0Sigor@sysoev.ru 
258*0Sigor@sysoev.ru             if (s + len > end) {
259*0Sigor@sysoev.ru                 return NULL;
260*0Sigor@sysoev.ru             }
261*0Sigor@sysoev.ru 
262*0Sigor@sysoev.ru             if (nxt_memcasecmp(s, s2, len) == 0) {
263*0Sigor@sysoev.ru                 return (u_char *) s - 1;
264*0Sigor@sysoev.ru             }
265*0Sigor@sysoev.ru         }
266*0Sigor@sysoev.ru     }
267*0Sigor@sysoev.ru 
268*0Sigor@sysoev.ru     return NULL;
269*0Sigor@sysoev.ru }
270*0Sigor@sysoev.ru 
271*0Sigor@sysoev.ru 
272*0Sigor@sysoev.ru /*
273*0Sigor@sysoev.ru  * nxt_rstrstrn() is intended to search for static substring "ss"
274*0Sigor@sysoev.ru  * with known length "len" in string "s" limited by parameter "end"
275*0Sigor@sysoev.ru  * in reverse order.  Zeros are ignored in both strings.
276*0Sigor@sysoev.ru  */
277*0Sigor@sysoev.ru 
278*0Sigor@sysoev.ru u_char *
279*0Sigor@sysoev.ru nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t len)
280*0Sigor@sysoev.ru {
281*0Sigor@sysoev.ru     u_char        c1, c2;
282*0Sigor@sysoev.ru     const u_char  *s1, *s2;
283*0Sigor@sysoev.ru 
284*0Sigor@sysoev.ru     s1 = end - len;
285*0Sigor@sysoev.ru     s2 = (u_char *) ss;
286*0Sigor@sysoev.ru     c2 = *s2++;
287*0Sigor@sysoev.ru     len--;
288*0Sigor@sysoev.ru 
289*0Sigor@sysoev.ru     while (s < s1) {
290*0Sigor@sysoev.ru         c1 = *s1;
291*0Sigor@sysoev.ru 
292*0Sigor@sysoev.ru         if (c1 == c2) {
293*0Sigor@sysoev.ru             if (nxt_memcmp(s1 + 1, s2, len) == 0) {
294*0Sigor@sysoev.ru                 return (u_char *) s1;
295*0Sigor@sysoev.ru             }
296*0Sigor@sysoev.ru         }
297*0Sigor@sysoev.ru 
298*0Sigor@sysoev.ru         s1--;
299*0Sigor@sysoev.ru     }
300*0Sigor@sysoev.ru 
301*0Sigor@sysoev.ru     return NULL;
302*0Sigor@sysoev.ru }
303*0Sigor@sysoev.ru 
304*0Sigor@sysoev.ru 
305*0Sigor@sysoev.ru size_t
306*0Sigor@sysoev.ru nxt_str_strip(u_char *start, u_char *end)
307*0Sigor@sysoev.ru {
308*0Sigor@sysoev.ru     u_char  *p;
309*0Sigor@sysoev.ru 
310*0Sigor@sysoev.ru     for (p = end - 1; p >= start; p--) {
311*0Sigor@sysoev.ru         if (*p != NXT_CR && *p != NXT_LF) {
312*0Sigor@sysoev.ru             break;
313*0Sigor@sysoev.ru         }
314*0Sigor@sysoev.ru     }
315*0Sigor@sysoev.ru 
316*0Sigor@sysoev.ru     return (p + 1) - start;
317*0Sigor@sysoev.ru }
318