summaryrefslogtreecommitdiffstats
path: root/lib/libcbor/src
diff options
context:
space:
mode:
authordjm <djm@openbsd.org>2019-11-14 21:11:34 +0000
committerdjm <djm@openbsd.org>2019-11-14 21:11:34 +0000
commitda0d961c2c28322a016c9e47e9898b8a67695a06 (patch)
tree98cc58b7052570a785fb26702de946f8f6519f3a /lib/libcbor/src
parentAdd missing cross-reference to NOTES section. (diff)
downloadwireguard-openbsd-da0d961c2c28322a016c9e47e9898b8a67695a06.tar.xz
wireguard-openbsd-da0d961c2c28322a016c9e47e9898b8a67695a06.zip
Add libcbor; an implementation of the Concise Binary Object
Representation (CBOR) encoding format defined in RFC7049. This is a dependency of libfido2, that we'll use for U2F/FIDO support in OpenSSH. feedback and "Looks good enough to me" deraadt@
Diffstat (limited to 'lib/libcbor/src')
-rw-r--r--lib/libcbor/src/allocators.c19
-rw-r--r--lib/libcbor/src/cbor.c391
-rw-r--r--lib/libcbor/src/cbor.h68
-rw-r--r--lib/libcbor/src/cbor/arrays.c157
-rw-r--r--lib/libcbor/src/cbor/arrays.h112
-rw-r--r--lib/libcbor/src/cbor/bytestrings.c118
-rw-r--r--lib/libcbor/src/cbor/bytestrings.h123
-rw-r--r--lib/libcbor/src/cbor/callbacks.c104
-rw-r--r--lib/libcbor/src/cbor/callbacks.h187
-rw-r--r--lib/libcbor/src/cbor/common.c188
-rw-r--r--lib/libcbor/src/cbor/common.h261
-rw-r--r--lib/libcbor/src/cbor/configuration.h15
-rw-r--r--lib/libcbor/src/cbor/configuration.h.in15
-rw-r--r--lib/libcbor/src/cbor/data.h212
-rw-r--r--lib/libcbor/src/cbor/encoding.c186
-rw-r--r--lib/libcbor/src/cbor/encoding.h107
-rw-r--r--lib/libcbor/src/cbor/floats_ctrls.c191
-rw-r--r--lib/libcbor/src/cbor/floats_ctrls.h203
-rw-r--r--lib/libcbor/src/cbor/internal/builder_callbacks.c359
-rw-r--r--lib/libcbor/src/cbor/internal/builder_callbacks.h81
-rw-r--r--lib/libcbor/src/cbor/internal/encoders.c112
-rw-r--r--lib/libcbor/src/cbor/internal/encoders.h32
-rw-r--r--lib/libcbor/src/cbor/internal/loaders.c99
-rw-r--r--lib/libcbor/src/cbor/internal/loaders.h36
-rw-r--r--lib/libcbor/src/cbor/internal/memory_utils.c46
-rw-r--r--lib/libcbor/src/cbor/internal/memory_utils.h37
-rw-r--r--lib/libcbor/src/cbor/internal/stack.c33
-rw-r--r--lib/libcbor/src/cbor/internal/stack.h40
-rw-r--r--lib/libcbor/src/cbor/internal/unicode.c69
-rw-r--r--lib/libcbor/src/cbor/internal/unicode.h34
-rw-r--r--lib/libcbor/src/cbor/ints.c207
-rw-r--r--lib/libcbor/src/cbor/ints.h203
-rw-r--r--lib/libcbor/src/cbor/maps.c141
-rw-r--r--lib/libcbor/src/cbor/maps.h107
-rw-r--r--lib/libcbor/src/cbor/serialization.c287
-rw-r--r--lib/libcbor/src/cbor/serialization.h123
-rw-r--r--lib/libcbor/src/cbor/streaming.c684
-rw-r--r--lib/libcbor/src/cbor/streaming.h38
-rw-r--r--lib/libcbor/src/cbor/strings.c133
-rw-r--r--lib/libcbor/src/cbor/strings.h144
-rw-r--r--lib/libcbor/src/cbor/tags.c45
-rw-r--r--lib/libcbor/src/cbor/tags.h63
42 files changed, 5810 insertions, 0 deletions
diff --git a/lib/libcbor/src/allocators.c b/lib/libcbor/src/allocators.c
new file mode 100644
index 00000000000..ff22509a193
--- /dev/null
+++ b/lib/libcbor/src/allocators.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "cbor/common.h"
+
+_cbor_malloc_t _cbor_malloc = malloc;
+_cbor_realloc_t _cbor_realloc = realloc;
+_cbor_free_t _cbor_free = free;
+
+void cbor_set_allocs(_cbor_malloc_t custom_malloc, _cbor_realloc_t custom_realloc, _cbor_free_t custom_free)
+{
+ _cbor_malloc = custom_malloc;
+ _cbor_realloc = custom_realloc;
+ _cbor_free = custom_free;
+}
diff --git a/lib/libcbor/src/cbor.c b/lib/libcbor/src/cbor.c
new file mode 100644
index 00000000000..86a3012480c
--- /dev/null
+++ b/lib/libcbor/src/cbor.c
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "cbor.h"
+#include "cbor/internal/builder_callbacks.h"
+#include "cbor/internal/loaders.h"
+
+cbor_item_t * cbor_load(cbor_data source,
+ size_t source_size,
+ struct cbor_load_result *result)
+{
+ /* Context stack */
+ static struct cbor_callbacks callbacks = {
+ .uint8 = &cbor_builder_uint8_callback,
+ .uint16 = &cbor_builder_uint16_callback,
+ .uint32 = &cbor_builder_uint32_callback,
+ .uint64 = &cbor_builder_uint64_callback,
+
+ .negint8 = &cbor_builder_negint8_callback,
+ .negint16 = &cbor_builder_negint16_callback,
+ .negint32 = &cbor_builder_negint32_callback,
+ .negint64 = &cbor_builder_negint64_callback,
+
+ .byte_string = &cbor_builder_byte_string_callback,
+ .byte_string_start = &cbor_builder_byte_string_start_callback,
+
+ .string = &cbor_builder_string_callback,
+ .string_start = &cbor_builder_string_start_callback,
+
+ .array_start = &cbor_builder_array_start_callback,
+ .indef_array_start = &cbor_builder_indef_array_start_callback,
+
+ .map_start = &cbor_builder_map_start_callback,
+ .indef_map_start = &cbor_builder_indef_map_start_callback,
+
+ .tag = &cbor_builder_tag_callback,
+
+ .null = &cbor_builder_null_callback,
+ .undefined = &cbor_builder_undefined_callback,
+ .boolean = &cbor_builder_boolean_callback,
+ .float2 = &cbor_builder_float2_callback,
+ .float4 = &cbor_builder_float4_callback,
+ .float8 = &cbor_builder_float8_callback,
+ .indef_break = &cbor_builder_indef_break_callback
+ };
+
+ if (source_size == 0) {
+ result->error.code = CBOR_ERR_NODATA;
+ return NULL;
+ }
+ struct _cbor_stack stack = _cbor_stack_init();
+
+ /* Target for callbacks */
+ struct _cbor_decoder_context context = (struct _cbor_decoder_context) {
+ .stack = &stack,
+ .creation_failed = false,
+ .syntax_error = false
+ };
+ struct cbor_decoder_result decode_result;
+ *result = (struct cbor_load_result) {.read = 0, .error = {.code = CBOR_ERR_NONE}};
+
+ do {
+ if (source_size > result->read) { /* Check for overflows */
+ decode_result = cbor_stream_decode(
+ source + result->read,
+ source_size - result->read,
+ &callbacks,
+ &context);
+ } else {
+ result->error = (struct cbor_error) {
+ .code = CBOR_ERR_NOTENOUGHDATA,
+ .position = result->read
+ };
+ goto error;
+ }
+
+ switch (decode_result.status) {
+ case CBOR_DECODER_FINISHED:
+ /* Everything OK */
+ {
+ result->read += decode_result.read;
+ break;
+ }
+ case CBOR_DECODER_NEDATA:
+ /* Data length doesn't match MTB expectation */
+ {
+ result->error.code = CBOR_ERR_NOTENOUGHDATA;
+ goto error;
+ }
+ case CBOR_DECODER_EBUFFER:
+ /* Fallthrough */
+ case CBOR_DECODER_ERROR:
+ /* Reserved/malformated item */
+ {
+ result->error.code = CBOR_ERR_MALFORMATED;
+ goto error;
+ }
+ }
+
+ if (context.creation_failed) {
+ /* Most likely unsuccessful allocation - our callback has failed */
+ result->error.code = CBOR_ERR_MEMERROR;
+ goto error;
+ } else if (context.syntax_error) {
+ result->error.code = CBOR_ERR_SYNTAXERROR;
+ goto error;
+ }
+ } while (stack.size > 0);
+
+ /* Move the result before free */
+ cbor_item_t *result_item = context.root;
+ return result_item;
+
+ error:
+ result->error.position = result->read;
+ //debug_print("Failed with decoder error %d at %d\n", result->error.code, result->error.position);
+ //cbor_describe(stack.top->item, stdout);
+ /* Free the stack */
+ while (stack.size > 0) {
+ cbor_decref(&stack.top->item);
+ _cbor_stack_pop(&stack);
+ }
+ return NULL;
+}
+
+
+static cbor_item_t * _cbor_copy_int(cbor_item_t * item, bool negative)
+{
+ cbor_item_t * res;
+ switch (cbor_int_get_width(item)) {
+ case CBOR_INT_8: res = cbor_build_uint8(cbor_get_uint8(item)); break;
+ case CBOR_INT_16: res = cbor_build_uint16(cbor_get_uint16(item)); break;
+ case CBOR_INT_32: res = cbor_build_uint32(cbor_get_uint32(item)); break;
+ case CBOR_INT_64: res = cbor_build_uint64(cbor_get_uint64(item)); break;
+ default: return NULL;
+ }
+
+ if (negative)
+ cbor_mark_negint(res);
+
+ return res;
+}
+
+static cbor_item_t * _cbor_copy_float_ctrl(cbor_item_t * item)
+{
+ switch (cbor_float_get_width(item)) {
+ case CBOR_FLOAT_0:
+ return cbor_build_ctrl(cbor_ctrl_value(item));
+ case CBOR_FLOAT_16:
+ return cbor_build_float2(cbor_float_get_float2(item));
+ case CBOR_FLOAT_32:
+ return cbor_build_float4(cbor_float_get_float4(item));
+ case CBOR_FLOAT_64:
+ return cbor_build_float8(cbor_float_get_float8(item));
+ }
+
+ return NULL;
+}
+
+cbor_item_t * cbor_copy(cbor_item_t * item)
+{
+ switch (cbor_typeof(item)) {
+ case CBOR_TYPE_UINT:
+ return _cbor_copy_int(item, false);
+ case CBOR_TYPE_NEGINT:
+ return _cbor_copy_int(item, true);
+ case CBOR_TYPE_BYTESTRING:
+ if (cbor_bytestring_is_definite(item)) {
+ return cbor_build_bytestring(cbor_bytestring_handle(item), cbor_bytestring_length(item));
+ } else {
+ cbor_item_t * res = cbor_new_indefinite_bytestring();
+ for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++)
+ cbor_bytestring_add_chunk(
+ res,
+ cbor_move(
+ cbor_copy(cbor_bytestring_chunks_handle(item)[i])
+ )
+ );
+ return res;
+ }
+ case CBOR_TYPE_STRING:
+ if (cbor_string_is_definite(item)) {
+ return cbor_build_stringn((const char *) cbor_string_handle(item), cbor_string_length(item));
+ } else {
+ cbor_item_t * res = cbor_new_indefinite_string();
+ for (size_t i = 0; i < cbor_string_chunk_count(item); i++)
+ cbor_string_add_chunk(
+ res,
+ cbor_move(
+ cbor_copy(cbor_string_chunks_handle(item)[i])
+ )
+ );
+ return res;
+ }
+ case CBOR_TYPE_ARRAY: {
+ cbor_item_t * res;
+ if (cbor_array_is_definite(item))
+ res = cbor_new_definite_array(cbor_array_size(item));
+ else
+ res = cbor_new_indefinite_array();
+
+ for (size_t i = 0; i < cbor_array_size(item); i++)
+ cbor_array_push(
+ res,
+ cbor_move(cbor_copy(cbor_move(cbor_array_get(item, i))))
+ );
+ return res;
+ }
+ case CBOR_TYPE_MAP: {
+ cbor_item_t * res;
+ if (cbor_map_is_definite(item))
+ res = cbor_new_definite_map(cbor_map_size(item));
+ else
+ res = cbor_new_indefinite_map();
+
+ struct cbor_pair * it = cbor_map_handle(item);
+ for (size_t i = 0; i < cbor_map_size(item); i++)
+ cbor_map_add(res, (struct cbor_pair) {
+ .key = cbor_move(cbor_copy(it[i].key)),
+ .value = cbor_move(cbor_copy(it[i].value))
+ });
+ return res;
+ }
+ case CBOR_TYPE_TAG:
+ return cbor_build_tag(
+ cbor_tag_value(item),
+ cbor_move(cbor_copy(cbor_tag_item(item)))
+ );
+ case CBOR_TYPE_FLOAT_CTRL:
+ return _cbor_copy_float_ctrl(item);
+ }
+
+ return NULL;
+}
+
+#if CBOR_PRETTY_PRINTER
+
+#include <inttypes.h>
+#include <wchar.h>
+#include <locale.h>
+#include <stdlib.h>
+
+#define __STDC_FORMAT_MACROS
+
+static int _pow(int b, int ex)
+{
+ if (ex == 0) return 1;
+ int res = b;
+ while (--ex > 0) res *= b;
+ return res;
+}
+
+static void _cbor_nested_describe(cbor_item_t *item, FILE *out, int indent)
+{
+ setlocale(LC_ALL, "");
+ switch (cbor_typeof(item)) {
+ case CBOR_TYPE_UINT: {
+ fprintf(out, "%*s[CBOR_TYPE_UINT] ", indent, " ");
+ fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item)));
+ fprintf(out, "Value: %"PRIu64"\n", cbor_get_int(item));
+ break;
+ };
+ case CBOR_TYPE_NEGINT: {
+ fprintf(out, "%*s[CBOR_TYPE_NEGINT] ", indent, " ");
+ fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item)));
+ fprintf(out, "Value: -%"PRIu64" -1\n", cbor_get_int(item));
+ break;
+ };
+ case CBOR_TYPE_BYTESTRING: {
+ fprintf(out, "%*s[CBOR_TYPE_BYTESTRING] ", indent, " ");
+ if (cbor_bytestring_is_indefinite(item)) {
+ fprintf(out,
+ "Indefinite, with %zu chunks:\n",
+ cbor_bytestring_chunk_count(item));
+ for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++)
+ _cbor_nested_describe(
+ cbor_bytestring_chunks_handle(item)[i],
+ out,
+ indent + 4);
+ } else {
+ fprintf(out,
+ "Definite, length %zuB\n",
+ cbor_bytestring_length(item));
+ }
+ break;
+ };
+ case CBOR_TYPE_STRING: {
+ fprintf(out, "%*s[CBOR_TYPE_STRING] ", indent, " ");
+ if (cbor_string_is_indefinite(item)) {
+ fprintf(out,
+ "Indefinite, with %zu chunks:\n",
+ cbor_string_chunk_count(item));
+ for (size_t i = 0; i < cbor_string_chunk_count(item); i++)
+ _cbor_nested_describe(
+ cbor_string_chunks_handle(item)[i],
+ out,
+ indent + 4);
+ } else {
+ fprintf(out,
+ "Definite, length %zuB, %zu codepoints\n",
+ cbor_string_length(item),
+ cbor_string_codepoint_count(item));
+ /* Careful - this doesn't support multibyte characters! */
+ /* Printing those is out of the scope of this demo :) */
+ /* libICU is your friend */
+ fprintf(out, "%*s", indent + 4, " ");
+ /* XXX: no null at the end -> confused vprintf */
+ fwrite(cbor_string_handle(item), (int) cbor_string_length(item), 1, out);
+ fprintf(out, "\n");
+ }
+ break;
+ };
+ case CBOR_TYPE_ARRAY: {
+ fprintf(out, "%*s[CBOR_TYPE_ARRAY] ", indent, " ");
+ if (cbor_array_is_definite(item)) {
+ fprintf(out,
+ "Definite, size: %zu\n",
+ cbor_array_size(item));
+ } else {
+ fprintf(out,
+ "Indefinite, size: %zu\n",
+ cbor_array_size(item));
+ }
+
+ for (size_t i = 0; i < cbor_array_size(item); i++)
+ _cbor_nested_describe(
+ cbor_array_handle(item)[i],
+ out,
+ indent + 4);
+ break;
+ };
+ case CBOR_TYPE_MAP: {
+ fprintf(out, "%*s[CBOR_TYPE_MAP] ", indent, " ");
+ if (cbor_map_is_definite(item)) {
+ fprintf(out,
+ "Definite, size: %zu\n",
+ cbor_map_size(item));
+ } else {
+ fprintf(out,
+ "Indefinite, size: %zu\n",
+ cbor_map_size(item));
+ }
+
+ for (size_t i = 0; i < cbor_map_size(item); i++) {
+ _cbor_nested_describe(
+ cbor_map_handle(item)[i].key,
+ out,
+ indent + 4);
+ _cbor_nested_describe(
+ cbor_map_handle(item)[i].value,
+ out,
+ indent + 4);
+ }
+ break;
+ };
+ case CBOR_TYPE_TAG: {
+ fprintf(out, "%*s[CBOR_TYPE_TAG] ", indent, " ");
+ fprintf(out, "Value: %"PRIu64"\n", cbor_tag_value(item));
+ _cbor_nested_describe(cbor_tag_item(item), out, indent + 4);
+ break;
+ };
+ case CBOR_TYPE_FLOAT_CTRL: {
+ fprintf(out, "%*s[CBOR_TYPE_FLOAT_CTRL] ", indent, " ");
+ if (cbor_float_ctrl_is_ctrl(item)) {
+ if (cbor_is_bool(item))
+ fprintf(out, "Bool: %s\n", cbor_ctrl_is_bool(item) ? "true" : "false");
+ else if (cbor_is_undef(item))
+ fprintf(out, "Undefined\n");
+ else if (cbor_is_null(item))
+ fprintf(out, "Null\n");
+ else
+ fprintf(out, "Simple value %d\n", cbor_ctrl_value(item));
+ } else {
+ fprintf(out, "Width: %dB, ", _pow(2, cbor_float_get_width(item)));
+ fprintf(out, "value: %lf\n", cbor_float_get_float(item));
+ }
+ break;
+ };
+ }
+}
+
+void cbor_describe(cbor_item_t *item, FILE *out)
+{
+ _cbor_nested_describe(item, out, 0);
+}
+
+#endif
diff --git a/lib/libcbor/src/cbor.h b/lib/libcbor/src/cbor.h
new file mode 100644
index 00000000000..b8a857e2c67
--- /dev/null
+++ b/lib/libcbor/src/cbor.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+
+#ifndef LIBCBOR_H_
+#define LIBCBOR_H_
+
+#include "cbor/data.h"
+#include "cbor/common.h"
+
+#include "cbor/arrays.h"
+#include "cbor/bytestrings.h"
+#include "cbor/floats_ctrls.h"
+#include "cbor/ints.h"
+#include "cbor/maps.h"
+#include "cbor/strings.h"
+#include "cbor/tags.h"
+
+#include "cbor/encoding.h"
+#include "cbor/serialization.h"
+#include "cbor/callbacks.h"
+#include "cbor/streaming.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+* ============================================================================
+* High level decoding
+* ============================================================================
+*/
+
+/** Loads data item from a buffer
+ *
+ * @param source The buffer
+ * @param source_size
+ * @param result[out] Result indicator. #CBOR_ERR_NONE on success
+ * @return **new** CBOR item or `NULL` on failure. In that case, \p result contains location and description of the error.
+ */
+cbor_item_t * cbor_load(cbor_data source,
+ size_t source_size,
+ struct cbor_load_result * result);
+
+/** Deep copy of an item
+ *
+ * All the reference counts in the new structure are set to one.
+ *
+ * @param item[borrow] item to copy
+ * @return **new** CBOR deep copy
+ */
+cbor_item_t * cbor_copy(cbor_item_t * item);
+
+#if CBOR_PRETTY_PRINTER
+#include <stdio.h>
+
+void cbor_describe(cbor_item_t * item, FILE * out);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_H_
diff --git a/lib/libcbor/src/cbor/arrays.c b/lib/libcbor/src/cbor/arrays.c
new file mode 100644
index 00000000000..4e3f0b67cf3
--- /dev/null
+++ b/lib/libcbor/src/cbor/arrays.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <string.h>
+#include "arrays.h"
+#include "internal/memory_utils.h"
+
+size_t cbor_array_size(const cbor_item_t *item)
+{
+ assert(cbor_isa_array(item));
+ return item->metadata.array_metadata.end_ptr;
+}
+
+size_t cbor_array_allocated(const cbor_item_t * item)
+{
+ assert(cbor_isa_array(item));
+ return item->metadata.array_metadata.allocated;
+}
+
+
+cbor_item_t * cbor_array_get(const cbor_item_t * item, size_t index)
+{
+ return cbor_incref(((cbor_item_t **) item->data)[index]);
+}
+
+bool cbor_array_set(cbor_item_t * item, size_t index, cbor_item_t * value)
+{
+ if (index == item->metadata.array_metadata.end_ptr) {
+ return cbor_array_push(item, value);
+ } else if (index < item->metadata.array_metadata.end_ptr) {
+ return cbor_array_replace(item, index, value);
+ } else {
+ return false;
+ }
+ return true;
+}
+
+bool cbor_array_replace(cbor_item_t * item, size_t index, cbor_item_t * value)
+{
+ if (index >= item->metadata.array_metadata.end_ptr)
+ return false;
+ /* We cannot use cbor_array_get as that would increase the refcount */
+ cbor_intermediate_decref(((cbor_item_t **) item->data)[index]);
+ ((cbor_item_t **) item->data)[index] = cbor_incref(value);
+ return true;
+}
+
+bool cbor_array_push(cbor_item_t *array, cbor_item_t *pushee)
+{
+ assert(cbor_isa_array(array));
+ struct _cbor_array_metadata *metadata = (struct _cbor_array_metadata *) &array->metadata;
+ cbor_item_t **data = (cbor_item_t **) array->data;
+ if (cbor_array_is_definite(array)) {
+ /* Do not reallocate definite arrays */
+ if (metadata->end_ptr >= metadata->allocated) {
+ return false;
+ }
+ data[metadata->end_ptr++] = pushee;
+ } else {
+ /* Exponential realloc */
+ if (metadata->end_ptr >= metadata->allocated) {
+ // Check for overflows first
+ if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) {
+ return false;
+ }
+
+ size_t new_allocation = metadata->allocated == 0 ? 1 : CBOR_BUFFER_GROWTH * metadata->allocated;
+
+ unsigned char * new_data = _cbor_realloc_multiple(array->data, sizeof(cbor_item_t *), new_allocation);
+ if (new_data == NULL) {
+ return false;
+ }
+
+ array->data = new_data;
+ metadata->allocated = new_allocation;
+ }
+ ((cbor_item_t **)array->data)[metadata->end_ptr++] = pushee;
+ }
+ cbor_incref(pushee);
+ return true;
+}
+
+
+bool cbor_array_is_definite(const cbor_item_t *item)
+{
+ assert(cbor_isa_array(item));
+ return item->metadata.array_metadata.type == _CBOR_METADATA_DEFINITE;
+}
+
+bool cbor_array_is_indefinite(const cbor_item_t *item)
+{
+ assert(cbor_isa_array(item));
+ return item->metadata.array_metadata.type == _CBOR_METADATA_INDEFINITE;
+}
+
+cbor_item_t **cbor_array_handle(const cbor_item_t *item)
+{
+ assert(cbor_isa_array(item));
+ return (cbor_item_t **) item->data;
+}
+
+cbor_item_t *cbor_new_definite_array(size_t size)
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
+ if (item == NULL) {
+ return NULL;
+ }
+
+ cbor_item_t ** data = _cbor_alloc_multiple(sizeof(cbor_item_t *), size);
+ if (data == NULL) {
+ _CBOR_FREE(item);
+ return NULL;
+ }
+
+ for (size_t i = 0; i < size; i++)
+ data[i] = NULL;
+
+ *item = (cbor_item_t) {
+ .refcount = 1,
+ .type = CBOR_TYPE_ARRAY,
+ .metadata = {
+ .array_metadata = {
+ .type = _CBOR_METADATA_DEFINITE,
+ .allocated = size,
+ .end_ptr = 0
+ }
+ },
+ .data = (unsigned char *)data
+ };
+
+ return item;
+}
+
+cbor_item_t *cbor_new_indefinite_array()
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
+ if (item == NULL)
+ return NULL;
+
+ *item = (cbor_item_t) {
+ .refcount = 1,
+ .type = CBOR_TYPE_ARRAY,
+ .metadata = {
+ .array_metadata = {
+ .type = _CBOR_METADATA_INDEFINITE,
+ .allocated = 0,
+ .end_ptr = 0
+ }
+ },
+ .data = NULL /* Can be safely realloc-ed */
+ };
+ return item;
+}
diff --git a/lib/libcbor/src/cbor/arrays.h b/lib/libcbor/src/cbor/arrays.h
new file mode 100644
index 00000000000..62629f4e1c6
--- /dev/null
+++ b/lib/libcbor/src/cbor/arrays.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_ARRAYS_H
+#define LIBCBOR_ARRAYS_H
+
+#include "cbor/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Get the number of members
+ *
+ * @param item[borrow] An array
+ * @return The number of members
+ */
+size_t cbor_array_size(const cbor_item_t * item);
+
+/** Get the size of the allocated storage
+ *
+ * @param item[borrow] An array
+ * @return The size of the allocated storage (number of items)
+ */
+size_t cbor_array_allocated(const cbor_item_t * item);
+
+/** Get item by index
+ *
+ * @param item[borrow] An array
+ * @param index The index
+ * @return **incref** The item, or `NULL` in case of boundary violation
+ */
+cbor_item_t * cbor_array_get(const cbor_item_t * item, size_t index);
+
+/** Set item by index
+ *
+ * Creating arrays with holes is not possible
+ *
+ * @param item[borrow] An array
+ * @param value[incref] The item to assign
+ * @param index The index, first item is 0.
+ * @return true on success, false on allocation failure.
+ */
+bool cbor_array_set(cbor_item_t * item, size_t index, cbor_item_t * value);
+
+/** Replace item at an index
+ *
+ * The item being replace will be #cbor_decref 'ed.
+ *
+ * @param item[borrow] An array
+ * @param value[incref] The item to assign
+ * @param index The index, first item is 0.
+ * @return true on success, false on allocation failure.
+ */
+bool cbor_array_replace(cbor_item_t * item, size_t index, cbor_item_t * value);
+
+/** Is the array definite?
+ *
+ * @param item[borrow] An array
+ * @return Is the array definite?
+ */
+bool cbor_array_is_definite(const cbor_item_t * item);
+
+/** Is the array indefinite?
+ *
+ * @param item[borrow] An array
+ * @return Is the array indefinite?
+ */
+bool cbor_array_is_indefinite(const cbor_item_t * item);
+
+/** Get the array contents
+ *
+ * The items may be reordered and modified as long as references remain consistent.
+ *
+ * @param item[borrow] An array
+ * @return #cbor_array_size items
+ */
+cbor_item_t ** cbor_array_handle(const cbor_item_t * item);
+
+/** Create new definite array
+ *
+ * @param size Number of slots to preallocate
+ * @return **new** array or `NULL` upon malloc failure
+ */
+cbor_item_t * cbor_new_definite_array(size_t size);
+
+/** Create new indefinite array
+ *
+ * @return **new** array or `NULL` upon malloc failure
+ */
+cbor_item_t * cbor_new_indefinite_array();
+
+/** Append to the end
+ *
+ * For indefinite items, storage may be realloacted. For definite items, only the
+ * preallocated capacity is available.
+ *
+ * @param array[borrow] An array
+ * @param pushee[incref] The item to push
+ * @return true on success, false on failure
+ */
+bool cbor_array_push(cbor_item_t * array, cbor_item_t * pushee);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_ARRAYS_H
diff --git a/lib/libcbor/src/cbor/bytestrings.c b/lib/libcbor/src/cbor/bytestrings.c
new file mode 100644
index 00000000000..ada4832f0d9
--- /dev/null
+++ b/lib/libcbor/src/cbor/bytestrings.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <string.h>
+#include "bytestrings.h"
+#include "internal/memory_utils.h"
+
+size_t cbor_bytestring_length(const cbor_item_t *item)
+{
+ assert(cbor_isa_bytestring(item));
+ return item->metadata.bytestring_metadata.length;
+}
+
+unsigned char *cbor_bytestring_handle(const cbor_item_t *item)
+{
+ assert(cbor_isa_bytestring(item));
+ return item->data;
+}
+
+bool cbor_bytestring_is_definite(const cbor_item_t *item)
+{
+ assert(cbor_isa_bytestring(item));
+ return item->metadata.bytestring_metadata.type == _CBOR_METADATA_DEFINITE;
+}
+
+bool cbor_bytestring_is_indefinite(const cbor_item_t *item)
+{
+ return !cbor_bytestring_is_definite(item);
+}
+
+cbor_item_t *cbor_new_definite_bytestring()
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
+ *item = (cbor_item_t) {
+ .refcount = 1,
+ .type = CBOR_TYPE_BYTESTRING,
+ .metadata = {.bytestring_metadata = {_CBOR_METADATA_DEFINITE, 0}}
+ };
+ return item;
+}
+
+cbor_item_t *cbor_new_indefinite_bytestring()
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
+ *item = (cbor_item_t) {
+ .refcount = 1,
+ .type = CBOR_TYPE_BYTESTRING,
+ .metadata = {.bytestring_metadata = {.type = _CBOR_METADATA_INDEFINITE, .length = 0}},
+ .data = _CBOR_MALLOC(sizeof(struct cbor_indefinite_string_data))
+ };
+ *((struct cbor_indefinite_string_data *) item->data) = (struct cbor_indefinite_string_data) {
+ .chunk_count = 0,
+ .chunk_capacity = 0,
+ .chunks = NULL,
+ };
+ return item;
+}
+
+cbor_item_t *cbor_build_bytestring(cbor_data handle, size_t length)
+{
+ cbor_item_t *res = cbor_new_definite_bytestring();
+ void * content = _CBOR_MALLOC(length);
+ memcpy(content, handle, length);
+ cbor_bytestring_set_handle(res, content, length);
+ return res;
+}
+
+void cbor_bytestring_set_handle(cbor_item_t *item, cbor_mutable_data CBOR_RESTRICT_POINTER data, size_t length)
+{
+ assert(cbor_isa_bytestring(item));
+ assert(cbor_bytestring_is_definite(item));
+ item->data = data;
+ item->metadata.bytestring_metadata.length = length;
+}
+
+cbor_item_t **cbor_bytestring_chunks_handle(const cbor_item_t *item)
+{
+ assert(cbor_isa_bytestring(item));
+ assert(cbor_bytestring_is_indefinite(item));
+ return ((struct cbor_indefinite_string_data *) item->data)->chunks;
+}
+
+size_t cbor_bytestring_chunk_count(const cbor_item_t *item)
+{
+ assert(cbor_isa_bytestring(item));
+ assert(cbor_bytestring_is_indefinite(item));
+ return ((struct cbor_indefinite_string_data *) item->data)->chunk_count;
+
+}
+
+bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk)
+{
+ assert(cbor_isa_bytestring(item));
+ assert(cbor_bytestring_is_indefinite(item));
+ struct cbor_indefinite_string_data *data = (struct cbor_indefinite_string_data *) item->data;
+ if (data->chunk_count == data->chunk_capacity) {
+ /* We need more space */
+ if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) {
+ return false;
+ }
+
+ data->chunk_capacity = data->chunk_capacity == 0 ? 1 : CBOR_BUFFER_GROWTH * (data->chunk_capacity);
+
+ cbor_item_t **new_chunks_data = _cbor_realloc_multiple(data->chunks, sizeof(cbor_item_t *), data->chunk_capacity);
+
+ if (new_chunks_data == NULL) {
+ return false;
+ }
+
+ data->chunks = new_chunks_data;
+ }
+ data->chunks[data->chunk_count++] = cbor_incref(chunk);
+ return true;
+}
diff --git a/lib/libcbor/src/cbor/bytestrings.h b/lib/libcbor/src/cbor/bytestrings.h
new file mode 100644
index 00000000000..a5eb98b5e7e
--- /dev/null
+++ b/lib/libcbor/src/cbor/bytestrings.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_BYTESTRINGS_H
+#define LIBCBOR_BYTESTRINGS_H
+
+#include "cbor/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+* ============================================================================
+* Byte string manipulation
+* ============================================================================
+*/
+
+/** Returns the length of the binary data
+ *
+ * For definite byte strings only
+ *
+ * @param item[borrow] a definite bytestring
+ * @return length of the binary data. Zero if no chunk has been attached yet
+ */
+size_t cbor_bytestring_length(const cbor_item_t *item);
+
+/** Is the byte string definite?
+ *
+ * @param item[borrow] a byte string
+ * @return Is the byte string definite?
+ */
+bool cbor_bytestring_is_definite(const cbor_item_t *item);
+
+/** Is the byte string indefinite?
+ *
+ * @param item[borrow] a byte string
+ * @return Is the byte string indefinite?
+ */
+bool cbor_bytestring_is_indefinite(const cbor_item_t *item);
+
+/** Get the handle to the binary data
+ *
+ * Definite items only. Modifying the data is allowed. In that case, the caller takes
+ * responsibility for the effect on items this item might be a part of
+ *
+ * @param item[borrow] A definite byte string
+ * @return The address of the binary data. `NULL` if no data have been assigned yet.
+ */
+cbor_mutable_data cbor_bytestring_handle(const cbor_item_t *item);
+
+/** Set the handle to the binary data
+ *
+ * @param item[borrow] A definite byte string
+ * @param data The memory block. The caller gives up the ownership of the block. libcbor will deallocate it when appropriate using its free function
+ * @param length Length of the data block
+ */
+void cbor_bytestring_set_handle(cbor_item_t *item, cbor_mutable_data CBOR_RESTRICT_POINTER data, size_t length);
+
+/** Get the handle to the array of chunks
+ *
+ * Manipulations with the memory block (e.g. sorting it) are allowed, but the validity and the number of chunks must be retained.
+ *
+ * @param item[borrow] A indefinite byte string
+ * @return array of #cbor_bytestring_chunk_count definite bytestrings
+ */
+cbor_item_t **cbor_bytestring_chunks_handle(const cbor_item_t *item);
+
+/** Get the number of chunks this string consist of
+ *
+ * @param item[borrow] A indefinite bytestring
+ * @return The chunk count. 0 for freshly created items.
+ */
+size_t cbor_bytestring_chunk_count(const cbor_item_t *item);
+
+/** Appends a chunk to the bytestring
+ *
+ * Indefinite byte strings only.
+ *
+ * May realloc the chunk storage.
+ *
+ * @param item[borrow] An indefinite byte string
+ * @param item[incref] A definite byte string
+ * @return true on success, false on realloc failure. In that case, the refcount of `chunk` is not increased and the `item` is left intact.
+ */
+bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk);
+
+/** Creates a new definite byte string
+ *
+ * The handle is initialized to `NULL` and length to 0
+ *
+ * @return **new** definite bytestring. `NULL` on malloc failure.
+ */
+cbor_item_t *cbor_new_definite_bytestring();
+
+/** Creates a new indefinite byte string
+ *
+ * The chunks array is initialized to `NULL` and chunkcount to 0
+ *
+ * @return **new** indefinite bytestring. `NULL` on malloc failure.
+ */
+cbor_item_t *cbor_new_indefinite_bytestring();
+
+/** Creates a new byte string and initializes it
+ *
+ * The `handle` will be copied to a newly allocated block
+ *
+ * @param handle Block of binary data
+ * @param length Length of `data`
+ * @return A **new** byte string with content `handle`. `NULL` on malloc failure.
+ */
+cbor_item_t *cbor_build_bytestring(cbor_data handle, size_t length);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIBCBOR_BYTESTRINGS_H
diff --git a/lib/libcbor/src/cbor/callbacks.c b/lib/libcbor/src/cbor/callbacks.c
new file mode 100644
index 00000000000..81fe857319e
--- /dev/null
+++ b/lib/libcbor/src/cbor/callbacks.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "callbacks.h"
+
+#define CBOR_DUMMY_CALLBACK { }
+
+void cbor_null_uint8_callback(void *_ctx, uint8_t _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_uint16_callback(void *_ctx, uint16_t _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_uint32_callback(void *_ctx, uint32_t _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_uint64_callback(void *_ctx, uint64_t _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_negint8_callback(void *_ctx, uint8_t _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_negint16_callback(void *_ctx, uint16_t _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_negint32_callback(void *_ctx, uint32_t _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_negint64_callback(void *_ctx, uint64_t _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_string_callback(void *_ctx, cbor_data _val, size_t _val2) CBOR_DUMMY_CALLBACK
+
+void cbor_null_string_start_callback(void *_ctx) CBOR_DUMMY_CALLBACK
+
+void cbor_null_byte_string_callback(void *_ctx, cbor_data _val, size_t _val2) CBOR_DUMMY_CALLBACK
+
+void cbor_null_byte_string_start_callback(void *_ctx) CBOR_DUMMY_CALLBACK
+
+void cbor_null_array_start_callback(void *_ctx, size_t _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_indef_array_start_callback(void *_ctx) CBOR_DUMMY_CALLBACK
+
+void cbor_null_map_start_callback(void *_ctx, size_t _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_indef_map_start_callback(void *_ctx) CBOR_DUMMY_CALLBACK
+
+void cbor_null_tag_callback(void *_ctx, uint64_t _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_float2_callback(void *_ctx, float _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_float4_callback(void *_ctx, float _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_float8_callback(void *_ctx, double _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_null_callback(void *_ctx) CBOR_DUMMY_CALLBACK
+
+void cbor_null_undefined_callback(void *_ctx) CBOR_DUMMY_CALLBACK
+
+void cbor_null_boolean_callback(void *_ctx, bool _val) CBOR_DUMMY_CALLBACK
+
+void cbor_null_indef_break_callback(void *_ctx) CBOR_DUMMY_CALLBACK
+
+const struct cbor_callbacks cbor_empty_callbacks = {
+ /* Type 0 - Unsigned integers */
+ .uint8 = cbor_null_uint8_callback,
+ .uint16 = cbor_null_uint16_callback,
+ .uint32 = cbor_null_uint32_callback,
+ .uint64 = cbor_null_uint64_callback,
+
+ /* Type 1 - Negative integers */
+ .negint8 = cbor_null_negint8_callback,
+ .negint16 = cbor_null_negint16_callback,
+ .negint32 = cbor_null_negint32_callback,
+ .negint64 = cbor_null_negint64_callback,
+
+ /* Type 2 - Byte strings */
+ .byte_string_start = cbor_null_byte_string_start_callback,
+ .byte_string = cbor_null_byte_string_callback,
+
+ /* Type 3 - Strings */
+ .string_start = cbor_null_string_start_callback,
+ .string = cbor_null_string_callback,
+
+ /* Type 4 - Arrays */
+ .indef_array_start = cbor_null_indef_array_start_callback,
+ .array_start = cbor_null_array_start_callback,
+
+ /* Type 5 - Maps */
+ .indef_map_start = cbor_null_indef_map_start_callback,
+ .map_start = cbor_null_map_start_callback,
+
+ /* Type 6 - Tags */
+ .tag = cbor_null_tag_callback,
+
+ /* Type 7 - Floats & misc */
+ /* Type names cannot be member names */
+ .float2 = cbor_null_float2_callback,
+ /* 2B float is not supported in standard C */
+ .float4 = cbor_null_float4_callback,
+ .float8 = cbor_null_float8_callback,
+ .undefined = cbor_null_undefined_callback,
+ .null = cbor_null_null_callback,
+ .boolean = cbor_null_boolean_callback,
+
+ /* Shared indefinites */
+ .indef_break = cbor_null_indef_break_callback,
+};
diff --git a/lib/libcbor/src/cbor/callbacks.h b/lib/libcbor/src/cbor/callbacks.h
new file mode 100644
index 00000000000..7ca6cda9ea5
--- /dev/null
+++ b/lib/libcbor/src/cbor/callbacks.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_CALLBACKS_H
+#define LIBCBOR_CALLBACKS_H
+
+#include "cbor/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Callback prototype */
+typedef void(*cbor_int8_callback)(void *, uint8_t);
+
+/** Callback prototype */
+typedef void(*cbor_int16_callback)(void *, uint16_t);
+
+/** Callback prototype */
+typedef void(*cbor_int32_callback)(void *, uint32_t);
+
+/** Callback prototype */
+typedef void(*cbor_int64_callback)(void *, uint64_t);
+
+/** Callback prototype */
+typedef void(*cbor_simple_callback)(void *);
+
+/** Callback prototype */
+typedef void(*cbor_string_callback)(void *, cbor_data, size_t);
+
+/** Callback prototype */
+typedef void(*cbor_collection_callback)(void *, size_t);
+
+/** Callback prototype */
+typedef void(*cbor_float_callback)(void *, float);
+
+/** Callback prototype */
+typedef void(*cbor_double_callback)(void *, double);
+
+/** Callback prototype */
+typedef void(*cbor_bool_callback)(void *, bool);
+
+/** Callback bundle -- passed to the decoder */
+struct cbor_callbacks {
+ /** Unsigned int */
+ cbor_int8_callback uint8;
+ /** Unsigned int */
+ cbor_int16_callback uint16;
+ /** Unsigned int */
+ cbor_int32_callback uint32;
+ /** Unsigned int */
+ cbor_int64_callback uint64;
+
+ /** Negative int */
+ cbor_int64_callback negint64;
+ /** Negative int */
+ cbor_int32_callback negint32;
+ /** Negative int */
+ cbor_int16_callback negint16;
+ /** Negative int */
+ cbor_int8_callback negint8;
+
+ /** Definite byte string */
+ cbor_simple_callback byte_string_start;
+ /** Indefinite byte string start */
+ cbor_string_callback byte_string;
+
+ /** Definite string */
+ cbor_string_callback string;
+ /** Indefinite string start */
+ cbor_simple_callback string_start;
+
+ /** Definite array */
+ cbor_simple_callback indef_array_start;
+ /** Indefinite array */
+ cbor_collection_callback array_start;
+
+ /** Definite map */
+ cbor_simple_callback indef_map_start;
+ /** Indefinite map */
+ cbor_collection_callback map_start;
+
+ /** Tags */
+ cbor_int64_callback tag;
+
+ /** Half float */
+ cbor_float_callback float2;
+ /** Single float */
+ cbor_float_callback float4;
+ /** Double float */
+ cbor_double_callback float8;
+ /** Undef */
+ cbor_simple_callback undefined;
+ /** Null */
+ cbor_simple_callback null;
+ /** Bool */
+ cbor_bool_callback boolean;
+
+ /** Indefinite item break */
+ cbor_simple_callback indef_break;
+};
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_uint8_callback(void *, uint8_t);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_uint16_callback(void *, uint16_t);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_uint32_callback(void *, uint32_t);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_uint64_callback(void *, uint64_t);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_negint8_callback(void *, uint8_t);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_negint16_callback(void *, uint16_t);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_negint32_callback(void *, uint32_t);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_negint64_callback(void *, uint64_t);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_string_callback(void *, cbor_data, size_t);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_string_start_callback(void *);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_byte_string_callback(void *, cbor_data, size_t);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_byte_string_start_callback(void *);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_array_start_callback(void *, size_t);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_indef_array_start_callback(void *);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_map_start_callback(void *, size_t);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_indef_map_start_callback(void *);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_tag_callback(void *, uint64_t);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_float2_callback(void *, float);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_float4_callback(void *, float);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_float8_callback(void *, double);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_null_callback(void *);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_undefined_callback(void *);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_boolean_callback(void *, bool);
+
+/** Dummy callback implementation - does nothing */
+void cbor_null_indef_break_callback(void *);
+
+/** Dummy callback bundle - does nothing */
+extern const struct cbor_callbacks cbor_empty_callbacks;
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIBCBOR_CALLBACKS_H
diff --git a/lib/libcbor/src/cbor/common.c b/lib/libcbor/src/cbor/common.c
new file mode 100644
index 00000000000..77544ae8107
--- /dev/null
+++ b/lib/libcbor/src/cbor/common.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "cbor/common.h"
+#include "arrays.h"
+#include "bytestrings.h"
+#include "data.h"
+#include "floats_ctrls.h"
+#include "ints.h"
+#include "maps.h"
+#include "strings.h"
+#include "tags.h"
+
+bool cbor_isa_uint(const cbor_item_t *item)
+{
+ return item->type == CBOR_TYPE_UINT;
+}
+
+bool cbor_isa_negint(const cbor_item_t *item)
+{
+ return item->type == CBOR_TYPE_NEGINT;
+}
+
+bool cbor_isa_bytestring(const cbor_item_t *item)
+{
+ return item->type == CBOR_TYPE_BYTESTRING;
+}
+
+bool cbor_isa_string(const cbor_item_t *item)
+{
+ return item->type == CBOR_TYPE_STRING;
+}
+
+bool cbor_isa_array(const cbor_item_t *item)
+{
+ return item->type == CBOR_TYPE_ARRAY;
+}
+
+bool cbor_isa_map(const cbor_item_t *item)
+{
+ return item->type == CBOR_TYPE_MAP;
+}
+
+bool cbor_isa_tag(const cbor_item_t *item)
+{
+ return item->type == CBOR_TYPE_TAG;
+}
+
+bool cbor_isa_float_ctrl(const cbor_item_t *item)
+{
+ return item->type == CBOR_TYPE_FLOAT_CTRL;
+}
+
+
+cbor_type cbor_typeof(const cbor_item_t *item)
+{
+ return item->type;
+}
+
+
+bool cbor_is_int(const cbor_item_t *item)
+{
+ return cbor_isa_uint(item) || cbor_isa_negint(item);
+}
+
+
+bool cbor_is_bool(const cbor_item_t *item)
+{
+ return cbor_isa_float_ctrl(item) &&
+ (cbor_ctrl_value(item) == CBOR_CTRL_FALSE || cbor_ctrl_value(item) == CBOR_CTRL_TRUE);
+}
+
+bool cbor_is_null(const cbor_item_t *item)
+{
+ return cbor_isa_float_ctrl(item) && cbor_ctrl_value(item) == CBOR_CTRL_NULL;
+}
+
+bool cbor_is_undef(const cbor_item_t *item)
+{
+ return cbor_isa_float_ctrl(item) && cbor_ctrl_value(item) == CBOR_CTRL_UNDEF;
+}
+
+bool cbor_is_float(const cbor_item_t *item)
+{
+ return cbor_isa_float_ctrl(item) && !cbor_float_ctrl_is_ctrl(item);
+}
+
+
+cbor_item_t * cbor_incref(cbor_item_t *item)
+{
+ item->refcount++;
+ return item;
+}
+
+void cbor_decref(cbor_item_t **item_ref)
+{
+ cbor_item_t * item = *item_ref;
+ if (--item->refcount == 0) {
+ switch (item->type) {
+ case CBOR_TYPE_UINT:
+ /* Fallthrough */
+ case CBOR_TYPE_NEGINT:
+ /* Combined allocation, freeing the item suffices */
+ {
+ break;
+ }
+ case CBOR_TYPE_BYTESTRING: {
+ if (cbor_bytestring_is_definite(item)) {
+ _CBOR_FREE(item->data);
+ } else {
+ /* We need to decref all chunks */
+ cbor_item_t **handle = cbor_bytestring_chunks_handle(item);
+ for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++)
+ cbor_decref(&handle[i]);
+ _CBOR_FREE(((struct cbor_indefinite_string_data *) item->data)->chunks);
+ _CBOR_FREE(item->data);
+ }
+ break;
+ }
+ case CBOR_TYPE_STRING: {
+ if (cbor_string_is_definite(item)) {
+ _CBOR_FREE(item->data);
+ } else {
+ /* We need to decref all chunks */
+ cbor_item_t **handle = cbor_string_chunks_handle(item);
+ for (size_t i = 0; i < cbor_string_chunk_count(item); i++)
+ cbor_decref(&handle[i]);
+ _CBOR_FREE(((struct cbor_indefinite_string_data *) item->data)->chunks);
+ _CBOR_FREE(item->data);
+ }
+ break;
+ }
+ case CBOR_TYPE_ARRAY: {
+ /* Get all items and decref them */
+ cbor_item_t **handle = cbor_array_handle(item);
+ size_t size = cbor_array_size(item);
+ for (size_t i = 0; i < size; i++)
+ if (handle[i] != NULL)
+ cbor_decref(&handle[i]);
+ _CBOR_FREE(item->data);
+ break;
+ }
+ case CBOR_TYPE_MAP: {
+ struct cbor_pair *handle = cbor_map_handle(item);
+ for (size_t i = 0; i < item->metadata.map_metadata.end_ptr; i++, handle++) {
+ cbor_decref(&handle->key);
+ if (handle->value != NULL)
+ cbor_decref(&handle->value);
+ }
+ _CBOR_FREE(item->data);
+ break;
+ };
+ case CBOR_TYPE_TAG: {
+ if (item->metadata.tag_metadata.tagged_item != NULL)
+ cbor_decref(&item->metadata.tag_metadata.tagged_item);
+ _CBOR_FREE(item->data);
+ break;
+ }
+ case CBOR_TYPE_FLOAT_CTRL: {
+ /* Floats have combined allocation */
+ break;
+ }
+ }
+ _CBOR_FREE(item);
+ //TODO
+ *item_ref = NULL;
+ }
+}
+
+void cbor_intermediate_decref(cbor_item_t * item)
+{
+ cbor_decref(&item);
+}
+
+size_t cbor_refcount(const cbor_item_t * item)
+{
+ return item->refcount;
+}
+
+cbor_item_t * cbor_move(cbor_item_t * item)
+{
+ item->refcount--;
+ return item;
+}
diff --git a/lib/libcbor/src/cbor/common.h b/lib/libcbor/src/cbor/common.h
new file mode 100644
index 00000000000..9e0b63c4a6f
--- /dev/null
+++ b/lib/libcbor/src/cbor/common.h
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2014-2015 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_COMMON_H
+#define LIBCBOR_COMMON_H
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <assert.h>
+#include "data.h"
+#include "cbor/configuration.h"
+
+#ifdef __cplusplus
+extern "C" {
+
+/** C++ is not a subset of C99 -- 'restrict' qualifier is not a part of the language.
+ * This is a workaround to keep it in C headers -- compilers allow linking non-restrict
+ * signatures with restrict implementations.
+ *
+ * If you know a nicer way, please do let me know.
+ */
+#define CBOR_RESTRICT_POINTER
+
+#else
+
+// MSVC + C++ workaround
+#define CBOR_RESTRICT_POINTER CBOR_RESTRICT_SPECIFIER
+
+#endif
+
+static const uint8_t cbor_major_version = CBOR_MAJOR_VERSION;
+static const uint8_t cbor_minor_version = CBOR_MINOR_VERSION;
+static const uint8_t cbor_patch_version = CBOR_PATCH_VERSION;
+
+#define CBOR_VERSION TO_STR(CBOR_MAJOR_VERSION) "." TO_STR(CBOR_MINOR_VERSION) "." TO_STR(CBOR_PATCH_VERSION)
+#define CBOR_HEX_VERSION ((CBOR_MAJOR_VERSION << 16) | (CBOR_MINOR_VERSION << 8) | CBOR_PATCH_VERSION)
+
+
+/* http://stackoverflow.com/questions/1644868/c-define-macro-for-debug-printing */
+#ifdef DEBUG
+#include <stdio.h>
+#define debug_print(fmt, ...) do { \
+ if (DEBUG) \
+ fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, __VA_ARGS__); \
+ } while (0)
+#else
+#define debug_print(fmt, ...) do {} while (0)
+#endif
+
+#define TO_STR_(x) #x
+#define TO_STR(x) TO_STR_(x) /* enables proper double expansion */
+
+#if CBOR_CUSTOM_ALLOC
+
+typedef void * (* _cbor_malloc_t)(size_t);
+typedef void * (* _cbor_realloc_t)(void *, size_t);
+typedef void (* _cbor_free_t)(void *);
+
+extern _cbor_malloc_t _cbor_malloc;
+extern _cbor_realloc_t _cbor_realloc;
+extern _cbor_free_t _cbor_free;
+
+/** Sets the memory management routines to use.
+ *
+ * Only available when CBOR_CUSTOM_ALLOC is truthy
+ *
+ * \rst
+ * .. warning:: This function modifies the global state and should therefore be used accordingly. Changing the memory handlers while allocated items exist will result in a ``free``/``malloc`` mismatch. This function is not thread safe with respect to both itself and all the other *libcbor* functions that work with the heap.
+ * .. note:: `realloc` implementation must correctly support `NULL` reallocation
+ * \endrst
+ *
+ * @param custom_malloc malloc implementation
+ * @param custom_realloc realloc implementation
+ * @param custom_free free implementation
+ */
+void cbor_set_allocs(_cbor_malloc_t custom_malloc, _cbor_realloc_t custom_realloc, _cbor_free_t custom_free);
+
+#define _CBOR_MALLOC _cbor_malloc
+#define _CBOR_REALLOC _cbor_realloc
+#define _CBOR_FREE _cbor_free
+
+#else
+
+#define _CBOR_MALLOC malloc
+#define _CBOR_REALLOC realloc
+#define _CBOR_FREE free
+
+#endif
+
+/*
+* ============================================================================
+* Type manipulation
+* ============================================================================
+*/
+
+/** Get the type of the item
+ *
+ * @param item[borrow]
+ * @return The type
+ */
+cbor_type cbor_typeof(const cbor_item_t * item); /* Will be inlined iff link-time opt is enabled */
+
+/* Standard item types as described by the RFC */
+
+/** Does the item have the appropriate major type?
+ * @param item[borrow] the item
+ * @return Is the item an #CBOR_TYPE_UINT?
+ */
+bool cbor_isa_uint(const cbor_item_t * item);
+
+/** Does the item have the appropriate major type?
+ * @param item[borrow] the item
+ * @return Is the item a #CBOR_TYPE_NEGINT?
+ */
+bool cbor_isa_negint(const cbor_item_t * item);
+
+/** Does the item have the appropriate major type?
+ * @param item[borrow] the item
+ * @return Is the item a #CBOR_TYPE_BYTESTRING?
+ */
+bool cbor_isa_bytestring(const cbor_item_t * item);
+
+/** Does the item have the appropriate major type?
+ * @param item[borrow] the item
+ * @return Is the item a #CBOR_TYPE_STRING?
+ */
+bool cbor_isa_string(const cbor_item_t * item);
+
+/** Does the item have the appropriate major type?
+ * @param item[borrow] the item
+ * @return Is the item an #CBOR_TYPE_ARRAY?
+ */
+bool cbor_isa_array(const cbor_item_t * item);
+
+/** Does the item have the appropriate major type?
+ * @param item[borrow] the item
+ * @return Is the item a #CBOR_TYPE_MAP?
+ */
+bool cbor_isa_map(const cbor_item_t * item);
+
+/** Does the item have the appropriate major type?
+ * @param item[borrow] the item
+ * @return Is the item a #CBOR_TYPE_TAG?
+ */
+bool cbor_isa_tag(const cbor_item_t * item);
+
+/** Does the item have the appropriate major type?
+ * @param item[borrow] the item
+ * @return Is the item a #CBOR_TYPE_FLOAT_CTRL?
+ */
+bool cbor_isa_float_ctrl(const cbor_item_t * item);
+
+/* Practical types with respect to their semantics (but not tag values) */
+
+/** Is the item an integer, either positive or negative?
+ * @param item[borrow] the item
+ * @return Is the item an integer, either positive or negative?
+ */
+bool cbor_is_int(const cbor_item_t * item);
+
+/** Is the item an a floating point number?
+ * @param item[borrow] the item
+ * @return Is the item a floating point number?
+ */
+bool cbor_is_float(const cbor_item_t * item);
+
+/** Is the item an a boolean?
+ * @param item[borrow] the item
+ * @return Is the item a boolean?
+ */
+bool cbor_is_bool(const cbor_item_t * item);
+
+/** Does this item represent `null`
+ * \rst
+ * .. warning:: This is in no way related to the value of the pointer. Passing a null pointer will most likely result in a crash.
+ * \endrst
+ * @param item[borrow] the item
+ * @return Is the item (CBOR logical) null?
+ */
+bool cbor_is_null(const cbor_item_t * item);
+
+
+/** Does this item represent `undefined`
+ * \rst
+ * .. warning:: Care must be taken to distinguish nulls and undefined values in C.
+ * \endrst
+ * @param item[borrow] the item
+ * @return Is the item (CBOR logical) undefined?
+ */
+bool cbor_is_undef(const cbor_item_t * item);
+
+
+/*
+* ============================================================================
+* Memory management
+* ============================================================================
+*/
+
+/** Increases the reference count by one
+ *
+ * No dependent items are affected.
+ *
+ * @param item[incref] item the item
+ * @return the input reference
+ */
+cbor_item_t * cbor_incref(cbor_item_t * item);
+
+/** Decreases the reference count by one, deallocating the item if needed
+ *
+ * In case the item is deallocated, the reference count of any dependent items
+ * is adjusted accordingly in a recursive manner.
+ *
+ * @param item[take] the item. Set to `NULL` if deallocated
+ */
+void cbor_decref(cbor_item_t ** item);
+
+/** Decreases the reference count by one, deallocating the item if needed
+ *
+ * Convenience wrapper for #cbor_decref when its set-to-null behavior is not needed
+ *
+ * @param item[take] the item
+ */
+void cbor_intermediate_decref(cbor_item_t * item);
+
+/** Get the reference count
+ *
+ * \rst
+ * .. warning:: This does *not* account for transitive references.
+ * \endrst
+ *
+ * @param item[borrow] the item
+ * @return the reference count
+ */
+size_t cbor_refcount(const cbor_item_t * item);
+
+/** Provides CPP-like move construct
+ *
+ * Decreases the reference count by one, but does not deallocate the item even if its refcount
+ * reaches zero. This is useful for passing intermediate values to functions that increase
+ * reference count. Should only be used with functions that `incref` their arguments.
+ *
+ * \rst
+ * .. warning:: If the item is moved without correctly increasing the reference count afterwards, the memory will be leaked.
+ * \endrst
+ *
+ * @param item[take] the item
+ * @return the item with reference count decreased by one
+ */
+cbor_item_t * cbor_move(cbor_item_t * item);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_COMMON_H
diff --git a/lib/libcbor/src/cbor/configuration.h b/lib/libcbor/src/cbor/configuration.h
new file mode 100644
index 00000000000..3a8adf6a902
--- /dev/null
+++ b/lib/libcbor/src/cbor/configuration.h
@@ -0,0 +1,15 @@
+#ifndef LIBCBOR_CONFIGURATION_H
+#define LIBCBOR_CONFIGURATION_H
+
+#define CBOR_MAJOR_VERSION 0
+#define CBOR_MINOR_VERSION 5
+#define CBOR_PATCH_VERSION 0
+
+#define CBOR_CUSTOM_ALLOC 0
+#define CBOR_BUFFER_GROWTH 2
+#define CBOR_PRETTY_PRINTER 1
+
+#define CBOR_RESTRICT_SPECIFIER restrict
+#define CBOR_INLINE_SPECIFIER
+
+#endif //LIBCBOR_CONFIGURATION_H
diff --git a/lib/libcbor/src/cbor/configuration.h.in b/lib/libcbor/src/cbor/configuration.h.in
new file mode 100644
index 00000000000..b81a0e64185
--- /dev/null
+++ b/lib/libcbor/src/cbor/configuration.h.in
@@ -0,0 +1,15 @@
+#ifndef LIBCBOR_CONFIGURATION_H
+#define LIBCBOR_CONFIGURATION_H
+
+#define CBOR_MAJOR_VERSION ${CBOR_VERSION_MAJOR}
+#define CBOR_MINOR_VERSION ${CBOR_VERSION_MINOR}
+#define CBOR_PATCH_VERSION ${CBOR_VERSION_PATCH}
+
+#cmakedefine01 CBOR_CUSTOM_ALLOC
+#define CBOR_BUFFER_GROWTH ${CBOR_BUFFER_GROWTH}
+#cmakedefine01 CBOR_PRETTY_PRINTER
+
+#define CBOR_RESTRICT_SPECIFIER ${CBOR_RESTRICT_SPECIFIER}
+#define CBOR_INLINE_SPECIFIER ${CBOR_INLINE_SPECIFIER}
+
+#endif //LIBCBOR_CONFIGURATION_H
diff --git a/lib/libcbor/src/cbor/data.h b/lib/libcbor/src/cbor/data.h
new file mode 100644
index 00000000000..91b59db756a
--- /dev/null
+++ b/lib/libcbor/src/cbor/data.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_DATA_H
+#define LIBCBOR_DATA_H
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef const unsigned char * cbor_data;
+typedef unsigned char * cbor_mutable_data;
+
+/** Specifies the Major type of ::cbor_item_t */
+typedef enum cbor_type {
+ CBOR_TYPE_UINT /** 0 - positive integers */
+ ,CBOR_TYPE_NEGINT /** 1 - negative integers*/
+ ,CBOR_TYPE_BYTESTRING /** 2 - byte strings */
+ ,CBOR_TYPE_STRING /** 3 - strings */
+ ,CBOR_TYPE_ARRAY /** 4 - arrays */
+ ,CBOR_TYPE_MAP /** 5 - maps */
+ ,CBOR_TYPE_TAG /** 6 - tags */
+ ,CBOR_TYPE_FLOAT_CTRL /** 7 - decimals and special values (true, false, nil, ...) */
+} cbor_type;
+
+/** Possible decoding errors */
+typedef enum {
+ CBOR_ERR_NONE
+ ,CBOR_ERR_NOTENOUGHDATA
+ ,CBOR_ERR_NODATA
+ ,CBOR_ERR_MALFORMATED
+ ,CBOR_ERR_MEMERROR /** Memory error - item allocation failed. Is it too big for your allocator? */
+ ,CBOR_ERR_SYNTAXERROR /** Stack parsing algorithm failed */
+} cbor_error_code;
+
+/** Possible widths of #CBOR_TYPE_UINT items */
+typedef enum {
+ CBOR_INT_8
+ ,CBOR_INT_16
+ ,CBOR_INT_32
+ ,CBOR_INT_64
+} cbor_int_width;
+
+/** Possible widths of #CBOR_TYPE_FLOAT_CTRL items */
+typedef enum {
+ CBOR_FLOAT_0 /** Internal use - ctrl and special values */
+ ,CBOR_FLOAT_16 /** Half float */
+ ,CBOR_FLOAT_32 /** Single float */
+ ,CBOR_FLOAT_64 /** Double */
+} cbor_float_width;
+
+/** Metadata for dynamically sized types */
+typedef enum {
+ _CBOR_METADATA_DEFINITE
+ ,_CBOR_METADATA_INDEFINITE
+} _cbor_dst_metadata;
+
+/** Semantic mapping for CTRL simple values */
+typedef enum {
+ CBOR_CTRL_NONE = 0,
+ CBOR_CTRL_FALSE = 20,
+ CBOR_CTRL_TRUE = 21,
+ CBOR_CTRL_NULL = 22,
+ CBOR_CTRL_UNDEF = 23
+} _cbor_ctrl;
+
+/** Integers specific metadata */
+struct _cbor_int_metadata {
+ cbor_int_width width;
+};
+
+/** Bytestrings specific metadata */
+struct _cbor_bytestring_metadata {
+ size_t length;
+ _cbor_dst_metadata type;
+};
+
+/** Strings specific metadata */
+struct _cbor_string_metadata {
+ size_t length;
+ size_t codepoint_count; /* Sum of chunks' codepoint_counts for indefinite strings */
+ _cbor_dst_metadata type;
+};
+
+/** Arrays specific metadata */
+struct _cbor_array_metadata {
+ size_t allocated;
+ size_t end_ptr;
+ _cbor_dst_metadata type;
+};
+
+/** Maps specific metadata */
+struct _cbor_map_metadata {
+ size_t allocated;
+ size_t end_ptr;
+ _cbor_dst_metadata type;
+};
+
+/** Arrays specific metadata
+ *
+ * The pointer is included - cbor_item_metadata is
+ * 2 * sizeof(size_t) + sizeof(_cbor_string_type_metadata),
+ * lets use the space
+ */
+struct _cbor_tag_metadata {
+ struct cbor_item_t * tagged_item;
+ uint64_t value;
+};
+
+/** Floats specific metadata - includes CTRL values */
+struct _cbor_float_ctrl_metadata {
+ cbor_float_width width;
+ uint8_t ctrl;
+};
+
+/** Raw memory casts helper */
+union _cbor_float_helper {
+ float as_float;
+ uint32_t as_uint;
+};
+
+/** Raw memory casts helper */
+union _cbor_double_helper {
+ double as_double;
+ uint64_t as_uint;
+};
+
+/** Union of metadata across all possible types - discriminated in #cbor_item_t */
+union cbor_item_metadata {
+ struct _cbor_int_metadata int_metadata;
+ struct _cbor_bytestring_metadata bytestring_metadata;
+ struct _cbor_string_metadata string_metadata;
+ struct _cbor_array_metadata array_metadata;
+ struct _cbor_map_metadata map_metadata;
+ struct _cbor_tag_metadata tag_metadata;
+ struct _cbor_float_ctrl_metadata float_ctrl_metadata;
+};
+
+/** The item handle */
+typedef struct cbor_item_t {
+ /** Discriminated by type */
+ union cbor_item_metadata metadata;
+ /** Reference count - initialize to 0 */
+ size_t refcount;
+ /** Major type discriminator */
+ cbor_type type;
+ /** Raw data block - interpretation depends on metadata */
+ unsigned char * data;
+} cbor_item_t;
+
+/** Defines cbor_item_t#data structure for indefinite strings and bytestrings
+ *
+ * Used to cast the raw representation for a sane manipulation
+ */
+struct cbor_indefinite_string_data {
+ size_t chunk_count;
+ size_t chunk_capacity;
+ cbor_item_t * * chunks;
+};
+
+/** High-level decoding error */
+struct cbor_error {
+ /** Aproximate position */
+ size_t position;
+ /** Description */
+ cbor_error_code code;
+};
+
+/** Simple pair of items for use in maps */
+struct cbor_pair {
+ cbor_item_t * key, * value;
+};
+
+/** High-level decoding result */
+struct cbor_load_result {
+ /** Error indicator */
+ struct cbor_error error;
+ /** Number of bytes read*/
+ size_t read;
+};
+
+
+/** Streaming decoder result - status */
+enum cbor_decoder_status {
+ CBOR_DECODER_FINISHED /** OK, finished */
+ ,CBOR_DECODER_NEDATA /** Not enough data - mismatch with MTB */
+ ,CBOR_DECODER_EBUFFER /** Buffer manipulation problem */
+ ,CBOR_DECODER_ERROR /** Malformed or reserved MTB/value */
+};
+
+/** Streaming decoder result */
+struct cbor_decoder_result {
+ /** Bytes read */
+ size_t read;
+ /** The result */
+ enum cbor_decoder_status status;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_DATA_H
diff --git a/lib/libcbor/src/cbor/encoding.c b/lib/libcbor/src/cbor/encoding.c
new file mode 100644
index 00000000000..bb636d82145
--- /dev/null
+++ b/lib/libcbor/src/cbor/encoding.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "encoding.h"
+#include "internal/encoders.h"
+
+size_t cbor_encode_uint8(uint8_t value, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint8(value, buffer, buffer_size, 0x00);
+}
+
+size_t cbor_encode_uint16(uint16_t value, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint16(value, buffer, buffer_size, 0x00);
+}
+
+size_t cbor_encode_uint32(uint32_t value, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint32(value, buffer, buffer_size, 0x00);
+}
+
+size_t cbor_encode_uint64(uint64_t value, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint64(value, buffer, buffer_size, 0x00);
+}
+
+size_t cbor_encode_uint(uint64_t value, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint(value, buffer, buffer_size, 0x00);
+}
+
+
+size_t cbor_encode_negint8(uint8_t value, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint8(value, buffer, buffer_size, 0x20);
+}
+
+size_t cbor_encode_negint16(uint16_t value, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint16(value, buffer, buffer_size, 0x20);
+}
+
+size_t cbor_encode_negint32(uint32_t value, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint32(value, buffer, buffer_size, 0x20);
+}
+
+size_t cbor_encode_negint64(uint64_t value, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint64(value, buffer, buffer_size, 0x20);
+}
+
+size_t cbor_encode_negint(uint64_t value, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint(value, buffer, buffer_size, 0x20);
+}
+
+size_t cbor_encode_bytestring_start(size_t length, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint((size_t) length, buffer, buffer_size, 0x40);
+}
+
+size_t _cbor_encode_byte(uint8_t value, unsigned char *buffer, size_t buffer_size)
+{
+ if (buffer_size >= 1) {
+ buffer[0] = value;
+ return 1;
+ } else
+ return 0;
+}
+
+size_t cbor_encode_indef_bytestring_start(unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_byte(0x5F, buffer, buffer_size);
+}
+
+size_t cbor_encode_string_start(size_t length, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint((size_t) length, buffer, buffer_size, 0x60);
+}
+
+size_t cbor_encode_indef_string_start(unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_byte(0x7F, buffer, buffer_size);
+}
+
+size_t cbor_encode_array_start(size_t length, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint((size_t) length, buffer, buffer_size, 0x80);
+}
+
+size_t cbor_encode_indef_array_start(unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_byte(0x9F, buffer, buffer_size);
+}
+
+size_t cbor_encode_map_start(size_t length, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint((size_t) length, buffer, buffer_size, 0xA0);
+}
+
+size_t cbor_encode_indef_map_start(unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_byte(0xBF, buffer, buffer_size);
+}
+
+size_t cbor_encode_tag(uint64_t value, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint(value, buffer, buffer_size, 0xC0);
+}
+
+size_t cbor_encode_bool(bool value, unsigned char *buffer, size_t buffer_size)
+{
+ return value ? _cbor_encode_byte(0xF5, buffer, buffer_size) : _cbor_encode_byte(0xF4, buffer, buffer_size);
+}
+
+size_t cbor_encode_null(unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_byte(0xF6, buffer, buffer_size);
+}
+
+size_t cbor_encode_undef(unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_byte(0xF7, buffer, buffer_size);
+}
+
+size_t cbor_encode_half(float value, unsigned char *buffer, size_t buffer_size)
+{
+ /* Assuming value is normalized */
+ uint32_t val = ((union _cbor_float_helper) {.as_float = value}).as_uint;
+ uint16_t res;
+ uint8_t exp = (uint8_t) ((val & 0x7F800000) >> 23); /* 0b0111_1111_1000_0000_0000_0000_0000_0000 */
+ uint32_t mant = val & 0x7FFFFF; /* 0b0000_0000_0111_1111_1111_1111_1111_1111 */
+ if (exp == 0xFF) { /* Infinity or NaNs */
+ if (value != value) {
+ res = (uint16_t) 0x00e700; /* Not IEEE semantics - required by CBOR [s. 3.9] */
+ } else {
+ res = (uint16_t) ((val & 0x80000000) >> 16 | 0x7C00 | (mant ? 1 : 0) << 15);
+ }
+ } else if (exp == 0x00) { /* Zeroes or subnorms */
+ res = (uint16_t) ((val & 0x80000000) >> 16 | mant >> 13);
+ } else { /* Normal numbers */
+ int8_t logical_exp = (int8_t) (exp - 127);
+ assert(logical_exp == exp - 127);
+
+ // Now we know that 2^exp <= 0 logically
+ if (logical_exp < -24) {
+ /* No unambiguous representation exists, this float is not a half float and is too small to
+ be represented using a half, round off to zero. Consistent with the reference implementation. */
+ res = 0;
+ } else if (logical_exp < -14) {
+ /* Offset the remaining decimal places by shifting the significand, the value is lost.
+ This is an implementation decision that works around the absence of standard half-float
+ in the language. */
+ res = (uint16_t) (val & 0x80000000) >> 16 | (uint16_t) (1 << (24 + logical_exp));
+ } else {
+ res = (uint16_t) ((val & 0x80000000) >> 16 | ((((uint8_t) logical_exp) + 15) << 10) | (uint16_t) (mant >> 13));
+ }
+ }
+ return _cbor_encode_uint16(res, buffer, buffer_size, 0xE0);
+}
+
+size_t cbor_encode_single(float value, unsigned char *buffer, size_t buffer_size)
+{
+
+ return _cbor_encode_uint32(((union _cbor_float_helper) {.as_float = value}).as_uint, buffer, buffer_size, 0xE0);
+}
+
+size_t cbor_encode_double(double value, unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint64(((union _cbor_double_helper) {.as_double = value}).as_uint, buffer, buffer_size, 0xE0);
+}
+
+size_t cbor_encode_break(unsigned char *buffer, size_t buffer_size)
+{
+ return _cbor_encode_byte(0xFF, buffer, buffer_size);
+}
+
+size_t cbor_encode_ctrl(uint8_t value, unsigned char * buffer, size_t buffer_size)
+{
+ return _cbor_encode_uint8(value, buffer, buffer_size, 0xE0);
+}
diff --git a/lib/libcbor/src/cbor/encoding.h b/lib/libcbor/src/cbor/encoding.h
new file mode 100644
index 00000000000..8117582b6a1
--- /dev/null
+++ b/lib/libcbor/src/cbor/encoding.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_ENCODING_H
+#define LIBCBOR_ENCODING_H
+
+#include "cbor/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+* ============================================================================
+* Primitives encoding
+* ============================================================================
+*/
+
+size_t cbor_encode_uint8(uint8_t, unsigned char *, size_t);
+
+size_t cbor_encode_uint16(uint16_t, unsigned char *, size_t);
+
+size_t cbor_encode_uint32(uint32_t, unsigned char *, size_t);
+
+size_t cbor_encode_uint64(uint64_t, unsigned char *, size_t);
+
+size_t cbor_encode_uint(uint64_t, unsigned char *, size_t);
+
+size_t cbor_encode_negint8(uint8_t, unsigned char *, size_t);
+
+size_t cbor_encode_negint16(uint16_t, unsigned char *, size_t);
+
+size_t cbor_encode_negint32(uint32_t, unsigned char *, size_t);
+
+size_t cbor_encode_negint64(uint64_t, unsigned char *, size_t);
+
+size_t cbor_encode_negint(uint64_t, unsigned char *, size_t);
+
+size_t cbor_encode_bytestring_start(size_t, unsigned char *, size_t);
+
+size_t cbor_encode_indef_bytestring_start(unsigned char *, size_t);
+
+size_t cbor_encode_string_start(size_t, unsigned char *, size_t);
+
+size_t cbor_encode_indef_string_start(unsigned char *, size_t);
+
+size_t cbor_encode_array_start(size_t, unsigned char *, size_t);
+
+size_t cbor_encode_indef_array_start(unsigned char *, size_t);
+
+size_t cbor_encode_map_start(size_t, unsigned char *, size_t);
+
+size_t cbor_encode_indef_map_start(unsigned char *, size_t);
+
+size_t cbor_encode_tag(uint64_t, unsigned char *, size_t);
+
+size_t cbor_encode_bool(bool, unsigned char *, size_t);
+
+size_t cbor_encode_null(unsigned char *, size_t);
+
+size_t cbor_encode_undef(unsigned char *, size_t);
+
+/** Encodes a half-precision float
+ *
+ * Since there is no native representation or semantics for half floats
+ * in the language, we use single-precision floats, as every value that
+ * can be expressed as a half-float can also be expressed as a float.
+ *
+ * This however means that not all floats passed to this function can be
+ * unambiguously encoded. The behavior is as follows:
+ * - Infinity, NaN are preserved
+ * - Zero is preserved
+ * - Denormalized numbers keep their sign bit and 10 most significant bit of the significand
+ * - All other numbers
+ * - If the logical value of the exponent is < -24, the output is zero
+ * - If the logical value of the exponent is between -23 and -14, the output
+ * is cut off to represent the 'magnitude' of the input, by which we
+ * mean (-1)^{signbit} x 1.0e{exponent}. The value in the significand is lost.
+ * - In all other cases, the sign bit, the exponent, and 10 most significant bits
+ * of the significand are kept
+ *
+ * @param value
+ * @param buffer Target buffer
+ * @param buffer_size Available space in the buffer
+ * @return number of bytes written
+ */
+size_t cbor_encode_half(float, unsigned char *, size_t);
+
+size_t cbor_encode_single(float, unsigned char *, size_t);
+
+size_t cbor_encode_double(double, unsigned char *, size_t);
+
+size_t cbor_encode_break(unsigned char *, size_t);
+
+size_t cbor_encode_ctrl(uint8_t, unsigned char *, size_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIBCBOR_ENCODING_H
diff --git a/lib/libcbor/src/cbor/floats_ctrls.c b/lib/libcbor/src/cbor/floats_ctrls.c
new file mode 100644
index 00000000000..92bc1347ffc
--- /dev/null
+++ b/lib/libcbor/src/cbor/floats_ctrls.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "floats_ctrls.h"
+#include "assert.h"
+#include <math.h>
+
+cbor_float_width cbor_float_get_width(const cbor_item_t *item)
+{
+ assert(cbor_isa_float_ctrl(item));
+ return item->metadata.float_ctrl_metadata.width;
+}
+
+uint8_t cbor_ctrl_value(const cbor_item_t *item)
+{
+ assert(cbor_isa_float_ctrl(item));
+ assert(cbor_float_get_width(item) == CBOR_FLOAT_0);
+ return item->metadata.float_ctrl_metadata.ctrl;
+}
+
+bool cbor_float_ctrl_is_ctrl(const cbor_item_t *item)
+{
+ assert(cbor_isa_float_ctrl(item));
+ return cbor_float_get_width(item) == CBOR_FLOAT_0;
+}
+
+float cbor_float_get_float2(const cbor_item_t *item)
+{
+ assert(cbor_is_float(item));
+ assert(cbor_float_get_width(item) == CBOR_FLOAT_16);
+ return *(float *) item->data;
+}
+
+float cbor_float_get_float4(const cbor_item_t *item)
+{
+ assert(cbor_is_float(item));
+ assert(cbor_float_get_width(item) == CBOR_FLOAT_32);
+ return *(float *) item->data;
+}
+
+double cbor_float_get_float8(const cbor_item_t *item)
+{
+ assert(cbor_is_float(item));
+ assert(cbor_float_get_width(item) == CBOR_FLOAT_64);
+ return *(double *) item->data;
+}
+
+double cbor_float_get_float(const cbor_item_t * item)
+{
+ assert(cbor_is_float(item));
+ switch(cbor_float_get_width(item)) {
+ case CBOR_FLOAT_0: return NAN;
+ case CBOR_FLOAT_16: return cbor_float_get_float2(item);
+ case CBOR_FLOAT_32: return cbor_float_get_float4(item);
+ case CBOR_FLOAT_64: return cbor_float_get_float8(item);
+ }
+ return NAN; /* Compiler complaints */
+}
+
+void cbor_set_float2(cbor_item_t *item, float value)
+{
+ assert(cbor_is_float(item));
+ assert(cbor_float_get_width(item) == CBOR_FLOAT_16);
+ *((float *) item->data) = value;
+}
+
+void cbor_set_float4(cbor_item_t *item, float value)
+{
+ assert(cbor_is_float(item));
+ assert(cbor_float_get_width(item) == CBOR_FLOAT_32);
+ *((float *) item->data) = value;
+}
+
+void cbor_set_float8(cbor_item_t *item, double value)
+{
+ assert(cbor_is_float(item));
+ assert(cbor_float_get_width(item) == CBOR_FLOAT_64);
+ *((double *) item->data) = value;
+}
+
+void cbor_set_ctrl(cbor_item_t *item, uint8_t value)
+{
+ assert(cbor_isa_float_ctrl(item));
+ assert(cbor_float_get_width(item) == CBOR_FLOAT_0);
+ item->metadata.float_ctrl_metadata.ctrl = value;
+}
+
+bool cbor_ctrl_is_bool(const cbor_item_t *item)
+{
+ assert(cbor_is_bool(item));
+ return item->metadata.float_ctrl_metadata.ctrl == CBOR_CTRL_TRUE;
+}
+
+cbor_item_t *cbor_new_ctrl()
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
+ *item = (cbor_item_t) {
+ .type = CBOR_TYPE_FLOAT_CTRL,
+ .data = NULL,
+ .refcount = 1,
+ .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_0, .ctrl = CBOR_CTRL_NONE}}
+ };
+ return item;
+}
+
+cbor_item_t *cbor_new_float2()
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 4);
+ *item = (cbor_item_t) {
+ .type = CBOR_TYPE_FLOAT_CTRL,
+ .data = (unsigned char *) item + sizeof(cbor_item_t),
+ .refcount = 1,
+ .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_16}}
+ };
+ return item;
+}
+
+cbor_item_t *cbor_new_float4()
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 4);
+ *item = (cbor_item_t) {
+ .type = CBOR_TYPE_FLOAT_CTRL,
+ .data = (unsigned char *) item + sizeof(cbor_item_t),
+ .refcount = 1,
+ .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_32}}
+ };
+ return item;
+}
+
+cbor_item_t *cbor_new_float8()
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 8);
+ *item = (cbor_item_t) {
+ .type = CBOR_TYPE_FLOAT_CTRL,
+ .data = (unsigned char *) item + sizeof(cbor_item_t),
+ .refcount = 1,
+ .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_64}}
+ };
+ return item;
+}
+
+cbor_item_t *cbor_new_null()
+{
+ cbor_item_t *item = cbor_new_ctrl();
+ cbor_set_ctrl(item, CBOR_CTRL_NULL);
+ return item;
+}
+
+cbor_item_t *cbor_new_undef()
+{
+ cbor_item_t *item = cbor_new_ctrl();
+ cbor_set_ctrl(item, CBOR_CTRL_UNDEF);
+ return item;
+}
+
+cbor_item_t *cbor_build_bool(bool value)
+{
+ return cbor_build_ctrl(value ? CBOR_CTRL_TRUE : CBOR_CTRL_FALSE);
+}
+
+cbor_item_t *cbor_build_float2(float value)
+{
+ cbor_item_t *item = cbor_new_float2();
+ cbor_set_float2(item, value);
+ return item;
+}
+
+cbor_item_t *cbor_build_float4(float value)
+{
+ cbor_item_t *item = cbor_new_float4();
+ cbor_set_float4(item, value);
+ return item;
+}
+
+cbor_item_t *cbor_build_float8(double value)
+{
+ cbor_item_t *item = cbor_new_float8();
+ cbor_set_float8(item, value);
+ return item;
+}
+
+cbor_item_t *cbor_build_ctrl(uint8_t value)
+{
+ cbor_item_t *item = cbor_new_ctrl();
+ cbor_set_ctrl(item, value);
+ return item;
+}
diff --git a/lib/libcbor/src/cbor/floats_ctrls.h b/lib/libcbor/src/cbor/floats_ctrls.h
new file mode 100644
index 00000000000..a5cdc40e90b
--- /dev/null
+++ b/lib/libcbor/src/cbor/floats_ctrls.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_FLOATS_CTRLS_H
+#define LIBCBOR_FLOATS_CTRLS_H
+
+#include "cbor/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+* ============================================================================
+* Float manipulation
+* ============================================================================
+*/
+
+/** Is this a ctrl value?
+ *
+ * @param item[borrow] A float or ctrl item
+ * @return Is this a ctrl value?
+ */
+bool cbor_float_ctrl_is_ctrl(const cbor_item_t * item);
+
+/** Get the float width
+ *
+ * @param item[borrow] A float or ctrl item
+ * @return The width.
+ */
+cbor_float_width cbor_float_get_width(const cbor_item_t * item);
+
+/** Get a half precision float
+ *
+ * The item must have the corresponding width
+ *
+ * @param[borrow] A half precision float
+ * @return half precision value
+ */
+float cbor_float_get_float2(const cbor_item_t * item);
+
+/** Get a single precision float
+ *
+ * The item must have the corresponding width
+ *
+ * @param[borrow] A signle precision float
+ * @return single precision value
+ */
+float cbor_float_get_float4(const cbor_item_t * item);
+
+/** Get a double precision float
+ *
+ * The item must have the corresponding width
+ *
+ * @param[borrow] A double precision float
+ * @return double precision value
+ */
+double cbor_float_get_float8(const cbor_item_t * item);
+
+/** Get the float value represented as double
+ *
+ * Can be used regardless of the width.
+ *
+ * @param[borrow] Any float
+ * @return double precision value
+ */
+double cbor_float_get_float(const cbor_item_t * item);
+
+/** Constructs a new ctrl item
+ *
+ * The width cannot be changed once the item is created
+ *
+ * @return **new** 1B ctrl
+ */
+cbor_item_t * cbor_new_ctrl();
+
+/** Constructs a new float item
+ *
+ * The width cannot be changed once the item is created
+ *
+ * @return **new** 2B float
+ */
+cbor_item_t * cbor_new_float2();
+
+/** Constructs a new float item
+ *
+ * The width cannot be changed once the item is created
+ *
+ * @return **new** 4B float
+ */
+cbor_item_t * cbor_new_float4();
+
+/** Constructs a new float item
+ *
+ * The width cannot be changed once the item is created
+ *
+ * @return **new** 8B float
+ */
+cbor_item_t * cbor_new_float8();
+
+/** Constructs new null ctrl item
+ *
+ * @return **new** null ctrl item
+ */
+cbor_item_t * cbor_new_null();
+
+/** Constructs new under ctrl item
+ *
+ * @return **new** under ctrl item
+ */
+cbor_item_t * cbor_new_undef();
+
+/** Constructs new boolean ctrl item
+ *
+ * @param value The value to use
+ * @return **new** boolen ctrl item
+ */
+cbor_item_t * cbor_build_bool(bool value);
+
+/** Assign a control value
+ *
+ * \rst
+ * .. warning:: It is possible to produce an invalid CBOR value by assigning a invalid value using this mechanism. Please consult the standard before use.
+ * \endrst
+ *
+ * @param item[borrow] A ctrl item
+ * @param value The simple value to assign. Please consult the standard for allowed values
+ */
+void cbor_set_ctrl(cbor_item_t * item, uint8_t value);
+
+/** Assigns a float value
+ *
+ * @param item[borrow] A half precision float
+ * @param value The value to assign
+ */
+void cbor_set_float2(cbor_item_t * item, float value);
+
+/** Assigns a float value
+ *
+ * @param item[borrow] A single precision float
+ * @param value The value to assign
+ */
+void cbor_set_float4(cbor_item_t * item, float value);
+
+/** Assigns a float value
+ *
+ * @param item[borrow] A double precision float
+ * @param value The value to assign
+ */
+void cbor_set_float8(cbor_item_t * item, double value);
+
+/** Reads the control value
+ *
+ * @param item[borrow] A ctrl item
+ * @return the simple value
+ */
+uint8_t cbor_ctrl_value(const cbor_item_t * item);
+
+/** Is this ctrl item a boolean?
+ *
+ * @param item[borrow] A ctrl item
+ * @return Is this ctrl item a boolean?
+ */
+bool cbor_ctrl_is_bool(const cbor_item_t * item);
+
+/** Constructs a new float
+ *
+ * @param value the value to use
+ * @return **new** float
+ */
+cbor_item_t *cbor_build_float2(float value);
+
+/** Constructs a new float
+ *
+ * @param value the value to use
+ * @return **new** float
+ */
+cbor_item_t *cbor_build_float4(float value);
+
+/** Constructs a new float
+ *
+ * @param value the value to use
+ * @return **new** float
+ */
+cbor_item_t *cbor_build_float8(double value);
+
+/** Constructs a ctrl item
+ *
+ * @param value the value to use
+ * @return **new** ctrl item
+ */
+cbor_item_t *cbor_build_ctrl(uint8_t value);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_FLOATS_CTRLS_H
diff --git a/lib/libcbor/src/cbor/internal/builder_callbacks.c b/lib/libcbor/src/cbor/internal/builder_callbacks.c
new file mode 100644
index 00000000000..7f28d28433f
--- /dev/null
+++ b/lib/libcbor/src/cbor/internal/builder_callbacks.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "builder_callbacks.h"
+#include "unicode.h"
+#include <string.h>
+#include "../arrays.h"
+#include "../bytestrings.h"
+#include "../floats_ctrls.h"
+#include "../ints.h"
+#include "../maps.h"
+#include "../strings.h"
+#include "../tags.h"
+
+void _cbor_builder_append(cbor_item_t *item, struct _cbor_decoder_context *ctx)
+{
+ if (ctx->stack->size == 0) {
+ /* Top level item */
+ ctx->root = item;
+ } else {
+ /* Part of a bigger structure */
+ switch (ctx->stack->top->item->type) {
+ case CBOR_TYPE_ARRAY: {
+ if (cbor_array_is_definite(ctx->stack->top->item)) {
+ assert(ctx->stack->top->subitems > 0);
+ cbor_array_push(ctx->stack->top->item, item);
+ ctx->stack->top->subitems--;
+ if (ctx->stack->top->subitems == 0) {
+ cbor_item_t *item = ctx->stack->top->item;
+ _cbor_stack_pop(ctx->stack);
+ _cbor_builder_append(item, ctx);
+ }
+ cbor_decref(&item);
+ } else {
+ /* Indefinite array, don't bother with subitems */
+ cbor_array_push(ctx->stack->top->item, item);
+ cbor_decref(&item);
+ }
+ break;
+ }
+ case CBOR_TYPE_MAP: {
+ /* We use 0 and 1 subitems to distinguish between keys and values in indefinite items */
+ if (ctx->stack->top->subitems % 2) {
+ /* Odd record, this is a value */
+ _cbor_map_add_value(ctx->stack->top->item, cbor_move(item));
+ } else {
+ /* Even record, this is a key */
+ _cbor_map_add_key(ctx->stack->top->item, cbor_move(item));
+ }
+ if (cbor_map_is_definite(ctx->stack->top->item)) {
+ ctx->stack->top->subitems--;
+ if (ctx->stack->top->subitems == 0) {
+ cbor_item_t *item = ctx->stack->top->item;
+ _cbor_stack_pop(ctx->stack);
+ _cbor_builder_append(item, ctx);
+ }
+ } else {
+ ctx->stack->top->subitems ^= 1; /* Flip the indicator for indefinite items */
+ }
+ break;
+ }
+ case CBOR_TYPE_TAG: {
+ assert(ctx->stack->top->subitems == 1);
+ cbor_tag_set_item(ctx->stack->top->item, item);
+ cbor_decref(&item); /* Give up on our reference */
+ cbor_item_t *item = ctx->stack->top->item;
+ _cbor_stack_pop(ctx->stack);
+ _cbor_builder_append(item, ctx);
+ break;
+ }
+ default: {
+ cbor_decref(&item);
+ ctx->syntax_error = true;
+ }
+ }
+ }
+}
+
+
+#define CHECK_RES do { if (res == NULL) { ctx->creation_failed = true; return; } } while (0)
+
+void cbor_builder_uint8_callback(void *context, uint8_t value)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_int8();
+ CHECK_RES;
+ cbor_mark_uint(res);
+ cbor_set_uint8(res, value);
+ _cbor_builder_append(res, ctx);
+}
+
+void cbor_builder_uint16_callback(void *context, uint16_t value)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_int16();
+ CHECK_RES;
+ cbor_mark_uint(res);
+ cbor_set_uint16(res, value);
+ _cbor_builder_append(res, ctx);
+}
+
+void cbor_builder_uint32_callback(void *context, uint32_t value)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_int32();
+ CHECK_RES;
+ cbor_mark_uint(res);
+ cbor_set_uint32(res, value);
+ _cbor_builder_append(res, ctx);
+}
+
+void cbor_builder_uint64_callback(void *context, uint64_t value)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_int64();
+ CHECK_RES;
+ cbor_mark_uint(res);
+ cbor_set_uint64(res, value);
+ _cbor_builder_append(res, ctx);
+}
+
+void cbor_builder_negint8_callback(void *context, uint8_t value)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_int8();
+ CHECK_RES;
+ cbor_mark_negint(res);
+ cbor_set_uint8(res, value);
+ _cbor_builder_append(res, ctx);
+}
+
+void cbor_builder_negint16_callback(void *context, uint16_t value)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_int16();
+ cbor_mark_negint(res);
+ cbor_set_uint16(res, value);
+ _cbor_builder_append(res, ctx);
+}
+
+void cbor_builder_negint32_callback(void *context, uint32_t value)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_int32();
+ CHECK_RES;
+ cbor_mark_negint(res);
+ cbor_set_uint32(res, value);
+ _cbor_builder_append(res, ctx);
+}
+
+void cbor_builder_negint64_callback(void *context, uint64_t value)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_int64();
+ CHECK_RES;
+ cbor_mark_negint(res);
+ cbor_set_uint64(res, value);
+ _cbor_builder_append(res, ctx);
+}
+
+void cbor_builder_byte_string_callback(void *context, cbor_data data, size_t length)
+{
+ struct _cbor_decoder_context *ctx = context;
+ unsigned char *new_handle = _CBOR_MALLOC(length);
+ if (new_handle == NULL) {
+ ctx->creation_failed = true;
+ return;
+ }
+
+ memcpy(new_handle, data, length);
+ cbor_item_t *res = cbor_new_definite_bytestring();
+
+ if (res == NULL) {
+ _CBOR_FREE(new_handle);
+ ctx->creation_failed = true;
+ return;
+ }
+
+ cbor_bytestring_set_handle(res, new_handle, length);
+
+ if (ctx->stack->size > 0 && cbor_isa_bytestring(ctx->stack->top->item)) {
+ if (cbor_bytestring_is_indefinite(ctx->stack->top->item)) {
+ cbor_bytestring_add_chunk(ctx->stack->top->item, cbor_move(res));
+ } else {
+ cbor_decref(&res);
+ ctx->syntax_error = true;
+ }
+ } else {
+ _cbor_builder_append(res, ctx);
+ }
+}
+
+void cbor_builder_byte_string_start_callback(void *context)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_indefinite_bytestring();
+ CHECK_RES;
+ _cbor_stack_push(ctx->stack, res, 0);
+}
+
+
+void cbor_builder_string_callback(void *context, cbor_data data, size_t length)
+{
+ struct _cbor_decoder_context *ctx = context;
+ struct _cbor_unicode_status unicode_status;
+
+ size_t codepoint_count = _cbor_unicode_codepoint_count(data, length, &unicode_status);
+
+ if (unicode_status.status == _CBOR_UNICODE_BADCP) {
+ ctx->syntax_error = true;
+ return;
+ }
+
+ unsigned char *new_handle = _CBOR_MALLOC(length);
+
+ if (new_handle == NULL) {
+ ctx->creation_failed = true;
+ return;
+ }
+
+ memcpy(new_handle, data, length);
+ cbor_item_t *res = cbor_new_definite_string();
+ cbor_string_set_handle(res, new_handle, length);
+ res->metadata.string_metadata.codepoint_count = codepoint_count;
+
+ /* Careful here: order matters */
+ if (ctx->stack->size > 0 && cbor_isa_string(ctx->stack->top->item)) {
+ if (cbor_string_is_indefinite(ctx->stack->top->item)) {
+ cbor_string_add_chunk(ctx->stack->top->item, cbor_move(res));
+ } else {
+ cbor_decref(&res);
+ ctx->syntax_error = true;
+ }
+ } else {
+ _cbor_builder_append(res, ctx);
+ }
+}
+
+void cbor_builder_string_start_callback(void *context)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_indefinite_string();
+ CHECK_RES;
+ _cbor_stack_push(ctx->stack, res, 0);
+}
+
+void cbor_builder_array_start_callback(void *context, size_t size)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_definite_array(size);
+ CHECK_RES;
+ if (size > 0) {
+ _cbor_stack_push(ctx->stack, res, size);
+ } else {
+ _cbor_builder_append(res, ctx);
+ }
+}
+
+void cbor_builder_indef_array_start_callback(void *context)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_indefinite_array();
+ CHECK_RES;
+ _cbor_stack_push(ctx->stack, res, 0);
+}
+
+void cbor_builder_indef_map_start_callback(void *context)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_indefinite_map();
+ CHECK_RES;
+ _cbor_stack_push(ctx->stack, res, 0);
+}
+
+void cbor_builder_map_start_callback(void *context, size_t size)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_definite_map(size);
+ CHECK_RES;
+ if (size > 0) {
+ _cbor_stack_push(ctx->stack, res, size * 2);
+ } else {
+ _cbor_builder_append(res, ctx);
+ }
+}
+
+void cbor_builder_indef_break_callback(void *context)
+{
+ struct _cbor_decoder_context *ctx = context;
+ if (ctx->stack->size == 0) {
+ // TODO complain
+ } else {
+ cbor_item_t *item = ctx->stack->top->item;
+ _cbor_stack_pop(ctx->stack);
+ _cbor_builder_append(item, ctx);
+ }
+}
+
+void cbor_builder_float2_callback(void *context, float value)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_float2();
+ cbor_set_float2(res, value);
+ _cbor_builder_append(res, ctx);
+}
+
+void cbor_builder_float4_callback(void *context, float value)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_float4();
+ CHECK_RES;
+ cbor_set_float4(res, value);
+ _cbor_builder_append(res, ctx);
+}
+
+void cbor_builder_float8_callback(void *context, double value)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_float8();
+ CHECK_RES;
+ cbor_set_float8(res, value);
+ _cbor_builder_append(res, ctx);
+}
+
+void cbor_builder_null_callback(void *context)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_null();
+ CHECK_RES;
+ _cbor_builder_append(res, ctx);
+}
+
+void cbor_builder_undefined_callback(void *context)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_undef();
+ CHECK_RES;
+ _cbor_builder_append(res, ctx);
+}
+
+void cbor_builder_boolean_callback(void *context, bool value)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_build_bool(value);
+ CHECK_RES;
+ _cbor_builder_append(res, ctx);
+}
+
+void cbor_builder_tag_callback(void *context, uint64_t value)
+{
+ struct _cbor_decoder_context *ctx = context;
+ cbor_item_t *res = cbor_new_tag(value);
+ CHECK_RES;
+ _cbor_stack_push(ctx->stack, res, 1);
+}
diff --git a/lib/libcbor/src/cbor/internal/builder_callbacks.h b/lib/libcbor/src/cbor/internal/builder_callbacks.h
new file mode 100644
index 00000000000..b16294f16af
--- /dev/null
+++ b/lib/libcbor/src/cbor/internal/builder_callbacks.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_BUILDER_CALLBACKS_H
+#define LIBCBOR_BUILDER_CALLBACKS_H
+
+#include "cbor/common.h"
+#include "../callbacks.h"
+#include "stack.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** High-level decoding context */
+struct _cbor_decoder_context {
+ /** Callback creating the last item has failed */
+ bool creation_failed;
+ /** Stack expectation mismatch */
+ bool syntax_error;
+ cbor_item_t *root;
+ struct _cbor_stack *stack;
+};
+
+void cbor_builder_uint8_callback(void *, uint8_t);
+
+void cbor_builder_uint16_callback(void *, uint16_t);
+
+void cbor_builder_uint32_callback(void *, uint32_t);
+
+void cbor_builder_uint64_callback(void *, uint64_t);
+
+void cbor_builder_negint8_callback(void *, uint8_t);
+
+void cbor_builder_negint16_callback(void *, uint16_t);
+
+void cbor_builder_negint32_callback(void *, uint32_t);
+
+void cbor_builder_negint64_callback(void *, uint64_t);
+
+void cbor_builder_string_callback(void *, cbor_data, size_t);
+
+void cbor_builder_string_start_callback(void *);
+
+void cbor_builder_byte_string_callback(void *, cbor_data, size_t);
+
+void cbor_builder_byte_string_start_callback(void *);
+
+void cbor_builder_array_start_callback(void *, size_t);
+
+void cbor_builder_indef_array_start_callback(void *);
+
+void cbor_builder_map_start_callback(void *, size_t);
+
+void cbor_builder_indef_map_start_callback(void *);
+
+void cbor_builder_tag_callback(void *, uint64_t);
+
+void cbor_builder_float2_callback(void *, float);
+
+void cbor_builder_float4_callback(void *, float);
+
+void cbor_builder_float8_callback(void *, double);
+
+void cbor_builder_null_callback(void *);
+
+void cbor_builder_undefined_callback(void *);
+
+void cbor_builder_boolean_callback(void *, bool);
+
+void cbor_builder_indef_break_callback(void *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_BUILDER_CALLBACKS_H
diff --git a/lib/libcbor/src/cbor/internal/encoders.c b/lib/libcbor/src/cbor/internal/encoders.c
new file mode 100644
index 00000000000..478b3885cb1
--- /dev/null
+++ b/lib/libcbor/src/cbor/internal/encoders.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "encoders.h"
+
+#if HAVE_ENDIAN_H
+#include <endian.h>
+#endif
+
+size_t _cbor_encode_uint8(uint8_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
+{
+ if (value <= 23) {
+ if (buffer_size >= 1) {
+ buffer[0] = value + offset;
+ return 1;
+ }
+ } else {
+ if (buffer_size >= 2) {
+ buffer[0] = 0x18 + offset;
+ buffer[1] = value;
+ return 2;
+ }
+ }
+ return 0;
+}
+
+size_t _cbor_encode_uint16(uint16_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
+{
+ if (buffer_size >= 3) {
+ buffer[0] = 0x19 + offset;
+
+#ifdef HAVE_ENDIAN_H
+ *(uint16_t *) &buffer[1] = htobe16(value);
+#else
+ #ifdef IS_BIG_ENDIAN
+ *(uint16_t *) &buffer[1] = value;
+ #else
+ buffer[1] = value >> 8;
+ buffer[2] = value;
+ #endif
+#endif
+
+ return 3;
+ } else
+ return 0;
+}
+
+size_t _cbor_encode_uint32(uint32_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
+{
+ if (buffer_size >= 5) {
+ buffer[0] = 0x1A + offset;
+
+#ifdef HAVE_ENDIAN_H
+ *(uint32_t *) &buffer[1] = htobe32(value);
+#else
+ #ifdef IS_BIG_ENDIAN
+ *(uint32_t *) &buffer[1] = value;
+ #else
+ buffer[1] = value >> 24;
+ buffer[2] = value >> 16;
+ buffer[3] = value >> 8;
+ buffer[4] = value;
+ #endif
+#endif
+
+ return 5;
+ } else
+ return 0;
+}
+
+size_t _cbor_encode_uint64(uint64_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
+{
+ if (buffer_size >= 9) {
+ buffer[0] = 0x1B + offset;
+
+#ifdef HAVE_ENDIAN_H
+ *(uint64_t *) &buffer[1] = htobe64(value);
+#else
+ #ifdef IS_BIG_ENDIAN
+ *(uint64_t *) &buffer[1] = value;
+ #else
+ buffer[1] = value >> 56;
+ buffer[2] = value >> 48;
+ buffer[3] = value >> 40;
+ buffer[4] = value >> 32;
+ buffer[5] = value >> 24;
+ buffer[6] = value >> 16;
+ buffer[7] = value >> 8;
+ buffer[8] = value;
+ #endif
+#endif
+
+ return 9;
+ } else
+ return 0;
+}
+
+size_t _cbor_encode_uint(uint64_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
+{
+ if (value <= UINT16_MAX) if (value <= UINT8_MAX)
+ return _cbor_encode_uint8((uint8_t) value, buffer, buffer_size, offset);
+ else
+ return _cbor_encode_uint16((uint16_t) value, buffer, buffer_size, offset);
+ else if (value <= UINT32_MAX)
+ return _cbor_encode_uint32((uint32_t) value, buffer, buffer_size, offset);
+ else
+ return _cbor_encode_uint64((uint64_t) value, buffer, buffer_size, offset);
+}
diff --git a/lib/libcbor/src/cbor/internal/encoders.h b/lib/libcbor/src/cbor/internal/encoders.h
new file mode 100644
index 00000000000..5629e60905a
--- /dev/null
+++ b/lib/libcbor/src/cbor/internal/encoders.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_ENCODERS_H
+#define LIBCBOR_ENCODERS_H
+
+#include "cbor/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+size_t _cbor_encode_uint8(uint8_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset);
+
+size_t _cbor_encode_uint16(uint16_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset);
+
+size_t _cbor_encode_uint32(uint32_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset);
+
+size_t _cbor_encode_uint64(uint64_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset);
+
+size_t _cbor_encode_uint(uint64_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_ENCODERS_H
diff --git a/lib/libcbor/src/cbor/internal/loaders.c b/lib/libcbor/src/cbor/internal/loaders.c
new file mode 100644
index 00000000000..184691ca65a
--- /dev/null
+++ b/lib/libcbor/src/cbor/internal/loaders.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "loaders.h"
+#include <math.h>
+
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#endif
+
+uint8_t _cbor_load_uint8(cbor_data source)
+{
+ return (uint8_t) *source;
+}
+
+uint16_t _cbor_load_uint16(const unsigned char *source)
+{
+#ifdef HAVE_ENDIAN_H
+ return be16toh(*(uint16_t *) source);
+#else
+ #ifdef IS_BIG_ENDIAN
+ return *(uint16_t *) source;
+ #else
+ return ((uint16_t) *(source + 0) << 8) +
+ (uint8_t) *(source + 1);
+ #endif
+#endif
+}
+
+uint32_t _cbor_load_uint32(const unsigned char *source)
+{
+#ifdef HAVE_ENDIAN_H
+ return be32toh(*(uint32_t *) source);
+#else
+ #ifdef IS_BIG_ENDIAN
+ return *(uint32_t *) source;
+ #else
+ return ((uint32_t) *(source + 0) << 0x18) +
+ ((uint32_t) *(source + 1) << 0x10) +
+ ((uint16_t) *(source + 2) << 0x08) +
+ (uint8_t) *(source + 3);
+ #endif
+#endif
+}
+
+uint64_t _cbor_load_uint64(const unsigned char *source)
+{
+#ifdef HAVE_ENDIAN_H
+ return be64toh(*(uint64_t *) source);
+#else
+ #ifdef IS_BIG_ENDIAN
+ return *(uint64_t *) source;
+ #else
+ return ((uint64_t) *(source + 0) << 0x38) +
+ ((uint64_t) *(source + 1) << 0x30) +
+ ((uint64_t) *(source + 2) << 0x28) +
+ ((uint64_t) *(source + 3) << 0x20) +
+ ((uint32_t) *(source + 4) << 0x18) +
+ ((uint32_t) *(source + 5) << 0x10) +
+ ((uint16_t) *(source + 6) << 0x08) +
+ (uint8_t) *(source + 7);
+ #endif
+#endif
+}
+
+/* As per http://tools.ietf.org/html/rfc7049#appendix-D */
+float _cbor_decode_half(unsigned char *halfp)
+{
+ int half = (halfp[0] << 8) + halfp[1];
+ int exp = (half >> 10) & 0x1f;
+ int mant = half & 0x3ff;
+ double val;
+ if (exp == 0) val = ldexp(mant, -24);
+ else if (exp != 31) val = ldexp(mant + 1024, exp - 25);
+ else val = mant == 0 ? INFINITY : NAN;
+ return (float) (half & 0x8000 ? -val : val);
+}
+
+double _cbor_load_half(cbor_data source)
+{
+ /* Discard const */
+ return _cbor_decode_half((unsigned char *) source);
+}
+
+float _cbor_load_float(cbor_data source)
+{
+ union _cbor_float_helper helper = {.as_uint = _cbor_load_uint32(source)};
+ return helper.as_float;
+}
+
+double _cbor_load_double(cbor_data source)
+{
+ union _cbor_double_helper helper = {.as_uint = _cbor_load_uint64(source)};
+ return helper.as_double;
+}
diff --git a/lib/libcbor/src/cbor/internal/loaders.h b/lib/libcbor/src/cbor/internal/loaders.h
new file mode 100644
index 00000000000..cd5c1b5a45c
--- /dev/null
+++ b/lib/libcbor/src/cbor/internal/loaders.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_LOADERS_H
+#define LIBCBOR_LOADERS_H
+
+#include "cbor/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Read the given uint from the given location, no questions asked */
+uint8_t _cbor_load_uint8(const unsigned char *source);
+
+uint16_t _cbor_load_uint16(const unsigned char *source);
+
+uint32_t _cbor_load_uint32(const unsigned char *source);
+
+uint64_t _cbor_load_uint64(const unsigned char *source);
+
+double _cbor_load_half(cbor_data source);
+
+float _cbor_load_float(cbor_data source);
+
+double _cbor_load_double(cbor_data source);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_LOADERS_H
diff --git a/lib/libcbor/src/cbor/internal/memory_utils.c b/lib/libcbor/src/cbor/internal/memory_utils.c
new file mode 100644
index 00000000000..4d1024c4236
--- /dev/null
+++ b/lib/libcbor/src/cbor/internal/memory_utils.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "memory_utils.h"
+#include "cbor/common.h"
+
+// TODO: Consider builtins (https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html)
+
+/** Highest on bit position */
+size_t _cbor_highest_bit(size_t number)
+{
+ size_t bit = 0;
+ while (number != 0) {
+ bit++;
+ number >>= 1;
+ }
+
+ return bit;
+}
+
+bool _cbor_safe_to_multiply(size_t a, size_t b)
+{
+ return _cbor_highest_bit(a) + _cbor_highest_bit(b) <= sizeof(size_t) * 8;
+}
+
+void * _cbor_alloc_multiple(size_t item_size, size_t item_count)
+{
+ if (_cbor_safe_to_multiply(item_size, item_count)) {
+ return _CBOR_MALLOC(item_size * item_count);
+ } else {
+ return NULL;
+ }
+}
+
+void * _cbor_realloc_multiple(void * pointer, size_t item_size, size_t item_count)
+{
+ if (_cbor_safe_to_multiply(item_size, item_count)) {
+ return _CBOR_REALLOC(pointer, item_size * item_count);
+ } else {
+ return NULL;
+ }
+}
diff --git a/lib/libcbor/src/cbor/internal/memory_utils.h b/lib/libcbor/src/cbor/internal/memory_utils.h
new file mode 100644
index 00000000000..cec008d7578
--- /dev/null
+++ b/lib/libcbor/src/cbor/internal/memory_utils.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_MEMORY_UTILS_H
+#define LIBCBOR_MEMORY_UTILS_H
+
+#include <string.h>
+#include <stdbool.h>
+
+/** Can a and b be multiplied without overflowing size_t? */
+bool _cbor_safe_to_multiply(size_t a, size_t b);
+
+/** Overflow-proof contiguous array allocation
+ *
+ * @param item_size
+ * @param item_count
+ * @return Region of item_size * item_count bytes, or NULL if the total size overflows size_t or the underlying allocator failed
+ */
+void * _cbor_alloc_multiple(size_t item_size, size_t item_count);
+
+
+/** Overflow-proof contiguous array reallocation
+ *
+ * This implements the OpenBSD `reallocarray` functionality.
+ *
+ * @param pointer
+ * @param item_size
+ * @param item_count
+ * @return Realloc'd of item_size * item_count bytes, or NULL if the total size overflows size_t or the underlying allocator failed
+ */
+void * _cbor_realloc_multiple(void * pointer, size_t item_size, size_t item_count);
+
+#endif //LIBCBOR_MEMORY_UTILS_H
diff --git a/lib/libcbor/src/cbor/internal/stack.c b/lib/libcbor/src/cbor/internal/stack.c
new file mode 100644
index 00000000000..65e15fe9379
--- /dev/null
+++ b/lib/libcbor/src/cbor/internal/stack.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "stack.h"
+
+struct _cbor_stack _cbor_stack_init()
+{
+ return (struct _cbor_stack) {.top = NULL, .size = 0};
+}
+
+void _cbor_stack_pop(struct _cbor_stack *stack)
+{
+ struct _cbor_stack_record *top = stack->top;
+ stack->top = stack->top->lower;
+ _CBOR_FREE(top);
+ stack->size--;
+}
+
+struct _cbor_stack_record *_cbor_stack_push(struct _cbor_stack *stack, cbor_item_t *item, size_t subitems)
+{
+ struct _cbor_stack_record *new_top = _CBOR_MALLOC(sizeof(struct _cbor_stack_record));
+ if (new_top == NULL)
+ return NULL;
+
+ *new_top = (struct _cbor_stack_record) {stack->top, item, subitems};
+ stack->top = new_top;
+ stack->size++;
+ return new_top;
+}
diff --git a/lib/libcbor/src/cbor/internal/stack.h b/lib/libcbor/src/cbor/internal/stack.h
new file mode 100644
index 00000000000..53b97090ade
--- /dev/null
+++ b/lib/libcbor/src/cbor/internal/stack.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_STACK_H
+#define LIBCBOR_STACK_H
+
+#include "cbor/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Simple stack record for the parser */
+struct _cbor_stack_record {
+ struct _cbor_stack_record *lower;
+ cbor_item_t *item;
+ size_t subitems;
+};
+
+/** Stack handle - contents and size */
+struct _cbor_stack {
+ struct _cbor_stack_record *top;
+ size_t size;
+};
+
+struct _cbor_stack _cbor_stack_init();
+
+void _cbor_stack_pop(struct _cbor_stack *);
+
+struct _cbor_stack_record *_cbor_stack_push(struct _cbor_stack *, cbor_item_t *, size_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_STACK_H
diff --git a/lib/libcbor/src/cbor/internal/unicode.c b/lib/libcbor/src/cbor/internal/unicode.c
new file mode 100644
index 00000000000..23403095561
--- /dev/null
+++ b/lib/libcbor/src/cbor/internal/unicode.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "unicode.h"
+
+#define UTF8_ACCEPT 0
+#define UTF8_REJECT 1
+
+static const uint8_t utf8d[] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 00..1f */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 20..3f */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40..5f */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 60..7f */
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, /* 80..9f */
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* a0..bf */
+ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* c0..df */
+ 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, /* e0..ef */
+ 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, /* f0..ff */
+ 0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, /* s0..s0 */
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, /* s1..s2 */
+ 1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, /* s3..s4 */
+ 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, /* s5..s6 */
+ 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* s7..s8 */
+};
+
+/* Copyright of this function: (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> */
+/* See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. */
+uint32_t _cbor_unicode_decode(uint32_t* state, uint32_t* codep, uint32_t byte) {
+ uint32_t type = utf8d[byte];
+
+ *codep = (*state != UTF8_ACCEPT) ?
+ (byte & 0x3fu) | (*codep << 6) :
+ (0xff >> type) & (byte);
+
+ *state = utf8d[256 + *state * 16 + type];
+ return *state;
+}
+
+size_t _cbor_unicode_codepoint_count(cbor_data source, size_t source_length, struct _cbor_unicode_status * status)
+{
+ *status = (struct _cbor_unicode_status) { .location = 0, .status = _CBOR_UNICODE_OK };
+ uint32_t codepoint, state = UTF8_ACCEPT, res;
+ size_t pos = 0, count = 0;
+
+ for (; pos < source_length; pos++)
+ {
+ res = _cbor_unicode_decode(&state, &codepoint, source[pos]);
+
+ if (res == UTF8_ACCEPT) {
+ count++;
+ } else if (res == UTF8_REJECT) {
+ goto error;
+ }
+ }
+
+ /* Unfinished multibyte codepoint */
+ if (state != UTF8_ACCEPT)
+ goto error;
+
+ return count;
+
+ error:
+ *status = (struct _cbor_unicode_status) { .location = pos, .status = _CBOR_UNICODE_BADCP };
+ return -1;
+}
diff --git a/lib/libcbor/src/cbor/internal/unicode.h b/lib/libcbor/src/cbor/internal/unicode.h
new file mode 100644
index 00000000000..9d80bafcab2
--- /dev/null
+++ b/lib/libcbor/src/cbor/internal/unicode.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_UNICODE_H
+#define LIBCBOR_UNICODE_H
+
+#include "cbor/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum _cbor_unicode_status_error {
+ _CBOR_UNICODE_OK,
+ _CBOR_UNICODE_BADCP
+};
+
+/** Signals unicode validation error and possibly its location */
+struct _cbor_unicode_status {
+ enum _cbor_unicode_status_error status;
+ size_t location;
+};
+
+size_t _cbor_unicode_codepoint_count(cbor_data source, size_t source_length, struct _cbor_unicode_status * status);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_UNICODE_H
diff --git a/lib/libcbor/src/cbor/ints.c b/lib/libcbor/src/cbor/ints.c
new file mode 100644
index 00000000000..26f08cd3453
--- /dev/null
+++ b/lib/libcbor/src/cbor/ints.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "ints.h"
+
+cbor_int_width cbor_int_get_width(const cbor_item_t *item)
+{
+ assert(cbor_is_int(item));
+ return item->metadata.int_metadata.width;
+}
+
+uint8_t cbor_get_uint8(const cbor_item_t *item)
+{
+ assert(cbor_is_int(item));
+ assert(cbor_int_get_width(item) == CBOR_INT_8);
+ return *item->data;
+}
+
+uint16_t cbor_get_uint16(const cbor_item_t *item)
+{
+ assert(cbor_is_int(item));
+ assert(cbor_int_get_width(item) == CBOR_INT_16);
+ return *(uint16_t *) item->data;
+}
+
+uint32_t cbor_get_uint32(const cbor_item_t *item)
+{
+ assert(cbor_is_int(item));
+ assert(cbor_int_get_width(item) == CBOR_INT_32);
+ return *(uint32_t *) item->data;
+}
+
+uint64_t cbor_get_uint64(const cbor_item_t *item)
+{
+ assert(cbor_is_int(item));
+ assert(cbor_int_get_width(item) == CBOR_INT_64);
+ return *(uint64_t *) item->data;
+}
+
+uint64_t cbor_get_int(const cbor_item_t * item)
+{
+ assert(cbor_is_int(item));
+ switch(cbor_int_get_width(item)) {
+ case CBOR_INT_8: return cbor_get_uint8(item);
+ case CBOR_INT_16: return cbor_get_uint16(item);
+ case CBOR_INT_32: return cbor_get_uint32(item);
+ case CBOR_INT_64: return cbor_get_uint64(item);
+ }
+ return 0xDEADBEEF; /* Compiler complaints */
+}
+
+void cbor_set_uint8(cbor_item_t *item, uint8_t value)
+{
+ assert(cbor_is_int(item));
+ assert(cbor_int_get_width(item) == CBOR_INT_8);
+ *item->data = value;
+}
+
+void cbor_set_uint16(cbor_item_t *item, uint16_t value)
+{
+ assert(cbor_is_int(item));
+ assert(cbor_int_get_width(item) == CBOR_INT_16);
+ *(uint16_t *) item->data = value;
+}
+
+
+void cbor_set_uint32(cbor_item_t *item, uint32_t value)
+{
+ assert(cbor_is_int(item));
+ assert(cbor_int_get_width(item) == CBOR_INT_32);
+ *(uint32_t *) item->data = value;
+}
+
+void cbor_set_uint64(cbor_item_t *item, uint64_t value)
+{
+ assert(cbor_is_int(item));
+ assert(cbor_int_get_width(item) == CBOR_INT_64);
+ *(uint64_t *) item->data = value;
+}
+
+void cbor_mark_uint(cbor_item_t *item)
+{
+ assert(cbor_is_int(item));
+ item->type = CBOR_TYPE_UINT;
+}
+
+void cbor_mark_negint(cbor_item_t *item)
+{
+ assert(cbor_is_int(item));
+ item->type = CBOR_TYPE_NEGINT;
+}
+
+cbor_item_t *cbor_new_int8()
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 1);
+ *item = (cbor_item_t) {
+ .data = (unsigned char *) item + sizeof(cbor_item_t),
+ .refcount = 1,
+ .metadata = {.int_metadata = {.width = CBOR_INT_8}},
+ .type = CBOR_TYPE_UINT
+ };
+ return item;
+}
+
+cbor_item_t *cbor_new_int16()
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 2);
+ *item = (cbor_item_t) {
+ .data = (unsigned char *) item + sizeof(cbor_item_t),
+ .refcount = 1,
+ .metadata = {.int_metadata = {.width = CBOR_INT_16}},
+ .type = CBOR_TYPE_UINT
+ };
+ return item;
+}
+
+cbor_item_t *cbor_new_int32()
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 4);
+ *item = (cbor_item_t) {
+ .data = (unsigned char *) item + sizeof(cbor_item_t),
+ .refcount = 1,
+ .metadata = {.int_metadata = {.width = CBOR_INT_32}},
+ .type = CBOR_TYPE_UINT
+ };
+ return item;
+}
+
+cbor_item_t *cbor_new_int64()
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 8);
+ *item = (cbor_item_t) {
+ .data = (unsigned char *) item + sizeof(cbor_item_t),
+ .refcount = 1,
+ .metadata = {.int_metadata = {.width = CBOR_INT_64}},
+ .type = CBOR_TYPE_UINT
+ };
+ return item;
+}
+
+cbor_item_t *cbor_build_uint8(uint8_t value)
+{
+ cbor_item_t *item = cbor_new_int8();
+ cbor_set_uint8(item, value);
+ cbor_mark_uint(item);
+ return item;
+}
+
+cbor_item_t *cbor_build_uint16(uint16_t value)
+{
+ cbor_item_t *item = cbor_new_int16();
+ cbor_set_uint16(item, value);
+ cbor_mark_uint(item);
+ return item;
+}
+
+cbor_item_t *cbor_build_uint32(uint32_t value)
+{
+ cbor_item_t *item = cbor_new_int32();
+ cbor_set_uint32(item, value);
+ cbor_mark_uint(item);
+ return item;
+}
+
+cbor_item_t *cbor_build_uint64(uint64_t value)
+{
+ cbor_item_t *item = cbor_new_int64();
+ cbor_set_uint64(item, value);
+ cbor_mark_uint(item);
+ return item;
+}
+
+cbor_item_t *cbor_build_negint8(uint8_t value)
+{
+ cbor_item_t *item = cbor_new_int8();
+ cbor_set_uint8(item, value);
+ cbor_mark_negint(item);
+ return item;
+}
+
+cbor_item_t *cbor_build_negint16(uint16_t value)
+{
+ cbor_item_t *item = cbor_new_int16();
+ cbor_set_uint16(item, value);
+ cbor_mark_negint(item);
+ return item;
+}
+
+cbor_item_t *cbor_build_negint32(uint32_t value)
+{
+ cbor_item_t *item = cbor_new_int32();
+ cbor_set_uint32(item, value);
+ cbor_mark_negint(item);
+ return item;
+}
+
+cbor_item_t *cbor_build_negint64(uint64_t value)
+{
+ cbor_item_t *item = cbor_new_int64();
+ cbor_set_uint64(item, value);
+ cbor_mark_negint(item);
+ return item;
+}
diff --git a/lib/libcbor/src/cbor/ints.h b/lib/libcbor/src/cbor/ints.h
new file mode 100644
index 00000000000..31f9d056a4b
--- /dev/null
+++ b/lib/libcbor/src/cbor/ints.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_INTS_H
+#define LIBCBOR_INTS_H
+
+#include "cbor/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+* ============================================================================
+* Integer (uints and negints) manipulation
+* ============================================================================
+*/
+
+/** Extracts the integer value
+ *
+ * @param item[borrow] positive or negative integer
+ * @return the value
+ */
+uint8_t cbor_get_uint8(const cbor_item_t *item);
+
+/** Extracts the integer value
+ *
+ * @param item[borrow] positive or negative integer
+ * @return the value
+ */
+uint16_t cbor_get_uint16(const cbor_item_t *item);
+
+/** Extracts the integer value
+ *
+ * @param item[borrow] positive or negative integer
+ * @return the value
+ */
+uint32_t cbor_get_uint32(const cbor_item_t *item);
+
+/** Extracts the integer value
+ *
+ * @param item[borrow] positive or negative integer
+ * @return the value
+ */
+uint64_t cbor_get_uint64(const cbor_item_t *item);
+
+/** Extracts the integer value
+ *
+ * @param item[borrow] positive or negative integer
+ * @return the value, extended to `uint64_t`
+ */
+uint64_t cbor_get_int(const cbor_item_t *item);
+
+/** Assigns the integer value
+ *
+ * @param item[borrow] positive or negative integer item
+ * @param value the value to assign. For negative integer, the logical value is `-value - 1`
+ */
+void cbor_set_uint8(cbor_item_t *item, uint8_t value);
+
+/** Assigns the integer value
+ *
+ * @param item[borrow] positive or negative integer item
+ * @param value the value to assign. For negative integer, the logical value is `-value - 1`
+ */
+void cbor_set_uint16(cbor_item_t *item, uint16_t value);
+
+/** Assigns the integer value
+ *
+ * @param item[borrow] positive or negative integer item
+ * @param value the value to assign. For negative integer, the logical value is `-value - 1`
+ */
+void cbor_set_uint32(cbor_item_t *item, uint32_t value);
+
+/** Assigns the integer value
+ *
+ * @param item[borrow] positive or negative integer item
+ * @param value the value to assign. For negative integer, the logical value is `-value - 1`
+ */
+void cbor_set_uint64(cbor_item_t *item, uint64_t value);
+
+/** Queries the integer width
+ *
+ * @param item[borrow] positive or negative integer item
+ * @return the width
+ */
+cbor_int_width cbor_int_get_width(const cbor_item_t *item);
+
+/** Marks the integer item as a positive integer
+ *
+ * The data value is not changed
+ *
+ * @param item[borrow] positive or negative integer item
+ */
+void cbor_mark_uint(cbor_item_t *item);
+
+/** Marks the integer item as a negative integer
+ *
+ * The data value is not changed
+ *
+ * @param item[borrow] positive or negative integer item
+ */
+void cbor_mark_negint(cbor_item_t *item);
+
+/** Allocates new integer with 1B width
+ *
+ * The width cannot be changed once allocated
+ *
+ * @return **new** positive integer. The value is not initialized.
+ */
+cbor_item_t *cbor_new_int8();
+
+/** Allocates new integer with 2B width
+ *
+ * The width cannot be changed once allocated
+ *
+ * @return **new** positive integer. The value is not initialized.
+ */
+cbor_item_t *cbor_new_int16();
+
+/** Allocates new integer with 4B width
+ *
+ * The width cannot be changed once allocated
+ *
+ * @return **new** positive integer. The value is not initialized.
+ */
+cbor_item_t *cbor_new_int32();
+
+/** Allocates new integer with 8B width
+ *
+ * The width cannot be changed once allocated
+ *
+ * @return **new** positive integer. The value is not initialized.
+ */
+cbor_item_t *cbor_new_int64();
+
+/** Constructs a new positive integer
+ *
+ * @param value the value to use
+ * @return **new** positive integer
+ */
+cbor_item_t *cbor_build_uint8(uint8_t value);
+
+/** Constructs a new positive integer
+ *
+ * @param value the value to use
+ * @return **new** positive integer
+ */
+cbor_item_t *cbor_build_uint16(uint16_t value);
+
+/** Constructs a new positive integer
+ *
+ * @param value the value to use
+ * @return **new** positive integer
+ */
+cbor_item_t *cbor_build_uint32(uint32_t value);
+
+/** Constructs a new positive integer
+ *
+ * @param value the value to use
+ * @return **new** positive integer
+ */
+cbor_item_t *cbor_build_uint64(uint64_t value);
+
+/** Constructs a new negative integer
+ *
+ * @param value the value to use
+ * @return **new** negative integer
+ */
+cbor_item_t *cbor_build_negint8(uint8_t value);
+
+/** Constructs a new negative integer
+ *
+ * @param value the value to use
+ * @return **new** negative integer
+ */
+cbor_item_t *cbor_build_negint16(uint16_t value);
+
+/** Constructs a new negative integer
+ *
+ * @param value the value to use
+ * @return **new** negative integer
+ */
+cbor_item_t *cbor_build_negint32(uint32_t value);
+
+/** Constructs a new negative integer
+ *
+ * @param value the value to use
+ * @return **new** negative integer
+ */
+cbor_item_t *cbor_build_negint64(uint64_t value);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_INTS_H
diff --git a/lib/libcbor/src/cbor/maps.c b/lib/libcbor/src/cbor/maps.c
new file mode 100644
index 00000000000..8a70d0cad64
--- /dev/null
+++ b/lib/libcbor/src/cbor/maps.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "maps.h"
+#include "internal/memory_utils.h"
+
+size_t cbor_map_size(const cbor_item_t *item)
+{
+ assert(cbor_isa_map(item));
+ return item->metadata.map_metadata.end_ptr;
+}
+
+size_t cbor_map_allocated(const cbor_item_t *item)
+{
+ assert(cbor_isa_map(item));
+ return item->metadata.map_metadata.allocated;
+}
+
+cbor_item_t *cbor_new_definite_map(size_t size)
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
+ if (item == NULL) {
+ return NULL;
+ }
+ *item = (cbor_item_t) {
+ .refcount = 1,
+ .type = CBOR_TYPE_MAP,
+ .metadata = {.map_metadata = {
+ .allocated = size,
+ .type = _CBOR_METADATA_DEFINITE,
+ .end_ptr = 0
+ }},
+ .data = _cbor_alloc_multiple(sizeof(struct cbor_pair), size)
+ };
+ if (item->data == NULL) {
+ _CBOR_FREE(item);
+ return NULL;
+ }
+ return item;
+}
+
+cbor_item_t *cbor_new_indefinite_map()
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
+ if (item == NULL)
+ return NULL;
+ *item = (cbor_item_t) {
+ .refcount = 1,
+ .type = CBOR_TYPE_MAP,
+ .metadata = {.map_metadata = {
+ .allocated = 0,
+ .type = _CBOR_METADATA_INDEFINITE,
+ .end_ptr = 0
+ }},
+ .data = NULL
+ };
+
+ return item;
+}
+
+
+bool _cbor_map_add_key(cbor_item_t *item, cbor_item_t *key)
+{
+ assert(cbor_isa_map(item));
+ struct _cbor_map_metadata *metadata = (struct _cbor_map_metadata *) &item->metadata;
+ if (cbor_map_is_definite(item)) {
+ struct cbor_pair *data = cbor_map_handle(item);
+ if (metadata->end_ptr >= metadata->allocated) {
+ /* Don't realloc definite preallocated map */
+ return false;
+ }
+
+ data[metadata->end_ptr].key = key;
+ data[metadata->end_ptr++].value = NULL;
+ } else {
+ if (metadata->end_ptr >= metadata->allocated) {
+ /* Exponential realloc */
+ // Check for overflows first
+ if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) {
+ return false;
+ }
+
+ size_t new_allocation = metadata->allocated == 0 ? 1 : CBOR_BUFFER_GROWTH * metadata->allocated;
+
+ unsigned char * new_data = _cbor_realloc_multiple(item->data, sizeof(struct cbor_pair), new_allocation);
+
+ if (new_data == NULL) {
+ return false;
+ }
+
+ item->data = new_data;
+ metadata->allocated = new_allocation;
+ }
+ struct cbor_pair *data = cbor_map_handle(item);
+ data[metadata->end_ptr].key = key;
+ data[metadata->end_ptr++].value = NULL;
+ }
+ cbor_incref(key);
+ return true;
+}
+
+bool _cbor_map_add_value(cbor_item_t *item, cbor_item_t *value)
+{
+ assert(cbor_isa_map(item));
+ cbor_incref(value);
+ cbor_map_handle(item)[
+ /* Move one back since we are assuming _add_key (which increased the ptr)
+ * was the previous operation on this object */
+ item->metadata.map_metadata.end_ptr - 1
+ ].value = value;
+ return true;
+}
+
+bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair)
+{
+ assert(cbor_isa_map(item));
+ if (!_cbor_map_add_key(item, pair.key))
+ return false;
+ return _cbor_map_add_value(item, pair.value);
+}
+
+bool cbor_map_is_definite(const cbor_item_t *item)
+{
+ assert(cbor_isa_map(item));
+ return item->metadata.map_metadata.type == _CBOR_METADATA_DEFINITE;
+}
+
+bool cbor_map_is_indefinite(const cbor_item_t *item)
+{
+ return !cbor_map_is_definite(item);
+}
+
+struct cbor_pair *cbor_map_handle(const cbor_item_t *item)
+{
+ assert(cbor_isa_map(item));
+ return (struct cbor_pair *) item->data;
+}
diff --git a/lib/libcbor/src/cbor/maps.h b/lib/libcbor/src/cbor/maps.h
new file mode 100644
index 00000000000..cd433b310f3
--- /dev/null
+++ b/lib/libcbor/src/cbor/maps.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_MAPS_H
+#define LIBCBOR_MAPS_H
+
+#include "cbor/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+* ============================================================================
+* Map manipulation
+* ============================================================================
+*/
+
+/** Get the number of pairs
+ *
+ * @param item[borrow] A map
+ * @return The number of pairs
+ */
+size_t cbor_map_size(const cbor_item_t *item);
+
+/** Get the size of the allocated storage
+ *
+ * @param item[borrow] A map
+ * @return Allocated storage size (as the number of #cbor_pair items)
+ */
+size_t cbor_map_allocated(const cbor_item_t *item);
+
+/** Create a new definite map
+ *
+ * @param size The number of slots to preallocate
+ * @return **new** definite map. `NULL` on malloc failure.
+ */
+cbor_item_t *cbor_new_definite_map(size_t size);
+
+/** Create a new indefinite map
+ *
+ * @param size The number of slots to preallocate
+ * @return **new** definite map. `NULL` on malloc failure.
+ */
+cbor_item_t *cbor_new_indefinite_map();
+
+/** Add a pair to the map
+ *
+ * For definite maps, items can only be added to the preallocated space. For indefinite
+ * maps, the storage will be expanded as needed
+ *
+ * @param item[borrow] A map
+ * @param pair[incref] The key-value pair to add (incref is member-wise)
+ * @return `true` on success, `false` if either reallocation failed or the preallcoated storage is full
+ */
+bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair);
+
+/** Add a key to the map
+ *
+ * Sets the value to `NULL`. Internal API.
+ *
+ * @param item[borrow] A map
+ * @param key[incref] The key
+ * @return `true` on success, `false` if either reallocation failed or the preallcoated storage is full
+ */
+bool _cbor_map_add_key(cbor_item_t *item, cbor_item_t *key);
+
+/** Add a value to the map
+ *
+ * Assumes that #_cbor_map_add_key has been called. Internal API.
+ *
+ * @param item[borrow] A map
+ * @param key[incref] The value
+ * @return `true` on success, `false` if either reallocation failed or the preallcoated storage is full
+ */
+bool _cbor_map_add_value(cbor_item_t *item, cbor_item_t *value);
+
+/** Is this map definite?
+ *
+ * @param item[borrow] A map
+ * @return Is this map definite?
+ */
+bool cbor_map_is_definite(const cbor_item_t *item);
+
+/** Is this map indefinite?
+ *
+ * @param item[borrow] A map
+ * @return Is this map indefinite?
+ */
+bool cbor_map_is_indefinite(const cbor_item_t *item);
+
+/** Get the pairs storage
+ *
+ * @param item[borrow] A map
+ * @return Array of #cbor_map_size pairs. Manipulation is possible as long as references remain valid.
+ */
+struct cbor_pair *cbor_map_handle(const cbor_item_t *item);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_MAPS_H
diff --git a/lib/libcbor/src/cbor/serialization.c b/lib/libcbor/src/cbor/serialization.c
new file mode 100644
index 00000000000..52f2bbe8b34
--- /dev/null
+++ b/lib/libcbor/src/cbor/serialization.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "serialization.h"
+#include "encoding.h"
+#include "cbor/arrays.h"
+#include "cbor/bytestrings.h"
+#include "cbor/floats_ctrls.h"
+#include "cbor/ints.h"
+#include "cbor/maps.h"
+#include "cbor/strings.h"
+#include "cbor/tags.h"
+#include "internal/memory_utils.h"
+#include <string.h>
+
+size_t cbor_serialize(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
+{
+ switch (cbor_typeof(item)) {
+ case CBOR_TYPE_UINT:
+ return cbor_serialize_uint(item, buffer, buffer_size);
+ case CBOR_TYPE_NEGINT:
+ return cbor_serialize_negint(item, buffer, buffer_size);
+ case CBOR_TYPE_BYTESTRING:
+ return cbor_serialize_bytestring(item, buffer, buffer_size);
+ case CBOR_TYPE_STRING:
+ return cbor_serialize_string(item, buffer, buffer_size);
+ case CBOR_TYPE_ARRAY:
+ return cbor_serialize_array(item, buffer, buffer_size);
+ case CBOR_TYPE_MAP:
+ return cbor_serialize_map(item, buffer, buffer_size);
+ case CBOR_TYPE_TAG:
+ return cbor_serialize_tag(item, buffer, buffer_size);
+ case CBOR_TYPE_FLOAT_CTRL:
+ return cbor_serialize_float_ctrl(item, buffer, buffer_size);
+ default:
+ return 0;
+ }
+}
+
+size_t cbor_serialize_alloc(const cbor_item_t * item,
+ unsigned char ** buffer,
+ size_t * buffer_size)
+{
+ size_t bfr_size = 32;
+ unsigned char * bfr = _CBOR_MALLOC(bfr_size), * tmp_bfr;
+ if (bfr == NULL) {
+ return 0;
+ }
+
+ size_t written;
+
+ /* This is waaay too optimistic - figure out something smarter (eventually) */
+ while ((written = cbor_serialize(item, bfr, bfr_size)) == 0) {
+ if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, bfr_size)) {
+ _CBOR_FREE(bfr);
+ return 0;
+ }
+
+ tmp_bfr = _CBOR_REALLOC(bfr, bfr_size *= 2);
+
+ if (tmp_bfr == NULL) {
+ _CBOR_FREE(bfr);
+ return 0;
+ }
+ bfr = tmp_bfr;
+ }
+ *buffer = bfr;
+ *buffer_size = bfr_size;
+ return written;
+}
+
+size_t cbor_serialize_uint(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
+{
+ assert(cbor_isa_uint(item));
+ switch (cbor_int_get_width(item)) {
+ case CBOR_INT_8:
+ return cbor_encode_uint8(cbor_get_uint8(item), buffer, buffer_size);
+ case CBOR_INT_16:
+ return cbor_encode_uint16(cbor_get_uint16(item), buffer, buffer_size);
+ case CBOR_INT_32:
+ return cbor_encode_uint32(cbor_get_uint32(item), buffer, buffer_size);
+ case CBOR_INT_64:
+ return cbor_encode_uint64(cbor_get_uint64(item), buffer, buffer_size);
+ default:
+ return 0;
+ }
+}
+
+size_t cbor_serialize_negint(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
+{
+ assert(cbor_isa_negint(item));
+ switch (cbor_int_get_width(item)) {
+ case CBOR_INT_8:
+ return cbor_encode_negint8(cbor_get_uint8(item), buffer, buffer_size);
+ case CBOR_INT_16:
+ return cbor_encode_negint16(cbor_get_uint16(item), buffer, buffer_size);
+ case CBOR_INT_32:
+ return cbor_encode_negint32(cbor_get_uint32(item), buffer, buffer_size);
+ case CBOR_INT_64:
+ return cbor_encode_negint64(cbor_get_uint64(item), buffer, buffer_size);
+ default:
+ return 0;
+ }
+}
+
+size_t cbor_serialize_bytestring(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
+{
+ assert(cbor_isa_bytestring(item));
+ if (cbor_bytestring_is_definite(item)) {
+ size_t length = cbor_bytestring_length(item);
+ size_t written = cbor_encode_bytestring_start(length, buffer, buffer_size);
+ if (written && (buffer_size - written >= length)) {
+ memcpy(buffer + written, cbor_bytestring_handle(item), length);
+ return written + length;
+ } else
+ return 0;
+ } else {
+ assert(cbor_bytestring_is_indefinite(item));
+ size_t chunk_count = cbor_bytestring_chunk_count(item);
+ size_t written = cbor_encode_indef_bytestring_start(buffer, buffer_size);
+
+ if (written == 0)
+ return 0;
+
+ cbor_item_t **chunks = cbor_bytestring_chunks_handle(item);
+ for (size_t i = 0; i < chunk_count; i++) {
+ size_t chunk_written = cbor_serialize_bytestring(chunks[i], buffer + written, buffer_size - written);
+ if (chunk_written == 0)
+ return 0;
+ else
+ written += chunk_written;
+ }
+ if (cbor_encode_break(buffer + written, buffer_size - written) > 0)
+ return written + 1;
+ else
+ return 0;
+ }
+}
+
+size_t cbor_serialize_string(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
+{
+ assert(cbor_isa_string(item));
+ if (cbor_string_is_definite(item)) {
+ size_t length = cbor_string_length(item);
+ size_t written = cbor_encode_string_start(length, buffer, buffer_size);
+ if (written && (buffer_size - written >= length)) {
+ memcpy(buffer + written, cbor_string_handle(item), length);
+ return written + length;
+ } else
+ return 0;
+ } else {
+ assert(cbor_string_is_indefinite(item));
+ size_t chunk_count = cbor_string_chunk_count(item);
+ size_t written = cbor_encode_indef_string_start(buffer, buffer_size);
+
+ if (written == 0)
+ return 0;
+
+ cbor_item_t **chunks = cbor_string_chunks_handle(item);
+ for (size_t i = 0; i < chunk_count; i++) {
+ size_t chunk_written = cbor_serialize_string(chunks[i], buffer + written, buffer_size - written);
+ if (chunk_written == 0)
+ return 0;
+ else
+ written += chunk_written;
+ }
+ if (cbor_encode_break(buffer + written, buffer_size - written) > 0)
+ return written + 1;
+ else
+ return 0;
+ }
+}
+
+size_t cbor_serialize_array(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
+{
+ assert(cbor_isa_array(item));
+ size_t size = cbor_array_size(item),
+ written = 0;
+ cbor_item_t **handle = cbor_array_handle(item);
+ if (cbor_array_is_definite(item)) {
+ written = cbor_encode_array_start(size, buffer, buffer_size);
+ } else {
+ assert(cbor_array_is_indefinite(item));
+ written = cbor_encode_indef_array_start(buffer, buffer_size);
+ }
+ if (written == 0)
+ return 0;
+
+ size_t item_written;
+ for (size_t i = 0; i < size; i++) {
+ item_written = cbor_serialize(*(handle++), buffer + written, buffer_size - written);
+ if (item_written == 0)
+ return 0;
+ else
+ written += item_written;
+ }
+
+ if (cbor_array_is_definite(item)) {
+ return written;
+ } else {
+ assert(cbor_array_is_indefinite(item));
+ item_written = cbor_encode_break(buffer + written, buffer_size - written);
+ if (item_written == 0)
+ return 0;
+ else
+ return written + 1;
+ }
+}
+
+size_t cbor_serialize_map(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
+{
+ assert(cbor_isa_map(item));
+ size_t size = cbor_map_size(item),
+ written = 0;
+ struct cbor_pair * handle = cbor_map_handle(item);
+
+ if (cbor_map_is_definite(item)) {
+ written = cbor_encode_map_start(size, buffer, buffer_size);
+ } else {
+ assert(cbor_map_is_indefinite(item));
+ written = cbor_encode_indef_map_start(buffer, buffer_size);
+ }
+ if (written == 0)
+ return 0;
+
+ size_t item_written;
+ for (size_t i = 0; i < size; i++) {
+ item_written = cbor_serialize(handle->key, buffer + written, buffer_size - written);
+ if (item_written == 0)
+ return 0;
+ else
+ written += item_written;
+ item_written = cbor_serialize((handle++)->value, buffer + written, buffer_size - written);
+ if (item_written == 0)
+ return 0;
+ else
+ written += item_written;
+ }
+
+ if (cbor_map_is_definite(item)) {
+ return written;
+ } else {
+ assert(cbor_map_is_indefinite(item));
+ item_written = cbor_encode_break(buffer + written, buffer_size - written);
+ if (item_written == 0)
+ return 0;
+ else
+ return written + 1;
+ }
+}
+
+size_t cbor_serialize_tag(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
+{
+ assert(cbor_isa_tag(item));
+ size_t written = cbor_encode_tag(cbor_tag_value(item), buffer, buffer_size);
+ if (written == 0)
+ return 0;
+
+ size_t item_written = cbor_serialize(cbor_tag_item(item), buffer + written, buffer_size - written);
+ if (item_written == 0)
+ return 0;
+ else
+ return written + item_written;
+}
+
+size_t cbor_serialize_float_ctrl(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
+{
+ assert(cbor_isa_float_ctrl(item));
+ switch (cbor_float_get_width(item)) {
+ case CBOR_FLOAT_0:
+ /* CTRL - special treatment */
+ return cbor_encode_ctrl(cbor_ctrl_value(item), buffer, buffer_size);
+ case CBOR_FLOAT_16:
+ return cbor_encode_half(cbor_float_get_float2(item), buffer, buffer_size);
+ case CBOR_FLOAT_32:
+ return cbor_encode_single(cbor_float_get_float4(item), buffer, buffer_size);
+ case CBOR_FLOAT_64:
+ return cbor_encode_double(cbor_float_get_float8(item), buffer, buffer_size);
+ }
+
+ /* Should never happen - make the compiler happy */
+ return 0;
+}
diff --git a/lib/libcbor/src/cbor/serialization.h b/lib/libcbor/src/cbor/serialization.h
new file mode 100644
index 00000000000..75b0f02437e
--- /dev/null
+++ b/lib/libcbor/src/cbor/serialization.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_SERIALIZATION_H
+#define LIBCBOR_SERIALIZATION_H
+
+#include "cbor/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+* ============================================================================
+* High level encoding
+* ============================================================================
+*/
+
+/** Serialize the given item
+ *
+ * @param item[borrow] A data item
+ * @param buffer Buffer to serialize to
+ * @param buffer_size Size of the \p buffer
+ * @return Length of the result. 0 on failure.
+ */
+size_t cbor_serialize(const cbor_item_t * item, cbor_mutable_data buffer, size_t buffer_size);
+
+/** Serialize the given item, allocating buffers as needed
+ *
+ * \rst
+ * .. warning:: It is your responsibility to free the buffer using an appropriate ``free`` implementation.
+ * \endrst
+ *
+ * @param item[borrow] A data item
+ * @param buffer[out] Buffer containing the result
+ * @param buffer_size[out] Size of the \p buffer
+ * @return Length of the result. 0 on failure, in which case \p buffer is ``NULL``.
+ */
+size_t cbor_serialize_alloc(const cbor_item_t * item, cbor_mutable_data * buffer, size_t * buffer_size);
+
+/** Serialize an uint
+ *
+ * @param item[borrow] A uint
+ * @param buffer Buffer to serialize to
+ * @param buffer_size Size of the \p buffer
+ * @return Length of the result. 0 on failure.
+ */
+size_t cbor_serialize_uint(const cbor_item_t *, cbor_mutable_data, size_t);
+
+/** Serialize a negint
+ *
+ * @param item[borrow] A neging
+ * @param buffer Buffer to serialize to
+ * @param buffer_size Size of the \p buffer
+ * @return Length of the result. 0 on failure.
+ */
+size_t cbor_serialize_negint(const cbor_item_t *, cbor_mutable_data, size_t);
+
+/** Serialize a bytestring
+ *
+ * @param item[borrow] A bytestring
+ * @param buffer Buffer to serialize to
+ * @param buffer_size Size of the \p buffer
+ * @return Length of the result. 0 on failure.
+ */
+size_t cbor_serialize_bytestring(const cbor_item_t *, cbor_mutable_data, size_t);
+
+/** Serialize a string
+ *
+ * @param item[borrow] A string
+ * @param buffer Buffer to serialize to
+ * @param buffer_size Size of the \p buffer
+ * @return Length of the result. 0 on failure.
+ */
+size_t cbor_serialize_string(const cbor_item_t *, cbor_mutable_data, size_t);
+
+/** Serialize an array
+ *
+ * @param item[borrow] An array
+ * @param buffer Buffer to serialize to
+ * @param buffer_size Size of the \p buffer
+ * @return Length of the result. 0 on failure.
+ */
+size_t cbor_serialize_array(const cbor_item_t *, cbor_mutable_data, size_t);
+
+/** Serialize a map
+ *
+ * @param item[borrow] A map
+ * @param buffer Buffer to serialize to
+ * @param buffer_size Size of the \p buffer
+ * @return Length of the result. 0 on failure.
+ */
+size_t cbor_serialize_map(const cbor_item_t *, cbor_mutable_data, size_t);
+
+/** Serialize a tag
+ *
+ * @param item[borrow] A tag
+ * @param buffer Buffer to serialize to
+ * @param buffer_size Size of the \p buffer
+ * @return Length of the result. 0 on failure.
+ */
+size_t cbor_serialize_tag(const cbor_item_t *, cbor_mutable_data, size_t);
+
+/** Serialize a
+ *
+ * @param item[borrow] A float or ctrl
+ * @param buffer Buffer to serialize to
+ * @param buffer_size Size of the \p buffer
+ * @return Length of the result. 0 on failure.
+ */
+size_t cbor_serialize_float_ctrl(const cbor_item_t *, cbor_mutable_data, size_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIBCBOR_SERIALIZATION_H
diff --git a/lib/libcbor/src/cbor/streaming.c b/lib/libcbor/src/cbor/streaming.c
new file mode 100644
index 00000000000..b6398c5b541
--- /dev/null
+++ b/lib/libcbor/src/cbor/streaming.c
@@ -0,0 +1,684 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "streaming.h"
+#include "internal/loaders.h"
+
+bool static _cbor_claim_bytes(size_t required,
+ size_t provided, struct cbor_decoder_result *result)
+{
+ if (required > (provided - result->read)) {
+ /* We need to keep all the metadata if parsing is to be resumed */
+ result->read = 0;
+ result->status = CBOR_DECODER_NEDATA;
+ return false;
+ } else {
+ result->read += required;
+ return true;
+ }
+}
+
+
+struct cbor_decoder_result cbor_stream_decode(cbor_data source, size_t source_size,
+ const struct cbor_callbacks *callbacks,
+ void *context)
+{
+ /* If we have no data, we cannot read even the MTB */
+ if (source_size < 1) {
+ return (struct cbor_decoder_result) {0, CBOR_DECODER_EBUFFER};
+ }
+
+ /* If we have a byte, assume it's the MTB */
+ struct cbor_decoder_result result = {1, CBOR_DECODER_FINISHED};
+
+ switch (*source) {
+ case 0x00: /* Fallthrough */
+ case 0x01: /* Fallthrough */
+ case 0x02: /* Fallthrough */
+ case 0x03: /* Fallthrough */
+ case 0x04: /* Fallthrough */
+ case 0x05: /* Fallthrough */
+ case 0x06: /* Fallthrough */
+ case 0x07: /* Fallthrough */
+ case 0x08: /* Fallthrough */
+ case 0x09: /* Fallthrough */
+ case 0x0A: /* Fallthrough */
+ case 0x0B: /* Fallthrough */
+ case 0x0C: /* Fallthrough */
+ case 0x0D: /* Fallthrough */
+ case 0x0E: /* Fallthrough */
+ case 0x0F: /* Fallthrough */
+ case 0x10: /* Fallthrough */
+ case 0x11: /* Fallthrough */
+ case 0x12: /* Fallthrough */
+ case 0x13: /* Fallthrough */
+ case 0x14: /* Fallthrough */
+ case 0x15: /* Fallthrough */
+ case 0x16: /* Fallthrough */
+ case 0x17:
+ /* Embedded one byte unsigned integer */
+ {
+ callbacks->uint8(context, _cbor_load_uint8(source));
+ return result;
+ }
+ case 0x18:
+ /* One byte unsigned integer */
+ {
+ if (_cbor_claim_bytes(1, source_size, &result)) {
+ callbacks->uint8(context, _cbor_load_uint8(source + 1));
+ }
+ return result;
+ }
+ case 0x19:
+ /* Two bytes unsigned integer */
+ {
+ if (_cbor_claim_bytes(2, source_size, &result)) {
+ callbacks->uint16(context, _cbor_load_uint16(source + 1));
+ }
+ return result;
+ }
+ case 0x1A:
+ /* Four bytes unsigned integer */
+ {
+ if (_cbor_claim_bytes(4, source_size, &result)) {
+ callbacks->uint32(context, _cbor_load_uint32(source + 1));
+ }
+ return result;
+ }
+ case 0x1B:
+ /* Eight bytes unsigned integer */
+ {
+ if (_cbor_claim_bytes(8, source_size, &result)) {
+ callbacks->uint64(context, _cbor_load_uint64(source + 1));
+ }
+ return result;
+ }
+ case 0x1C: /* Fallthrough */
+ case 0x1D: /* Fallthrough */
+ case 0x1E: /* Fallthrough */
+ case 0x1F:
+ /* Reserved */
+ {
+ return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
+ }
+ case 0x20: /* Fallthrough */
+ case 0x21: /* Fallthrough */
+ case 0x22: /* Fallthrough */
+ case 0x23: /* Fallthrough */
+ case 0x24: /* Fallthrough */
+ case 0x25: /* Fallthrough */
+ case 0x26: /* Fallthrough */
+ case 0x27: /* Fallthrough */
+ case 0x28: /* Fallthrough */
+ case 0x29: /* Fallthrough */
+ case 0x2A: /* Fallthrough */
+ case 0x2B: /* Fallthrough */
+ case 0x2C: /* Fallthrough */
+ case 0x2D: /* Fallthrough */
+ case 0x2E: /* Fallthrough */
+ case 0x2F: /* Fallthrough */
+ case 0x30: /* Fallthrough */
+ case 0x31: /* Fallthrough */
+ case 0x32: /* Fallthrough */
+ case 0x33: /* Fallthrough */
+ case 0x34: /* Fallthrough */
+ case 0x35: /* Fallthrough */
+ case 0x36: /* Fallthrough */
+ case 0x37:
+ /* Embedded one byte negative integer */
+ {
+ callbacks->negint8(context, _cbor_load_uint8(source) - 0x20); /* 0x20 offset */
+ return result;
+ }
+ case 0x38:
+ /* One byte negative integer */
+ {
+ if (_cbor_claim_bytes(1, source_size, &result)) {
+ callbacks->negint8(context, _cbor_load_uint8(source + 1));
+ }
+ return result;
+ }
+ case 0x39:
+ /* Two bytes negative integer */
+ {
+ if (_cbor_claim_bytes(2, source_size, &result)) {
+ callbacks->negint16(context, _cbor_load_uint16(source + 1));
+ }
+ return result;
+ }
+ case 0x3A:
+ /* Four bytes negative integer */
+ {
+ if (_cbor_claim_bytes(4, source_size, &result)) {
+ callbacks->negint32(context, _cbor_load_uint32(source + 1));
+ }
+ return result;
+ }
+ case 0x3B:
+ /* Eight bytes negative integer */
+ {
+ if (_cbor_claim_bytes(8, source_size, &result)) {
+ callbacks->negint64(context, _cbor_load_uint64(source + 1));
+ }
+ return result;
+ }
+ case 0x3C: /* Fallthrough */
+ case 0x3D: /* Fallthrough */
+ case 0x3E: /* Fallthrough */
+ case 0x3F:
+ /* Reserved */
+ {
+ return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
+ }
+ case 0x40: /* Fallthrough */
+ case 0x41: /* Fallthrough */
+ case 0x42: /* Fallthrough */
+ case 0x43: /* Fallthrough */
+ case 0x44: /* Fallthrough */
+ case 0x45: /* Fallthrough */
+ case 0x46: /* Fallthrough */
+ case 0x47: /* Fallthrough */
+ case 0x48: /* Fallthrough */
+ case 0x49: /* Fallthrough */
+ case 0x4A: /* Fallthrough */
+ case 0x4B: /* Fallthrough */
+ case 0x4C: /* Fallthrough */
+ case 0x4D: /* Fallthrough */
+ case 0x4E: /* Fallthrough */
+ case 0x4F: /* Fallthrough */
+ case 0x50: /* Fallthrough */
+ case 0x51: /* Fallthrough */
+ case 0x52: /* Fallthrough */
+ case 0x53: /* Fallthrough */
+ case 0x54: /* Fallthrough */
+ case 0x55: /* Fallthrough */
+ case 0x56: /* Fallthrough */
+ case 0x57:
+ /* Embedded length byte string */
+ {
+ size_t length = (size_t) _cbor_load_uint8(source) - 0x40; /* 0x40 offset */
+ if (_cbor_claim_bytes(length, source_size, &result)) {
+ callbacks->byte_string(context, source + 1, length);
+ }
+ return result;
+ }
+ case 0x58:
+ /* One byte length byte string */
+ // TODO template this?
+ {
+ if (_cbor_claim_bytes(1, source_size, &result)) {
+ size_t length = (size_t) _cbor_load_uint8(source + 1);
+ if (_cbor_claim_bytes(length, source_size, &result)) {
+ callbacks->byte_string(context, source + 1 + 1, length);
+ }
+ }
+ return result;
+ }
+ case 0x59:
+ /* Two bytes length byte string */
+ {
+ if (_cbor_claim_bytes(2, source_size, &result)) {
+ size_t length = (size_t) _cbor_load_uint16(source + 1);
+ if (_cbor_claim_bytes(length, source_size, &result)) {
+ callbacks->byte_string(context, source + 1 + 2, length);
+ }
+ }
+ return result;
+ }
+ case 0x5A:
+ /* Four bytes length byte string */
+ {
+ if (_cbor_claim_bytes(4, source_size, &result)) {
+ size_t length = (size_t) _cbor_load_uint32(source + 1);
+ if (_cbor_claim_bytes(length, source_size, &result)) {
+ callbacks->byte_string(context, source + 1 + 4, length);
+ }
+ }
+ return result;
+ }
+ case 0x5B:
+ /* Eight bytes length byte string */
+ {
+ if (_cbor_claim_bytes(8, source_size, &result)) {
+ size_t length = (size_t) _cbor_load_uint64(source + 1);
+ if (_cbor_claim_bytes(length, source_size, &result)) {
+ callbacks->byte_string(context, source + 1 + 8, length);
+ }
+ }
+ return result;
+ }
+ case 0x5C: /* Fallthrough */
+ case 0x5D: /* Fallthrough */
+ case 0x5E:
+ /* Reserved */
+ {
+ return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
+ }
+ case 0x5F:
+ /* Indefinite byte string */
+ {
+ callbacks->byte_string_start(context);
+ return result;
+ }
+ case 0x60: /* Fallthrough */
+ case 0x61: /* Fallthrough */
+ case 0x62: /* Fallthrough */
+ case 0x63: /* Fallthrough */
+ case 0x64: /* Fallthrough */
+ case 0x65: /* Fallthrough */
+ case 0x66: /* Fallthrough */
+ case 0x67: /* Fallthrough */
+ case 0x68: /* Fallthrough */
+ case 0x69: /* Fallthrough */
+ case 0x6A: /* Fallthrough */
+ case 0x6B: /* Fallthrough */
+ case 0x6C: /* Fallthrough */
+ case 0x6D: /* Fallthrough */
+ case 0x6E: /* Fallthrough */
+ case 0x6F: /* Fallthrough */
+ case 0x70: /* Fallthrough */
+ case 0x71: /* Fallthrough */
+ case 0x72: /* Fallthrough */
+ case 0x73: /* Fallthrough */
+ case 0x74: /* Fallthrough */
+ case 0x75: /* Fallthrough */
+ case 0x76: /* Fallthrough */
+ case 0x77:
+ /* Embedded one byte length string */
+ {
+ size_t length = (size_t) _cbor_load_uint8(source) - 0x60; /* 0x60 offset */
+ if (_cbor_claim_bytes(length, source_size, &result)) {
+ callbacks->string(context, source + 1, length);
+ }
+ return result;
+ }
+ case 0x78:
+ /* One byte length string */
+ {
+ if (_cbor_claim_bytes(1, source_size, &result)) {
+ size_t length = (size_t) _cbor_load_uint8(source + 1);
+ if (_cbor_claim_bytes(length, source_size, &result)) {
+ callbacks->string(context, source + 1 + 1, length);
+ }
+ }
+ return result;
+ }
+ case 0x79:
+ /* Two bytes length string */
+ {
+ if (_cbor_claim_bytes(2, source_size, &result)) {
+ size_t length = (size_t) _cbor_load_uint16(source + 1);
+ if (_cbor_claim_bytes(length, source_size, &result)) {
+ callbacks->string(context, source + 1 + 2, length);
+ }
+ }
+ return result;
+ }
+ case 0x7A:
+ /* Four bytes length string */
+ {
+ if (_cbor_claim_bytes(4, source_size, &result)) {
+ size_t length = (size_t) _cbor_load_uint32(source + 1);
+ if (_cbor_claim_bytes(length, source_size, &result)) {
+ callbacks->string(context, source + 1 + 4, length);
+ }
+ }
+ return result;
+ }
+ case 0x7B:
+ /* Eight bytes length string */
+ {
+ if (_cbor_claim_bytes(8, source_size, &result)) {
+ size_t length = (size_t) _cbor_load_uint64(source + 1);
+ if (_cbor_claim_bytes(length, source_size, &result)) {
+ callbacks->string(context, source + 1 + 8, length);
+ }
+ }
+ return result;
+ }
+ case 0x7C: /* Fallthrough */
+ case 0x7D: /* Fallthrough */
+ case 0x7E:
+ /* Reserved */
+ {
+ return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
+ }
+ case 0x7F:
+ /* Indefinite length string */
+ {
+ callbacks->string_start(context);
+ return result;
+ }
+ case 0x80: /* Fallthrough */
+ case 0x81: /* Fallthrough */
+ case 0x82: /* Fallthrough */
+ case 0x83: /* Fallthrough */
+ case 0x84: /* Fallthrough */
+ case 0x85: /* Fallthrough */
+ case 0x86: /* Fallthrough */
+ case 0x87: /* Fallthrough */
+ case 0x88: /* Fallthrough */
+ case 0x89: /* Fallthrough */
+ case 0x8A: /* Fallthrough */
+ case 0x8B: /* Fallthrough */
+ case 0x8C: /* Fallthrough */
+ case 0x8D: /* Fallthrough */
+ case 0x8E: /* Fallthrough */
+ case 0x8F: /* Fallthrough */
+ case 0x90: /* Fallthrough */
+ case 0x91: /* Fallthrough */
+ case 0x92: /* Fallthrough */
+ case 0x93: /* Fallthrough */
+ case 0x94: /* Fallthrough */
+ case 0x95: /* Fallthrough */
+ case 0x96: /* Fallthrough */
+ case 0x97:
+ /* Embedded one byte length array */
+ {
+ callbacks->array_start(context, (size_t) _cbor_load_uint8(source) - 0x80); /* 0x40 offset */
+ return result;
+ }
+ case 0x98:
+ /* One byte length array */
+ {
+ if (_cbor_claim_bytes(1, source_size, &result)) {
+ callbacks->array_start(context, (size_t) _cbor_load_uint8(source + 1));
+ }
+ return result;
+ }
+ case 0x99:
+ /* Two bytes length string */
+ {
+ if (_cbor_claim_bytes(2, source_size, &result)) {
+ callbacks->array_start(context, (size_t) _cbor_load_uint16(source + 1));
+ }
+ return result;
+ }
+ case 0x9A:
+ /* Four bytes length string */
+ {
+ if (_cbor_claim_bytes(4, source_size, &result)) {
+ callbacks->array_start(context, (size_t) _cbor_load_uint32(source + 1));
+ }
+ return result;
+ }
+ case 0x9B:
+ /* Eight bytes length string */
+ {
+ if (_cbor_claim_bytes(8, source_size, &result)) {
+ callbacks->array_start(context, (size_t) _cbor_load_uint64(source + 1));
+ }
+ return result;
+ }
+ case 0x9C: /* Fallthrough */
+ case 0x9D: /* Fallthrough */
+ case 0x9E:
+ /* Reserved */
+ {
+ return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
+ }
+ case 0x9F:
+ /* Indefinite length array */
+ {
+ callbacks->indef_array_start(context);
+ return result;
+ }
+ case 0xA0: /* Fallthrough */
+ case 0xA1: /* Fallthrough */
+ case 0xA2: /* Fallthrough */
+ case 0xA3: /* Fallthrough */
+ case 0xA4: /* Fallthrough */
+ case 0xA5: /* Fallthrough */
+ case 0xA6: /* Fallthrough */
+ case 0xA7: /* Fallthrough */
+ case 0xA8: /* Fallthrough */
+ case 0xA9: /* Fallthrough */
+ case 0xAA: /* Fallthrough */
+ case 0xAB: /* Fallthrough */
+ case 0xAC: /* Fallthrough */
+ case 0xAD: /* Fallthrough */
+ case 0xAE: /* Fallthrough */
+ case 0xAF: /* Fallthrough */
+ case 0xB0: /* Fallthrough */
+ case 0xB1: /* Fallthrough */
+ case 0xB2: /* Fallthrough */
+ case 0xB3: /* Fallthrough */
+ case 0xB4: /* Fallthrough */
+ case 0xB5: /* Fallthrough */
+ case 0xB6: /* Fallthrough */
+ case 0xB7:
+ /* Embedded one byte length map */
+ {
+ callbacks->map_start(context, (size_t) _cbor_load_uint8(source) - 0xA0); /* 0xA0 offset */
+ return result;
+ }
+ case 0xB8:
+ /* One byte length map */
+ {
+ if (_cbor_claim_bytes(1, source_size, &result)) {
+ callbacks->map_start(context, (size_t) _cbor_load_uint8(source + 1));
+ }
+ return result;
+ }
+ case 0xB9:
+ /* Two bytes length map */
+ {
+ if (_cbor_claim_bytes(2, source_size, &result)) {
+ callbacks->map_start(context, (size_t) _cbor_load_uint16(source + 1));
+ }
+ return result;
+ }
+ case 0xBA:
+ /* Four bytes length map */
+ {
+ if (_cbor_claim_bytes(4, source_size, &result)) {
+ callbacks->map_start(context, (size_t) _cbor_load_uint32(source + 1));
+ }
+ return result;
+ }
+ case 0xBB:
+ /* Eight bytes length map */
+ {
+ if (_cbor_claim_bytes(8, source_size, &result)) {
+ callbacks->map_start(context, (size_t) _cbor_load_uint64(source + 1));
+ }
+ return result;
+ }
+ case 0xBC: /* Fallthrough */
+ case 0xBD: /* Fallthrough */
+ case 0xBE:
+ /* Reserved */
+ {
+ return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
+ }
+ case 0xBF:
+ /* Indefinite length map */
+ {
+ callbacks->indef_map_start(context);
+ return result;
+ }
+ case 0xC0:
+ /* Text date/time - RFC 3339 tag, fallthrough */
+ case 0xC1:
+ /* Epoch date tag, fallthrough */
+ case 0xC2:
+ /* Positive bignum tag, fallthrough */
+ case 0xC3:
+ /* Negative bignum tag, fallthrough */
+ case 0xC4:
+ /* Fraction, fallthrough */
+ case 0xC5:
+ /* Big float */
+ {
+ callbacks->tag(context, _cbor_load_uint8(source) - 0xC0); /* 0xC0 offset */
+ return result;
+ }
+ case 0xC6: /* Fallthrough */
+ case 0xC7: /* Fallthrough */
+ case 0xC8: /* Fallthrough */
+ case 0xC9: /* Fallthrough */
+ case 0xCA: /* Fallthrough */
+ case 0xCB: /* Fallthrough */
+ case 0xCC: /* Fallthrough */
+ case 0xCD: /* Fallthrough */
+ case 0xCE: /* Fallthrough */
+ case 0xCF: /* Fallthrough */
+ case 0xD0: /* Fallthrough */
+ case 0xD1: /* Fallthrough */
+ case 0xD2: /* Fallthrough */
+ case 0xD3: /* Fallthrough */
+ case 0xD4: /* Unassigned tag value */
+ {
+ return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
+ }
+ case 0xD5: /* Expected b64url conversion tag - fallthrough */
+ case 0xD6: /* Expected b64 conversion tag - fallthrough */
+ case 0xD7: /* Expected b16 conversion tag */
+ {
+ callbacks->tag(context, _cbor_load_uint8(source) - 0xC0); /* 0xC0 offset */
+ return result;
+ }
+ case 0xD8: /* 1B tag */
+ {
+ if (_cbor_claim_bytes(1, source_size, &result)) {
+ callbacks->tag(context, _cbor_load_uint8(source + 1));
+ }
+ return result;
+ }
+ case 0xD9: /* 2B tag */
+ {
+ if (_cbor_claim_bytes(2, source_size, &result)) {
+ callbacks->tag(context, _cbor_load_uint16(source + 1));
+ }
+ return result;
+ }
+ case 0xDA: /* 4B tag */
+ {
+ if (_cbor_claim_bytes(4, source_size, &result)) {
+ callbacks->tag(context, _cbor_load_uint32(source + 1));
+ }
+ return result;
+ }
+ case 0xDB: /* 8B tag */
+ {
+ if (_cbor_claim_bytes(8, source_size, &result)) {
+ callbacks->tag(context, _cbor_load_uint64(source + 1));
+ }
+ return result;
+ }
+ case 0xDC: /* Fallthrough */
+ case 0xDD: /* Fallthrough */
+ case 0xDE: /* Fallthrough */
+ case 0xDF: /* Reserved */
+ {
+ return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
+ }
+ case 0xE0: /* Fallthrough */
+ case 0xE1: /* Fallthrough */
+ case 0xE2: /* Fallthrough */
+ case 0xE3: /* Fallthrough */
+ case 0xE4: /* Fallthrough */
+ case 0xE5: /* Fallthrough */
+ case 0xE6: /* Fallthrough */
+ case 0xE7: /* Fallthrough */
+ case 0xE8: /* Fallthrough */
+ case 0xE9: /* Fallthrough */
+ case 0xEA: /* Fallthrough */
+ case 0xEB: /* Fallthrough */
+ case 0xEC: /* Fallthrough */
+ case 0xED: /* Fallthrough */
+ case 0xEE: /* Fallthrough */
+ case 0xEF: /* Fallthrough */
+ case 0xF0: /* Fallthrough */
+ case 0xF1: /* Fallthrough */
+ case 0xF2: /* Fallthrough */
+ case 0xF3: /* Simple value - unassigned */
+ {
+ return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
+ }
+ case 0xF4:
+ /* False */
+ {
+ callbacks->boolean(context, false);
+ return result;
+ }
+ case 0xF5:
+ /* True */
+ {
+ callbacks->boolean(context, true);
+ return result;
+ }
+ case 0xF6:
+ /* Null */
+ {
+ callbacks->null(context);
+ return result;
+ }
+ case 0xF7:
+ /* Undefined */
+ {
+ callbacks->undefined(context);
+ return result;
+ }
+ case 0xF8:
+ /* 1B simple value, unassigned */
+ {
+ return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
+ }
+ case 0xF9:
+ /* 2B float */
+ {
+ if (_cbor_claim_bytes(2, source_size, &result)) {
+ callbacks->float2(context, _cbor_load_half(source + 1));
+ }
+ return result;
+ }
+ case 0xFA:
+ /* 4B float */
+ {
+ if (_cbor_claim_bytes(4, source_size, &result)) {
+ callbacks->float4(context, _cbor_load_float(source + 1));
+ }
+ return result;
+ }
+ case 0xFB:
+ /* 8B float */
+ {
+ if (_cbor_claim_bytes(8, source_size, &result)) {
+ callbacks->float8(context, _cbor_load_double(source + 1));
+ }
+ return result;
+ }
+ case 0xFC: /* Fallthrough */
+ case 0xFD: /* Fallthrough */
+ case 0xFE:
+ /* Reserved */
+ {
+ return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
+ }
+ case 0xFF:
+ /* Break */
+ {
+ callbacks->indef_break(context);
+ return result;
+ }
+ default: /* Never happens - this shuts up the compiler */
+ {
+ return result;
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/libcbor/src/cbor/streaming.h b/lib/libcbor/src/cbor/streaming.h
new file mode 100644
index 00000000000..b3e3c685b91
--- /dev/null
+++ b/lib/libcbor/src/cbor/streaming.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_STREAMING_H
+#define LIBCBOR_STREAMING_H
+
+#include "cbor/common.h"
+#include "callbacks.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Stateless decoder
+ *
+ * Will try parsing the \p buffer and will invoke the appropriate callback on success.
+ * Decodes one item at a time. No memory allocations occur.
+ *
+ * @param buffer Input buffer
+ * @param buffer_size Length of the buffer
+ * @param callbacks The callback bundle
+ * @param context An arbitrary pointer to allow for maintaining context.
+ */
+struct cbor_decoder_result cbor_stream_decode(cbor_data buffer,
+ size_t buffer_size,
+ const struct cbor_callbacks * callbacks,
+ void * context);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_STREAMING_H
diff --git a/lib/libcbor/src/cbor/strings.c b/lib/libcbor/src/cbor/strings.c
new file mode 100644
index 00000000000..35589ac9cf7
--- /dev/null
+++ b/lib/libcbor/src/cbor/strings.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <string.h>
+#include "strings.h"
+#include "internal/memory_utils.h"
+
+cbor_item_t *cbor_new_definite_string()
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
+ *item = (cbor_item_t) {
+ .refcount = 1,
+ .type = CBOR_TYPE_STRING,
+ .metadata = {.string_metadata = {_CBOR_METADATA_DEFINITE, 0}}
+ };
+ return item;
+}
+
+cbor_item_t *cbor_new_indefinite_string()
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
+ *item = (cbor_item_t) {
+ .refcount = 1,
+ .type = CBOR_TYPE_STRING,
+ .metadata = {.string_metadata = {.type = _CBOR_METADATA_INDEFINITE, .length = 0}},
+ .data = _CBOR_MALLOC(sizeof(struct cbor_indefinite_string_data))
+ };
+ *((struct cbor_indefinite_string_data *) item->data) = (struct cbor_indefinite_string_data) {
+ .chunk_count = 0,
+ .chunk_capacity = 0,
+ .chunks = NULL,
+ };
+ return item;
+}
+
+cbor_item_t *cbor_build_string(const char *val)
+{
+ cbor_item_t *item = cbor_new_definite_string();
+ size_t len = strlen(val);
+ unsigned char * handle = _CBOR_MALLOC(len);
+ memcpy(handle, val, len);
+ cbor_string_set_handle(item, handle, len);
+ return item;
+}
+
+cbor_item_t *cbor_build_stringn(const char *val, size_t length)
+{
+ cbor_item_t *item = cbor_new_definite_string();
+ unsigned char * handle = _CBOR_MALLOC(length);
+ memcpy(handle, val, length);
+ cbor_string_set_handle(item, handle, length);
+ return item;
+}
+
+void cbor_string_set_handle(cbor_item_t *item, cbor_mutable_data CBOR_RESTRICT_POINTER data, size_t length)
+{
+ assert(cbor_isa_string(item));
+ assert(cbor_string_is_definite(item));
+ item->data = data;
+ item->metadata.string_metadata.length = length;
+}
+
+cbor_item_t **cbor_string_chunks_handle(const cbor_item_t *item)
+{
+ assert(cbor_isa_string(item));
+ assert(cbor_string_is_indefinite(item));
+ return ((struct cbor_indefinite_string_data *) item->data)->chunks;
+}
+
+size_t cbor_string_chunk_count(const cbor_item_t *item)
+{
+ assert(cbor_isa_string(item));
+ assert(cbor_string_is_indefinite(item));
+ return ((struct cbor_indefinite_string_data *) item->data)->chunk_count;
+
+}
+
+bool cbor_string_add_chunk(cbor_item_t *item, cbor_item_t *chunk)
+{
+ assert(cbor_isa_string(item));
+ assert(cbor_string_is_indefinite(item));
+ struct cbor_indefinite_string_data *data = (struct cbor_indefinite_string_data *) item->data;
+ if (data->chunk_count == data->chunk_capacity) {
+ /* We need more space */
+ if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) {
+ return false;
+ }
+
+ data->chunk_capacity = data->chunk_capacity == 0 ? 1 : CBOR_BUFFER_GROWTH * (data->chunk_capacity);
+ cbor_item_t **new_chunks_data = _cbor_realloc_multiple(data->chunks, sizeof(cbor_item_t *), data->chunk_capacity);
+
+ if (new_chunks_data == NULL) {
+ return false;
+ }
+
+ data->chunks = new_chunks_data;
+ }
+ data->chunks[data->chunk_count++] = cbor_incref(chunk);
+ return true;
+}
+
+size_t cbor_string_length(const cbor_item_t *item)
+{
+ assert(cbor_isa_string(item));
+ return item->metadata.string_metadata.length;
+}
+
+unsigned char *cbor_string_handle(const cbor_item_t *item)
+{
+ assert(cbor_isa_string(item));
+ return item->data;
+}
+
+size_t cbor_string_codepoint_count(const cbor_item_t *item)
+{
+ assert(cbor_isa_string(item));
+ return item->metadata.string_metadata.codepoint_count;
+}
+
+bool cbor_string_is_definite(const cbor_item_t *item)
+{
+ assert(cbor_isa_string(item));
+ return item->metadata.string_metadata.type == _CBOR_METADATA_DEFINITE;
+}
+
+bool cbor_string_is_indefinite(const cbor_item_t *item)
+{
+ return !cbor_string_is_definite(item);
+}
diff --git a/lib/libcbor/src/cbor/strings.h b/lib/libcbor/src/cbor/strings.h
new file mode 100644
index 00000000000..2ec3de9cb20
--- /dev/null
+++ b/lib/libcbor/src/cbor/strings.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_STRINGS_H
+#define LIBCBOR_STRINGS_H
+
+#include "cbor/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+* ============================================================================
+* String manipulation
+* ============================================================================
+*/
+
+/** Returns the length of the underlying string
+ *
+ * For definite strings only
+ *
+ * @param item[borrow] a definite string
+ * @return length of the string. Zero if no chunk has been attached yet
+ */
+size_t cbor_string_length(const cbor_item_t *item);
+
+/** The number of codepoints in this string
+ *
+ * Might differ from length if there are multibyte ones
+ *
+ * @param item[borrow] A string
+ * @return The number of codepoints in this string
+ */
+size_t cbor_string_codepoint_count(const cbor_item_t *item);
+
+/** Is the string definite?
+ *
+ * @param item[borrow] a string
+ * @return Is the string definite?
+ */
+bool cbor_string_is_definite(const cbor_item_t *item);
+
+/** Is the string indefinite?
+ *
+ * @param item[borrow] a string
+ * @return Is the string indefinite?
+ */
+bool cbor_string_is_indefinite(const cbor_item_t *item);
+
+/** Get the handle to the underlying string
+ *
+ * Definite items only. Modifying the data is allowed. In that case, the caller takes
+ * responsibility for the effect on items this item might be a part of
+ *
+ * @param item[borrow] A definite string
+ * @return The address of the underlying string. `NULL` if no data have been assigned yet.
+ */
+cbor_mutable_data cbor_string_handle(const cbor_item_t *item);
+
+/** Set the handle to the underlying string
+ *
+ *
+ * \rst
+ * .. warning:: Using a pointer to a stack allocated constant is a common mistake. Lifetime of the string will expire when it goes out of scope and the CBOR item will be left inconsistent.
+ * \endrst
+ *
+ * @param item[borrow] A definite string
+ * @param data The memory block. The caller gives up the ownership of the block. libcbor will deallocate it when appropriate using its free function
+ * @param length Length of the data block
+ */
+void cbor_string_set_handle(cbor_item_t *item, cbor_mutable_data CBOR_RESTRICT_POINTER data, size_t length);
+
+/** Get the handle to the array of chunks
+ *
+ * Manipulations with the memory block (e.g. sorting it) are allowed, but the validity and the number of chunks must be retained.
+ *
+ * @param item[borrow] A indefinite string
+ * @return array of #cbor_string_chunk_count definite strings
+ */
+cbor_item_t **cbor_string_chunks_handle(const cbor_item_t *item);
+
+/** Get the number of chunks this string consist of
+ *
+ * @param item[borrow] A indefinite string
+ * @return The chunk count. 0 for freshly created items.
+ */
+size_t cbor_string_chunk_count(const cbor_item_t *item);
+
+/** Appends a chunk to the string
+ *
+ * Indefinite strings only.
+ *
+ * May realloc the chunk storage.
+ *
+ * @param item[borrow] An indefinite string
+ * @param item[incref] A definite string
+ * @return true on success. false on realloc failure. In that case, the refcount of `chunk` is not increased and the `item` is left intact.
+ */
+bool cbor_string_add_chunk(cbor_item_t *item, cbor_item_t *chunk);
+
+/** Creates a new definite string
+ *
+ * The handle is initialized to `NULL` and length to 0
+ *
+ * @return **new** definite string. `NULL` on malloc failure.
+ */
+cbor_item_t *cbor_new_definite_string();
+
+/** Creates a new indefinite string
+ *
+ * The chunks array is initialized to `NULL` and chunkcount to 0
+ *
+ * @return **new** indefinite string. `NULL` on malloc failure.
+ */
+cbor_item_t *cbor_new_indefinite_string();
+
+/** Creates a new string and initializes it
+ *
+ * The `val` will be copied to a newly allocated block
+ *
+ * @param val A null-terminated UTF-8 string
+ * @return A **new** string with content `handle`. `NULL` on malloc failure.
+ */
+cbor_item_t *cbor_build_string(const char *val);
+
+/** Creates a new string and initializes it
+ *
+ * The `handle` will be copied to a newly allocated block
+ *
+ * @param val A UTF-8 string, at least \p length long (excluding the null byte)
+ * @return A **new** string with content `handle`. `NULL` on malloc failure.
+ */
+cbor_item_t *cbor_build_stringn(const char *val, size_t length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_STRINGS_H
diff --git a/lib/libcbor/src/cbor/tags.c b/lib/libcbor/src/cbor/tags.c
new file mode 100644
index 00000000000..09ec05610b0
--- /dev/null
+++ b/lib/libcbor/src/cbor/tags.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "tags.h"
+
+cbor_item_t *cbor_new_tag(uint64_t value)
+{
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
+ *item = (cbor_item_t) {
+ .refcount = 1,
+ .type = CBOR_TYPE_TAG,
+ .metadata = {.tag_metadata = {.value = value, .tagged_item = NULL}},
+ .data = NULL /* Never used */
+ };
+ return item;
+}
+
+cbor_item_t *cbor_tag_item(const cbor_item_t *item)
+{
+ assert(cbor_isa_tag(item));
+ return item->metadata.tag_metadata.tagged_item;
+}
+
+uint64_t cbor_tag_value(const cbor_item_t *item)
+{
+ assert(cbor_isa_tag(item));
+ return item->metadata.tag_metadata.value;
+}
+
+void cbor_tag_set_item(cbor_item_t *item, cbor_item_t *tagged_item)
+{
+ assert(cbor_isa_tag(item));
+ cbor_incref(tagged_item);
+ item->metadata.tag_metadata.tagged_item = tagged_item;
+}
+
+cbor_item_t * cbor_build_tag(uint64_t value, cbor_item_t * item) {
+ cbor_item_t *res = cbor_new_tag(value);
+ cbor_tag_set_item(res, item);
+ return res;
+}
diff --git a/lib/libcbor/src/cbor/tags.h b/lib/libcbor/src/cbor/tags.h
new file mode 100644
index 00000000000..f74cb636e3f
--- /dev/null
+++ b/lib/libcbor/src/cbor/tags.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LIBCBOR_TAGS_H
+#define LIBCBOR_TAGS_H
+
+#include "cbor/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+* ============================================================================
+* Tag manipulation
+* ============================================================================
+*/
+
+/** Create a new tag
+ *
+ * @param value The tag value. Please consult the tag repository
+ * @return **new** tag. Item reference is `NULL`.
+ */
+cbor_item_t *cbor_new_tag(uint64_t value);
+
+/** Get the tagged item
+ *
+ * @param item[borrow] A tag
+ * @return **incref** the tagged item
+ */
+cbor_item_t *cbor_tag_item(const cbor_item_t *item);
+
+/** Get tag value
+ *
+ * @param item[borrow] A tag
+ * @return The tag value. Please consult the tag repository
+ */
+uint64_t cbor_tag_value(const cbor_item_t *item);
+
+/** Set the tagged item
+ *
+ * @param item[borrow] A tag
+ * @param tagged_item[incref] The item to tag
+ */
+void cbor_tag_set_item(cbor_item_t *item, cbor_item_t *tagged_item);
+
+/** Build a new tag
+ *
+ * @param item[incref] The tagee
+ * @param value Tag value
+ * @return **new** tag item
+ */
+cbor_item_t * cbor_build_tag(uint64_t value, cbor_item_t * item);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIBCBOR_TAGS_H