xref: /unit/src/nxt_string.c (revision 65)
10Sigor@sysoev.ru 
20Sigor@sysoev.ru /*
30Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
40Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
50Sigor@sysoev.ru  */
60Sigor@sysoev.ru 
70Sigor@sysoev.ru #include <nxt_main.h>
80Sigor@sysoev.ru 
90Sigor@sysoev.ru 
100Sigor@sysoev.ru nxt_str_t *
11*65Sigor@sysoev.ru nxt_str_alloc(nxt_mp_t *mp, size_t length)
120Sigor@sysoev.ru {
130Sigor@sysoev.ru     nxt_str_t  *s;
140Sigor@sysoev.ru 
1510Sigor@sysoev.ru     /* The string start is allocated aligned to be close to nxt_str_t. */
16*65Sigor@sysoev.ru     s = nxt_mp_get(mp, sizeof(nxt_str_t) + length);
170Sigor@sysoev.ru 
180Sigor@sysoev.ru     if (nxt_fast_path(s != NULL)) {
1910Sigor@sysoev.ru         s->length = length;
2010Sigor@sysoev.ru         s->start = (u_char *) s + sizeof(nxt_str_t);
210Sigor@sysoev.ru     }
220Sigor@sysoev.ru 
230Sigor@sysoev.ru     return s;
240Sigor@sysoev.ru }
250Sigor@sysoev.ru 
260Sigor@sysoev.ru 
270Sigor@sysoev.ru /*
280Sigor@sysoev.ru  * nxt_str_dup() creates a new string with a copy of a source string.
290Sigor@sysoev.ru  * If length of the source string is zero, then the new string anyway
300Sigor@sysoev.ru  * gets a pointer somewhere in mem_pool.
310Sigor@sysoev.ru  */
320Sigor@sysoev.ru 
330Sigor@sysoev.ru nxt_str_t *
34*65Sigor@sysoev.ru nxt_str_dup(nxt_mp_t *mp, nxt_str_t *dst, const nxt_str_t *src)
350Sigor@sysoev.ru {
360Sigor@sysoev.ru     u_char  *p;
370Sigor@sysoev.ru 
380Sigor@sysoev.ru     if (dst == NULL) {
3910Sigor@sysoev.ru         /* The string start is allocated aligned to be close to nxt_str_t. */
40*65Sigor@sysoev.ru         dst = nxt_mp_get(mp, sizeof(nxt_str_t) + src->length);
410Sigor@sysoev.ru         if (nxt_slow_path(dst == NULL)) {
420Sigor@sysoev.ru             return NULL;
430Sigor@sysoev.ru         }
440Sigor@sysoev.ru 
450Sigor@sysoev.ru         p = (u_char *) dst;
460Sigor@sysoev.ru         p += sizeof(nxt_str_t);
4710Sigor@sysoev.ru         dst->start = p;
480Sigor@sysoev.ru 
490Sigor@sysoev.ru     } else {
50*65Sigor@sysoev.ru         dst->start = nxt_mp_nget(mp, src->length);
5110Sigor@sysoev.ru         if (nxt_slow_path(dst->start == NULL)) {
520Sigor@sysoev.ru             return NULL;
530Sigor@sysoev.ru         }
540Sigor@sysoev.ru     }
550Sigor@sysoev.ru 
5610Sigor@sysoev.ru     nxt_memcpy(dst->start, src->start, src->length);
5710Sigor@sysoev.ru     dst->length = src->length;
580Sigor@sysoev.ru 
590Sigor@sysoev.ru     return dst;
600Sigor@sysoev.ru }
610Sigor@sysoev.ru 
620Sigor@sysoev.ru 
630Sigor@sysoev.ru /*
640Sigor@sysoev.ru  * nxt_str_copy() creates a C style zero-terminated copy of a source
650Sigor@sysoev.ru  * nxt_str_t.  The function is intended to create strings suitable
660Sigor@sysoev.ru  * for libc and kernel interfaces so result is pointer to char instead
670Sigor@sysoev.ru  * of u_char to minimize casts.  The copy is aligned to 2 bytes thus
680Sigor@sysoev.ru  * the lowest bit may be used as marker.
690Sigor@sysoev.ru  */
700Sigor@sysoev.ru 
710Sigor@sysoev.ru char *
72*65Sigor@sysoev.ru nxt_str_copy(nxt_mp_t *mp, const nxt_str_t *src)
730Sigor@sysoev.ru {
740Sigor@sysoev.ru     char  *p, *dst;
750Sigor@sysoev.ru 
76*65Sigor@sysoev.ru     dst = nxt_mp_align(mp, 2, src->length + 1);
770Sigor@sysoev.ru 
780Sigor@sysoev.ru     if (nxt_fast_path(dst != NULL)) {
7910Sigor@sysoev.ru         p = nxt_cpymem(dst, src->start, src->length);
800Sigor@sysoev.ru         *p = '\0';
810Sigor@sysoev.ru     }
820Sigor@sysoev.ru 
830Sigor@sysoev.ru     return dst;
840Sigor@sysoev.ru }
850Sigor@sysoev.ru 
860Sigor@sysoev.ru 
870Sigor@sysoev.ru void
8810Sigor@sysoev.ru nxt_memcpy_lowcase(u_char *dst, const u_char *src, size_t length)
890Sigor@sysoev.ru {
900Sigor@sysoev.ru     u_char  c;
910Sigor@sysoev.ru 
9210Sigor@sysoev.ru     while (length != 0) {
930Sigor@sysoev.ru         c = *src++;
940Sigor@sysoev.ru         *dst++ = nxt_lowcase(c);
9510Sigor@sysoev.ru         length--;
960Sigor@sysoev.ru     }
970Sigor@sysoev.ru }
980Sigor@sysoev.ru 
990Sigor@sysoev.ru 
1000Sigor@sysoev.ru u_char *
10110Sigor@sysoev.ru nxt_cpystrn(u_char *dst, const u_char *src, size_t length)
1020Sigor@sysoev.ru {
10310Sigor@sysoev.ru     if (length == 0) {
1040Sigor@sysoev.ru         return dst;
1050Sigor@sysoev.ru     }
1060Sigor@sysoev.ru 
10710Sigor@sysoev.ru     while (--length != 0) {
1080Sigor@sysoev.ru         *dst = *src;
1090Sigor@sysoev.ru 
1100Sigor@sysoev.ru         if (*dst == '\0') {
1110Sigor@sysoev.ru             return dst;
1120Sigor@sysoev.ru         }
1130Sigor@sysoev.ru 
1140Sigor@sysoev.ru         dst++;
1150Sigor@sysoev.ru         src++;
1160Sigor@sysoev.ru     }
1170Sigor@sysoev.ru 
1180Sigor@sysoev.ru     *dst = '\0';
1190Sigor@sysoev.ru 
1200Sigor@sysoev.ru     return dst;
1210Sigor@sysoev.ru }
1220Sigor@sysoev.ru 
1230Sigor@sysoev.ru 
1240Sigor@sysoev.ru nxt_int_t
1250Sigor@sysoev.ru nxt_strcasecmp(const u_char *s1, const u_char *s2)
1260Sigor@sysoev.ru {
1270Sigor@sysoev.ru     u_char     c1, c2;
1280Sigor@sysoev.ru     nxt_int_t  n;
1290Sigor@sysoev.ru 
1300Sigor@sysoev.ru     for ( ;; ) {
1310Sigor@sysoev.ru         c1 = *s1++;
1320Sigor@sysoev.ru         c2 = *s2++;
1330Sigor@sysoev.ru 
1340Sigor@sysoev.ru         c1 = nxt_lowcase(c1);
1350Sigor@sysoev.ru         c2 = nxt_lowcase(c2);
1360Sigor@sysoev.ru 
1370Sigor@sysoev.ru         n = c1 - c2;
1380Sigor@sysoev.ru 
1390Sigor@sysoev.ru         if (n != 0) {
1400Sigor@sysoev.ru             return n;
1410Sigor@sysoev.ru         }
1420Sigor@sysoev.ru 
1430Sigor@sysoev.ru         if (c1 == 0) {
1440Sigor@sysoev.ru             return 0;
1450Sigor@sysoev.ru         }
1460Sigor@sysoev.ru     }
1470Sigor@sysoev.ru }
1480Sigor@sysoev.ru 
1490Sigor@sysoev.ru 
1500Sigor@sysoev.ru nxt_int_t
15110Sigor@sysoev.ru nxt_strncasecmp(const u_char *s1, const u_char *s2, size_t length)
1520Sigor@sysoev.ru {
1530Sigor@sysoev.ru     u_char     c1, c2;
1540Sigor@sysoev.ru     nxt_int_t  n;
1550Sigor@sysoev.ru 
15610Sigor@sysoev.ru     while (length-- != 0) {
1570Sigor@sysoev.ru         c1 = *s1++;
1580Sigor@sysoev.ru         c2 = *s2++;
1590Sigor@sysoev.ru 
1600Sigor@sysoev.ru         c1 = nxt_lowcase(c1);
1610Sigor@sysoev.ru         c2 = nxt_lowcase(c2);
1620Sigor@sysoev.ru 
1630Sigor@sysoev.ru         n = c1 - c2;
1640Sigor@sysoev.ru 
1650Sigor@sysoev.ru         if (n != 0) {
1660Sigor@sysoev.ru             return n;
1670Sigor@sysoev.ru         }
1680Sigor@sysoev.ru 
1690Sigor@sysoev.ru         if (c1 == 0) {
1700Sigor@sysoev.ru             return 0;
1710Sigor@sysoev.ru         }
1720Sigor@sysoev.ru     }
1730Sigor@sysoev.ru 
1740Sigor@sysoev.ru     return 0;
1750Sigor@sysoev.ru }
1760Sigor@sysoev.ru 
1770Sigor@sysoev.ru 
1780Sigor@sysoev.ru nxt_int_t
17910Sigor@sysoev.ru nxt_memcasecmp(const u_char *s1, const u_char *s2, size_t length)
1800Sigor@sysoev.ru {
1810Sigor@sysoev.ru     u_char     c1, c2;
1820Sigor@sysoev.ru     nxt_int_t  n;
1830Sigor@sysoev.ru 
18410Sigor@sysoev.ru     while (length-- != 0) {
1850Sigor@sysoev.ru         c1 = *s1++;
1860Sigor@sysoev.ru         c2 = *s2++;
1870Sigor@sysoev.ru 
1880Sigor@sysoev.ru         c1 = nxt_lowcase(c1);
1890Sigor@sysoev.ru         c2 = nxt_lowcase(c2);
1900Sigor@sysoev.ru 
1910Sigor@sysoev.ru         n = c1 - c2;
1920Sigor@sysoev.ru 
1930Sigor@sysoev.ru         if (n != 0) {
1940Sigor@sysoev.ru             return n;
1950Sigor@sysoev.ru         }
1960Sigor@sysoev.ru     }
1970Sigor@sysoev.ru 
1980Sigor@sysoev.ru     return 0;
1990Sigor@sysoev.ru }
2000Sigor@sysoev.ru 
2010Sigor@sysoev.ru 
2020Sigor@sysoev.ru /*
2030Sigor@sysoev.ru  * nxt_memstrn() is intended for search of static substring "ss"
20410Sigor@sysoev.ru  * with known length "length" in string "s" limited by parameter "end".
2050Sigor@sysoev.ru  * Zeros are ignored in both strings.
2060Sigor@sysoev.ru  */
2070Sigor@sysoev.ru 
2080Sigor@sysoev.ru u_char *
20910Sigor@sysoev.ru nxt_memstrn(const u_char *s, const u_char *end, const char *ss, size_t length)
2100Sigor@sysoev.ru {
2110Sigor@sysoev.ru     u_char  c1, c2, *s2;
2120Sigor@sysoev.ru 
2130Sigor@sysoev.ru     s2 = (u_char *) ss;
2140Sigor@sysoev.ru     c2 = *s2++;
21510Sigor@sysoev.ru     length--;
2160Sigor@sysoev.ru 
2170Sigor@sysoev.ru     while (s < end) {
2180Sigor@sysoev.ru         c1 = *s++;
2190Sigor@sysoev.ru 
2200Sigor@sysoev.ru         if (c1 == c2) {
2210Sigor@sysoev.ru 
22210Sigor@sysoev.ru             if (s + length > end) {
2230Sigor@sysoev.ru                 return NULL;
2240Sigor@sysoev.ru             }
2250Sigor@sysoev.ru 
22610Sigor@sysoev.ru             if (nxt_memcmp(s, s2, length) == 0) {
2270Sigor@sysoev.ru                 return (u_char *) s - 1;
2280Sigor@sysoev.ru             }
2290Sigor@sysoev.ru         }
2300Sigor@sysoev.ru     }
2310Sigor@sysoev.ru 
2320Sigor@sysoev.ru     return NULL;
2330Sigor@sysoev.ru }
2340Sigor@sysoev.ru 
2350Sigor@sysoev.ru 
2360Sigor@sysoev.ru /*
2370Sigor@sysoev.ru  * nxt_strcasestrn() is intended for caseless search of static substring
23810Sigor@sysoev.ru  * "ss" with known length "length" in string "s" limited by parameter "end".
2390Sigor@sysoev.ru  * Zeros are ignored in both strings.
2400Sigor@sysoev.ru  */
2410Sigor@sysoev.ru 
2420Sigor@sysoev.ru u_char *
24310Sigor@sysoev.ru nxt_memcasestrn(const u_char *s, const u_char *end, const char *ss,
24410Sigor@sysoev.ru     size_t length)
2450Sigor@sysoev.ru {
2460Sigor@sysoev.ru     u_char  c1, c2, *s2;
2470Sigor@sysoev.ru 
2480Sigor@sysoev.ru     s2 = (u_char *) ss;
2490Sigor@sysoev.ru     c2 = *s2++;
2500Sigor@sysoev.ru     c2 = nxt_lowcase(c2);
25110Sigor@sysoev.ru     length--;
2520Sigor@sysoev.ru 
2530Sigor@sysoev.ru     while (s < end) {
2540Sigor@sysoev.ru         c1 = *s++;
2550Sigor@sysoev.ru         c1 = nxt_lowcase(c1);
2560Sigor@sysoev.ru 
2570Sigor@sysoev.ru         if (c1 == c2) {
2580Sigor@sysoev.ru 
25910Sigor@sysoev.ru             if (s + length > end) {
2600Sigor@sysoev.ru                 return NULL;
2610Sigor@sysoev.ru             }
2620Sigor@sysoev.ru 
26310Sigor@sysoev.ru             if (nxt_memcasecmp(s, s2, length) == 0) {
2640Sigor@sysoev.ru                 return (u_char *) s - 1;
2650Sigor@sysoev.ru             }
2660Sigor@sysoev.ru         }
2670Sigor@sysoev.ru     }
2680Sigor@sysoev.ru 
2690Sigor@sysoev.ru     return NULL;
2700Sigor@sysoev.ru }
2710Sigor@sysoev.ru 
2720Sigor@sysoev.ru 
2730Sigor@sysoev.ru /*
2740Sigor@sysoev.ru  * nxt_rstrstrn() is intended to search for static substring "ss"
27510Sigor@sysoev.ru  * with known length "length" in string "s" limited by parameter "end"
2760Sigor@sysoev.ru  * in reverse order.  Zeros are ignored in both strings.
2770Sigor@sysoev.ru  */
2780Sigor@sysoev.ru 
2790Sigor@sysoev.ru u_char *
28010Sigor@sysoev.ru nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t length)
2810Sigor@sysoev.ru {
2820Sigor@sysoev.ru     u_char        c1, c2;
2830Sigor@sysoev.ru     const u_char  *s1, *s2;
2840Sigor@sysoev.ru 
28510Sigor@sysoev.ru     s1 = end - length;
2860Sigor@sysoev.ru     s2 = (u_char *) ss;
2870Sigor@sysoev.ru     c2 = *s2++;
28810Sigor@sysoev.ru     length--;
2890Sigor@sysoev.ru 
2900Sigor@sysoev.ru     while (s < s1) {
2910Sigor@sysoev.ru         c1 = *s1;
2920Sigor@sysoev.ru 
2930Sigor@sysoev.ru         if (c1 == c2) {
29410Sigor@sysoev.ru             if (nxt_memcmp(s1 + 1, s2, length) == 0) {
2950Sigor@sysoev.ru                 return (u_char *) s1;
2960Sigor@sysoev.ru             }
2970Sigor@sysoev.ru         }
2980Sigor@sysoev.ru 
2990Sigor@sysoev.ru         s1--;
3000Sigor@sysoev.ru     }
3010Sigor@sysoev.ru 
3020Sigor@sysoev.ru     return NULL;
3030Sigor@sysoev.ru }
3040Sigor@sysoev.ru 
3050Sigor@sysoev.ru 
3060Sigor@sysoev.ru size_t
3070Sigor@sysoev.ru nxt_str_strip(u_char *start, u_char *end)
3080Sigor@sysoev.ru {
3090Sigor@sysoev.ru     u_char  *p;
3100Sigor@sysoev.ru 
3110Sigor@sysoev.ru     for (p = end - 1; p >= start; p--) {
3120Sigor@sysoev.ru         if (*p != NXT_CR && *p != NXT_LF) {
3130Sigor@sysoev.ru             break;
3140Sigor@sysoev.ru         }
3150Sigor@sysoev.ru     }
3160Sigor@sysoev.ru 
3170Sigor@sysoev.ru     return (p + 1) - start;
3180Sigor@sysoev.ru }
319