/* * Copyright (c) 2014-2020 Pavel Kalvoda * * libcbor is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include #include #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); }