summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrimio <vasi.vilvoiu@gmail.com>2018-03-04 22:57:17 +0200
committerrimio <vasi.vilvoiu@gmail.com>2018-03-04 22:57:17 +0200
commit00d1b9ef4ac0ab4b22b5630fcfb85d0fdd1d8566 (patch)
tree11f1ee42c3cf44f537495092486179b15a84e04b
parent7ff2ce45235c0ccc3af994e5f16a9d2bc9b0416c (diff)
Basic encoder
-rw-r--r--include/ecbor.h94
-rw-r--r--src/ecbor.c45
-rw-r--r--src/ecbor_decoder.c39
-rw-r--r--src/ecbor_encoder.c556
-rw-r--r--src/ecbor_internal.h49
5 files changed, 737 insertions, 46 deletions
diff --git a/include/ecbor.h b/include/ecbor.h
index 87f52d8..62ae4b5 100644
--- a/include/ecbor.h
+++ b/include/ecbor.h
@@ -31,6 +31,7 @@ typedef enum {
ECBOR_ERR_NULL_ITEM = 20,
ECBOR_ERR_WRONG_MODE = 30,
+ ECBOR_ERR_WONT_ENCODE_INDEFINITE = 31,
/* bounds errors */
ECBOR_ERR_INVALID_END_OF_BUFFER = 50,
@@ -82,12 +83,13 @@ typedef enum {
* We keep value 7 reserved so there is no confusion. */
/* Following types are translated from major type #7 */
- ECBOR_TYPE_FP16 = 8,
- ECBOR_TYPE_FP32 = 9,
- ECBOR_TYPE_FP64 = 10,
- ECBOR_TYPE_BOOL = 11,
- ECBOR_TYPE_NULL = 12,
- ECBOR_TYPE_UNDEFINED = 13,
+ ECBOR_TYPE_STOP_CODE = 8,
+ ECBOR_TYPE_FP16 = 9,
+ ECBOR_TYPE_FP32 = 10,
+ ECBOR_TYPE_FP64 = 11,
+ ECBOR_TYPE_BOOL = 12,
+ ECBOR_TYPE_NULL = 13,
+ ECBOR_TYPE_UNDEFINED = 14,
/* Last type, used for bounds checking */
ECBOR_TYPE_LAST = ECBOR_TYPE_UNDEFINED
@@ -100,7 +102,7 @@ typedef struct ecbor_item ecbor_item_t;
struct ecbor_item {
/* item type */
ecbor_type_t type;
-
+
/* value */
union {
uint64_t uinteger;
@@ -144,7 +146,8 @@ typedef enum {
ECBOR_MODE_DECODE = 0,
ECBOR_MODE_DECODE_STREAMED = 1,
ECBOR_MODE_DECODE_TREE = 2,
- ECBOR_MODE_ENCODE = 3
+ ECBOR_MODE_ENCODE = 3,
+ ECBOR_MODE_ENCODE_STREAMED = 4
} ecbor_mode_t;
/*
@@ -186,6 +189,16 @@ typedef struct {
* Initialization routines
*/
extern ecbor_error_t
+ecbor_initialize_encode (ecbor_encode_context_t *context,
+ uint8_t *buffer,
+ size_t buffer_size);
+
+extern ecbor_error_t
+ecbor_initialize_encode_streamed (ecbor_encode_context_t *context,
+ uint8_t *buffer,
+ size_t buffer_size);
+
+extern ecbor_error_t
ecbor_initialize_decode (ecbor_decode_context_t *context,
const uint8_t *buffer,
size_t buffer_size);
@@ -206,7 +219,8 @@ ecbor_initialize_decode_tree (ecbor_decode_context_t *context,
/*
* Encoding routines
*/
-
+extern ecbor_error_t
+ecbor_encode (ecbor_encode_context_t *context, ecbor_item_t *item);
/*
* Decoding routines
@@ -218,13 +232,67 @@ extern ecbor_error_t
ecbor_decode_tree (ecbor_decode_context_t *context, ecbor_item_t **root);
/*
- * Tree API
- */
-
-/*
* Strict API
*/
+/* Simple builders */
+extern ecbor_item_t
+ecbor_int (int64_t value);
+
+extern ecbor_item_t
+ecbor_uint (int64_t value);
+
+extern ecbor_item_t
+ecbor_bstr (uint8_t *bstr, size_t length);
+
+extern ecbor_item_t
+ecbor_str (char *str, size_t length);
+
+extern ecbor_item_t
+ecbor_tag (ecbor_item_t *child, uint64_t tag_value);
+
+extern ecbor_item_t
+ecbor_fp32 (float value);
+
+extern ecbor_item_t
+ecbor_fp64 (double value);
+
+extern ecbor_item_t
+ecbor_bool (uint8_t value);
+
+extern ecbor_item_t
+ecbor_null (void);
+
+extern ecbor_item_t
+ecbor_undefined (void);
+
+
+/* Streamed encoding simple builders */
+extern ecbor_item_t
+ecbor_array_token (size_t length);
+
+extern ecbor_item_t
+ecbor_indefinite_array_token (void);
+
+extern ecbor_item_t
+ecbor_map_token (size_t length);
+
+extern ecbor_item_t
+ecbor_indefinite_map_token (void);
+
+extern ecbor_item_t
+ecbor_stop_code (void);
+
+
+/* Array and map builders */
+extern ecbor_error_t
+ecbor_array (ecbor_item_t *array, ecbor_item_t *items, size_t length);
+
+extern ecbor_error_t
+ecbor_map (ecbor_item_t *map, ecbor_item_t *keys, ecbor_item_t *values,
+ size_t length);
+
+
/* Metadata */
extern ecbor_type_t
ecbor_get_type (ecbor_item_t *item);
diff --git a/src/ecbor.c b/src/ecbor.c
index 59583ba..30d2ac5 100644
--- a/src/ecbor.c
+++ b/src/ecbor.c
@@ -90,6 +90,36 @@ ecbor_fp64_from_big_endian (double value)
#endif
}
+uint16_t
+ecbor_uint16_to_big_endian (uint16_t value)
+{
+ return ecbor_uint16_from_big_endian (value);
+}
+
+uint32_t
+ecbor_uint32_to_big_endian (uint32_t value)
+{
+ return ecbor_uint32_from_big_endian (value);
+}
+
+uint64_t
+ecbor_uint64_to_big_endian (uint64_t value)
+{
+ return ecbor_uint64_from_big_endian (value);
+}
+
+float
+ecbor_fp32_to_big_endian (float value)
+{
+ return ecbor_fp32_from_big_endian (value);
+}
+
+double
+ecbor_fp64_to_big_endian (double value)
+{
+ return ecbor_fp64_from_big_endian (value);
+}
+
ecbor_type_t
ecbor_get_type (ecbor_item_t *item)
{
@@ -552,4 +582,19 @@ ecbor_get_bool (ecbor_item_t *item, uint8_t *value)
(*value) = (uint8_t) item->value.uinteger;
return ECBOR_OK;
+}
+
+void
+ecbor_memcpy (void *dest, void *src, size_t num)
+{
+ /* TODO: Replace with memcpy when platform supports */
+ /* TODO: Optimize */
+ while (num > 4) {
+ *((uint32_t *) dest) = *((uint32_t *) src);
+ num -= 4;
+ }
+ while (num) {
+ *((uint8_t *) dest) = *((uint8_t *) src);
+ num --;
+ }
} \ No newline at end of file
diff --git a/src/ecbor_decoder.c b/src/ecbor_decoder.c
index 35f80a2..a422dd9 100644
--- a/src/ecbor_decoder.c
+++ b/src/ecbor_decoder.c
@@ -8,31 +8,12 @@
#include "ecbor.h"
#include "ecbor_internal.h"
-static ecbor_item_t null_item = {
- .type = ECBOR_TYPE_NONE,
- .value = {
- .tag = {
- .tag_value = 0,
- .child = NULL
- }
- },
- .size = 0,
- .length = 0,
- .is_indefinite = 0,
- .parent = NULL,
- .child = NULL,
- .next = NULL,
- .index = 0
-};
-
static ecbor_error_t
ecbor_initialize_decode_internal (ecbor_decode_context_t *context,
const uint8_t *buffer,
size_t buffer_size)
{
- if (!context) {
- return ECBOR_ERR_NULL_CONTEXT;
- }
+ ECBOR_INTERNAL_CHECK_CONTEXT_PTR (context);
if (!buffer) {
return ECBOR_ERR_NULL_INPUT_BUFFER;
}
@@ -522,6 +503,7 @@ ecbor_decode_next_internal (ecbor_decode_context_t *context,
if (additional == ECBOR_ADDITIONAL_INDEFINITE) {
/* stop code */
item->size = 1;
+ item->type = ECBOR_TYPE_STOP_CODE;
return ECBOR_END_OF_INDEFINITE;
} else if (additional <= ECBOR_ADDITIONAL_1BYTE) {
ecbor_error_t rc;
@@ -564,12 +546,8 @@ ecbor_decode_next_internal (ecbor_decode_context_t *context,
ecbor_error_t
ecbor_decode (ecbor_decode_context_t *context, ecbor_item_t *item)
{
- if (!context) {
- return ECBOR_ERR_NULL_CONTEXT;
- }
- if (!item) {
- return ECBOR_ERR_NULL_ITEM;
- }
+ ECBOR_INTERNAL_CHECK_CONTEXT_PTR (context);
+ ECBOR_INTERNAL_CHECK_ITEM_PTR (item);
if (context->mode != ECBOR_MODE_DECODE
&& context->mode != ECBOR_MODE_DECODE_STREAMED) {
@@ -597,12 +575,9 @@ ecbor_decode_tree (ecbor_decode_context_t *context, ecbor_item_t **root)
ecbor_error_t rc = ECBOR_OK;
ecbor_item_t *curr_node = NULL, *new_node = NULL;
- if (!context) {
- return ECBOR_ERR_NULL_CONTEXT;
- }
- if (!root) {
- return ECBOR_ERR_NULL_ITEM;
- }
+ ECBOR_INTERNAL_CHECK_CONTEXT_PTR (context);
+ ECBOR_INTERNAL_CHECK_ITEM_PTR (root);
+
if (context->mode != ECBOR_MODE_DECODE_TREE) {
return ECBOR_ERR_WRONG_MODE;
}
diff --git a/src/ecbor_encoder.c b/src/ecbor_encoder.c
index cd9159a..b144644 100644
--- a/src/ecbor_encoder.c
+++ b/src/ecbor_encoder.c
@@ -5,4 +5,558 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
-#include "ecbor.h" \ No newline at end of file
+#include "ecbor.h"
+#include "ecbor_internal.h"
+
+ecbor_error_t
+ecbor_initialize_encode (ecbor_encode_context_t *context,
+ uint8_t *buffer,
+ size_t buffer_size)
+{
+ ECBOR_INTERNAL_CHECK_CONTEXT_PTR (context);
+ if (!buffer) {
+ return ECBOR_ERR_NULL_OUTPUT_BUFFER;
+ }
+
+ context->out_position = buffer;
+ context->bytes_left = buffer_size;
+ context->mode = ECBOR_MODE_ENCODE;
+
+ return ECBOR_OK;
+}
+
+ecbor_error_t
+ecbor_initialize_encode_streamed (ecbor_encode_context_t *context,
+ uint8_t *buffer,
+ size_t buffer_size)
+{
+ ECBOR_INTERNAL_CHECK_CONTEXT_PTR (context);
+ if (!buffer) {
+ return ECBOR_ERR_NULL_OUTPUT_BUFFER;
+ }
+
+ context->out_position = buffer;
+ context->bytes_left = buffer_size;
+ context->mode = ECBOR_MODE_ENCODE_STREAMED;
+
+ return ECBOR_OK;
+}
+
+static ecbor_error_t
+ecbor_encode_uint (ecbor_encode_context_t *context, uint8_t major_type,
+ uint64_t value)
+{
+ uint8_t size = 0;
+
+ /* compute storage size */
+ if (value <= ECBOR_ADDITIONAL_LAST_INTEGER) {
+ size = 1;
+ } else if (value <= 0xFF) {
+ size = 2;
+ } else if (value <= 0xFFFF) {
+ size = 3;
+ } else if (value <= 0xFFFFFFFF) {
+ size = 5;
+ } else {
+ size = 9;
+ }
+
+ /* check buffer */
+ if (context->bytes_left < size) {
+ return ECBOR_ERR_INVALID_END_OF_BUFFER;
+ }
+
+ /* write value */
+ if (value <= ECBOR_ADDITIONAL_LAST_INTEGER) {
+ /* value coded in header */
+ (*context->out_position) = ((major_type & 0x7) << 5) | (value & 0x1f);
+ context->out_position ++;
+ context->bytes_left --;
+ } else if (value <= 0xFF) {
+ /* 1 extra byte */
+ (*context->out_position) =
+ ((major_type & 0x7) << 5) | ECBOR_ADDITIONAL_1BYTE;
+ context->out_position ++;
+ (*context->out_position) = (uint8_t) value;
+ context->out_position ++;
+ context->bytes_left -= 2;
+ } else if (value <= 0xFFFF) {
+ /* 2 extra bytes */
+ (*context->out_position) =
+ ((major_type & 0x7) << 5) | ECBOR_ADDITIONAL_2BYTE;
+ context->out_position ++;
+ (*((uint16_t *)context->out_position)) =
+ ecbor_uint16_to_big_endian ((uint16_t) value);
+ context->out_position += 2;
+ context->bytes_left -= 3;
+ } else if (value <= 0xFFFFFFFF) {
+ /* 4 extra bytes */
+ (*context->out_position) =
+ ((major_type & 0x7) << 5) | ECBOR_ADDITIONAL_4BYTE;
+ context->out_position ++;
+ (*((uint32_t *)context->out_position)) =
+ ecbor_uint32_to_big_endian ((uint32_t) value);
+ context->out_position += 4;
+ context->bytes_left -= 5;
+ } else {
+ /* 8 extra bytes */
+ (*context->out_position) =
+ ((major_type & 0x7) << 5) | ECBOR_ADDITIONAL_8BYTE;
+ context->out_position ++;
+ (*((uint64_t *)context->out_position)) =
+ ecbor_uint64_to_big_endian ((uint64_t) value);
+ context->out_position += 8;
+ context->bytes_left -= 9;
+ }
+
+ return ECBOR_OK;
+}
+
+static ecbor_error_t
+ecbor_encode_header (ecbor_encode_context_t *context, uint8_t major_type,
+ uint8_t additional)
+{
+ if (context->bytes_left < 1) {
+ return ECBOR_ERR_INVALID_END_OF_BUFFER;
+ }
+
+ (*context->out_position) =
+ ((((uint8_t)major_type) & 0x7) << 5) | (additional & 0x1f);
+ context->out_position ++;
+ context->bytes_left --;
+
+ return ECBOR_OK;
+}
+
+ecbor_error_t
+ecbor_encode (ecbor_encode_context_t *context, ecbor_item_t *item)
+{
+ ecbor_error_t rc;
+
+ ECBOR_INTERNAL_CHECK_CONTEXT_PTR (context);
+ ECBOR_INTERNAL_CHECK_ITEM_PTR (item);
+
+ if (context->bytes_left == 0) {
+ return ECBOR_ERR_INVALID_END_OF_BUFFER;
+ }
+ if (context->mode != ECBOR_MODE_ENCODE
+ && context->mode != ECBOR_MODE_ENCODE_STREAMED) {
+ /* only allow known modes of operation; junk in <mode> will generate
+ undefined behaviour */
+ return ECBOR_ERR_WRONG_MODE;
+ }
+
+ switch (item->type) {
+ case ECBOR_TYPE_UINT:
+ rc = ecbor_encode_uint (context, ECBOR_TYPE_UINT, item->value.uinteger);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+ break;
+
+ case ECBOR_TYPE_NINT:
+ {
+ uint64_t value = (-1) - item->value.integer;
+ rc = ecbor_encode_uint (context, ECBOR_TYPE_NINT, value);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+ }
+ break;
+
+ case ECBOR_TYPE_BSTR:
+ case ECBOR_TYPE_STR:
+ if (item->is_indefinite) {
+ if (context->mode == ECBOR_MODE_ENCODE) {
+ /* we do not support indefinite strings in non-stream mode */
+ return ECBOR_ERR_WONT_ENCODE_INDEFINITE;
+ }
+
+ /* write just header */
+ rc = ecbor_encode_header (context, item->type,
+ ECBOR_ADDITIONAL_INDEFINITE);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+ } else {
+ /* write header */
+ rc = ecbor_encode_uint (context, item->type, item->length);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ if (context->mode == ECBOR_MODE_ENCODE && item->length > 0) {
+ /* write string */
+ if (!item->value.string.str) {
+ return ECBOR_ERR_NULL_VALUE;
+ }
+ if (context->bytes_left < item->length) {
+ return ECBOR_ERR_INVALID_END_OF_BUFFER;
+ }
+
+ ecbor_memcpy ((void *) context->out_position,
+ (void *) item->value.string.str,
+ item->length);
+ context->out_position += item->length;
+ context->bytes_left -= item->length;
+ }
+ }
+ break;
+
+ case ECBOR_TYPE_ARRAY:
+ case ECBOR_TYPE_MAP:
+ if (item->is_indefinite) {
+ if (context->mode == ECBOR_MODE_ENCODE) {
+ /* we do not support indefinite maps and arrays in non-stream mode */
+ return ECBOR_ERR_WONT_ENCODE_INDEFINITE;
+ }
+
+ /* write just header */
+ rc = ecbor_encode_header (context, item->type,
+ ECBOR_ADDITIONAL_INDEFINITE);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+ } else {
+ size_t written_len;
+
+ if (item->type == ECBOR_TYPE_MAP) {
+ if (item->length % 2) {
+ return ECBOR_ERR_INVALID_KEY_VALUE_PAIR;
+ }
+ written_len = item->length / 2;
+ } else {
+ written_len = item->length;
+ }
+
+ /* write header */
+ rc = ecbor_encode_uint (context, item->type, written_len);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ if (context->mode == ECBOR_MODE_ENCODE && item->length > 0) {
+ size_t remaining = item->length;
+ ecbor_item_t *current = item->child;
+
+ while (remaining) {
+ /* write item */
+ if (!current) {
+ return ECBOR_ERR_NULL_ITEM;
+ }
+
+ rc = ecbor_encode (context, current);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ current = current->next;
+ }
+ }
+ }
+ break;
+
+ case ECBOR_TYPE_TAG:
+ /* write header */
+ rc = ecbor_encode_uint (context, item->type, item->value.tag.tag_value);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ if (context->mode == ECBOR_MODE_ENCODE) {
+ /* write tagged item */
+ ECBOR_INTERNAL_CHECK_ITEM_PTR (item->child);
+
+ rc = ecbor_encode (context, item->child);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+ }
+ break;
+
+ case ECBOR_TYPE_STOP_CODE:
+ rc = ecbor_encode_header (context, ECBOR_TYPE_SPECIAL,
+ ECBOR_ADDITIONAL_INDEFINITE);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+ break;
+
+ case ECBOR_TYPE_FP32:
+ {
+ float value_bigend =
+ ecbor_fp32_to_big_endian (item->value.fp32);
+
+ /* write header */
+ rc = ecbor_encode_header (context, ECBOR_TYPE_SPECIAL,
+ ECBOR_ADDITIONAL_4BYTE);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ /* write value */
+ if (context->bytes_left < sizeof (float)) {
+ return ECBOR_ERR_INVALID_END_OF_BUFFER;
+ }
+ (*((float *)context->out_position)) = value_bigend;
+ context->out_position += sizeof (float);
+ context->bytes_left -= sizeof (float);
+ }
+ break;
+
+ case ECBOR_TYPE_FP64:
+ {
+ double value_bigend =
+ ecbor_fp64_to_big_endian (item->value.fp64);
+
+ /* write header */
+ rc = ecbor_encode_header (context, ECBOR_TYPE_SPECIAL,
+ ECBOR_ADDITIONAL_4BYTE);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ /* write value */
+ if (context->bytes_left < sizeof (double)) {
+ return ECBOR_ERR_INVALID_END_OF_BUFFER;
+ }
+ (*((double *)context->out_position)) = value_bigend;
+ context->out_position += sizeof (double);
+ context->bytes_left -= sizeof (double);
+ }
+ break;
+
+ case ECBOR_TYPE_BOOL:
+ rc = ecbor_encode_header (context, ECBOR_TYPE_SPECIAL,
+ (item->value.integer ? ECBOR_SIMPLE_TRUE
+ : ECBOR_SIMPLE_FALSE));
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+ break;
+
+ case ECBOR_TYPE_NULL:
+ rc = ecbor_encode_header (context, ECBOR_TYPE_SPECIAL,
+ ECBOR_SIMPLE_NULL);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+ break;
+
+ case ECBOR_TYPE_UNDEFINED:
+ rc = ecbor_encode_header (context, ECBOR_TYPE_SPECIAL,
+ ECBOR_SIMPLE_UNDEFINED);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+ break;
+
+ default:
+ return ECBOR_ERR_INVALID_TYPE;
+ }
+
+ return ECBOR_OK;
+}
+
+ecbor_item_t
+ecbor_int (int64_t value)
+{
+ ecbor_item_t r = null_item;
+ if (value >= 0) {
+ r.type = ECBOR_TYPE_UINT;
+ r.value.uinteger = (uint64_t) value;
+ } else {
+ r.type = ECBOR_TYPE_NINT;
+ r.value.integer = value;
+ }
+ return r;
+}
+
+ecbor_item_t
+ecbor_uint (int64_t value)
+{
+ ecbor_item_t r = null_item;
+ r.type = ECBOR_TYPE_UINT;
+ r.value.uinteger = (uint64_t) value;
+ return r;
+}
+
+ecbor_item_t
+ecbor_bstr (uint8_t *bstr, size_t length)
+{
+ ecbor_item_t r = null_item;
+ r.type = ECBOR_TYPE_BSTR;
+ r.value.string.str = bstr;
+ r.length = length;
+ return r;
+}
+
+ecbor_item_t
+ecbor_str (char *str, size_t length)
+{
+ ecbor_item_t r = null_item;
+ r.type = ECBOR_TYPE_STR;
+ r.value.string.str = (uint8_t *)str;
+ r.length = length;
+ return r;
+}
+
+ecbor_item_t
+ecbor_tag (ecbor_item_t *child, uint64_t tag_value)
+{
+ ecbor_item_t r = null_item;
+ r.type = ECBOR_TYPE_TAG;
+ r.child = child;
+ r.value.tag.tag_value = tag_value;
+ return r;
+}
+
+ecbor_item_t
+ecbor_fp32 (float value)
+{
+ ecbor_item_t r = null_item;
+ r.type = ECBOR_TYPE_FP32;
+ r.value.fp32 = value;
+ return r;
+}
+
+ecbor_item_t
+ecbor_fp64 (double value)
+{
+ ecbor_item_t r = null_item;
+ r.type = ECBOR_TYPE_FP64;
+ r.value.fp64 = value;
+ return r;
+}
+
+ecbor_item_t
+ecbor_bool (uint8_t value)
+{
+ ecbor_item_t r = null_item;
+ r.type = ECBOR_TYPE_BOOL;
+ r.value.integer = value;
+ return r;
+}
+
+ecbor_item_t
+ecbor_null (void)
+{
+ ecbor_item_t r = null_item;
+ r.type = ECBOR_TYPE_NULL;
+ return r;
+}
+
+ecbor_item_t
+ecbor_undefined (void)
+{
+ ecbor_item_t r = null_item;
+ r.type = ECBOR_TYPE_UNDEFINED;
+ return r;
+}
+
+ecbor_item_t
+ecbor_array_token (size_t length)
+{
+ ecbor_item_t r = null_item;
+ r.type = ECBOR_TYPE_ARRAY;
+ r.length = length;
+ return r;
+}
+
+ecbor_item_t
+ecbor_indefinite_array_token (void)
+{
+ ecbor_item_t r = null_item;
+ r.type = ECBOR_TYPE_ARRAY;
+ r.is_indefinite = true;
+ return r;
+}
+
+ecbor_item_t
+ecbor_map_token (size_t length)
+{
+ ecbor_item_t r = null_item;
+ r.type = ECBOR_TYPE_MAP;
+ r.length = length;
+ return r;
+}
+
+ecbor_item_t
+ecbor_indefinite_map_token (void)
+{
+ ecbor_item_t r = null_item;
+ r.type = ECBOR_TYPE_MAP;
+ r.is_indefinite = true;
+ return r;
+}
+
+ecbor_item_t
+ecbor_stop_code (void)
+{
+ ecbor_item_t r = null_item;
+ r.type = ECBOR_TYPE_STOP_CODE;
+ return r;
+}
+
+
+/* Array and map builders */
+ecbor_error_t
+ecbor_array (ecbor_item_t *array, ecbor_item_t *items, size_t length)
+{
+ size_t i;
+
+ if (!array) {
+ return ECBOR_ERR_NULL_ARRAY;
+ }
+
+ array->type = ECBOR_TYPE_ARRAY;
+ array->length = length;
+ array->child = items;
+
+ if (length > 0) {
+ ECBOR_INTERNAL_CHECK_ITEM_PTR (items);
+ items->parent = array;
+
+ for (i = 1; i < length; i ++) {
+ items->next = (items + 1);
+ items ++;
+ }
+ }
+
+ return ECBOR_OK;
+}
+
+ecbor_error_t
+ecbor_map (ecbor_item_t *map, ecbor_item_t *keys, ecbor_item_t *values,
+ size_t length)
+{
+ size_t i;
+
+ if (!map) {
+ return ECBOR_ERR_NULL_MAP;
+ }
+
+ map->type = ECBOR_TYPE_MAP;
+ map->length = length;
+
+ if (length > 0) {
+ ECBOR_INTERNAL_CHECK_ITEM_PTR (keys);
+ ECBOR_INTERNAL_CHECK_ITEM_PTR (values);
+
+ map->child = keys;
+ keys->parent = map;
+ keys->next = values;
+ values->parent = map;
+ keys ++;
+ values ++;
+
+ for (i = 1; i < length; i ++) {
+ values->next = (keys + 1);
+ keys ++;
+ keys->next = (values + 1);
+ values ++;
+ }
+ }
+
+ return ECBOR_OK;
+} \ No newline at end of file
diff --git a/src/ecbor_internal.h b/src/ecbor_internal.h
index 8013fcb..9612c1a 100644
--- a/src/ecbor_internal.h
+++ b/src/ecbor_internal.h
@@ -22,6 +22,8 @@ enum {
/* Additional value meanings */
enum {
+ ECBOR_ADDITIONAL_LAST_INTEGER = 23,
+
ECBOR_ADDITIONAL_1BYTE = 24,
ECBOR_ADDITIONAL_2BYTE = 25,
ECBOR_ADDITIONAL_4BYTE = 26,
@@ -38,8 +40,32 @@ enum {
ECBOR_SIMPLE_UNDEFINED = 23
};
+/* Static item, for various initializations */
+static ecbor_item_t null_item = {
+ .type = ECBOR_TYPE_NONE,
+ .value = {
+ .tag = {
+ .tag_value = 0,
+ .child = NULL
+ }
+ },
+ .size = 0,
+ .length = 0,
+ .is_indefinite = 0,
+ .parent = NULL,
+ .child = NULL,
+ .next = NULL,
+ .index = 0
+};
+
/* Internal checks. Most of these macros rely on the function returning an
error code, and a 'rc' value being declared locally */
+#define ECBOR_INTERNAL_CHECK_CONTEXT_PTR(c) \
+ { \
+ if (!(c)) { \
+ return ECBOR_ERR_NULL_CONTEXT; \
+ } \
+ }
#define ECBOR_INTERNAL_CHECK_ITEM_PTR(i) \
{ \
if (!(i)) { \
@@ -86,4 +112,27 @@ ecbor_fp32_from_big_endian (float value);
extern double
ecbor_fp64_from_big_endian (double value);
+
+extern uint16_t
+ecbor_uint16_to_big_endian (uint16_t value);
+
+extern uint32_t
+ecbor_uint32_to_big_endian (uint32_t value);
+
+extern uint64_t
+ecbor_uint64_to_big_endian (uint64_t value);
+
+extern float
+ecbor_fp32_to_big_endian (float value);
+
+extern double
+ecbor_fp64_to_big_endian (double value);
+
+
+/*
+ * Memory
+ */
+extern void
+ecbor_memcpy (void *dest, void *src, size_t num);
+
#endif \ No newline at end of file