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