diff options
Diffstat (limited to 'components/common/cbor_dump/cbor_dump.c')
-rw-r--r-- | components/common/cbor_dump/cbor_dump.c | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/components/common/cbor_dump/cbor_dump.c b/components/common/cbor_dump/cbor_dump.c new file mode 100644 index 000000000..e711d2157 --- /dev/null +++ b/components/common/cbor_dump/cbor_dump.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stddef.h> +#include <string.h> +#include <qcbor/qcbor_decode.h> +#include "cbor_dump.h" + +/* Dump context structure */ +struct dump_context +{ + FILE *outfile; + unsigned int initial_indent; + const char *root_label; + const struct cbor_dictionary_entry *dictionary; + unsigned int dictionary_len; +}; + +static int dump_next_item(QCBORDecodeContext *decode_ctx, struct dump_context *dump_ctx); +static void dump_indent(struct dump_context *dump_ctx, const QCBORItem *item); +static void dump_label(struct dump_context *dump_ctx, const QCBORItem *item); +static void dump_value_separator(struct dump_context *dump_ctx, const QCBORItem *item); +static void dump_value(struct dump_context *dump_ctx, const QCBORItem *item); +static void dump_text_string(struct dump_context *dump_ctx, const uint8_t *data, size_t len); +static void dump_byte_string(struct dump_context *dump_ctx, const uint8_t *data, size_t len); +static const char *dictionary_lookup(struct dump_context *dump_ctx, int64_t id); + +int cbor_dump(FILE *file, + const uint8_t *cbor, size_t cbor_len, + unsigned int indent, const char *root_label, + const struct cbor_dictionary_entry *dictionary, unsigned int dictionary_len) +{ + int status = -1; + UsefulBufC cbor_buf; + UsefulBuf mem_pool; + uint8_t mem_pool_space[cbor_len + QCBOR_DECODE_MIN_MEM_POOL_SIZE]; + + cbor_buf.ptr = cbor; + cbor_buf.len = cbor_len; + + mem_pool.ptr = mem_pool_space; + mem_pool.len = sizeof(mem_pool_space); + + QCBORDecodeContext decode_ctx; + + QCBORDecode_Init(&decode_ctx, cbor_buf, QCBOR_DECODE_MODE_NORMAL); + status = QCBORDecode_SetMemPool(&decode_ctx, mem_pool, true); + + if (status == QCBOR_SUCCESS) { + + struct dump_context dump_ctx; + + dump_ctx.outfile = file; + dump_ctx.initial_indent = indent; + dump_ctx.root_label = root_label; + dump_ctx.dictionary = dictionary; + dump_ctx.dictionary_len = dictionary_len; + + while ((status = dump_next_item(&decode_ctx, &dump_ctx)) == QCBOR_SUCCESS); + + // Hitting the end of data is not an error. + if (status == QCBOR_ERR_NO_MORE_ITEMS) + status=QCBOR_SUCCESS; + } + + return status; +} + +static int dump_next_item(QCBORDecodeContext *decode_ctx, struct dump_context *dump_ctx) +{ + int status = -1; + QCBORItem item; + + status = QCBORDecode_GetNext(decode_ctx, &item); + + if (status == QCBOR_SUCCESS) { + + dump_indent(dump_ctx, &item); + dump_label(dump_ctx, &item); + dump_value_separator(dump_ctx, &item); + dump_value(dump_ctx, &item); + } + + return status; +} + +static void dump_indent(struct dump_context *dump_ctx, const QCBORItem *item) +{ + unsigned int num_tabs = dump_ctx->initial_indent + item->uNestingLevel; + + for (unsigned int i = 0; i < num_tabs; ++i) { + + fprintf(dump_ctx->outfile, " "); + } +} + +static void dump_label(struct dump_context *dump_ctx, const QCBORItem *item) +{ + switch (item->uLabelType) + { + case QCBOR_TYPE_INT64: + case QCBOR_TYPE_UINT64: + { + const char *label_string = dictionary_lookup(dump_ctx, item->label.int64); + if (label_string) + fprintf(dump_ctx->outfile, "%s:", label_string); + else + fprintf(dump_ctx->outfile, "%ld:", item->label.int64); + break; + } + case QCBOR_TYPE_TEXT_STRING: + fprintf(dump_ctx->outfile, "%s:", (const char*)item->label.string.ptr); + break; + case QCBOR_TYPE_NONE: + if (item->uNestingLevel == 0 && dump_ctx->root_label) { + fprintf(dump_ctx->outfile, "%s:", dump_ctx->root_label); + } + break; + default: + break; + } +} + +static void dump_value_separator(struct dump_context *dump_ctx, const QCBORItem *item) +{ + if ((item->uDataType == QCBOR_TYPE_ARRAY) || + (item->uDataType == QCBOR_TYPE_MAP)) { + + fprintf(dump_ctx->outfile, "\n"); + } + else { + + fprintf(dump_ctx->outfile, "\t"); + } + +} + +static void dump_value(struct dump_context *dump_ctx, const QCBORItem *item) +{ + if (item->uDataType == QCBOR_TYPE_TEXT_STRING) { + + dump_text_string(dump_ctx, (const char*)item->val.string.ptr, item->val.string.len); + fprintf(dump_ctx->outfile, "\n"); + } + else if (item->uDataType == QCBOR_TYPE_BYTE_STRING) { + + dump_byte_string(dump_ctx, (const char*)item->val.string.ptr, item->val.string.len); + fprintf(dump_ctx->outfile, "\n"); + } + else if (item->uDataType == QCBOR_TYPE_INT64) { + + fprintf(dump_ctx->outfile, "%ld\n", item->val.int64); + } + else if (item->uDataType == QCBOR_TYPE_UINT64) { + + fprintf(dump_ctx->outfile, "%lu\n", item->val.uint64); + } + else if ((item->uDataType != QCBOR_TYPE_NONE) && + (item->uDataType != QCBOR_TYPE_ARRAY) && + (item->uDataType != QCBOR_TYPE_MAP)) + { + + fprintf(dump_ctx->outfile, "value %d", item->uDataType); + } +} + +static void dump_text_string(struct dump_context *dump_ctx, const uint8_t *data, size_t len) +{ + char text_buf[len + 1]; + + memcpy(text_buf, data, len); + text_buf[len] = '\0'; + + fprintf(dump_ctx->outfile, "%s", text_buf); +} + +static void dump_byte_string(struct dump_context *dump_ctx, const uint8_t *data, size_t len) +{ + for (size_t i = 0; i < len; ++i) { + + fprintf(dump_ctx->outfile, "%02x ", data[i]); + } +} + +static const char *dictionary_lookup(struct dump_context *dump_ctx, int64_t id) +{ + const char *match = NULL; + + if (dump_ctx->dictionary) { + + for (size_t i = 0; i < dump_ctx->dictionary_len; ++i) { + + if (dump_ctx->dictionary[i].id == id) { + + match = dump_ctx->dictionary[i].string; + break; + } + } + } + + return match; +} |