-
Notifications
You must be signed in to change notification settings - Fork 94
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #277 from PJK/cjson2cbor
Add a CBOR to cJSON example
- Loading branch information
Showing
6 changed files
with
131 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters