cbor_example_main.c 7.8 KB

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