Merge in changes from SPUDlib, in preparation for moving to cmake
diff --git a/Makefile b/Makefile
index 40c5ee1..68e59ce 100644
--- a/Makefile
+++ b/Makefile
@@ -8,8 +8,8 @@
 	env MallocStackLogging=true ./cntest >new.out
 	-diff new.out expected.out
 
-cntest: cbor.h cn-cbor.h cn-cbor.c cn-error.c cn-manip.c test.c 
-	clang $(CFLAGS) cn-cbor.c cn-error.c cn-manip.c test.c -o cntest
+cntest: cbor.h cn-cbor.h cn-cbor.c cn-error.c cn-get.c test.c
+	clang $(CFLAGS) cn-cbor.c cn-error.c cn-get.c test.c -o cntest
 
 size: cn-cbor.o
 	size cn-cbor.o
diff --git a/cn-cbor.c b/cn-cbor.c
index 6336ee4..8136880 100644
--- a/cn-cbor.c
+++ b/cn-cbor.c
@@ -17,15 +17,19 @@
 #include "cn-cbor.h"
 #include "cbor.h"
 
-// can be redefined, e.g. for pool allocation
-#ifndef CN_CBOR_CALLOC
-#define CN_CBOR_CALLOC() calloc(1, sizeof(cn_cbor))
-#define CN_CBOR_FREE(cb) free((void*)(cb))
-#endif
-
 #define CN_CBOR_FAIL(code) do { pb->err = code;  goto fail; } while(0)
 
-void cn_cbor_free(const cn_cbor* cb) {
+#ifdef USE_CBOR_CONTEXT
+#define CBOR_CONTEXT_PARAM , context
+#define CN_CALLOC_CONTEXT() CN_CALLOC(context)
+#define CN_CBOR_FREE_CONTEXT(p) CN_FREE(p, context)
+#else
+#define CBOR_CONTEXT_PARAM
+#define CN_CALLOC_CONTEXT() CN_CALLOC
+#define CN_CBOR_FREE_CONTEXT(p) CN_FREE(p)
+#endif
+
+void cn_cbor_free(const cn_cbor* cb CBOR_CONTEXT) {
   cn_cbor* p = (cn_cbor*) cb;
   while (p) {
     cn_cbor* p1;
@@ -36,7 +40,7 @@
       if ((p1 = p->parent))
         p1->first_child = 0;
     }
-    CN_CBOR_FREE(p);
+    CN_CBOR_FREE_CONTEXT(p);
     p = p1;
   }
 }
@@ -81,7 +85,7 @@
   stmt;                                         \
   pos += n;
 
