summaryrefslogtreecommitdiffstats
path: root/src/blob.c
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2010-11-07 00:47:39 +0200
committerTimo Teräs <timo.teras@iki.fi>2010-11-07 00:47:39 +0200
commit25593b5e6fea76ed7c08db586924032c0810c27e (patch)
treeb632534eb96978ad620fee1e5a9a5d280e0b191e /src/blob.c
parente0450bd60a30ca944c16f84ee195463fd4aab653 (diff)
downloadsquark-25593b5e6fea76ed7c08db586924032c0810c27e.tar.bz2
squark-25593b5e6fea76ed7c08db586924032c0810c27e.tar.xz
squark: reorganize sources to src directory
Diffstat (limited to 'src/blob.c')
-rw-r--r--src/blob.c426
1 files changed, 426 insertions, 0 deletions
diff --git a/src/blob.c b/src/blob.c
new file mode 100644
index 0000000..1604308
--- /dev/null
+++ b/src/blob.c
@@ -0,0 +1,426 @@
+#include <time.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "blob.h"
+
+/* RFC 3986 section 2.3 Unreserved Characters (January 2005) */
+#define CTYPE_UNRESERVED 1
+
+static const char *xd = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+static const unsigned char chartype[128] = {
+ ['a'] = CTYPE_UNRESERVED,
+ ['b'] = CTYPE_UNRESERVED,
+ ['c'] = CTYPE_UNRESERVED,
+ ['d'] = CTYPE_UNRESERVED,
+ ['e'] = CTYPE_UNRESERVED,
+ ['f'] = CTYPE_UNRESERVED,
+ ['g'] = CTYPE_UNRESERVED,
+ ['h'] = CTYPE_UNRESERVED,
+ ['i'] = CTYPE_UNRESERVED,
+ ['j'] = CTYPE_UNRESERVED,
+ ['k'] = CTYPE_UNRESERVED,
+ ['l'] = CTYPE_UNRESERVED,
+ ['m'] = CTYPE_UNRESERVED,
+ ['n'] = CTYPE_UNRESERVED,
+ ['o'] = CTYPE_UNRESERVED,
+ ['p'] = CTYPE_UNRESERVED,
+ ['q'] = CTYPE_UNRESERVED,
+ ['r'] = CTYPE_UNRESERVED,
+ ['s'] = CTYPE_UNRESERVED,
+ ['t'] = CTYPE_UNRESERVED,
+ ['u'] = CTYPE_UNRESERVED,
+ ['v'] = CTYPE_UNRESERVED,
+ ['w'] = CTYPE_UNRESERVED,
+ ['x'] = CTYPE_UNRESERVED,
+ ['y'] = CTYPE_UNRESERVED,
+ ['z'] = CTYPE_UNRESERVED,
+ ['A'] = CTYPE_UNRESERVED,
+ ['B'] = CTYPE_UNRESERVED,
+ ['C'] = CTYPE_UNRESERVED,
+ ['D'] = CTYPE_UNRESERVED,
+ ['E'] = CTYPE_UNRESERVED,
+ ['F'] = CTYPE_UNRESERVED,
+ ['G'] = CTYPE_UNRESERVED,
+ ['H'] = CTYPE_UNRESERVED,
+ ['I'] = CTYPE_UNRESERVED,
+ ['J'] = CTYPE_UNRESERVED,
+ ['K'] = CTYPE_UNRESERVED,
+ ['L'] = CTYPE_UNRESERVED,
+ ['M'] = CTYPE_UNRESERVED,
+ ['N'] = CTYPE_UNRESERVED,
+ ['O'] = CTYPE_UNRESERVED,
+ ['P'] = CTYPE_UNRESERVED,
+ ['Q'] = CTYPE_UNRESERVED,
+ ['R'] = CTYPE_UNRESERVED,
+ ['S'] = CTYPE_UNRESERVED,
+ ['T'] = CTYPE_UNRESERVED,
+ ['U'] = CTYPE_UNRESERVED,
+ ['V'] = CTYPE_UNRESERVED,
+ ['W'] = CTYPE_UNRESERVED,
+ ['X'] = CTYPE_UNRESERVED,
+ ['Y'] = CTYPE_UNRESERVED,
+ ['Z'] = CTYPE_UNRESERVED,
+
+ ['0'] = CTYPE_UNRESERVED,
+ ['1'] = CTYPE_UNRESERVED,
+ ['2'] = CTYPE_UNRESERVED,
+ ['3'] = CTYPE_UNRESERVED,
+ ['4'] = CTYPE_UNRESERVED,
+ ['5'] = CTYPE_UNRESERVED,
+ ['6'] = CTYPE_UNRESERVED,
+ ['7'] = CTYPE_UNRESERVED,
+ ['8'] = CTYPE_UNRESERVED,
+ ['9'] = CTYPE_UNRESERVED,
+
+ ['-'] = CTYPE_UNRESERVED,
+ ['_'] = CTYPE_UNRESERVED,
+ ['.'] = CTYPE_UNRESERVED,
+ ['~'] = CTYPE_UNRESERVED,
+};
+
+static inline int dx(int c)
+{
+ if (likely(c >= '0' && c <= '9'))
+ return c - '0';
+ if (likely(c >= 'a' && c <= 'f'))
+ return c - 'a' + 0xa;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 0xa;
+ return -1;
+}
+
+char *blob_cstr_dup(blob_t b)
+{
+ char *p;
+
+ if (blob_is_null(b))
+ return NULL;
+
+ p = malloc(b.len+1);
+ if (p != NULL) {
+ memcpy(p, b.ptr, b.len);
+ p[b.len] = 0;
+ }
+ return p;
+}
+
+blob_t blob_dup(blob_t b)
+{
+ blob_t p;
+
+ if (blob_is_null(b))
+ return BLOB_NULL;
+
+ p.ptr = malloc(b.len);
+ if (p.ptr != NULL) {
+ memcpy(p.ptr, b.ptr, b.len);
+ p.len = b.len;
+ } else {
+ p.len = 0;
+ }
+ return p;
+}
+
+int blob_cmp(blob_t a, blob_t b)
+{
+ if (a.len != b.len)
+ return a.len - b.len;
+ return memcmp(a.ptr, b.ptr, a.len);
+}
+
+unsigned long blob_inet_addr(blob_t b)
+{
+ unsigned long ip = 0;
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ ip += blob_pull_uint(&b, 10);
+ ip <<= 8;
+ if (!blob_pull_matching(&b, BLOB_STR(".")))
+ return 0;
+ }
+ ip += blob_pull_uint(&b, 10);
+ if (b.len != 0)
+ return 0;
+ return htonl(ip);
+}
+
+
+blob_t blob_pushed(blob_t buffer, blob_t left)
+{
+ if (buffer.ptr + buffer.len != left.ptr + left.len)
+ return BLOB_NULL;
+ return BLOB_PTR_LEN(buffer.ptr, left.ptr - buffer.ptr);
+}
+
+void blob_push(blob_t *b, blob_t d)
+{
+ if (b->len >= d.len) {
+ memcpy(b->ptr, d.ptr, d.len);
+ b->ptr += d.len;
+ b->len -= d.len;
+ } else {
+ *b = BLOB_NULL;
+ }
+}
+
+void blob_push_lower(blob_t *b, blob_t d)
+{
+ int i;
+
+ if (b->len < d.len) {
+ *b = BLOB_NULL;
+ return;
+ }
+ for (i = 0; i < d.len; i++)
+ b->ptr[i] = tolower(d.ptr[i]);
+ b->ptr += d.len;
+ b->len -= d.len;
+}
+
+void blob_push_byte(blob_t *b, unsigned char byte)
+{
+ if (b->len) {
+ b->ptr[0] = byte;
+ b->ptr ++;
+ b->len --;
+ } else {
+ *b = BLOB_NULL;
+ }
+}
+
+void blob_push_uint(blob_t *to, unsigned int value, int radix)
+{
+ char buf[64];
+ char *ptr = &buf[sizeof(buf)-1];
+
+ if (value == 0) {
+ blob_push_byte(to, '0');
+ return;
+ }
+
+ while (value != 0) {
+ *(ptr--) = xd[value % radix];
+ value /= radix;
+ }
+
+ blob_push(to, BLOB_PTR_PTR(ptr+1, &buf[sizeof(buf)-1]));
+}
+
+void blob_push_ctime(blob_t *to, time_t t)
+{
+ char buf[128];
+ blob_t b;
+
+ ctime_r(&t, buf);
+ b = BLOB_STRLEN(buf);
+ b.len--;
+ blob_push(to, b);
+}
+
+void blob_push_hexdump(blob_t *to, blob_t binary)
+{
+ char *d;
+ int i;
+
+ if (blob_is_null(*to))
+ return;
+
+ if (to->len < binary.len * 2) {
+ *to = BLOB_NULL;
+ return;
+ }
+
+ for (i = 0, d = to->ptr; i < binary.len; i++) {
+ *(d++) = xd[(binary.ptr[i] >> 4) & 0xf];
+ *(d++) = xd[binary.ptr[i] & 0xf];
+ }
+ to->ptr = d;
+ to->len -= binary.len * 2;
+}
+
+void blob_push_urldecode(blob_t *to, blob_t url)
+{
+ blob_t b, orig = *to;
+
+ do {
+ blob_pull_matching(&url, BLOB_STR("/"));
+ b = blob_pull_cspn(&url, BLOB_STR("/"));
+ if (blob_is_null(b) || blob_cmp(b, BLOB_STR(".")) == 0) {
+ /* skip '.' or two consecutive / */
+ } else if (blob_cmp(b, BLOB_STR("..")) == 0) {
+ /* go up one path component */
+ blob_shrink_tail(to, blob_pushed(orig, b), '/');
+ } else {
+ /* copy decoded; FIXME decode percent encoding */
+ blob_push_byte(to, '/');
+ blob_push(to, b);
+ }
+ } while (!blob_is_null(url));
+}
+
+void blob_push_urlencode(blob_t *to, blob_t url)
+{
+ unsigned char c;
+ int i;
+
+ for (i = 0; i < url.len; i++) {
+ c = url.ptr[i];
+
+ if (c <= 127 && (chartype[c] & CTYPE_UNRESERVED)) {
+ blob_push_byte(to, c);
+ } else {
+ blob_push_byte(to, '%');
+ blob_push_uint(to, c, 16);
+ }
+ }
+}
+
+blob_t blob_pull(blob_t *b, int len)
+{
+ blob_t r;
+
+ if (b->len >= len) {
+ r = BLOB_PTR_LEN(b->ptr, len);
+ b->ptr += len;
+ b->len -= len;
+ return r;
+ }
+ *b = BLOB_NULL;
+ return BLOB_NULL;
+}
+
+void blob_pull_skip(blob_t *b, int len)
+{
+ if (b->len >= len) {
+ b->ptr += len;
+ b->len -= len;
+ } else {
+ *b = BLOB_NULL;
+ }
+}
+
+int blob_pull_matching(blob_t *b, blob_t e)
+{
+ if (b->len < e.len)
+ return 0;
+ if (memcmp(b->ptr, e.ptr, e.len) != 0)
+ return 0;
+ b->ptr += e.len;
+ b->len -= e.len;
+ return 1;
+}
+
+unsigned int blob_pull_uint(blob_t *b, int radix)
+{
+ unsigned int val;
+ int ch;
+
+ val = 0;
+ while (b->len && b->ptr[0] != 0) {
+ ch = dx(b->ptr[0]);
+ if (ch < 0 || ch >= radix)
+ break;
+ val *= radix;
+ val += ch;
+
+ b->ptr++;
+ b->len--;
+ }
+
+ return val;
+}
+
+blob_t blob_pull_spn(blob_t *b, const blob_t reject)
+{
+ blob_t t = *b;
+ int i;
+
+ for (i = 0; i < t.len; i++) {
+ if (memchr(reject.ptr, t.ptr[i], reject.len) == NULL) {
+ *b = BLOB_PTR_LEN(t.ptr + i, t.len - i);
+ return BLOB_PTR_LEN(t.ptr, i);
+ }
+ }
+
+ *b = BLOB_NULL;
+ return t;
+}
+
+blob_t blob_pull_cspn(blob_t *b, const blob_t reject)
+{
+ blob_t t = *b;
+ int i;
+
+ for (i = 0; i < t.len; i++) {
+ if (memchr(reject.ptr, t.ptr[i], reject.len) != NULL) {
+ *b = BLOB_PTR_LEN(t.ptr + i, t.len - i);
+ return BLOB_PTR_LEN(t.ptr, i);
+ }
+ }
+
+ *b = BLOB_NULL;
+ return t;
+}
+
+blob_t blob_expand_head(blob_t *b, blob_t limits, unsigned char sep)
+{
+ blob_t t = *b;
+ blob_t r;
+
+ if (t.ptr < limits.ptr || t.ptr+t.len > limits.ptr+limits.len)
+ return BLOB_NULL;
+ while (t.ptr > limits.ptr && t.ptr[-1] == sep)
+ t.ptr--, t.len++;
+
+ r.ptr = t.ptr;
+ r.len = 0;
+ while (t.ptr > limits.ptr && t.ptr[-1] != sep) {
+ t.ptr--, t.len++;
+ r.ptr--, r.len++;
+ }
+ *b = t;
+ return r;
+}
+
+blob_t blob_expand_tail(blob_t *b, blob_t limits, unsigned char sep)
+{
+ blob_t t = *b;
+ blob_t r;
+
+ if (t.ptr < limits.ptr || t.ptr+t.len > limits.ptr+limits.len)
+ return BLOB_NULL;
+ while (t.ptr + t.len < limits.ptr + limits.len && t.ptr[t.len] == sep)
+ t.len++;
+
+ r.ptr = t.ptr + t.len;
+ r.len = 0;
+ while (t.ptr + t.len < limits.ptr + limits.len && t.ptr[t.len] != sep) {
+ t.len++;
+ r.len++;
+ }
+ *b = t;
+ return r;
+}
+
+blob_t blob_shrink_tail(blob_t *b, blob_t limits, unsigned char sep)
+{
+ blob_t t = *b;
+ blob_t r;
+
+ if (t.ptr <= limits.ptr || t.ptr+t.len > limits.ptr+limits.len)
+ return BLOB_NULL;
+ while (t.len && t.ptr[t.len-1] == sep)
+ t.len--;
+
+ r.ptr = t.ptr;
+ r.len = 0;
+ while (t.len && t.ptr[t.len-1] != sep) {
+ t.len--;
+ r.ptr--, r.len++;
+ }
+ *b = t;
+ return r;
+}