1 /* CBOR Example
2
3 This example code is in the Public Domain (or CC0 licensed, at your option.)
4
5 Unless required by applicable law or agreed to in writing, this
6 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7 CONDITIONS OF ANY KIND, either express or implied.
8 */
9 #include <stdio.h>
10 #include "esp_log.h"
11 #include "cbor.h"
12
13 static const char *TAG = "example";
14
15 #define CBOR_CHECK(a, str, goto_tag, ret_value, ...) \
16 do \
17 { \
18 if ((a) != CborNoError) \
19 { \
20 ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
21 ret = ret_value; \
22 goto goto_tag; \
23 } \
24 } while (0)
25
indent(int nestingLevel)26 static void indent(int nestingLevel)
27 {
28 while (nestingLevel--) {
29 printf(" ");
30 }
31 }
32
dumpbytes(const uint8_t * buf,size_t len)33 static void dumpbytes(const uint8_t *buf, size_t len)
34 {
35 while (len--) {
36 printf("%02X ", *buf++);
37 }
38 }
39
40 /**
41 * Decode CBOR data manuallly
42 */
example_dump_cbor_buffer(CborValue * it,int nestingLevel)43 static CborError example_dump_cbor_buffer(CborValue *it, int nestingLevel)
44 {
45 CborError ret = CborNoError;
46 while (!cbor_value_at_end(it)) {
47 CborType type = cbor_value_get_type(it);
48
49 indent(nestingLevel);
50 switch (type) {
51 case CborArrayType: {
52 CborValue recursed;
53 assert(cbor_value_is_container(it));
54 puts("Array[");
55 ret = cbor_value_enter_container(it, &recursed);
56 CBOR_CHECK(ret, "enter container failed", err, ret);
57 ret = example_dump_cbor_buffer(&recursed, nestingLevel + 1);
58 CBOR_CHECK(ret, "recursive dump failed", err, ret);
59 ret = cbor_value_leave_container(it, &recursed);
60 CBOR_CHECK(ret, "leave container failed", err, ret);
61 indent(nestingLevel);
62 puts("]");
63 continue;
64 }
65 case CborMapType: {
66 CborValue recursed;
67 assert(cbor_value_is_container(it));
68 puts("Map{");
69 ret = cbor_value_enter_container(it, &recursed);
70 CBOR_CHECK(ret, "enter container failed", err, ret);
71 ret = example_dump_cbor_buffer(&recursed, nestingLevel + 1);
72 CBOR_CHECK(ret, "recursive dump failed", err, ret);
73 ret = cbor_value_leave_container(it, &recursed);
74 CBOR_CHECK(ret, "leave container failed", err, ret);
75 indent(nestingLevel);
76 puts("}");
77 continue;
78 }
79 case CborIntegerType: {
80 int64_t val;
81 ret = cbor_value_get_int64(it, &val);
82 CBOR_CHECK(ret, "parse int64 failed", err, ret);
83 printf("%lld\n", (long long)val);
84 break;
85 }
86 case CborByteStringType: {
87 uint8_t *buf;
88 size_t n;
89 ret = cbor_value_dup_byte_string(it, &buf, &n, it);
90 CBOR_CHECK(ret, "parse byte string failed", err, ret);
91 dumpbytes(buf, n);
92 puts("");
93 free(buf);
94 continue;
95 }
96 case CborTextStringType: {
97 char *buf;
98 size_t n;
99 ret = cbor_value_dup_text_string(it, &buf, &n, it);
100 CBOR_CHECK(ret, "parse text string failed", err, ret);
101 puts(buf);
102 free(buf);
103 continue;
104 }
105 case CborTagType: {
106 CborTag tag;
107 ret = cbor_value_get_tag(it, &tag);
108 CBOR_CHECK(ret, "parse tag failed", err, ret);
109 printf("Tag(%lld)\n", (long long)tag);
110 break;
111 }
112 case CborSimpleType: {
113 uint8_t type;
114 ret = cbor_value_get_simple_type(it, &type);
115 CBOR_CHECK(ret, "parse simple type failed", err, ret);
116 printf("simple(%u)\n", type);
117 break;
118 }
119 case CborNullType:
120 puts("null");
121 break;
122 case CborUndefinedType:
123 puts("undefined");
124 break;
125 case CborBooleanType: {
126 bool val;
127 ret = cbor_value_get_boolean(it, &val);
128 CBOR_CHECK(ret, "parse boolean type failed", err, ret);
129 puts(val ? "true" : "false");
130 break;
131 }
132 case CborHalfFloatType: {
133 uint16_t val;
134 ret = cbor_value_get_half_float(it, &val);
135 CBOR_CHECK(ret, "parse half float type failed", err, ret);
136 printf("__f16(%04x)\n", val);
137 break;
138 }
139 case CborFloatType: {
140 float val;
141 ret = cbor_value_get_float(it, &val);
142 CBOR_CHECK(ret, "parse float type failed", err, ret);
143 printf("%g\n", val);
144 break;
145 }
146 case CborDoubleType: {
147 double val;
148 ret = cbor_value_get_double(it, &val);
149 CBOR_CHECK(ret, "parse double float type failed", err, ret);
150 printf("%g\n", val);
151 break;
152 }
153 case CborInvalidType: {
154 ret = CborErrorUnknownType;
155 CBOR_CHECK(ret, "unknown cbor type", err, ret);
156 break;
157 }
158 }
159
160 ret = cbor_value_advance_fixed(it);
161 CBOR_CHECK(ret, "fix value failed", err, ret);
162 }
163 return CborNoError;
164 err:
165 return ret;
166 }
167
168
app_main(void)169 void app_main(void)
170 {
171 CborEncoder root_encoder;
172 CborParser root_parser;
173 CborValue it;
174 uint8_t buf[100];
175
176 // Initialize the outermost cbor encoder
177 cbor_encoder_init(&root_encoder, buf, sizeof(buf), 0);
178
179 // Create an array containing several items
180 CborEncoder array_encoder;
181 CborEncoder map_encoder;
182 cbor_encoder_create_array(&root_encoder, &array_encoder, 5); // [
183 // 1. Create a map containing several pairs
184 cbor_encoder_create_map(&array_encoder, &map_encoder, 3); // {
185 // chip:esp32
186 cbor_encode_text_stringz(&map_encoder, "chip");
187 cbor_encode_text_stringz(&map_encoder, "esp32");
188 // unicore:false
189 cbor_encode_text_stringz(&map_encoder, "unicore");
190 cbor_encode_boolean(&map_encoder, false);
191 // ip:[192,168,1,100]
192 cbor_encode_text_stringz(&map_encoder, "ip");
193 CborEncoder array2;
194 cbor_encoder_create_array(&map_encoder, &array2, 4); // [
195 // Encode several numbers
196 cbor_encode_uint(&array2, 192);
197 cbor_encode_uint(&array2, 168);
198 cbor_encode_uint(&array2, 1);
199 cbor_encode_uint(&array2, 100);
200 cbor_encoder_close_container(&map_encoder, &array2); // ]
201 cbor_encoder_close_container(&array_encoder, &map_encoder); // }
202 // 2. Encode float number
203 cbor_encode_float(&array_encoder, 3.14);
204 // 3. Encode simple value
205 cbor_encode_simple_value(&array_encoder, 99);
206 // 4. Encode a string
207 cbor_encode_text_stringz(&array_encoder, "2019-07-10 09:00:00+0000");
208 // 5. Encode a undefined value
209 cbor_encode_undefined(&array_encoder);
210 cbor_encoder_close_container(&root_encoder, &array_encoder); // ]
211
212 // If error happend when encoding, then this value should be meaningless
213 ESP_LOGI(TAG, "encoded buffer size %d", cbor_encoder_get_buffer_size(&root_encoder, buf));
214
215 // Initialize the cbor parser and the value iterator
216 cbor_parser_init(buf, sizeof(buf), 0, &root_parser, &it);
217
218 ESP_LOGI(TAG, "convert CBOR to JSON");
219 // Dump the values in JSON format
220 cbor_value_to_json(stdout, &it, 0);
221 puts("");
222
223 ESP_LOGI(TAG, "decode CBOR manually");
224 // Decode CBOR data manully
225 example_dump_cbor_buffer(&it, 0);
226 }
227