Merge branch 'hildjj-master'
diff --git a/Makefile b/Makefile
index 554c767..1752a6d 100644
--- a/Makefile
+++ b/Makefile
@@ -8,8 +8,8 @@
 	env MallocStackLogging=true ./cntest >new.out
 	-diff new.out expected.out
 
-cntest: test.c cbor.h cn-cbor.h cn-cbor.c
-	clang $(CFLAGS) cn-cbor.c test.c -o cntest
+cntest: test.c cbor.h cn-cbor.h cn-cbor.c cn-manip.c
+	clang $(CFLAGS) cn-cbor.c cn-error.c cn-manip.c test.c -o cntest
 
 size: cn-cbor.o
 	size cn-cbor.o
diff --git a/cn-cbor.c b/cn-cbor.c
index 0a9779f..e0fd53b 100644
--- a/cn-cbor.c
+++ b/cn-cbor.c
@@ -14,7 +14,10 @@
 #include <assert.h>
 #include <math.h>
 
+#include <arpa/inet.h>
+
 #include "cn-cbor.h"
+#include "cbor.h"
 
 // can be redefined, e.g. for pool allocation
 #ifndef CN_CBOR_CALLOC
@@ -84,8 +87,22 @@
   unsigned char *pos = pb->buf;
   unsigned char *ebuf = pb->ebuf;
   cn_cbor* parent = top_parent;
+  int ib;
+  unsigned int mt;
+  int ai;
+  uint64_t val;
+  cn_cbor* cb = NULL;
+  union {
+    float f;
+    uint32_t u;
+  } u32;
+  union {
+    double d;
+    uint64_t u;
+  } u64;
+
 again:
-  TAKE(pos, ebuf, 1, int ib = ntoh8p(pos) );
+  TAKE(pos, ebuf, 1, ib = ntoh8p(pos) );
   if (ib == IB_BREAK) {
     if (!(parent->flags & CN_CBOR_FL_INDEF))
       CN_CBOR_FAIL(CN_CBOR_ERR_BREAK_OUTSIDE_INDEF);
@@ -100,11 +117,11 @@
     }
     goto complete;
   }
-  unsigned int mt = ib >> 5;
-  int ai = ib & 0x1f;
-  uint64_t val = ai;
+  mt = ib >> 5;
+  ai = ib & 0x1f;
+  val = ai;
 
-  cn_cbor* cb = CN_CBOR_CALLOC();
+  cb = CN_CBOR_CALLOC();
   if (!cb)
     CN_CBOR_FAIL(CN_CBOR_ERR_OUT_OF_MEMORY);
 
@@ -166,19 +183,11 @@
     case AI_2: cb->type = CN_CBOR_DOUBLE; cb->v.dbl = decode_half(val); break;
     case AI_4:
       cb->type = CN_CBOR_DOUBLE;
-      union {
-        float f;
-        uint32_t u;
-      } u32;
       u32.u = val;
       cb->v.dbl = u32.f;
       break;
     case AI_8:
       cb->type = CN_CBOR_DOUBLE;
-      union {
-        double d;
-        uint64_t u;
-      } u64;
       u64.u = val;
       cb->v.dbl = u64.d;
       break;
@@ -216,22 +225,22 @@
 }
 
 const cn_cbor* cn_cbor_decode(const char* buf, size_t len, cn_cbor_errback *errp) {
-  cn_cbor catcher = {CN_CBOR_INVALID, 0, {0}, 0, 0, 0, 0, 0};
+  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);
-  if (ret) {
-    ret->parent = 0;            /* mark as top node */
+  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);
     }
-  //fail:
     if (errp) {
       errp->err = pb.err;
       errp->pos = pb.buf - (unsigned char *)buf;
     }
-    return 0;
+    return NULL;
   }
   return ret;
 }
diff --git a/cn-cbor.h b/cn-cbor.h
index 62d8b78..7764190 100644
--- a/cn-cbor.h
+++ b/cn-cbor.h
@@ -8,9 +8,6 @@
 } /* Duh. */
 #endif
 
-/* protocol constants: */
-#include "cbor.h"
-
 typedef enum cn_cbor_type {
   CN_CBOR_NULL,
   CN_CBOR_FALSE,   CN_CBOR_TRUE,
@@ -58,6 +55,8 @@
   CN_CBOR_ERR_OUT_OF_MEMORY,
 } cn_cbor_error;
 
+extern const char *cn_cbor_error_str[];
+
 typedef struct cn_cbor_errback {
   int pos;
   cn_cbor_error err;
diff --git a/cn-error.c b/cn-error.c
new file mode 100644
index 0000000..b1dd58c
--- /dev/null
+++ b/cn-error.c
@@ -0,0 +1,11 @@
+const char *cn_cbor_error_str[] = {
+ "CN_CBOR_NO_ERROR",
+ "CN_CBOR_ERR_OUT_OF_DATA",
+ "CN_CBOR_ERR_NOT_ALL_DATA_CONSUMED",
+ "CN_CBOR_ERR_ODD_SIZE_INDEF_MAP",
+ "CN_CBOR_ERR_BREAK_OUTSIDE_INDEF",
+ "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"
+};
diff --git a/cn-manip.c b/cn-manip.c
new file mode 100644
index 0000000..4f91c45
--- /dev/null
+++ b/cn-manip.c
@@ -0,0 +1,69 @@
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "cn-cbor.h"
+
+const cn_cbor* cn_cbor_mapget_int(const cn_cbor* cb, int key) {
+  cn_cbor* cp;
+  assert(cb);
+  for (cp = cb->first_child; cp && cp->next; cp = cp->next->next) {
+    switch(cp->type) {
+    case CN_CBOR_UINT:
+      if (cp->v.uint == (unsigned long)key) {
+        return cp->next;
+      }
+    case CN_CBOR_INT:
+      if (cp->v.sint == (long)key) {
+        return cp->next;
+      }
+      break;
+    default:
+      ; // skip non-integer keys
+    }
+  }
+  return NULL;
+}
+
+const cn_cbor* cn_cbor_mapget_string(const cn_cbor* cb, const char* key) {
+  cn_cbor *cp;
+  int keylen;
+  assert(cb);
+  assert(key);
+  keylen = strlen(key);
+  for (cp = cb->first_child; cp && cp->next; cp = cp->next->next) {
+    switch(cp->type) {
+    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;
+      }
+      if (memcmp(key, cp->v.str, keylen) == 0) {
+        return cp->next;
+      }
+    default:
+      ; // skip non-string keys
+    }
+  }
+  return NULL;
+}
+
+const cn_cbor* cn_cbor_index(const cn_cbor* cb, int idx) {
+  cn_cbor *cp;
+  int i = 0;
+  assert(cb);
+  for (cp = cb->first_child; cp; cp = cp->next) {
+    if (i == idx) {
+      return cp;
+    }
+    i++;
+  }
+  return NULL;
+}