diff options
Diffstat (limited to 'examples/cbor2cjson.c')
-rw-r--r-- | examples/cbor2cjson.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/examples/cbor2cjson.c b/examples/cbor2cjson.c new file mode 100644 index 000000000000..99ddc9ee09e1 --- /dev/null +++ b/examples/cbor2cjson.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2014-2020 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 <cjson/cJSON.h> +#include <stdio.h> +#include <string.h> + +#include "cbor.h" + +void usage(void) { + printf("Usage: cbor2cjson [input file]\n"); + exit(1); +} + +cJSON* cbor_to_cjson(cbor_item_t* item) { + switch (cbor_typeof(item)) { + case CBOR_TYPE_UINT: + return cJSON_CreateNumber(cbor_get_int(item)); + case CBOR_TYPE_NEGINT: + return cJSON_CreateNumber(-1 - cbor_get_int(item)); + case CBOR_TYPE_BYTESTRING: + // cJSON only handles null-terminated string -- binary data would have to + // be escaped + return cJSON_CreateString("Unsupported CBOR item: Bytestring"); + case CBOR_TYPE_STRING: + if (cbor_string_is_definite(item)) { + // cJSON only handles null-terminated string + char* null_terminated_string = malloc(cbor_string_length(item) + 1); + memcpy(null_terminated_string, cbor_string_handle(item), + cbor_string_length(item)); + null_terminated_string[cbor_string_length(item)] = 0; + cJSON* result = cJSON_CreateString(null_terminated_string); + free(null_terminated_string); + return result; + } + return cJSON_CreateString("Unsupported CBOR item: Chunked string"); + case CBOR_TYPE_ARRAY: { + cJSON* result = cJSON_CreateArray(); + for (size_t i = 0; i < cbor_array_size(item); i++) { + cJSON_AddItemToArray(result, cbor_to_cjson(cbor_array_get(item, i))); + } + return result; + } + case CBOR_TYPE_MAP: { + cJSON* result = cJSON_CreateObject(); + for (size_t i = 0; i < cbor_map_size(item); i++) { + char* key = malloc(128); + snprintf(key, 128, "Surrogate key %zu", i); + // JSON only support string keys + if (cbor_isa_string(cbor_map_handle(item)[i].key) && + cbor_string_is_definite(cbor_map_handle(item)[i].key)) { + size_t key_length = cbor_string_length(cbor_map_handle(item)[i].key); + if (key_length > 127) key_length = 127; + // Null-terminated madness + memcpy(key, cbor_string_handle(cbor_map_handle(item)[i].key), + key_length); + key[key_length] = 0; + } + + cJSON_AddItemToObject(result, key, + cbor_to_cjson(cbor_map_handle(item)[i].value)); + free(key); + } + return result; + } + case CBOR_TYPE_TAG: + return cJSON_CreateString("Unsupported CBOR item: Tag"); + case CBOR_TYPE_FLOAT_CTRL: + if (cbor_float_ctrl_is_ctrl(item)) { + if (cbor_is_bool(item)) return cJSON_CreateBool(cbor_get_bool(item)); + if (cbor_is_null(item)) return cJSON_CreateNull(); + return cJSON_CreateString("Unsupported CBOR item: Control value"); + } + return cJSON_CreateNumber(cbor_float_get_float(item)); + } + + return cJSON_CreateNull(); +} + +/* + * Reads CBOR data from a file and outputs JSON using cJSON + * $ ./examples/cbor2cjson examples/data/nested_array.cbor + */ + +int main(int argc, char* argv[]) { + if (argc != 2) usage(); + FILE* f = fopen(argv[1], "rb"); + if (f == NULL) usage(); + fseek(f, 0, SEEK_END); + size_t length = (size_t)ftell(f); + fseek(f, 0, SEEK_SET); + unsigned char* buffer = malloc(length); + fread(buffer, length, 1, f); + + /* Assuming `buffer` contains `length` bytes of input data */ + struct cbor_load_result result; + cbor_item_t* item = cbor_load(buffer, length, &result); + free(buffer); + + if (result.error.code != CBOR_ERR_NONE) { + printf( + "There was an error while reading the input near byte %zu (read %zu " + "bytes in total): ", + result.error.position, result.read); + exit(1); + } + + cJSON* cjson_item = cbor_to_cjson(item); + char* json_string = cJSON_Print(cjson_item); + printf("%s\n", json_string); + free(json_string); + fflush(stdout); + + /* Deallocate the result */ + cbor_decref(&item); + cJSON_Delete(cjson_item); + + fclose(f); +} |