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