xref: /unit/src/nxt_string.c (revision 216:07257705cd64)
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_mp_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_mp_get(mp, sizeof(nxt_str_t) + length);
17 
18     if (nxt_fast_path(s != NULL)) {
19         s->length = length;
20         s->start = nxt_pointer_to(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_mp_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_mp_get(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_mp_nget(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_cstrz() 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.
68  */
69 
70 char *
71 nxt_str_cstrz(nxt_mp_t *mp, const nxt_str_t *src)
72 {
73     char  *p, *dst;
74 
75     dst = nxt_mp_alloc(mp, src->length + 1);
76 
77     if (nxt_fast_path(dst != NULL)) {
78         p = nxt_cpymem(dst, src->start, src->length);
79         *p = '\0';
80     }
81 
82     return dst;
83 }
84 
85 
86 void
87 nxt_memcpy_lowcase(u_char *dst, const u_char *src, size_t length)
88 {
89     u_char  c;
90 
91     while (length != 0) {
92         c = *src++;
93         *dst++ = nxt_lowcase(c);
94         length--;
95     }
96 }
97 
98 
99 u_char *
100 nxt_cpystrn(u_char *dst, const u_char *src, size_t length)
101 {
102     if (length == 0) {
103         return dst;
104     }
105 
106     while (--length != 0) {
107         *dst = *src;
108 
109         if (*dst == '\0') {
110             return dst;
111         }
112 
113         dst++;
114         src++;
115     }
116 
117     *dst = '\0';
118 
119     return dst;
120 }
121 
122 
123 nxt_int_t
124 nxt_strcasecmp(const u_char *s1, const u_char *s2)
125 {
126     u_char     c1, c2;
127     nxt_int_t  n;
128 
129     for ( ;; ) {
130         c1 = *s1++;
131         c2 = *s2++;
132 
133         c1 = nxt_lowcase(c1);
134         c2 = nxt_lowcase(c2);
135 
136         n = c1 - c2;
137 
138         if (n != 0) {
139             return n;
140         }
141 
142         if (c1 == 0) {
143             return 0;
144         }
145     }
146 }
147 
148 
149 nxt_int_t
150 nxt_strncasecmp(const u_char *s1, const u_char *s2, size_t length)
151 {
152     u_char     c1, c2;
153     nxt_int_t  n;
154 
155     while (length-- != 0) {
156         c1 = *s1++;
157         c2 = *s2++;
158 
159         c1 = nxt_lowcase(c1);
160         c2 = nxt_lowcase(c2);
161 
162         n = c1 - c2;
163 
164         if (n != 0) {
165             return n;
166         }
167 
168         if (c1 == 0) {
169             return 0;
170         }
171     }
172 
173     return 0;
174 }
175 
176 
177 nxt_int_t
178 nxt_memcasecmp(const u_char *s1, const u_char *s2, size_t length)
179 {
180     u_char     c1, c2;
181     nxt_int_t  n;
182 
183     while (length-- != 0) {
184         c1 = *s1++;
185         c2 = *s2++;
186 
187         c1 = nxt_lowcase(c1);
188         c2 = nxt_lowcase(c2);
189 
190         n = c1 - c2;
191 
192         if (n != 0) {
193             return n;
194         }
195     }
196 
197     return 0;
198 }
199 
200 
201 /*
202  * nxt_memstrn() is intended for search of static substring "ss"
203  * with known length "length" in string "s" limited by parameter "end".
204  * Zeros are ignored in both strings.
205  */
206 
207 u_char *
208 nxt_memstrn(const u_char *s, const u_char *end, const char *ss, size_t length)
209 {
210     u_char  c1, c2, *s2;
211 
212     s2 = (u_char *) ss;
213     c2 = *s2++;
214     length--;
215 
216     while (s < end) {
217         c1 = *s++;
218 
219         if (c1 == c2) {
220 
221             if (s + length > end) {
222                 return NULL;
223             }
224 
225             if (nxt_memcmp(s, s2, length) == 0) {
226                 return (u_char *) s - 1;
227             }
228         }
229     }
230 
231     return NULL;
232 }
233 
234 
235 /*
236  * nxt_strcasestrn() is intended for caseless search of static substring
237  * "ss" with known length "length" in string "s" limited by parameter "end".
238  * Zeros are ignored in both strings.
239  */
240 
241 u_char *
242 nxt_memcasestrn(const u_char *s, const u_char *end, const char *ss,
243     size_t length)
244 {
245     u_char  c1, c2, *s2;
246 
247     s2 = (u_char *) ss;
248     c2 = *s2++;
249     c2 = nxt_lowcase(c2);
250     length--;
251 
252     while (s < end) {
253         c1 = *s++;
254         c1 = nxt_lowcase(c1);
255 
256         if (c1 == c2) {
257 
258             if (s + length > end) {
259                 return NULL;
260             }
261 
262             if (nxt_memcasecmp(s, s2, length) == 0) {
263                 return (u_char *) s - 1;
264             }
265         }
266     }
267 
268     return NULL;
269 }
270 
271 
272 /*
273  * nxt_rstrstrn() is intended to search for static substring "ss"
274  * with known length "length" in string "s" limited by parameter "end"
275  * in reverse order.  Zeros are ignored in both strings.
276  */
277 
278 u_char *
279 nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t length)
280 {
281     u_char        c1, c2;
282     const u_char  *s1, *s2;
283 
284     s1 = end - length;
285     s2 = (u_char *) ss;
286     c2 = *s2++;
287     length--;
288 
289     while (s < s1) {
290         c1 = *s1;
291 
292         if (c1 == c2) {
293             if (nxt_memcmp(s1 + 1, s2, length) == 0) {
294                 return (u_char *) s1;
295             }
296         }
297 
298         s1--;
299     }
300 
301     return NULL;
302 }
303 
304 
305 size_t
306 nxt_str_strip(u_char *start, u_char *end)
307 {
308     u_char  *p;
309 
310     for (p = end - 1; p >= start; p--) {
311         if (*p != NXT_CR && *p != NXT_LF) {
312             break;
313         }
314     }
315 
316     return (p + 1) - start;
317 }
318