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