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