summaryrefslogtreecommitdiff
path: root/src/ecbor-describe/ecbor_describe.c
diff options
context:
space:
mode:
authorrimio <vasi.vilvoiu@gmail.com>2018-03-05 23:32:48 +0200
committerrimio <vasi.vilvoiu@gmail.com>2018-03-05 23:32:48 +0200
commite3f3c0d12eb83af50f984332a8ddae6f27197b12 (patch)
treea352968cbdd340f19ade64ebd0d78ca49e88aae7 /src/ecbor-describe/ecbor_describe.c
parentf8b56be188fa5ea9706f91ec7ca513740850af02 (diff)
Change dir structure to accomodate multiple tools
Diffstat (limited to 'src/ecbor-describe/ecbor_describe.c')
-rw-r--r--src/ecbor-describe/ecbor_describe.c483
1 files changed, 483 insertions, 0 deletions
diff --git a/src/ecbor-describe/ecbor_describe.c b/src/ecbor-describe/ecbor_describe.c
new file mode 100644
index 0000000..52b2eed
--- /dev/null
+++ b/src/ecbor-describe/ecbor_describe.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2018 Vasile Vilvoiu <vasi.vilvoiu@gmail.com>
+ *
+ * libecbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include <malloc.h>
+#include <ecbor.h>
+
+/*
+ * Command line arguments
+ */
+static struct option long_options[] = {
+ { "tree", no_argument, 0, 't' },
+ { "help", no_argument, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+/*
+ * Item buffer for tree mode
+ */
+#define MAX_ITEMS 1024
+static ecbor_item_t items_buffer[MAX_ITEMS];
+
+void
+print_help (void);
+void
+print_ecbor_error (ecbor_error_t err);
+ecbor_error_t
+print_ecbor_item (ecbor_item_t *item, unsigned int level, char *prefix);
+
+/*
+ * Print help
+ */
+void
+print_help (void)
+{
+ printf ("Usage: ecbor-describe [options] <filename>\n");
+ printf (" options:\n");
+ printf (" -t, --tree Use tree decoding mode\n");
+ printf (" -h, --help Display this help message\n");
+}
+
+void
+print_ecbor_error (ecbor_error_t err)
+{
+ printf ("ECBOR error %d\n", err);
+}
+
+ecbor_error_t
+print_ecbor_item (ecbor_item_t *item, unsigned int level, char *prefix)
+{
+ static const unsigned int max_str_print_len = 64;
+ static const char *msg_too_large = "<too_large>";
+ ecbor_type_t mt;
+ ecbor_error_t rc;
+ unsigned int i;
+
+ for(i = 0; i < level * 2; i ++) putchar(' ');
+ printf (prefix);
+
+ mt = ecbor_get_type (item);
+ switch (mt) {
+ case ECBOR_TYPE_NINT:
+ {
+ int64_t val;
+
+ rc = ecbor_get_int64 (item, &val);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ printf ("[NINT] value %lld\n", (long long int)val);
+ }
+ break;
+
+ case ECBOR_TYPE_UINT:
+ {
+ uint64_t val;
+
+ rc = ecbor_get_uint64 (item, &val);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ printf ("[UINT] value %llu\n", (unsigned long long int) val);
+ }
+ break;
+
+ case ECBOR_TYPE_STR:
+ {
+ size_t len;
+
+ rc = ecbor_get_length (item, &len);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ if (ECBOR_IS_INDEFINITE (item)) {
+ size_t nchunks;
+
+ rc = ecbor_get_str_chunk_count (item, &nchunks);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ printf ("[STR] len %u (indefinite)\n", (unsigned int) len);
+ for (i = 0; i < nchunks; i ++) {
+ ecbor_item_t chunk;
+
+ rc = ecbor_get_str_chunk (item, i, &chunk);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ rc = print_ecbor_item (&chunk, level + 1, "");
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+ }
+ } else {
+ char *val;
+
+ rc = ecbor_get_str (item, &val);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ printf ("[STR] len %u value '%.*s'\n", (unsigned int) len,
+ (int)(len <= max_str_print_len ? len : strlen(msg_too_large)),
+ (len <= max_str_print_len ? val : msg_too_large));
+ }
+ }
+ break;
+
+ case ECBOR_TYPE_BSTR:
+ {
+ size_t len;
+
+ rc = ecbor_get_length (item, &len);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ if (ECBOR_IS_INDEFINITE (item)) {
+ size_t nchunks;
+
+ rc = ecbor_get_bstr_chunk_count (item, &nchunks);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ printf ("[BSTR] len %u (indefinite)\n", (unsigned int) len);
+ for (i = 0; i < nchunks; i ++) {
+ ecbor_item_t chunk;
+
+ rc = ecbor_get_bstr_chunk (item, i, &chunk);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ rc = print_ecbor_item (&chunk, level + 1, "");
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+ }
+ } else {
+ uint8_t *val;
+
+ rc = ecbor_get_bstr (item, &val);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ printf ("[BSTR] len %u value ", (unsigned int) len);
+ if (len > max_str_print_len) {
+ printf ("'%s'\n", msg_too_large);
+ } else {
+ printf ("'");
+ for (i = 0; i < len; i ++) {
+ printf("%02x", val[i]);
+ }
+ printf ("'\n");
+ }
+ }
+ }
+ break;
+
+ case ECBOR_TYPE_ARRAY:
+ {
+ size_t len, i;
+
+ rc = ecbor_get_length (item, &len);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ printf ("[ARRAY] len %u %s\n", (unsigned int) len,
+ (ECBOR_IS_INDEFINITE (item) ? "(indefinite)" : ""));
+ for (i = 0; i < len; i ++) {
+ ecbor_item_t child;
+
+ rc = ecbor_get_array_item (item, i, &child);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ rc = print_ecbor_item (&child, level+1, "");
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+ }
+ }
+ break;
+
+ case ECBOR_TYPE_MAP:
+ {
+ size_t len, i;
+ char kv_msg[100] = { 0 };
+
+ rc = ecbor_get_length (item, &len);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ printf ("[MAP] len %u %s\n", (unsigned int) len,
+ (ECBOR_IS_INDEFINITE (item) ? "(indefinite)" : ""));
+ for (i = 0; i < len; i ++) {
+ ecbor_item_t k, v;
+
+ rc = ecbor_get_map_item (item, i, &k, &v);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ sprintf (kv_msg, "key[%u]: ", (unsigned int) i);
+ rc = print_ecbor_item (&k, level+2, kv_msg);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ sprintf (kv_msg, "val[%u]: ", (unsigned int) i);
+ rc = print_ecbor_item (&v, level+2, kv_msg);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+ }
+ }
+ break;
+
+ case ECBOR_TYPE_TAG:
+ {
+ uint64_t val;
+ ecbor_item_t child;
+
+ rc = ecbor_get_tag_value (item, &val);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ printf ("[TAG] value %lld\n", (long long int)val);
+
+ rc = ecbor_get_tag_item (item, &child);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ rc = print_ecbor_item (&child, level+1, "");
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+ }
+ break;
+
+ case ECBOR_TYPE_FP32:
+ {
+ float val;
+
+ rc = ecbor_get_fp32 (item, &val);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ printf ("[FP32] value %f\n", val);
+ }
+ break;
+
+ case ECBOR_TYPE_FP64:
+ {
+ double val;
+
+ rc = ecbor_get_fp64 (item, &val);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ printf ("[FP64] value %f\n", val);
+ }
+ break;
+
+ case ECBOR_TYPE_BOOL:
+ {
+ uint8_t val;
+
+ rc = ecbor_get_bool (item, &val);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ printf ("[BOOL] value %s\n", (val ? "true" : "false"));
+ }
+ break;
+
+ case ECBOR_TYPE_NULL:
+ printf ("[NULL]\n");
+ break;
+
+ case ECBOR_TYPE_UNDEFINED:
+ printf ("[UNDEFINED]\n");
+ break;
+
+ default:
+ printf ("[UNKNOWN]\n");
+ break;
+ }
+
+ return ECBOR_OK;
+}
+
+/*
+ * Program entry
+ */
+int
+main(int argc, char **argv)
+{
+ char *filename = NULL;
+ unsigned char *cbor = NULL;
+ long int cbor_length = 0;
+ int tree_mode = 0;
+
+ /* parse arguments */
+ while (1) {
+ int option_index, c;
+
+ c = getopt_long (argc, argv, "ht", long_options, &option_index);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 't':
+ tree_mode = 1;
+ break;
+
+ default:
+ print_help ();
+ return 0;
+ }
+ }
+
+ if (optind != (argc-1)) {
+ fprintf (stderr, "Expecting exactly one file name!\n");
+ print_help ();
+ return -1;
+ } else {
+ filename = strdup (argv[optind]);
+ }
+
+ /* load CBOR data from file */
+ {
+ FILE *fp;
+
+ fprintf (stderr, "Reading CBOR from file '%s'\n", filename);
+ fp = fopen (filename, "rb");
+ if (!fp) {
+ fprintf (stderr, "Error opening file!\n");
+ return -1;
+ }
+
+ if (fseek (fp, 0L, SEEK_END)) {
+ fprintf (stderr, "Error seeking end of file!\n");
+ fclose (fp);
+ return -1;
+ }
+ cbor_length = ftell(fp);
+ if (cbor_length < 0) {
+ fprintf (stderr, "Error determining input size!\n");
+ fclose (fp);
+ return -1;
+ }
+ if (fseek (fp, 0L, SEEK_SET)) {
+ fprintf (stderr, "Error seeking beginning of file!\n");
+ fclose (fp);
+ return -1;
+ }
+
+ cbor = (unsigned char *) malloc (cbor_length);
+ if (!cbor) {
+ fprintf (stderr, "Error allocating %d bytes!\n", (int) cbor_length);
+ fclose (fp);
+ return -1;
+ }
+
+ if (fread (cbor, 1, cbor_length, fp) != (size_t) cbor_length) {
+ fprintf (stderr, "Error reading %d bytes!\n", (int) cbor_length);
+ fclose (fp);
+ return -1;
+ }
+
+ fclose (fp);
+ free (filename);
+ }
+
+ /* parse CBOR data */
+ {
+ ecbor_decode_context_t context;
+ ecbor_error_t rc;
+
+ if (tree_mode) {
+ rc = ecbor_initialize_decode_tree (&context, cbor, cbor_length,
+ items_buffer, MAX_ITEMS);
+ } else {
+ rc = ecbor_initialize_decode (&context, cbor, cbor_length);
+ }
+ if (rc != ECBOR_OK) {
+ print_ecbor_error (rc);
+ return -1;
+ }
+
+ fprintf (stderr, "CBOR objects:\n");
+
+ if (tree_mode) {
+ /* decode all */
+ ecbor_item_t *item;
+
+ rc = ecbor_decode_tree (&context, &item);
+ if (rc != ECBOR_OK) {
+ print_ecbor_error (rc);
+ return -1;
+ }
+
+ while (item) {
+ rc = print_ecbor_item (item, 0, "");
+ if (rc != ECBOR_OK) {
+ print_ecbor_error (rc);
+ return -1;
+ }
+
+ item = item->next;
+ }
+ } else {
+ /* normal mode, consume */
+ ecbor_item_t item;
+
+ while (1) {
+ rc = ecbor_decode (&context, &item);
+ if (rc != ECBOR_OK) {
+ if (rc == ECBOR_END_OF_BUFFER) {
+ break;
+ }
+ print_ecbor_error (rc);
+ return -1;
+ }
+
+ rc = print_ecbor_item (&item, 0, "");
+ if (rc != ECBOR_OK) {
+ print_ecbor_error (rc);
+ return -1;
+ }
+ }
+ }
+ }
+
+ free (cbor);
+
+ /* all ok */
+ return 0;
+} \ No newline at end of file