cs_str.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908
  1. /**
  2. * cs_str.c
  3. * Copyright (c) 2007-2018 ls
  4. **/
  5. #include "../inc/cs.h"
  6. #include "../inc/cs_str.h"
  7. static const u_char _hex_char[] = "0123456789ABCDEF";
  8. /* everything except: ! ( ) * - . 0-9 A-Z _ a-z */
  9. static const u_char _uri_char[] = {
  10. /*
  11. 0 1 2 3 4 5 6 7 8 9 A B C D E F
  12. */
  13. /* 00 - 0F control chars */
  14. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  15. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
  16. /* 20 - 2F space " # $ % & ' + , / */
  17. 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1,
  18. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; < = > ? */
  19. 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F @ */
  20. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 50 - 5F [ \ ] ^ */
  21. 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6F ` */
  22. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /* 70 - 7F { | } ~ DEL */
  23. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */
  24. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */
  25. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A0 - AF */
  26. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* B0 - BF */
  27. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* C0 - CF */
  28. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* D0 - DF */
  29. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* E0 - EF */
  30. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - FF */
  31. };
  32. CS_API size_t cs_strerror(u_char *err, const char *fmt, ...) {
  33. size_t n;
  34. va_list ap;
  35. if (!err) {
  36. return (0);
  37. }
  38. va_start(ap, fmt);
  39. n = (size_t)vsnprintf((char *)err, CS_KB, fmt, ap);
  40. va_end(ap);
  41. return (n);
  42. }
  43. CS_API size_t cs_strlen(const u_char *s) {
  44. const u_char *str;
  45. for (str = s; *str; ++str);
  46. return (str - s);
  47. }
  48. CS_API u_char *cs_tolower(u_char *s) {
  49. u_char *c;
  50. for (c = s; *c; c++) {
  51. if (*c >= 'A' && *c <= 'Z') {
  52. *c |= 32;
  53. }
  54. }
  55. return (s);
  56. }
  57. CS_API u_char *cs_toupper(u_char *s) {
  58. u_char *c;
  59. for (c = s; *c; c++) {
  60. if (*c >= 'a' && *c <= 'z') {
  61. *c &= ~32;
  62. }
  63. }
  64. return (s);
  65. }
  66. CS_API u_char *cs_strcpy(u_char *d, const u_char *s) {
  67. u_char *save = d;
  68. for (; (*d = *s) != '\0'; ++s, ++d);
  69. return (save);
  70. }
  71. CS_API u_char *cs_strncpy(u_char *d, const u_char *s, size_t n) {
  72. if (n != 0) {
  73. u_char *to = d;
  74. const u_char *from = s;
  75. do {
  76. if ((*to++ = *from++) == 0) {
  77. /* NUL pad the remaining n-1 bytes */
  78. while (--n != 0)
  79. *to++ = 0;
  80. break;
  81. }
  82. } while (--n != 0);
  83. }
  84. return (d);
  85. }
  86. CS_API u_char *cs_strcat(u_char *d, const u_char *s) {
  87. u_char *save = d;
  88. for (; *d; ++d);
  89. while ((*d++ = *s++) != '\0');
  90. return (save);
  91. }
  92. CS_API u_char *cs_strncat(u_char *d, const u_char *s, size_t n) {
  93. u_char *dst = d;
  94. const u_char *str = s;
  95. if (n != 0) {
  96. while (*dst != 0) {
  97. dst++;
  98. }
  99. do {
  100. if ((*dst = *str++) == 0) {
  101. break;
  102. }
  103. dst++;
  104. } while (--n != 0);
  105. *dst = 0;
  106. }
  107. return (d);
  108. }
  109. CS_API int cs_strcmp(const u_char *s1, const u_char *s2) {
  110. while (*s1 == *s2++) {
  111. if (*s1++ == 0) {
  112. return (0);
  113. }
  114. }
  115. return (*s1 - *--s2);
  116. }
  117. CS_API int cs_strncmp(const u_char *s1, const u_char *s2, size_t n) {
  118. if (n == 0) {
  119. return (0);
  120. }
  121. do {
  122. if (*s1 != *s2++) {
  123. return (*s1 - *--s2);
  124. }
  125. if (*s1++ == 0) {
  126. break;
  127. }
  128. } while (--n != 0);
  129. return (0);
  130. }
  131. CS_API int cs_strcasecmp(u_char *s1, u_char *s2) {
  132. u_char c1, c2;
  133. for ( ; ; ) {
  134. c1 = *s1++;
  135. c2 = *s2++;
  136. c1 = (u_char)((c1 >= 'A' && c1 <= 'Z') ? (c1 | 0x20) : c1);
  137. c2 = (u_char)((c2 >= 'A' && c2 <= 'Z') ? (c2 | 0x20) : c2);
  138. if (c1 == c2) {
  139. if (c1) {
  140. continue;
  141. }
  142. return (0);
  143. }
  144. return (c1 - c2);
  145. }
  146. }
  147. CS_API int cs_strncasecmp(u_char *s1, u_char *s2, size_t n) {
  148. u_char c1, c2;
  149. while (n) {
  150. c1 = *s1++;
  151. c2 = *s2++;
  152. c1 = (u_char)((c1 >= 'A' && c1 <= 'Z') ? (c1 | 0x20) : c1);
  153. c2 = (u_char)((c2 >= 'A' && c2 <= 'Z') ? (c2 | 0x20) : c2);
  154. if (c1 == c2) {
  155. if (c1) {
  156. n--;
  157. continue;
  158. }
  159. return (0);
  160. }
  161. return (c1 - c2);
  162. }
  163. return (0);
  164. }
  165. CS_API u_char *cs_strchr(const u_char *s, u_char c) {
  166. const u_char *p = s;
  167. for ( ; ; ) {
  168. if (*p == c) {
  169. return ((u_char *)p);
  170. }
  171. if (!*p) {
  172. return (NULL);
  173. }
  174. p++;
  175. }
  176. }
  177. CS_API u_char *cs_strstr(const u_char *s, u_char *d) {
  178. register u_char *cp = (u_char *)s;
  179. register u_char *s1, *s2;
  180. if (!*d) {
  181. return ((u_char *)s);
  182. }
  183. while (*cp) {
  184. s1 = cp;
  185. s2 = (u_char *)d;
  186. while (*s1 && *s2 && !(*s1 - *s2)) {
  187. s1++, s2++;
  188. }
  189. if (!*s2) {
  190. return (cp);
  191. }
  192. cp++;
  193. }
  194. return (NULL);
  195. }
  196. CS_API u_char *cs_strrchr(const u_char *s, u_char c) {
  197. u_char *start = (u_char *)s;
  198. /* find end of string */
  199. while (*s++);
  200. /* search towards front */
  201. while (--s != start && *s != c);
  202. if (*s == c) { /* char found ? */
  203. return ((u_char *)s);
  204. }
  205. return (NULL);
  206. }
  207. CS_API size_t cs_strchrcpy(u_char *d, const u_char *s, u_char c) {
  208. register u_char *cp = (u_char *)s;
  209. while (*cp) {
  210. if (*cp == c) {
  211. break;
  212. }
  213. if (!*cp) {
  214. return (0);
  215. }
  216. *d++ = *cp;
  217. cp++;
  218. }
  219. return (cp - s);
  220. }
  221. CS_API u_char *cs_strdup(u_char *s, size_t n) {
  222. u_char *cp;
  223. cp = (u_char *)malloc(n + sizeof(u_char));
  224. if (cp) {
  225. cs_bcpy(cp, s, n);
  226. *(cp + n) = '\0';
  227. return (cp);
  228. }
  229. return (NULL);
  230. }
  231. CS_API cs_buf_t *cs_buf_init(u_char *p, size_t n) {
  232. cs_buf_t *buf = (cs_buf_t *)p;
  233. buf->buf = p + sizeof(cs_buf_t);
  234. buf->used = 0;
  235. buf->size = n - sizeof(cs_buf_t);
  236. return (buf);
  237. }
  238. CS_API cs_buf_t *cs_buf_new(size_t n) {
  239. cs_buf_t *buf = NULL;
  240. u_char *p = (u_char *)cs_malloc((sizeof(cs_buf_t) + n) * sizeof(u_char));
  241. if (p) {
  242. buf = (cs_buf_t *)p;
  243. buf->buf = p + sizeof(cs_buf_t);
  244. buf->size = n;
  245. buf->used = 0;
  246. }
  247. return (buf);
  248. }
  249. CS_API void cs_buf_free(cs_buf_t *buf) {
  250. if (buf) {
  251. cs_free(buf);
  252. }
  253. }
  254. CS_API size_t cs_buf_cat(cs_buf_t *d, cs_buf_t *s) {
  255. size_t n = d->used;
  256. if ((d->used + s->used) > d->size) {
  257. n = s->size - s->used;
  258. }
  259. cs_bcpy(d->buf + d->used, s->buf, n);
  260. d->used += n;
  261. return (n);
  262. }
  263. CS_API u_char *cs_buf_bcpy(cs_buf_t *buf, u_char *s, size_t n) {
  264. u_char *p = buf->buf;
  265. cs_bcpy(buf->buf + buf->used, s, n);
  266. buf->used = n;
  267. return (p);
  268. }
  269. CS_API u_char *cs_buf_bcat(cs_buf_t *buf, u_char *s, size_t n) {
  270. u_char *p = buf->buf;
  271. size_t len = n;
  272. if ((buf->used + n) > buf->size) {
  273. len = buf->size - buf->used;
  274. }
  275. cs_bcpy(buf->buf + buf->used, s, len);
  276. buf->used += len;
  277. return (p);
  278. }
  279. CS_API int cs_buf_cmp(cs_buf_t *d, cs_buf_t *s) {
  280. if (d->used == s->used) {
  281. return cs_bcmp(d->buf, s->buf, d->used);
  282. }
  283. return (int)(d->used - s->used);
  284. }
  285. CS_API cs_int_t cs_atoi(u_char *s, size_t n) {
  286. cs_int_t value, neg, c;
  287. if (n == 0) {
  288. return (0);
  289. }
  290. c = *s;
  291. if (c == '-') {
  292. neg = 1;
  293. s++;
  294. n--;
  295. } else {
  296. neg = 0;
  297. }
  298. for (value = 0; n--; s++) {
  299. if (*s < '0' || *s > '9') {
  300. return (0);
  301. }
  302. value = value * 10 + (*s - '0');
  303. }
  304. if (neg) {
  305. value = value * -1;
  306. }
  307. return (value);
  308. }
  309. CS_API cs_int64_t cs_atoi64(u_char *s, size_t n) {
  310. cs_int64_t value;
  311. cs_int_t neg, c;
  312. if (n == 0) {
  313. return (0);
  314. }
  315. c = *s;
  316. if (c == '-') {
  317. neg = 1;
  318. s++;
  319. n--;
  320. } else {
  321. neg = 0;
  322. }
  323. for (value = 0; n--; s++) {
  324. if (*s < '0' || *s > '9') {
  325. return (0);
  326. }
  327. value = value * 10 + (*s - '0');
  328. }
  329. if (neg) {
  330. value = value * -1;
  331. }
  332. return (value);
  333. }
  334. CS_API cs_uint_t cs_atou(u_char *s, size_t n) {
  335. cs_uint_t value;
  336. if (n == 0) {
  337. return (0);
  338. }
  339. for (value = 0; n--; s++) {
  340. if (*s < '0' || *s > '9') {
  341. return (0);
  342. }
  343. value = value * 10 + (*s - '0');
  344. }
  345. return (value);
  346. }
  347. CS_API cs_int_t cs_htoi(u_char *s, size_t n) {
  348. u_char c, ch;
  349. cs_int_t value;
  350. for (value = 0; n--; s++){
  351. ch = *s;
  352. if (ch >= '0' && ch <= '9') {
  353. value = value * 16 + (ch - '0');
  354. continue;
  355. }
  356. c = (u_char) (ch | 0x20);
  357. if (c >= 'a' && c <= 'f') {
  358. value = value * 16 + (c - 'a' + 10);
  359. continue;
  360. }
  361. }
  362. return (value);
  363. }
  364. CS_API cs_uint_t cs_htou(u_char *s, size_t n) {
  365. u_char c, ch;
  366. cs_uint_t value;
  367. for (value = 0; n--; s++){
  368. ch = *s;
  369. if (ch >= '0' && ch <= '9') {
  370. value = value * 16 + (ch - '0');
  371. continue;
  372. }
  373. c = (u_char) (ch | 0x20);
  374. if (c >= 'a' && c <= 'f') {
  375. value = value * 16 + (c - 'a' + 10);
  376. continue;
  377. }
  378. }
  379. return (value);
  380. }
  381. CS_API cs_int_t cs_btoi(u_char *s, size_t n) {
  382. u_char c, ch;
  383. cs_int_t value;
  384. for (value = 0; n--; s++) {
  385. ch = _hex_char[(*s) >> 4];
  386. if (ch >= '0' && ch <= '9') {
  387. value = value * 16 + (ch - '0');
  388. } else {
  389. c = (u_char) (ch | 0x20);
  390. if (c >= 'a' && c <= 'f') {
  391. value = value * 16 + (c - 'a' + 10);
  392. }
  393. }
  394. ch = _hex_char[(*s) & 0x0f];
  395. if (ch >= '0' && ch <= '9') {
  396. value = value * 16 + (ch - '0');
  397. } else {
  398. c = (u_char) (ch | 0x20);
  399. if (c >= 'a' && c <= 'f') {
  400. value = value * 16 + (c - 'a' + 10);
  401. }
  402. }
  403. }
  404. return (value);
  405. }
  406. CS_API cs_int_t cs_btou(u_char *s, size_t n) {
  407. u_char c, ch;
  408. cs_uint_t value;
  409. for (value = 0; n--; s++) {
  410. ch = _hex_char[(*s) >> 4];
  411. if (ch >= '0' && ch <= '9') {
  412. value = value * 16 + (ch - '0');
  413. } else {
  414. c = (u_char) (ch | 0x20);
  415. if (c >= 'a' && c <= 'f') {
  416. value = value * 16 + (c - 'a' + 10);
  417. }
  418. }
  419. ch = _hex_char[(*s) & 0x0f];
  420. if (ch >= '0' && ch <= '9') {
  421. value = value * 16 + (ch - '0');
  422. } else {
  423. c = (u_char) (ch | 0x20);
  424. if (c >= 'a' && c <= 'f') {
  425. value = value * 16 + (c - 'a' + 10);
  426. }
  427. }
  428. }
  429. return (value);
  430. }
  431. CS_API size_t cs_uri_escape(u_char *d, const u_char *s) {
  432. u_char *cp = d;
  433. size_t n;
  434. if (d == NULL) {
  435. n = 0;
  436. while (*s) {
  437. if (_uri_char[*s]) {
  438. n++;
  439. }
  440. s++;
  441. }
  442. return (n);
  443. }
  444. while (*s) {
  445. if (_uri_char[*s]) {
  446. *d++ = '%';
  447. *d++ = _hex_char[(*s) >> 4];
  448. *d++ = _hex_char[(*s) & 0x0f];
  449. s++;
  450. } else {
  451. *d++ = *s++;
  452. }
  453. }
  454. return (d - cp);
  455. }
  456. CS_API size_t cs_uri_unescape(u_char *d, const u_char *s) {
  457. register unsigned char high, low;
  458. u_char *cp = d;
  459. while ((*s) != '\0') {
  460. if (*s == '%') {
  461. X2C(*(s + 1), high);
  462. if (high < 0x10) {
  463. X2C(*(s + 2), low);
  464. if (low < 0x10) {
  465. high = (u_char)((high << 4) | low);
  466. *d = high;
  467. s += 2;
  468. }
  469. }
  470. } else if (*s == '+') {
  471. *d = ' ';
  472. } else {
  473. *d = *s;
  474. }
  475. d++;
  476. s++;
  477. }
  478. return (d - cp);
  479. }
  480. /* from ngx_string.c */
  481. CS_API size_t cs_json_escape(u_char *d, u_char *s, size_t n) {
  482. u_char ch, *cp = d;
  483. size_t len;
  484. if (d == NULL) {
  485. len = 0;
  486. while (n) {
  487. ch = *s++;
  488. if (ch == '\\' || ch == '"') {
  489. len++;
  490. } else if (ch <= 0x1f) {
  491. len += sizeof("\\u001F") - 2;
  492. }
  493. n--;
  494. }
  495. return (len);
  496. }
  497. while (n) {
  498. ch = *s++;
  499. if (ch > 0x1f) {
  500. if (ch == '\\' || ch == '"') {
  501. *d++ = '\\';
  502. }
  503. *d++ = ch;
  504. } else {
  505. *d++ = '\\'; *d++ = 'u'; *d++ = '0'; *d++ = '0';
  506. *d++ = '0' + (ch >> 4);
  507. ch &= 0xf;
  508. *d++ = (ch < 10) ? ('0' + ch) : ('A' + ch - 10);
  509. }
  510. n--;
  511. }
  512. return (d - cp);
  513. }
  514. CS_API size_t cs_hex_dump(u_char *d, u_char *s, size_t n) {
  515. u_char *cp = d;
  516. while (n--) {
  517. *d++ = _hex_char[*s >> 4];
  518. *d++ = _hex_char[*s++ & 0xf];
  519. }
  520. return (d - cp);
  521. }
  522. CS_API size_t cs_hex_undump(u_char *d, const u_char *s, size_t n) {
  523. size_t i = 0;
  524. register u_char ch, digit;
  525. u_char *cp = d;
  526. for (i = 0; i < n; i++) {
  527. X2C(*(s + i) ,ch);
  528. ch = ch << 4;
  529. i++;
  530. X2C(*(s + i), digit);
  531. ch += digit;
  532. *d++ = ch;
  533. }
  534. return (d - cp);
  535. }
  536. /* from ngx_string.c */
  537. static void _cs_base64_encode_internal(
  538. cs_buf_t *dst, cs_buf_t *src, const u_char *basis, cs_uint_t padding) {
  539. u_char *d, *s;
  540. size_t len;
  541. len = src->used;
  542. s = src->buf;
  543. d = dst->buf;
  544. while (len > 2) {
  545. *d++ = basis[(s[0] >> 2) & 0x3f];
  546. *d++ = basis[((s[0] & 3) << 4) | (s[1] >> 4)];
  547. *d++ = basis[((s[1] & 0x0f) << 2) | (s[2] >> 6)];
  548. *d++ = basis[s[2] & 0x3f];
  549. s += 3;
  550. len -= 3;
  551. }
  552. if (len) {
  553. *d++ = basis[(s[0] >> 2) & 0x3f];
  554. if (len == 1) {
  555. *d++ = basis[(s[0] & 3) << 4];
  556. if (padding) {
  557. *d++ = '=';
  558. }
  559. } else {
  560. *d++ = basis[((s[0] & 3) << 4) | (s[1] >> 4)];
  561. *d++ = basis[(s[1] & 0x0f) << 2];
  562. }
  563. if (padding) {
  564. *d++ = '=';
  565. }
  566. }
  567. dst->used = d - dst->buf;
  568. }
  569. /* from ngx_string.c */
  570. CS_API void cs_base64_encode(cs_buf_t *d, cs_buf_t *s) {
  571. static u_char basis64[] =
  572. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  573. _cs_base64_encode_internal(d, s, basis64, 1);
  574. }
  575. /* from ngx_string.c */
  576. static cs_int_t _cs_base64_decode_internal(
  577. cs_buf_t *dst, cs_buf_t *src, const u_char *basis) {
  578. size_t len;
  579. u_char *d, *s;
  580. for (len = 0; len < src->used; len++) {
  581. if (src->buf[len] == '=') {
  582. break;
  583. }
  584. if (basis[src->buf[len]] == 77) {
  585. return (CS_ERR);
  586. }
  587. }
  588. if (len % 4 == 1) {
  589. return (CS_ERR);
  590. }
  591. s = src->buf;
  592. d = dst->buf;
  593. while (len > 3) {
  594. *d++ = (u_char) (basis[s[0]] << 2 | basis[s[1]] >> 4);
  595. *d++ = (u_char) (basis[s[1]] << 4 | basis[s[2]] >> 2);
  596. *d++ = (u_char) (basis[s[2]] << 6 | basis[s[3]]);
  597. s += 4;
  598. len -= 4;
  599. }
  600. if (len > 1) {
  601. *d++ = (u_char) (basis[s[0]] << 2 | basis[s[1]] >> 4);
  602. }
  603. if (len > 2) {
  604. *d++ = (u_char) (basis[s[1]] << 4 | basis[s[2]] >> 2);
  605. }
  606. dst->used = d - dst->buf;
  607. return (CS_OK);
  608. }
  609. /* from ngx_string.c */
  610. CS_API cs_int_t cs_base64_decode(cs_buf_t *d, cs_buf_t *s) {
  611. static u_char basis64[] = {
  612. 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
  613. 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
  614. 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77, 77, 63,
  615. 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77,
  616. 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
  617. 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 77,
  618. 77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
  619. 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77,
  620. 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
  621. 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
  622. 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
  623. 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
  624. 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
  625. 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
  626. 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
  627. 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77
  628. };
  629. return _cs_base64_decode_internal(d, s, basis64);
  630. }
  631. /* from ngx_string.c */
  632. CS_API cs_uint_t cs_utf8_decode(u_char **s, size_t n) {
  633. size_t len;
  634. cs_uint_t u, i, valid;
  635. u = **s;
  636. if(u > 0xf0){
  637. u &= 0x07;
  638. valid = 0xffff;
  639. len = 3;
  640. } else if (u > 0xe0) {
  641. u &= 0x0f;
  642. valid = 0x7ff;
  643. len = 2;
  644. } else if (u > 0xc0) {
  645. u &= 0x1f;
  646. valid = 0x7f;
  647. len = 1;
  648. } else{
  649. (*s)++;
  650. return (0xffffffff);
  651. }
  652. if (n - 1 < len) {
  653. return (0xfffffffe);
  654. }
  655. (*s)++;
  656. while (len) {
  657. i = *(*s)++;
  658. if (i < 0x80) {
  659. return (0xffffffff);
  660. }
  661. u = (u << 6) | (i & 0x3f);
  662. len--;
  663. }
  664. if (u > valid) {
  665. return (u);
  666. }
  667. return (0xffffffff);
  668. }
  669. /* from ngx_string.c */
  670. CS_API size_t cs_utf8_length(u_char *s, size_t n) {
  671. u_char c, *last;
  672. size_t len;
  673. last = s + n;
  674. for (len = 0; s < last; len++) {
  675. c = *s;
  676. if (c < 0x80) {
  677. s++;
  678. continue;
  679. }
  680. if (cs_utf8_decode(&s, n) > 0x10ffff) {
  681. /* invalid UTF-8 */
  682. return n;
  683. }
  684. }
  685. return (len);
  686. }
  687. /*
  688. djb2
  689. this algorithm (k=33) was first reported by dan bernstein many years ago
  690. in comp.lang.c.
  691. another version of this algorithm (now favored by bernstein) uses xor:
  692. hash(i) = hash(i - 1) * 33 ^ str[i];
  693. the magic of number 33 (why it works better than many other constants,
  694. prime or not)
  695. has never been adequately explained.
  696. */
  697. CS_API cs_uint_t cs_hash_djb2(const u_char *s) {
  698. const u_char *cp = s;
  699. cs_uint_t hash = 5381;
  700. while (*cp) {
  701. hash = ((hash << 5) + hash) + *cp; /* hash = hash * 33 + c */
  702. cp++;
  703. }
  704. return (hash);
  705. }
  706. CS_API cs_uint64_t cs_hash_djb2_64(const u_char *s) {
  707. const u_char *cp = s;
  708. cs_uint64_t hash = 5381;
  709. while (*cp) {
  710. hash = ((hash << 5) + hash) + *cp; /* hash = hash * 33 + c */
  711. cp++;
  712. }
  713. return (hash);
  714. }