-static cn_cbor *decode_item (struct parse_buf *pb, cn_cbor* top_parent) {
+static cn_cbor *decode_item (struct parse_buf *pb CBOR_CONTEXT, cn_cbor* top_parent) {
   unsigned char *pos = pb->buf;
   unsigned char *ebuf = pb->ebuf;
   cn_cbor* parent = top_parent;
@@ -89,7 +93,7 @@
   unsigned int mt;
   int ai;
   uint64_t val;
-  cn_cbor* cb;
+  cn_cbor* cb = NULL;
   union {
     float f;
     uint32_t u;
@@ -119,7 +123,7 @@
   ai = ib & 0x1f;
   val = ai;
 
-  cb = CN_CBOR_CALLOC();
+  cb = CN_CALLOC_CONTEXT();
   if (!cb)
     CN_CBOR_FAIL(CN_CBOR_ERR_OUT_OF_MEMORY);
 
@@ -159,7 +163,7 @@
   case MT_BYTES: case MT_TEXT:
     cb->v.str = (char *) pos;
     cb->length = val;
-    TAKE(pos, ebuf, val, );
+    TAKE(pos, ebuf, val, ;);
     break;
   case MT_MAP:
     val <<= 1;
@@ -222,19 +226,24 @@
   return 0;
 }
 
-const cn_cbor* cn_cbor_decode(const char* buf, size_t len, cn_cbor_errback *errp) {
+const cn_cbor* cn_cbor_decode(const unsigned char* buf, size_t len CBOR_CONTEXT, cn_cbor_errback *errp) {
   cn_cbor catcher = {CN_CBOR_INVALID, 0, {0}, 0, NULL, NULL, NULL, NULL};
-  struct parse_buf pb = {(unsigned char *)buf, (unsigned char *)buf+len, CN_CBOR_NO_ERROR};
-  cn_cbor* ret = decode_item(&pb, &catcher);
+  struct parse_buf pb;
+  cn_cbor* ret;
+
+  pb.buf  = (unsigned char *)buf;
+  pb.ebuf = (unsigned char *)buf+len;
+  pb.err  = CN_CBOR_NO_ERROR;
+  ret = decode_item(&pb CBOR_CONTEXT_PARAM, &catcher);
   if (ret != NULL) {
     /* mark as top node */
     ret->parent = NULL;
   } else {
     if (catcher.first_child) {
       catcher.first_child->parent = 0;
-      cn_cbor_free(catcher.first_child);
+      cn_cbor_free(catcher.first_child CBOR_CONTEXT_PARAM);
     }
-  //fail:
+//fail:
     if (errp) {
       errp->err = pb.err;
       errp->pos = pb.buf - (unsigned char *)buf;
diff --git a/cn-cbor.h b/cn-cbor.h
index 2bf9416..c0ecfa9 100644
--- a/cn-cbor.h
+++ b/cn-cbor.h
@@ -52,7 +52,8 @@
   CN_CBOR_ERR_MT_UNDEF_FOR_INDEF,
   CN_CBOR_ERR_RESERVED_AI,
   CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING,
-  CN_CBOR_ERR_OUT_OF_MEMORY,
+  CN_CBOR_ERR_INVALID_PARAMETER,
+  CN_CBOR_ERR_OUT_OF_MEMORY
 } cn_cbor_error;
 
 extern const char *cn_cbor_error_str[];
@@ -62,13 +63,44 @@
   cn_cbor_error err;
 } cn_cbor_errback;
 
-const cn_cbor* cn_cbor_decode(const char* buf, size_t len, cn_cbor_errback *errp);
+#ifdef USE_CBOR_CONTEXT
+
+typedef void* (*cn_alloc_func)(size_t count, size_t size, void *context);
+typedef void (*cn_free_func)(void *ptr, void *context);
+
+typedef struct cn_cbor_context {
+    cn_alloc_func calloc_func;
+    cn_free_func  free_func;
+    void *context;
+} cn_cbor_context;
+
+#define CN_CALLOC(ctx) ((ctx) && (ctx)->calloc_func) ? \
+    (ctx)->calloc_func(1, sizeof(cn_cbor), (ctx)->context) : \
+    calloc(1, sizeof(cn_cbor));
+#define CN_FREE(ptr, ctx) ((ctx) && (ctx)->free_func) ? \
+    (ctx)->free_func((ptr), (ctx)->context) : \
+    free((ptr));
+#define CBOR_CONTEXT , cn_cbor_context *context
+#define CBOR_CONTEXT_COMMA cn_cbor_context *context,
+
+#else
+
+#define CBOR_CONTEXT
+#define CBOR_CONTEXT_COMMA
+#ifndef CN_CALLOC
+#define CN_CALLOC calloc(1, sizeof(cn_cbor))
+#endif
+#ifndef CN_FREE
+#define CN_FREE free
+#endif
+
+#endif
+
+const cn_cbor* cn_cbor_decode(const unsigned char* buf, size_t len CBOR_CONTEXT, cn_cbor_errback *errp);
 const cn_cbor* cn_cbor_mapget_string(const cn_cbor* cb, const char* key);
 const cn_cbor* cn_cbor_mapget_int(const cn_cbor* cb, int key);
-const cn_cbor* cn_cbor_index(const cn_cbor* cb, unsigned int idx);
-
-const cn_cbor* cn_cbor_alloc(cn_cbor_type t);
-void cn_cbor_free(const cn_cbor* js);
+const cn_cbor* cn_cbor_index(const cn_cbor* cb, int idx);
+void cn_cbor_free(const cn_cbor* js CBOR_CONTEXT);
 
 #ifdef  __cplusplus
 }
diff --git a/cn-get.c b/cn-get.c
index 130ab97..4f91c45 100644
--- a/cn-get.c
+++ b/cn-get.c
@@ -33,7 +33,14 @@
   keylen = strlen(key);
   for (cp = cb->first_child; cp && cp->next; cp = cp->next->next) {
     switch(cp->type) {
-    case CN_CBOR_TEXT: // fall through
+    case CN_CBOR_TEXT:
+      if (keylen != cp->length) {
+        continue;
+      }
+      if (strncmp(key, cp->v.str, cp->length) == 0) {
+        return cp->next;
+      }
+      break;
     case CN_CBOR_BYTES:
       if (keylen != cp->length) {
         continue;
@@ -48,9 +55,9 @@
   return NULL;
 }
 
-const cn_cbor* cn_cbor_index(const cn_cbor* cb, unsigned int idx) {
+const cn_cbor* cn_cbor_index(const cn_cbor* cb, int idx) {
   cn_cbor *cp;
-  unsigned int i = 0;
+  int i = 0;
   assert(cb);
   for (cp = cb->first_child; cp; cp = cp->next) {
     if (i == idx) {
diff --git a/test.c b/test.c
index 5b949ee..0b8ef3f 100644
--- a/test.c
+++ b/test.c
@@ -8,7 +8,7 @@
 
 #define ERROR(msg, p) fprintf(stderr, "ERROR: " msg " %s\n", (p));
 
-static char* load_file(const char* filepath, char **end) {
+static unsigned char* load_file(const char* filepath, unsigned char **end) {
   struct stat st;
   if (stat(filepath, &st)==-1) {
     ERROR("can't find file", filepath);
@@ -19,7 +19,7 @@
     ERROR("can't open file", filepath);
     return 0;
   }
-  char* text=malloc(st.st_size+1); // this is not going to be freed
+  unsigned char* text=malloc(st.st_size+1); // this is not going to be freed
   if (st.st_size!=read(fd, text, st.st_size)) {
     ERROR("can't read file", filepath);
     close(fd);
@@ -92,7 +92,7 @@
   "CN_CBOR_ERR_OUT_OF_MEMORY",
 };
 
-static void cn_cbor_decode_test(const char *buf, int len) {
+static void cn_cbor_decode_test(const unsigned char *buf, int len) {
   struct cn_cbor_errback back;
   const cn_cbor *ret = cn_cbor_decode(buf, len, &back);
   if (ret)
@@ -102,24 +102,25 @@
 
 int main() {
   char buf[100000];
-  char *end;
-  char *s = load_file("cases.cbor", &end);
+  unsigned char *end;
+  char *bufend;
+  unsigned char *s = load_file("cases.cbor", &end);
   printf("%zd\n", end-s);
   const cn_cbor *cb = cn_cbor_decode(s, end-s, 0);
   if (cb) {
-    dump(cb, buf, &end, 0);
-    *end = 0;
+    dump(cb, buf, &bufend, 0);
+    *bufend = 0;
     printf("%s\n", buf);
     cn_cbor_free(cb);
     cb = 0;                     /* for leaks testing */
   }
-  cn_cbor_decode_test("\xff", 1);    /* break outside indef */
-  cn_cbor_decode_test("\x1f", 1);    /* mt undef for indef */
-  cn_cbor_decode_test("\x00\x00", 2);    /* not all data consumed */
-  cn_cbor_decode_test("\x81", 1);    /* out of data */
-  cn_cbor_decode_test("\x1c", 1);    /* reserved ai */
-  cn_cbor_decode_test("\xbf\x00\xff", 3);    /* odd size indef map */
-  cn_cbor_decode_test("\x7f\x40\xff", 3);    /* wrong nesting in indef string */
+  cn_cbor_decode_test((const unsigned char*)"\xff", 1);    /* break outside indef */
+  cn_cbor_decode_test((const unsigned char*)"\x1f", 1);    /* mt undef for indef */
+  cn_cbor_decode_test((const unsigned char*)"\x00\x00", 2);    /* not all data consumed */
+  cn_cbor_decode_test((const unsigned char*)"\x81", 1);    /* out of data */
+  cn_cbor_decode_test((const unsigned char*)"\x1c", 1);    /* reserved ai */
+  cn_cbor_decode_test((const unsigned char*)"\xbf\x00\xff", 3);    /* odd size indef map */
+  cn_cbor_decode_test((const unsigned char*)"\x7f\x40\xff", 3);    /* wrong nesting in indef string */
   system("leaks test");
 }