1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
/*
* Contributed by Jacob Teplitsky <jacob.teplitsky@ericsson.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
/**
* This code demonstrates how cJSON (https://github.com/DaveGamble/cJSON)
* callbacks can be used in conjuction with the streaming parser to translate
* JSON to CBOR. Please note that cbor_builder_* APIs are internal and thus
* subject to change.
*
* The example will only be compiled when cJSON is available
*/
#include <cjson/cJSON.h>
#include <float.h>
#include <math.h>
#include <string.h>
#include "cbor.h"
#include "cbor/internal/builder_callbacks.h"
#include "cbor/internal/loaders.h"
typedef void (*cbor_load_callback_t)(cJSON *, const struct cbor_callbacks *,
void *);
cbor_item_t *cjson_cbor_load(void *source,
cbor_load_callback_t cbor_load_callback) {
static struct cbor_callbacks callbacks = {
.uint64 = &cbor_builder_uint64_callback,
.negint64 = &cbor_builder_negint64_callback,
.string = &cbor_builder_string_callback,
.array_start = &cbor_builder_array_start_callback,
.map_start = &cbor_builder_map_start_callback,
.null = &cbor_builder_null_callback,
.boolean = &cbor_builder_boolean_callback,
.float4 = &cbor_builder_float4_callback,
};
/* Context stack */
struct _cbor_stack stack = _cbor_stack_init();
/* Target for callbacks */
struct _cbor_decoder_context context = (struct _cbor_decoder_context){
.stack = &stack,
};
cbor_load_callback(source, &callbacks, &context);
return context.root;
}
void cjson_cbor_stream_decode(cJSON *source,
const struct cbor_callbacks *callbacks,
void *context) {
switch (source->type) {
case cJSON_False: {
callbacks->boolean(context, false);
return;
}
case cJSON_True: {
callbacks->boolean(context, true);
return;
}
case cJSON_NULL: {
callbacks->null(context);
return;
}
case cJSON_Number: {
// This is stupid -- ints and doubles cannot are not distinguished
if (fabs(source->valuedouble - source->valueint) > DBL_EPSILON) {
callbacks->float4(context, source->valuedouble);
} else {
// XXX: This is not portable
if (source->valueint >= 0) {
callbacks->uint64(context, source->valueint);
} else {
callbacks->negint64(context, source->valueint + 1);
}
}
return;
}
case cJSON_String: {
// XXX: Assume cJSON handled unicode correctly
callbacks->string(context, (unsigned char *)source->valuestring,
strlen(source->valuestring));
return;
}
case cJSON_Array: {
callbacks->array_start(context, cJSON_GetArraySize(source));
cJSON *item = source->child;
while (item != NULL) {
cjson_cbor_stream_decode(item, callbacks, context);
item = item->next;
}
return;
}
case cJSON_Object: {
callbacks->map_start(context, cJSON_GetArraySize(source));
cJSON *item = source->child;
while (item != NULL) {
callbacks->string(context, (unsigned char *)item->string,
strlen(item->string));
cjson_cbor_stream_decode(item, callbacks, context);
item = item->next;
}
return;
}
}
}
void usage(void) {
printf("Usage: cjson [input JSON file]\n");
exit(1);
}
int main(int argc, char *argv[]) {
if (argc != 2) usage();
FILE *f = fopen(argv[1], "rb");
if (f == NULL) usage();
/* Read input file into a buffer (cJSON doesn't work with streams) */
fseek(f, 0, SEEK_END);
size_t length = (size_t)ftell(f);
fseek(f, 0, SEEK_SET);
char *json_buffer = malloc(length + 1);
fread(json_buffer, length, 1, f);
json_buffer[length] = '\0';
/* Convert between JSON and CBOR */
cJSON *json = cJSON_Parse(json_buffer);
cbor_item_t *cbor = cjson_cbor_load(json, cjson_cbor_stream_decode);
/* Print out CBOR bytes */
unsigned char *buffer;
size_t buffer_size;
cbor_serialize_alloc(cbor, &buffer, &buffer_size);
fwrite(buffer, 1, buffer_size, stdout);
free(buffer);
fflush(stdout);
cJSON_Delete(json);
cbor_decref(&cbor);
}
|