libcbor 0.12.0
libcbor is a C library for parsing and generating CBOR, the general-purpose schema-less binary data format.
Loading...
Searching...
No Matches
cbor.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
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#include "cbor.h"
11
12cbor_item_t* cbor_load(cbor_data source, size_t source_size,
13 struct cbor_load_result* result) {
14 /* Context stack */
15 static struct cbor_callbacks callbacks = {
20
25
27 .byte_string_start = &cbor_builder_byte_string_start_callback,
28
31
33 .indef_array_start = &cbor_builder_indef_array_start_callback,
34
36 .indef_map_start = &cbor_builder_indef_map_start_callback,
37
39
46 .indef_break = &cbor_builder_indef_break_callback};
47
48 if (source_size == 0) {
49 result->error.code = CBOR_ERR_NODATA;
50 return NULL;
51 }
52 struct _cbor_stack stack = _cbor_stack_init();
53
54 /* Target for callbacks */
55 struct _cbor_decoder_context context = (struct _cbor_decoder_context){
56 .stack = &stack, .creation_failed = false, .syntax_error = false};
57 struct cbor_decoder_result decode_result;
58 *result =
59 (struct cbor_load_result){.read = 0, .error = {.code = CBOR_ERR_NONE}};
60
61 do {
62 if (source_size > result->read) { /* Check for overflows */
63 decode_result =
64 cbor_stream_decode(source + result->read, source_size - result->read,
65 &callbacks, &context);
66 } else {
67 result->error = (struct cbor_error){.code = CBOR_ERR_NOTENOUGHDATA,
68 .position = result->read};
69 goto error;
70 }
71
72 switch (decode_result.status) {
73 case CBOR_DECODER_FINISHED:
74 /* Everything OK */
75 {
76 result->read += decode_result.read;
77 break;
78 }
80 /* Data length doesn't match MTB expectation */
81 {
82 result->error.code = CBOR_ERR_NOTENOUGHDATA;
83 goto error;
84 }
86 /* Reserved/malformed item */
87 {
88 result->error.code = CBOR_ERR_MALFORMATED;
89 goto error;
90 }
91 }
92
93 if (context.creation_failed) {
94 /* Most likely unsuccessful allocation - our callback has failed */
95 result->error.code = CBOR_ERR_MEMERROR;
96 goto error;
97 } else if (context.syntax_error) {
98 result->error.code = CBOR_ERR_SYNTAXERROR;
99 goto error;
100 }
101 } while (stack.size > 0);
102
103 return context.root;
104
105error:
106 result->error.position = result->read;
107 // debug_print("Failed with decoder error %d at %d\n", result->error.code,
108 // result->error.position); cbor_describe(stack.top->item, stdout);
109 /* Free the stack */
110 while (stack.size > 0) {
111 cbor_decref(&stack.top->item);
112 _cbor_stack_pop(&stack);
113 }
114 return NULL;
115}
116
117static cbor_item_t* _cbor_copy_int(cbor_item_t* item, bool negative) {
118 cbor_item_t* res = NULL;
119 switch (cbor_int_get_width(item)) {
120 case CBOR_INT_8:
121 res = cbor_build_uint8(cbor_get_uint8(item));
122 break;
123 case CBOR_INT_16:
125 break;
126 case CBOR_INT_32:
128 break;
129 case CBOR_INT_64:
131 break;
132 }
133
134 if (negative) cbor_mark_negint(res);
135
136 return res;
137}
138
139static cbor_item_t* _cbor_copy_float_ctrl(cbor_item_t* item) {
140 switch (cbor_float_get_width(item)) {
141 case CBOR_FLOAT_0:
142 return cbor_build_ctrl(cbor_ctrl_value(item));
143 case CBOR_FLOAT_16:
145 case CBOR_FLOAT_32:
147 case CBOR_FLOAT_64:
149 default:
151 return NULL;
152 }
153}
154
156 switch (cbor_typeof(item)) {
157 case CBOR_TYPE_UINT:
158 return _cbor_copy_int(item, false);
159 case CBOR_TYPE_NEGINT:
160 return _cbor_copy_int(item, true);
162 if (cbor_bytestring_is_definite(item)) {
165 } else {
167 if (res == NULL) {
168 return NULL;
169 }
170
171 for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++) {
172 cbor_item_t* chunk_copy =
174 if (chunk_copy == NULL) {
175 cbor_decref(&res);
176 return NULL;
177 }
178 if (!cbor_bytestring_add_chunk(res, chunk_copy)) {
179 cbor_decref(&chunk_copy);
180 cbor_decref(&res);
181 return NULL;
182 }
183 cbor_decref(&chunk_copy);
184 }
185 return res;
186 }
187 case CBOR_TYPE_STRING:
188 if (cbor_string_is_definite(item)) {
189 return cbor_build_stringn((const char*)cbor_string_handle(item),
190 cbor_string_length(item));
191 } else {
193 if (res == NULL) {
194 return NULL;
195 }
196
197 for (size_t i = 0; i < cbor_string_chunk_count(item); i++) {
198 cbor_item_t* chunk_copy =
200 if (chunk_copy == NULL) {
201 cbor_decref(&res);
202 return NULL;
203 }
204 if (!cbor_string_add_chunk(res, chunk_copy)) {
205 cbor_decref(&chunk_copy);
206 cbor_decref(&res);
207 return NULL;
208 }
209 cbor_decref(&chunk_copy);
210 }
211 return res;
212 }
213 case CBOR_TYPE_ARRAY: {
214 cbor_item_t* res;
215 if (cbor_array_is_definite(item)) {
217 } else {
219 }
220 if (res == NULL) {
221 return NULL;
222 }
223
224 for (size_t i = 0; i < cbor_array_size(item); i++) {
225 cbor_item_t* entry_copy = cbor_copy(cbor_move(cbor_array_get(item, i)));
226 if (entry_copy == NULL) {
227 cbor_decref(&res);
228 return NULL;
229 }
230 if (!cbor_array_push(res, entry_copy)) {
231 cbor_decref(&entry_copy);
232 cbor_decref(&res);
233 return NULL;
234 }
235 cbor_decref(&entry_copy);
236 }
237 return res;
238 }
239 case CBOR_TYPE_MAP: {
240 cbor_item_t* res;
241 if (cbor_map_is_definite(item)) {
243 } else {
245 }
246 if (res == NULL) {
247 return NULL;
248 }
249
250 struct cbor_pair* it = cbor_map_handle(item);
251 for (size_t i = 0; i < cbor_map_size(item); i++) {
252 cbor_item_t* key_copy = cbor_copy(it[i].key);
253 if (key_copy == NULL) {
254 cbor_decref(&res);
255 return NULL;
256 }
257 cbor_item_t* value_copy = cbor_copy(it[i].value);
258 if (value_copy == NULL) {
259 cbor_decref(&res);
260 cbor_decref(&key_copy);
261 return NULL;
262 }
263 if (!cbor_map_add(res, (struct cbor_pair){.key = key_copy,
264 .value = value_copy})) {
265 cbor_decref(&res);
266 cbor_decref(&key_copy);
267 cbor_decref(&value_copy);
268 return NULL;
269 }
270 cbor_decref(&key_copy);
271 cbor_decref(&value_copy);
272 }
273 return res;
274 }
275 case CBOR_TYPE_TAG: {
276 cbor_item_t* item_copy = cbor_copy(cbor_move(cbor_tag_item(item)));
277 if (item_copy == NULL) {
278 return NULL;
279 }
280 cbor_item_t* tag = cbor_build_tag(cbor_tag_value(item), item_copy);
281 cbor_decref(&item_copy);
282 return tag;
283 }
285 return _cbor_copy_float_ctrl(item);
286 default:
288 return NULL;
289 }
290}
291
292#if CBOR_PRETTY_PRINTER
293
294#include <inttypes.h>
295#include <locale.h>
296#include <wchar.h>
297
298#define __STDC_FORMAT_MACROS
299
300static int _pow(int b, int ex) {
301 if (ex == 0) return 1;
302 int res = b;
303 while (--ex > 0) res *= b;
304 return res;
305}
306
307static void _cbor_type_marquee(FILE* out, char* label, int indent) {
308 fprintf(out, "%*.*s[%s] ", indent, indent, " ", label);
309}
310
311static void _cbor_nested_describe(cbor_item_t* item, FILE* out, int indent) {
312 const int indent_offset = 4;
313 switch (cbor_typeof(item)) {
314 case CBOR_TYPE_UINT: {
315 _cbor_type_marquee(out, "CBOR_TYPE_UINT", indent);
316 fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item)));
317 fprintf(out, "Value: %" PRIu64 "\n", cbor_get_int(item));
318 break;
319 }
320 case CBOR_TYPE_NEGINT: {
321 _cbor_type_marquee(out, "CBOR_TYPE_NEGINT", indent);
322 fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item)));
323 fprintf(out, "Value: -%" PRIu64 " - 1\n", cbor_get_int(item));
324 break;
325 }
327 _cbor_type_marquee(out, "CBOR_TYPE_BYTESTRING", indent);
329 fprintf(out, "Indefinite, Chunks: %zu, Chunk data:\n",
331 for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++)
332 _cbor_nested_describe(cbor_bytestring_chunks_handle(item)[i], out,
333 indent + indent_offset);
334 } else {
335 const unsigned char* data = cbor_bytestring_handle(item);
336 fprintf(out, "Definite, Length: %zuB, Data:\n",
338 fprintf(out, "%*s", indent + indent_offset, " ");
339 for (size_t i = 0; i < cbor_bytestring_length(item); i++)
340 fprintf(out, "%02x", (int)(data[i] & 0xff));
341 fprintf(out, "\n");
342 }
343 break;
344 }
345 case CBOR_TYPE_STRING: {
346 _cbor_type_marquee(out, "CBOR_TYPE_STRING", indent);
347 if (cbor_string_is_indefinite(item)) {
348 fprintf(out, "Indefinite, Chunks: %zu, Chunk data:\n",
350 for (size_t i = 0; i < cbor_string_chunk_count(item); i++)
351 _cbor_nested_describe(cbor_string_chunks_handle(item)[i], out,
352 indent + indent_offset);
353 } else {
354 fprintf(out, "Definite, Length: %zuB, Codepoints: %zu, Data:\n",
356 fprintf(out, "%*s", indent + indent_offset, " ");
357 // Note: The string is not escaped, whitespace and control character
358 // will be printed in verbatim and take effect.
359 fwrite(cbor_string_handle(item), sizeof(unsigned char),
360 cbor_string_length(item), out);
361 fprintf(out, "\n");
362 }
363 break;
364 }
365 case CBOR_TYPE_ARRAY: {
366 _cbor_type_marquee(out, "CBOR_TYPE_ARRAY", indent);
367 if (cbor_array_is_definite(item)) {
368 fprintf(out, "Definite, Size: %zu, Contents:\n", cbor_array_size(item));
369 } else {
370 fprintf(out, "Indefinite, Size: %zu, Contents:\n",
371 cbor_array_size(item));
372 }
373
374 for (size_t i = 0; i < cbor_array_size(item); i++)
375 _cbor_nested_describe(cbor_array_handle(item)[i], out,
376 indent + indent_offset);
377 break;
378 }
379 case CBOR_TYPE_MAP: {
380 _cbor_type_marquee(out, "CBOR_TYPE_MAP", indent);
381 if (cbor_map_is_definite(item)) {
382 fprintf(out, "Definite, Size: %zu, Contents:\n", cbor_map_size(item));
383 } else {
384 fprintf(out, "Indefinite, Size: %zu, Contents:\n", cbor_map_size(item));
385 }
386
387 // TODO: Label and group keys and values
388 for (size_t i = 0; i < cbor_map_size(item); i++) {
389 fprintf(out, "%*sMap entry %zu\n", indent + indent_offset, " ", i);
390 _cbor_nested_describe(cbor_map_handle(item)[i].key, out,
391 indent + 2 * indent_offset);
392 _cbor_nested_describe(cbor_map_handle(item)[i].value, out,
393 indent + 2 * indent_offset);
394 }
395 break;
396 }
397 case CBOR_TYPE_TAG: {
398 _cbor_type_marquee(out, "CBOR_TYPE_TAG", indent);
399 fprintf(out, "Value: %" PRIu64 "\n", cbor_tag_value(item));
400 _cbor_nested_describe(cbor_move(cbor_tag_item(item)), out,
401 indent + indent_offset);
402 break;
403 }
405 _cbor_type_marquee(out, "CBOR_TYPE_FLOAT_CTRL", indent);
406 if (cbor_float_ctrl_is_ctrl(item)) {
407 if (cbor_is_bool(item))
408 fprintf(out, "Bool: %s\n", cbor_get_bool(item) ? "true" : "false");
409 else if (cbor_is_undef(item))
410 fprintf(out, "Undefined\n");
411 else if (cbor_is_null(item))
412 fprintf(out, "Null\n");
413 else
414 fprintf(out, "Simple value: %d\n", cbor_ctrl_value(item));
415 } else {
416 fprintf(out, "Width: %dB, ", _pow(2, cbor_float_get_width(item)));
417 fprintf(out, "Value: %lf\n", cbor_float_get_float(item));
418 }
419 break;
420 }
421 }
422}
423
424void cbor_describe(cbor_item_t* item, FILE* out) {
425 _cbor_nested_describe(item, out, 0);
426}
427
428#endif
size_t cbor_array_size(const cbor_item_t *item)
Get the number of members.
Definition arrays.c:12
cbor_item_t ** cbor_array_handle(const cbor_item_t *item)
Get the array contents.
Definition arrays.c:92
bool cbor_array_push(cbor_item_t *array, cbor_item_t *pushee)
Append to the end.
Definition arrays.c:44
bool cbor_array_is_definite(const cbor_item_t *item)
Is the array definite?
Definition arrays.c:82
cbor_item_t * cbor_new_definite_array(size_t size)
Create new definite array.
Definition arrays.c:97
cbor_item_t * cbor_array_get(const cbor_item_t *item, size_t index)
Get item by index.
Definition arrays.c:22
cbor_item_t * cbor_new_indefinite_array(void)
Create new indefinite array.
Definition arrays.c:118
void cbor_builder_byte_string_callback(void *context, cbor_data data, uint64_t length)
void cbor_builder_uint64_callback(void *context, uint64_t value)
void cbor_builder_boolean_callback(void *context, bool value)
void cbor_builder_byte_string_start_callback(void *context)
void cbor_builder_array_start_callback(void *context, uint64_t size)
void cbor_builder_string_start_callback(void *context)
void cbor_builder_indef_map_start_callback(void *context)
void cbor_builder_negint16_callback(void *context, uint16_t value)
void cbor_builder_undefined_callback(void *context)
void cbor_builder_negint32_callback(void *context, uint32_t value)
void cbor_builder_null_callback(void *context)
void cbor_builder_map_start_callback(void *context, uint64_t size)
void cbor_builder_uint32_callback(void *context, uint32_t value)
void cbor_builder_indef_array_start_callback(void *context)
void cbor_builder_uint16_callback(void *context, uint16_t value)
void cbor_builder_negint8_callback(void *context, uint8_t value)
void cbor_builder_string_callback(void *context, cbor_data data, uint64_t length)
void cbor_builder_tag_callback(void *context, uint64_t value)
void cbor_builder_uint8_callback(void *context, uint8_t value)
void cbor_builder_float4_callback(void *context, float value)
void cbor_builder_negint64_callback(void *context, uint64_t value)
void cbor_builder_float8_callback(void *context, double value)
void cbor_builder_float2_callback(void *context, float value)
void cbor_builder_indef_break_callback(void *context)
bool cbor_bytestring_is_definite(const cbor_item_t *item)
Is the byte string definite?
Definition bytestrings.c:22
bool cbor_bytestring_is_indefinite(const cbor_item_t *item)
Is the byte string indefinite?
Definition bytestrings.c:27
bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk)
Appends a chunk to the bytestring.
Definition bytestrings.c:92
size_t cbor_bytestring_length(const cbor_item_t *item)
Returns the length of the binary data.
Definition bytestrings.c:12
cbor_item_t ** cbor_bytestring_chunks_handle(const cbor_item_t *item)
Get the handle to the array of chunks.
Definition bytestrings.c:80
cbor_item_t * cbor_new_indefinite_bytestring(void)
Creates a new indefinite byte string.
Definition bytestrings.c:42
cbor_item_t * cbor_build_bytestring(cbor_data handle, size_t length)
Creates a new byte string and initializes it.
Definition bytestrings.c:61
size_t cbor_bytestring_chunk_count(const cbor_item_t *item)
Get the number of chunks this string consist of.
Definition bytestrings.c:86
unsigned char * cbor_bytestring_handle(const cbor_item_t *item)
Get the handle to the binary data.
Definition bytestrings.c:17
cbor_item_t * cbor_copy(cbor_item_t *item)
Take a deep copy of an item.
Definition cbor.c:155
cbor_item_t * cbor_load(cbor_data source, size_t source_size, struct cbor_load_result *result)
Loads data item from a buffer.
Definition cbor.c:12
cbor_item_t * cbor_move(cbor_item_t *item)
Provides CPP-like move construct.
Definition common.c:158
bool cbor_is_bool(const cbor_item_t *item)
Is the item an a boolean?
Definition common.c:60
cbor_type cbor_typeof(const cbor_item_t *item)
Get the type of the item.
Definition common.c:54
bool cbor_is_null(const cbor_item_t *item)
Does this item represent null
Definition common.c:66
void cbor_decref(cbor_item_t **item_ref)
Decreases the item's reference count by one, deallocating the item if needed.
Definition common.c:83
bool cbor_is_undef(const cbor_item_t *item)
Does this item represent undefined
Definition common.c:70
#define _CBOR_UNREACHABLE
Definition common.h:99
const unsigned char * cbor_data
Definition data.h:20
@ CBOR_ERR_NODATA
Definition data.h:47
@ CBOR_ERR_NONE
Definition data.h:45
@ CBOR_ERR_NOTENOUGHDATA
Definition data.h:46
@ CBOR_TYPE_MAP
5 - maps
Definition data.h:35
@ CBOR_TYPE_FLOAT_CTRL
7 - decimals and special values (true, false, nil, ...)
Definition data.h:39
@ CBOR_TYPE_TAG
6 - tags
Definition data.h:37
@ CBOR_TYPE_UINT
0 - positive integers
Definition data.h:25
@ CBOR_TYPE_BYTESTRING
2 - byte strings
Definition data.h:29
@ CBOR_TYPE_STRING
3 - strings
Definition data.h:31
@ CBOR_TYPE_NEGINT
1 - negative integers
Definition data.h:27
@ CBOR_TYPE_ARRAY
4 - arrays
Definition data.h:33
@ CBOR_DECODER_NEDATA
Not enough data to invoke a callback.
Definition data.h:224
@ CBOR_DECODER_ERROR
Bad data (reserved MTB, malformed value, etc.)
Definition data.h:226
@ CBOR_FLOAT_32
Single float.
Definition data.h:71
@ CBOR_FLOAT_16
Half float.
Definition data.h:69
@ CBOR_FLOAT_64
Double.
Definition data.h:73
@ CBOR_FLOAT_0
Internal use - ctrl and special values.
Definition data.h:67
@ CBOR_INT_16
Definition data.h:60
@ CBOR_INT_8
Definition data.h:59
@ CBOR_INT_64
Definition data.h:62
@ CBOR_INT_32
Definition data.h:61
cbor_float_width cbor_float_get_width(const cbor_item_t *item)
Get the float width.
cbor_item_t * cbor_build_ctrl(uint8_t value)
Constructs a ctrl item.
bool cbor_float_ctrl_is_ctrl(const cbor_item_t *item)
Is this a ctrl value?
double cbor_float_get_float8(const cbor_item_t *item)
Get a double precision float.
cbor_item_t * cbor_build_float4(float value)
Constructs a new float.
uint8_t cbor_ctrl_value(const cbor_item_t *item)
Reads the control value.
float cbor_float_get_float2(const cbor_item_t *item)
Get a half precision float.
cbor_item_t * cbor_build_float8(double value)
Constructs a new float.
float cbor_float_get_float4(const cbor_item_t *item)
Get a single precision float.
double cbor_float_get_float(const cbor_item_t *item)
Get the float value represented as double.
cbor_item_t * cbor_build_float2(float value)
Constructs a new float.
bool cbor_get_bool(const cbor_item_t *item)
Get value from a boolean ctrl item.
uint32_t cbor_get_uint32(const cbor_item_t *item)
Extracts the integer value.
Definition ints.c:27
uint16_t cbor_get_uint16(const cbor_item_t *item)
Extracts the integer value.
Definition ints.c:21
uint8_t cbor_get_uint8(const cbor_item_t *item)
Extracts the integer value.
Definition ints.c:15
cbor_item_t * cbor_build_uint16(uint16_t value)
Constructs a new positive integer.
Definition ints.c:139
cbor_int_width cbor_int_get_width(const cbor_item_t *item)
Queries the integer width.
Definition ints.c:10
void cbor_mark_negint(cbor_item_t *item)
Marks the integer item as a negative integer.
Definition ints.c:86
uint64_t cbor_get_uint64(const cbor_item_t *item)
Extracts the integer value.
Definition ints.c:33
uint64_t cbor_get_int(const cbor_item_t *item)
Extracts the integer value.
Definition ints.c:39
cbor_item_t * cbor_build_uint32(uint32_t value)
Constructs a new positive integer.
Definition ints.c:147
cbor_item_t * cbor_build_uint8(uint8_t value)
Constructs a new positive integer.
Definition ints.c:131
cbor_item_t * cbor_build_uint64(uint64_t value)
Constructs a new positive integer.
Definition ints.c:155
bool cbor_map_is_definite(const cbor_item_t *item)
Is this map definite?
Definition maps.c:113
struct cbor_pair * cbor_map_handle(const cbor_item_t *item)
Get the pairs storage.
Definition maps.c:122
size_t cbor_map_size(const cbor_item_t *item)
Get the number of pairs.
Definition maps.c:11
cbor_item_t * cbor_new_indefinite_map(void)
Create a new indefinite map.
Definition maps.c:37
cbor_item_t * cbor_new_definite_map(size_t size)
Create a new definite map.
Definition maps.c:21
bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair)
Add a pair to the map.
Definition maps.c:107
struct _cbor_stack _cbor_stack_init(void)
Definition stack.c:10
struct cbor_decoder_result cbor_stream_decode(cbor_data source, size_t source_size, const struct cbor_callbacks *callbacks, void *context)
Stateless decoder.
Definition streaming.c:43
bool cbor_string_add_chunk(cbor_item_t *item, cbor_item_t *chunk)
Appends a chunk to the string.
Definition strings.c:95
cbor_item_t * cbor_new_indefinite_string(void)
Creates a new indefinite string.
Definition strings.c:25
size_t cbor_string_codepoint_count(const cbor_item_t *item)
The number of codepoints in this string.
Definition strings.c:132
cbor_item_t * cbor_build_stringn(const char *val, size_t length)
Creates a new string and initializes it.
Definition strings.c:55
size_t cbor_string_length(const cbor_item_t *item)
Returns the length of the underlying string in bytes.
Definition strings.c:122
bool cbor_string_is_indefinite(const cbor_item_t *item)
Is the string indefinite?
Definition strings.c:142
bool cbor_string_is_definite(const cbor_item_t *item)
Is the string definite?
Definition strings.c:137
cbor_item_t ** cbor_string_chunks_handle(const cbor_item_t *item)
Get the handle to the array of chunks.
Definition strings.c:83
unsigned char * cbor_string_handle(const cbor_item_t *item)
Get the handle to the underlying string.
Definition strings.c:127
size_t cbor_string_chunk_count(const cbor_item_t *item)
Get the number of chunks this string consist of.
Definition strings.c:89
High-level decoding context.
bool creation_failed
Callback creating the last item has failed.
bool syntax_error
Stack expectation mismatch.
struct _cbor_stack * stack
Stack handle - contents and size.
Definition stack.h:35
Callback bundle – passed to the decoder.
Definition callbacks.h:51
Streaming decoder result.
Definition data.h:230
enum cbor_decoder_status status
The decoding status.
Definition data.h:241
High-level decoding error.
Definition data.h:193
cbor_error_code code
Description.
Definition data.h:197
The item handle.
Definition data.h:171
High-level decoding result.
Definition data.h:206
size_t read
Number of bytes read.
Definition data.h:210
struct cbor_error error
Error indicator.
Definition data.h:208
Simple pair of items for use in maps.
Definition data.h:201
cbor_item_t * value
Definition data.h:202
cbor_item_t * key
Definition data.h:202
cbor_item_t * cbor_tag_item(const cbor_item_t *tag)
Get the tagged item (what the tag points to).
Definition tags.c:23
uint64_t cbor_tag_value(const cbor_item_t *tag)
Get the tag value.
Definition tags.c:28
cbor_item_t * cbor_build_tag(uint64_t value, cbor_item_t *item)
Build a new tag.
Definition tags.c:39