|
@@ -0,0 +1,908 @@
|
|
|
+/**
|
|
|
+ * cs_str.c
|
|
|
+ * Copyright (c) 2007-2018 ls
|
|
|
+ **/
|
|
|
+#include "../inc/cs.h"
|
|
|
+#include "../inc/cs_str.h"
|
|
|
+
|
|
|
+static const u_char _hex_char[] = "0123456789ABCDEF";
|
|
|
+
|
|
|
+/* everything except: ! ( ) * - . 0-9 A-Z _ a-z */
|
|
|
+static const u_char _uri_char[] = {
|
|
|
+ /*
|
|
|
+ 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
|
+ */
|
|
|
+ /* 00 - 0F control chars */
|
|
|
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
|
|
|
+ /* 20 - 2F space " # $ % & ' + , / */
|
|
|
+ 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1,
|
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; < = > ? */
|
|
|
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F @ */
|
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 50 - 5F [ \ ] ^ */
|
|
|
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6F ` */
|
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /* 70 - 7F { | } ~ DEL */
|
|
|
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */
|
|
|
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */
|
|
|
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A0 - AF */
|
|
|
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* B0 - BF */
|
|
|
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* C0 - CF */
|
|
|
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* D0 - DF */
|
|
|
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* E0 - EF */
|
|
|
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - FF */
|
|
|
+};
|
|
|
+
|
|
|
+CS_API size_t cs_strerror(u_char *err, const char *fmt, ...) {
|
|
|
+ size_t n;
|
|
|
+ va_list ap;
|
|
|
+
|
|
|
+ if (!err) {
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+
|
|
|
+ va_start(ap, fmt);
|
|
|
+ n = (size_t)vsnprintf((char *)err, CS_KB, fmt, ap);
|
|
|
+ va_end(ap);
|
|
|
+
|
|
|
+ return (n);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API size_t cs_strlen(const u_char *s) {
|
|
|
+ const u_char *str;
|
|
|
+
|
|
|
+ for (str = s; *str; ++str);
|
|
|
+
|
|
|
+ return (str - s);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API u_char *cs_tolower(u_char *s) {
|
|
|
+ u_char *c;
|
|
|
+
|
|
|
+ for (c = s; *c; c++) {
|
|
|
+ if (*c >= 'A' && *c <= 'Z') {
|
|
|
+ *c |= 32;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (s);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API u_char *cs_toupper(u_char *s) {
|
|
|
+ u_char *c;
|
|
|
+
|
|
|
+ for (c = s; *c; c++) {
|
|
|
+ if (*c >= 'a' && *c <= 'z') {
|
|
|
+ *c &= ~32;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (s);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API u_char *cs_strcpy(u_char *d, const u_char *s) {
|
|
|
+ u_char *save = d;
|
|
|
+
|
|
|
+ for (; (*d = *s) != '\0'; ++s, ++d);
|
|
|
+
|
|
|
+ return (save);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API u_char *cs_strncpy(u_char *d, const u_char *s, size_t n) {
|
|
|
+ if (n != 0) {
|
|
|
+ u_char *to = d;
|
|
|
+ const u_char *from = s;
|
|
|
+
|
|
|
+ do {
|
|
|
+ if ((*to++ = *from++) == 0) {
|
|
|
+ /* NUL pad the remaining n-1 bytes */
|
|
|
+ while (--n != 0)
|
|
|
+ *to++ = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } while (--n != 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ return (d);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API u_char *cs_strcat(u_char *d, const u_char *s) {
|
|
|
+ u_char *save = d;
|
|
|
+
|
|
|
+ for (; *d; ++d);
|
|
|
+ while ((*d++ = *s++) != '\0');
|
|
|
+
|
|
|
+ return (save);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API u_char *cs_strncat(u_char *d, const u_char *s, size_t n) {
|
|
|
+ u_char *dst = d;
|
|
|
+ const u_char *str = s;
|
|
|
+
|
|
|
+ if (n != 0) {
|
|
|
+ while (*dst != 0) {
|
|
|
+ dst++;
|
|
|
+ }
|
|
|
+ do {
|
|
|
+ if ((*dst = *str++) == 0) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ dst++;
|
|
|
+ } while (--n != 0);
|
|
|
+ *dst = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (d);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API int cs_strcmp(const u_char *s1, const u_char *s2) {
|
|
|
+ while (*s1 == *s2++) {
|
|
|
+ if (*s1++ == 0) {
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (*s1 - *--s2);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API int cs_strncmp(const u_char *s1, const u_char *s2, size_t n) {
|
|
|
+ if (n == 0) {
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+
|
|
|
+ do {
|
|
|
+ if (*s1 != *s2++) {
|
|
|
+ return (*s1 - *--s2);
|
|
|
+ }
|
|
|
+ if (*s1++ == 0) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } while (--n != 0);
|
|
|
+
|
|
|
+ return (0);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API int cs_strcasecmp(u_char *s1, u_char *s2) {
|
|
|
+ u_char c1, c2;
|
|
|
+
|
|
|
+ for ( ; ; ) {
|
|
|
+ c1 = *s1++;
|
|
|
+ c2 = *s2++;
|
|
|
+
|
|
|
+ c1 = (u_char)((c1 >= 'A' && c1 <= 'Z') ? (c1 | 0x20) : c1);
|
|
|
+ c2 = (u_char)((c2 >= 'A' && c2 <= 'Z') ? (c2 | 0x20) : c2);
|
|
|
+
|
|
|
+ if (c1 == c2) {
|
|
|
+ if (c1) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+
|
|
|
+ return (c1 - c2);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+CS_API int cs_strncasecmp(u_char *s1, u_char *s2, size_t n) {
|
|
|
+ u_char c1, c2;
|
|
|
+
|
|
|
+ while (n) {
|
|
|
+ c1 = *s1++;
|
|
|
+ c2 = *s2++;
|
|
|
+
|
|
|
+ c1 = (u_char)((c1 >= 'A' && c1 <= 'Z') ? (c1 | 0x20) : c1);
|
|
|
+ c2 = (u_char)((c2 >= 'A' && c2 <= 'Z') ? (c2 | 0x20) : c2);
|
|
|
+
|
|
|
+ if (c1 == c2) {
|
|
|
+ if (c1) {
|
|
|
+ n--;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+ return (c1 - c2);
|
|
|
+ }
|
|
|
+
|
|
|
+ return (0);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API u_char *cs_strchr(const u_char *s, u_char c) {
|
|
|
+ const u_char *p = s;
|
|
|
+
|
|
|
+ for ( ; ; ) {
|
|
|
+ if (*p == c) {
|
|
|
+ return ((u_char *)p);
|
|
|
+ }
|
|
|
+ if (!*p) {
|
|
|
+ return (NULL);
|
|
|
+ }
|
|
|
+ p++;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+CS_API u_char *cs_strstr(const u_char *s, u_char *d) {
|
|
|
+ register u_char *cp = (u_char *)s;
|
|
|
+ register u_char *s1, *s2;
|
|
|
+
|
|
|
+ if (!*d) {
|
|
|
+ return ((u_char *)s);
|
|
|
+ }
|
|
|
+
|
|
|
+ while (*cp) {
|
|
|
+ s1 = cp;
|
|
|
+ s2 = (u_char *)d;
|
|
|
+
|
|
|
+ while (*s1 && *s2 && !(*s1 - *s2)) {
|
|
|
+ s1++, s2++;
|
|
|
+ }
|
|
|
+ if (!*s2) {
|
|
|
+ return (cp);
|
|
|
+ }
|
|
|
+ cp++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (NULL);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API u_char *cs_strrchr(const u_char *s, u_char c) {
|
|
|
+ u_char *start = (u_char *)s;
|
|
|
+
|
|
|
+ /* find end of string */
|
|
|
+ while (*s++);
|
|
|
+ /* search towards front */
|
|
|
+ while (--s != start && *s != c);
|
|
|
+
|
|
|
+ if (*s == c) { /* char found ? */
|
|
|
+ return ((u_char *)s);
|
|
|
+ }
|
|
|
+
|
|
|
+ return (NULL);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API size_t cs_strchrcpy(u_char *d, const u_char *s, u_char c) {
|
|
|
+ register u_char *cp = (u_char *)s;
|
|
|
+
|
|
|
+ while (*cp) {
|
|
|
+ if (*cp == c) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!*cp) {
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+ *d++ = *cp;
|
|
|
+ cp++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (cp - s);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API u_char *cs_strdup(u_char *s, size_t n) {
|
|
|
+ u_char *cp;
|
|
|
+
|
|
|
+ cp = (u_char *)malloc(n + sizeof(u_char));
|
|
|
+ if (cp) {
|
|
|
+ cs_bcpy(cp, s, n);
|
|
|
+ *(cp + n) = '\0';
|
|
|
+
|
|
|
+ return (cp);
|
|
|
+ }
|
|
|
+
|
|
|
+ return (NULL);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API cs_buf_t *cs_buf_init(u_char *p, size_t n) {
|
|
|
+ cs_buf_t *buf = (cs_buf_t *)p;
|
|
|
+
|
|
|
+ buf->buf = p + sizeof(cs_buf_t);
|
|
|
+ buf->used = 0;
|
|
|
+ buf->size = n - sizeof(cs_buf_t);
|
|
|
+
|
|
|
+ return (buf);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API cs_buf_t *cs_buf_new(size_t n) {
|
|
|
+ cs_buf_t *buf = NULL;
|
|
|
+
|
|
|
+ u_char *p = (u_char *)cs_malloc((sizeof(cs_buf_t) + n) * sizeof(u_char));
|
|
|
+ if (p) {
|
|
|
+ buf = (cs_buf_t *)p;
|
|
|
+ buf->buf = p + sizeof(cs_buf_t);
|
|
|
+ buf->size = n;
|
|
|
+ buf->used = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (buf);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API void cs_buf_free(cs_buf_t *buf) {
|
|
|
+ if (buf) {
|
|
|
+ cs_free(buf);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+CS_API size_t cs_buf_cat(cs_buf_t *d, cs_buf_t *s) {
|
|
|
+ size_t n = d->used;
|
|
|
+
|
|
|
+ if ((d->used + s->used) > d->size) {
|
|
|
+ n = s->size - s->used;
|
|
|
+ }
|
|
|
+
|
|
|
+ cs_bcpy(d->buf + d->used, s->buf, n);
|
|
|
+ d->used += n;
|
|
|
+
|
|
|
+ return (n);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API u_char *cs_buf_bcpy(cs_buf_t *buf, u_char *s, size_t n) {
|
|
|
+ u_char *p = buf->buf;
|
|
|
+
|
|
|
+ cs_bcpy(buf->buf + buf->used, s, n);
|
|
|
+ buf->used = n;
|
|
|
+
|
|
|
+ return (p);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API u_char *cs_buf_bcat(cs_buf_t *buf, u_char *s, size_t n) {
|
|
|
+ u_char *p = buf->buf;
|
|
|
+ size_t len = n;
|
|
|
+
|
|
|
+ if ((buf->used + n) > buf->size) {
|
|
|
+ len = buf->size - buf->used;
|
|
|
+ }
|
|
|
+
|
|
|
+ cs_bcpy(buf->buf + buf->used, s, len);
|
|
|
+ buf->used += len;
|
|
|
+
|
|
|
+ return (p);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API int cs_buf_cmp(cs_buf_t *d, cs_buf_t *s) {
|
|
|
+ if (d->used == s->used) {
|
|
|
+ return cs_bcmp(d->buf, s->buf, d->used);
|
|
|
+ }
|
|
|
+ return (int)(d->used - s->used);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API cs_int_t cs_atoi(u_char *s, size_t n) {
|
|
|
+ cs_int_t value, neg, c;
|
|
|
+
|
|
|
+ if (n == 0) {
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+
|
|
|
+ c = *s;
|
|
|
+ if (c == '-') {
|
|
|
+ neg = 1;
|
|
|
+ s++;
|
|
|
+ n--;
|
|
|
+ } else {
|
|
|
+ neg = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (value = 0; n--; s++) {
|
|
|
+ if (*s < '0' || *s > '9') {
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+
|
|
|
+ value = value * 10 + (*s - '0');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (neg) {
|
|
|
+ value = value * -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (value);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API cs_int64_t cs_atoi64(u_char *s, size_t n) {
|
|
|
+ cs_int64_t value;
|
|
|
+ cs_int_t neg, c;
|
|
|
+
|
|
|
+ if (n == 0) {
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+
|
|
|
+ c = *s;
|
|
|
+ if (c == '-') {
|
|
|
+ neg = 1;
|
|
|
+ s++;
|
|
|
+ n--;
|
|
|
+ } else {
|
|
|
+ neg = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (value = 0; n--; s++) {
|
|
|
+ if (*s < '0' || *s > '9') {
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+
|
|
|
+ value = value * 10 + (*s - '0');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (neg) {
|
|
|
+ value = value * -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (value);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API cs_uint_t cs_atou(u_char *s, size_t n) {
|
|
|
+ cs_uint_t value;
|
|
|
+
|
|
|
+ if (n == 0) {
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (value = 0; n--; s++) {
|
|
|
+ if (*s < '0' || *s > '9') {
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+
|
|
|
+ value = value * 10 + (*s - '0');
|
|
|
+ }
|
|
|
+
|
|
|
+ return (value);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API cs_int_t cs_htoi(u_char *s, size_t n) {
|
|
|
+ u_char c, ch;
|
|
|
+ cs_int_t value;
|
|
|
+
|
|
|
+ for (value = 0; n--; s++){
|
|
|
+ ch = *s;
|
|
|
+ if (ch >= '0' && ch <= '9') {
|
|
|
+ value = value * 16 + (ch - '0');
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ c = (u_char) (ch | 0x20);
|
|
|
+
|
|
|
+ if (c >= 'a' && c <= 'f') {
|
|
|
+ value = value * 16 + (c - 'a' + 10);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (value);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API cs_uint_t cs_htou(u_char *s, size_t n) {
|
|
|
+ u_char c, ch;
|
|
|
+ cs_uint_t value;
|
|
|
+
|
|
|
+ for (value = 0; n--; s++){
|
|
|
+ ch = *s;
|
|
|
+ if (ch >= '0' && ch <= '9') {
|
|
|
+ value = value * 16 + (ch - '0');
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ c = (u_char) (ch | 0x20);
|
|
|
+
|
|
|
+ if (c >= 'a' && c <= 'f') {
|
|
|
+ value = value * 16 + (c - 'a' + 10);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (value);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API cs_int_t cs_btoi(u_char *s, size_t n) {
|
|
|
+ u_char c, ch;
|
|
|
+ cs_int_t value;
|
|
|
+
|
|
|
+ for (value = 0; n--; s++) {
|
|
|
+ ch = _hex_char[(*s) >> 4];
|
|
|
+ if (ch >= '0' && ch <= '9') {
|
|
|
+ value = value * 16 + (ch - '0');
|
|
|
+ } else {
|
|
|
+ c = (u_char) (ch | 0x20);
|
|
|
+
|
|
|
+ if (c >= 'a' && c <= 'f') {
|
|
|
+ value = value * 16 + (c - 'a' + 10);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ch = _hex_char[(*s) & 0x0f];
|
|
|
+ if (ch >= '0' && ch <= '9') {
|
|
|
+ value = value * 16 + (ch - '0');
|
|
|
+ } else {
|
|
|
+ c = (u_char) (ch | 0x20);
|
|
|
+
|
|
|
+ if (c >= 'a' && c <= 'f') {
|
|
|
+ value = value * 16 + (c - 'a' + 10);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (value);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API cs_int_t cs_btou(u_char *s, size_t n) {
|
|
|
+ u_char c, ch;
|
|
|
+ cs_uint_t value;
|
|
|
+
|
|
|
+ for (value = 0; n--; s++) {
|
|
|
+ ch = _hex_char[(*s) >> 4];
|
|
|
+ if (ch >= '0' && ch <= '9') {
|
|
|
+ value = value * 16 + (ch - '0');
|
|
|
+ } else {
|
|
|
+ c = (u_char) (ch | 0x20);
|
|
|
+
|
|
|
+ if (c >= 'a' && c <= 'f') {
|
|
|
+ value = value * 16 + (c - 'a' + 10);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ch = _hex_char[(*s) & 0x0f];
|
|
|
+ if (ch >= '0' && ch <= '9') {
|
|
|
+ value = value * 16 + (ch - '0');
|
|
|
+ } else {
|
|
|
+ c = (u_char) (ch | 0x20);
|
|
|
+
|
|
|
+ if (c >= 'a' && c <= 'f') {
|
|
|
+ value = value * 16 + (c - 'a' + 10);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (value);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API size_t cs_uri_escape(u_char *d, const u_char *s) {
|
|
|
+ u_char *cp = d;
|
|
|
+ size_t n;
|
|
|
+
|
|
|
+ if (d == NULL) {
|
|
|
+ n = 0;
|
|
|
+ while (*s) {
|
|
|
+ if (_uri_char[*s]) {
|
|
|
+ n++;
|
|
|
+ }
|
|
|
+ s++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (n);
|
|
|
+ }
|
|
|
+
|
|
|
+ while (*s) {
|
|
|
+ if (_uri_char[*s]) {
|
|
|
+ *d++ = '%';
|
|
|
+ *d++ = _hex_char[(*s) >> 4];
|
|
|
+ *d++ = _hex_char[(*s) & 0x0f];
|
|
|
+ s++;
|
|
|
+ } else {
|
|
|
+ *d++ = *s++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (d - cp);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API size_t cs_uri_unescape(u_char *d, const u_char *s) {
|
|
|
+ register unsigned char high, low;
|
|
|
+ u_char *cp = d;
|
|
|
+
|
|
|
+ while ((*s) != '\0') {
|
|
|
+ if (*s == '%') {
|
|
|
+ X2C(*(s + 1), high);
|
|
|
+ if (high < 0x10) {
|
|
|
+ X2C(*(s + 2), low);
|
|
|
+ if (low < 0x10) {
|
|
|
+ high = (u_char)((high << 4) | low);
|
|
|
+ *d = high;
|
|
|
+ s += 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (*s == '+') {
|
|
|
+ *d = ' ';
|
|
|
+ } else {
|
|
|
+ *d = *s;
|
|
|
+ }
|
|
|
+ d++;
|
|
|
+ s++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (d - cp);
|
|
|
+}
|
|
|
+
|
|
|
+/* from ngx_string.c */
|
|
|
+CS_API size_t cs_json_escape(u_char *d, u_char *s, size_t n) {
|
|
|
+ u_char ch, *cp = d;
|
|
|
+ size_t len;
|
|
|
+
|
|
|
+ if (d == NULL) {
|
|
|
+ len = 0;
|
|
|
+
|
|
|
+ while (n) {
|
|
|
+ ch = *s++;
|
|
|
+
|
|
|
+ if (ch == '\\' || ch == '"') {
|
|
|
+ len++;
|
|
|
+ } else if (ch <= 0x1f) {
|
|
|
+ len += sizeof("\\u001F") - 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ n--;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (len);
|
|
|
+ }
|
|
|
+
|
|
|
+ while (n) {
|
|
|
+ ch = *s++;
|
|
|
+
|
|
|
+ if (ch > 0x1f) {
|
|
|
+ if (ch == '\\' || ch == '"') {
|
|
|
+ *d++ = '\\';
|
|
|
+ }
|
|
|
+
|
|
|
+ *d++ = ch;
|
|
|
+ } else {
|
|
|
+ *d++ = '\\'; *d++ = 'u'; *d++ = '0'; *d++ = '0';
|
|
|
+ *d++ = '0' + (ch >> 4);
|
|
|
+
|
|
|
+ ch &= 0xf;
|
|
|
+
|
|
|
+ *d++ = (ch < 10) ? ('0' + ch) : ('A' + ch - 10);
|
|
|
+ }
|
|
|
+
|
|
|
+ n--;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (d - cp);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API size_t cs_hex_dump(u_char *d, u_char *s, size_t n) {
|
|
|
+ u_char *cp = d;
|
|
|
+
|
|
|
+ while (n--) {
|
|
|
+ *d++ = _hex_char[*s >> 4];
|
|
|
+ *d++ = _hex_char[*s++ & 0xf];
|
|
|
+ }
|
|
|
+
|
|
|
+ return (d - cp);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API size_t cs_hex_undump(u_char *d, const u_char *s, size_t n) {
|
|
|
+ size_t i = 0;
|
|
|
+ register u_char ch, digit;
|
|
|
+ u_char *cp = d;
|
|
|
+
|
|
|
+ for (i = 0; i < n; i++) {
|
|
|
+ X2C(*(s + i) ,ch);
|
|
|
+ ch = ch << 4;
|
|
|
+ i++;
|
|
|
+ X2C(*(s + i), digit);
|
|
|
+ ch += digit;
|
|
|
+ *d++ = ch;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (d - cp);
|
|
|
+}
|
|
|
+
|
|
|
+/* from ngx_string.c */
|
|
|
+static void _cs_base64_encode_internal(
|
|
|
+ cs_buf_t *dst, cs_buf_t *src, const u_char *basis, cs_uint_t padding) {
|
|
|
+ u_char *d, *s;
|
|
|
+ size_t len;
|
|
|
+
|
|
|
+ len = src->used;
|
|
|
+ s = src->buf;
|
|
|
+ d = dst->buf;
|
|
|
+
|
|
|
+ while (len > 2) {
|
|
|
+ *d++ = basis[(s[0] >> 2) & 0x3f];
|
|
|
+ *d++ = basis[((s[0] & 3) << 4) | (s[1] >> 4)];
|
|
|
+ *d++ = basis[((s[1] & 0x0f) << 2) | (s[2] >> 6)];
|
|
|
+ *d++ = basis[s[2] & 0x3f];
|
|
|
+
|
|
|
+ s += 3;
|
|
|
+ len -= 3;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (len) {
|
|
|
+ *d++ = basis[(s[0] >> 2) & 0x3f];
|
|
|
+
|
|
|
+ if (len == 1) {
|
|
|
+ *d++ = basis[(s[0] & 3) << 4];
|
|
|
+ if (padding) {
|
|
|
+ *d++ = '=';
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ *d++ = basis[((s[0] & 3) << 4) | (s[1] >> 4)];
|
|
|
+ *d++ = basis[(s[1] & 0x0f) << 2];
|
|
|
+ }
|
|
|
+
|
|
|
+ if (padding) {
|
|
|
+ *d++ = '=';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ dst->used = d - dst->buf;
|
|
|
+}
|
|
|
+
|
|
|
+/* from ngx_string.c */
|
|
|
+CS_API void cs_base64_encode(cs_buf_t *d, cs_buf_t *s) {
|
|
|
+ static u_char basis64[] =
|
|
|
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
|
+
|
|
|
+ _cs_base64_encode_internal(d, s, basis64, 1);
|
|
|
+}
|
|
|
+
|
|
|
+/* from ngx_string.c */
|
|
|
+static cs_int_t _cs_base64_decode_internal(
|
|
|
+ cs_buf_t *dst, cs_buf_t *src, const u_char *basis) {
|
|
|
+ size_t len;
|
|
|
+ u_char *d, *s;
|
|
|
+
|
|
|
+ for (len = 0; len < src->used; len++) {
|
|
|
+ if (src->buf[len] == '=') {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (basis[src->buf[len]] == 77) {
|
|
|
+ return (CS_ERR);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (len % 4 == 1) {
|
|
|
+ return (CS_ERR);
|
|
|
+ }
|
|
|
+
|
|
|
+ s = src->buf;
|
|
|
+ d = dst->buf;
|
|
|
+
|
|
|
+ while (len > 3) {
|
|
|
+ *d++ = (u_char) (basis[s[0]] << 2 | basis[s[1]] >> 4);
|
|
|
+ *d++ = (u_char) (basis[s[1]] << 4 | basis[s[2]] >> 2);
|
|
|
+ *d++ = (u_char) (basis[s[2]] << 6 | basis[s[3]]);
|
|
|
+
|
|
|
+ s += 4;
|
|
|
+ len -= 4;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (len > 1) {
|
|
|
+ *d++ = (u_char) (basis[s[0]] << 2 | basis[s[1]] >> 4);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (len > 2) {
|
|
|
+ *d++ = (u_char) (basis[s[1]] << 4 | basis[s[2]] >> 2);
|
|
|
+ }
|
|
|
+
|
|
|
+ dst->used = d - dst->buf;
|
|
|
+
|
|
|
+ return (CS_OK);
|
|
|
+}
|
|
|
+
|
|
|
+/* from ngx_string.c */
|
|
|
+CS_API cs_int_t cs_base64_decode(cs_buf_t *d, cs_buf_t *s) {
|
|
|
+ static u_char basis64[] = {
|
|
|
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
|
|
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
|
|
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77, 77, 63,
|
|
|
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77,
|
|
|
+ 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
|
|
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 77,
|
|
|
+ 77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
|
|
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77,
|
|
|
+
|
|
|
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
|
|
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
|
|
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
|
|
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
|
|
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
|
|
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
|
|
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
|
|
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77
|
|
|
+ };
|
|
|
+
|
|
|
+ return _cs_base64_decode_internal(d, s, basis64);
|
|
|
+}
|
|
|
+
|
|
|
+/* from ngx_string.c */
|
|
|
+CS_API cs_uint_t cs_utf8_decode(u_char **s, size_t n) {
|
|
|
+ size_t len;
|
|
|
+ cs_uint_t u, i, valid;
|
|
|
+
|
|
|
+ u = **s;
|
|
|
+
|
|
|
+ if(u > 0xf0){
|
|
|
+ u &= 0x07;
|
|
|
+ valid = 0xffff;
|
|
|
+ len = 3;
|
|
|
+ } else if (u > 0xe0) {
|
|
|
+ u &= 0x0f;
|
|
|
+ valid = 0x7ff;
|
|
|
+ len = 2;
|
|
|
+ } else if (u > 0xc0) {
|
|
|
+ u &= 0x1f;
|
|
|
+ valid = 0x7f;
|
|
|
+ len = 1;
|
|
|
+ } else{
|
|
|
+ (*s)++;
|
|
|
+
|
|
|
+ return (0xffffffff);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (n - 1 < len) {
|
|
|
+ return (0xfffffffe);
|
|
|
+ }
|
|
|
+
|
|
|
+ (*s)++;
|
|
|
+
|
|
|
+ while (len) {
|
|
|
+ i = *(*s)++;
|
|
|
+
|
|
|
+ if (i < 0x80) {
|
|
|
+ return (0xffffffff);
|
|
|
+ }
|
|
|
+
|
|
|
+ u = (u << 6) | (i & 0x3f);
|
|
|
+ len--;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (u > valid) {
|
|
|
+ return (u);
|
|
|
+ }
|
|
|
+
|
|
|
+ return (0xffffffff);
|
|
|
+}
|
|
|
+
|
|
|
+/* from ngx_string.c */
|
|
|
+CS_API size_t cs_utf8_length(u_char *s, size_t n) {
|
|
|
+ u_char c, *last;
|
|
|
+ size_t len;
|
|
|
+
|
|
|
+ last = s + n;
|
|
|
+ for (len = 0; s < last; len++) {
|
|
|
+ c = *s;
|
|
|
+ if (c < 0x80) {
|
|
|
+ s++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cs_utf8_decode(&s, n) > 0x10ffff) {
|
|
|
+ /* invalid UTF-8 */
|
|
|
+ return n;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (len);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+djb2
|
|
|
+ this algorithm (k=33) was first reported by dan bernstein many years ago
|
|
|
+in comp.lang.c.
|
|
|
+another version of this algorithm (now favored by bernstein) uses xor:
|
|
|
+ hash(i) = hash(i - 1) * 33 ^ str[i];
|
|
|
+ the magic of number 33 (why it works better than many other constants,
|
|
|
+prime or not)
|
|
|
+has never been adequately explained.
|
|
|
+*/
|
|
|
+CS_API cs_uint_t cs_hash_djb2(const u_char *s) {
|
|
|
+ const u_char *cp = s;
|
|
|
+ cs_uint_t hash = 5381;
|
|
|
+
|
|
|
+ while (*cp) {
|
|
|
+ hash = ((hash << 5) + hash) + *cp; /* hash = hash * 33 + c */
|
|
|
+ cp++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (hash);
|
|
|
+}
|
|
|
+
|
|
|
+CS_API cs_uint64_t cs_hash_djb2_64(const u_char *s) {
|
|
|
+ const u_char *cp = s;
|
|
|
+ cs_uint64_t hash = 5381;
|
|
|
+
|
|
|
+ while (*cp) {
|
|
|
+ hash = ((hash << 5) + hash) + *cp; /* hash = hash * 33 + c */
|
|
|
+ cp++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (hash);
|
|
|
+}
|