xref: /unit/src/nxt_string.c (revision 0:a63ceefd6ab0)
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 len)
12 {
13     nxt_str_t  *s;
14 
15     /* The string data is allocated aligned to be close to nxt_str_t. */
16     s = nxt_mem_alloc(mp, sizeof(nxt_str_t) + len);
17 
18     if (nxt_fast_path(s != NULL)) {
19         s->len = len;
20         s->data = (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 data is allocated aligned to be close to nxt_str_t. */
40         dst = nxt_mem_alloc(mp, sizeof(nxt_str_t) + src->len);
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->data = p;
48 
49     } else {
50         dst->data = nxt_mem_nalloc(mp, src->len);
51         if (nxt_slow_path(dst->data == NULL)) {
52             return NULL;
53         }
54     }
55 
56     nxt_memcpy(dst->data, src->data, src->len);
57     dst->len = src->len;
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->len + 1);
77 
78     if (nxt_fast_path(dst != NULL)) {
79         p = nxt_cpymem(dst, src->data, src->len);
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 len)
89 {
90     u_char  c;
91 
92     while (len != 0) {
93         c = *src++;
94         *dst++ = nxt_lowcase(c);
95         len--;
96     }
97 }
98 
99 
100 u_char *
101 nxt_cpystrn(u_char *dst, const u_char *src, size_t len)
102 {
103     if (len == 0) {
104         return dst;
105     }
106 
107     while (--len != 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 len)
152 {
153     u_char     c1, c2;
154     nxt_int_t  n;
155 
156     while (len-- != 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 len)
180 {
181     u_char     c1, c2;
182     nxt_int_t  n;
183 
184     while (len-- != 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 "len" 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 len)
210 {
211     u_char  c1, c2, *s2;
212 
213     s2 = (u_char *) ss;
214     c2 = *s2++;
215     len--;
216 
217     while (s < end) {
218         c1 = *s++;
219 
220         if (c1 == c2) {
221 
222             if (s + len > end) {
223                 return NULL;
224             }
225 
226             if (nxt_memcmp(s, s2, len) == 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 "len" 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, size_t len)
244 {
245     u_char  c1, c2, *s2;
246 
247     s2 = (u_char *) ss;
248     c2 = *s2++;
249     c2 = nxt_lowcase(c2);
250     len--;
251 
252     while (s < end) {
253         c1 = *s++;
254         c1 = nxt_lowcase(c1);
255 
256         if (c1 == c2) {
257 
258             if (s + len > end) {
259                 return NULL;
260             }
261 
262             if (nxt_memcasecmp(s, s2, len) == 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 "len" 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 len)
280 {
281     u_char        c1, c2;
282     const u_char  *s1, *s2;
283 
284     s1 = end - len;
285     s2 = (u_char *) ss;
286     c2 = *s2++;
287     len--;
288 
289     while (s < s1) {
290         c1 = *s1;
291 
292         if (c1 == c2) {
293             if (nxt_memcmp(s1 + 1, s2, len) == 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