TinyCBOR 0.6.0 API
cbor.h
Go to the documentation of this file.
1/****************************************************************************
2**
3** Copyright (C) 2021 Intel Corporation
4**
5** Permission is hereby granted, free of charge, to any person obtaining a copy
6** of this software and associated documentation files (the "Software"), to deal
7** in the Software without restriction, including without limitation the rights
8** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9** copies of the Software, and to permit persons to whom the Software is
10** furnished to do so, subject to the following conditions:
11**
12** The above copyright notice and this permission notice shall be included in
13** all copies or substantial portions of the Software.
14**
15** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21** THE SOFTWARE.
22**
23****************************************************************************/
24
25#ifndef CBOR_H
26#define CBOR_H
27
28#ifndef assert
29#include <assert.h>
30#endif
31#include <limits.h>
32#include <stddef.h>
33#include <stdint.h>
34#include <string.h>
35#include <stdio.h>
36
37#ifdef CBOR_EXTERNAL_CFG
38#include "cbor_cfg.h"
39#endif
40
41#include "tinycbor-version.h"
42
43#define TINYCBOR_VERSION ((TINYCBOR_VERSION_MAJOR << 16) | (TINYCBOR_VERSION_MINOR << 8) | TINYCBOR_VERSION_PATCH)
44
45#ifdef __cplusplus
46extern "C" {
47#else
48#include <stdbool.h>
49#endif
50
51#ifndef SIZE_MAX
52/* Some systems fail to define SIZE_MAX in <stdint.h>, even though C99 requires it...
53 * Conversion from signed to unsigned is defined in 6.3.1.3 (Signed and unsigned integers) p2,
54 * which says: "the value is converted by repeatedly adding or subtracting one more than the
55 * maximum value that can be represented in the new type until the value is in the range of the
56 * new type."
57 * So -1 gets converted to size_t by adding SIZE_MAX + 1, which results in SIZE_MAX.
58 */
59# define SIZE_MAX ((size_t)-1)
60#endif
61
62#ifndef CBOR_API
63# define CBOR_API
64#endif
65#ifndef CBOR_PRIVATE_API
66# define CBOR_PRIVATE_API
67#endif
68#ifndef CBOR_INLINE_API
69# if defined(__cplusplus)
70# define CBOR_INLINE inline
71# define CBOR_INLINE_API inline
72# else
73# define CBOR_INLINE_API static CBOR_INLINE
74# if defined(_MSC_VER)
75# define CBOR_INLINE __inline
76# elif defined(__GNUC__)
77# define CBOR_INLINE __inline__
78# elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
79# define CBOR_INLINE inline
80# else
81# define CBOR_INLINE
82# endif
83# endif
84#endif
85
86typedef enum CborType {
87 CborIntegerType = 0x00,
88 CborByteStringType = 0x40,
89 CborTextStringType = 0x60,
90 CborArrayType = 0x80,
91 CborMapType = 0xa0,
92 CborTagType = 0xc0,
93 CborSimpleType = 0xe0,
94 CborBooleanType = 0xf5,
95 CborNullType = 0xf6,
96 CborUndefinedType = 0xf7,
97 CborHalfFloatType = 0xf9,
98 CborFloatType = 0xfa,
99 CborDoubleType = 0xfb,
100
101 CborInvalidType = 0xff /* equivalent to the break byte, so it will never be used */
102} CborType;
103
104typedef uint64_t CborTag;
105typedef enum CborKnownTags {
106 CborDateTimeStringTag = 0,
107 CborUnixTime_tTag = 1,
108 CborPositiveBignumTag = 2,
109 CborNegativeBignumTag = 3,
110 CborDecimalTag = 4,
111 CborBigfloatTag = 5,
112 CborCOSE_Encrypt0Tag = 16,
113 CborCOSE_Mac0Tag = 17,
114 CborCOSE_Sign1Tag = 18,
115 CborExpectedBase64urlTag = 21,
116 CborExpectedBase64Tag = 22,
117 CborExpectedBase16Tag = 23,
118 CborEncodedCborTag = 24,
119 CborUrlTag = 32,
120 CborBase64urlTag = 33,
121 CborBase64Tag = 34,
122 CborRegularExpressionTag = 35,
123 CborMimeMessageTag = 36,
124 CborCOSE_EncryptTag = 96,
125 CborCOSE_MacTag = 97,
126 CborCOSE_SignTag = 98,
127 CborSignatureTag = 55799
128} CborKnownTags;
129
130/* #define the constants so we can check with #ifdef */
131#define CborDateTimeStringTag CborDateTimeStringTag
132#define CborUnixTime_tTag CborUnixTime_tTag
133#define CborPositiveBignumTag CborPositiveBignumTag
134#define CborNegativeBignumTag CborNegativeBignumTag
135#define CborDecimalTag CborDecimalTag
136#define CborBigfloatTag CborBigfloatTag
137#define CborCOSE_Encrypt0Tag CborCOSE_Encrypt0Tag
138#define CborCOSE_Mac0Tag CborCOSE_Mac0Tag
139#define CborCOSE_Sign1Tag CborCOSE_Sign1Tag
140#define CborExpectedBase64urlTag CborExpectedBase64urlTag
141#define CborExpectedBase64Tag CborExpectedBase64Tag
142#define CborExpectedBase16Tag CborExpectedBase16Tag
143#define CborEncodedCborTag CborEncodedCborTag
144#define CborUrlTag CborUrlTag
145#define CborBase64urlTag CborBase64urlTag
146#define CborBase64Tag CborBase64Tag
147#define CborRegularExpressionTag CborRegularExpressionTag
148#define CborMimeMessageTag CborMimeMessageTag
149#define CborCOSE_EncryptTag CborCOSE_EncryptTag
150#define CborCOSE_MacTag CborCOSE_MacTag
151#define CborCOSE_SignTag CborCOSE_SignTag
152#define CborSignatureTag CborSignatureTag
153
154/* Error API */
155
156typedef enum CborError {
157 CborNoError = 0,
158
159 /* errors in all modes */
160 CborUnknownError,
161 CborErrorUnknownLength, /* request for length in array, map, or string with indeterminate length */
162 CborErrorAdvancePastEOF,
163 CborErrorIO,
164
165 /* parser errors streaming errors */
166 CborErrorGarbageAtEnd = 256,
167 CborErrorUnexpectedEOF,
168 CborErrorUnexpectedBreak,
169 CborErrorUnknownType, /* can only happen in major type 7 */
170 CborErrorIllegalType, /* type not allowed here */
171 CborErrorIllegalNumber,
172 CborErrorIllegalSimpleType, /* types of value less than 32 encoded in two bytes */
173 CborErrorNoMoreStringChunks,
174
175 /* parser errors in strict mode parsing only */
176 CborErrorUnknownSimpleType = 512,
177 CborErrorUnknownTag,
178 CborErrorInappropriateTagForType,
179 CborErrorDuplicateObjectKeys,
180 CborErrorInvalidUtf8TextString,
181 CborErrorExcludedType,
182 CborErrorExcludedValue,
183 CborErrorImproperValue,
184 CborErrorOverlongEncoding,
185 CborErrorMapKeyNotString,
186 CborErrorMapNotSorted,
187 CborErrorMapKeysNotUnique,
188
189 /* encoder errors */
190 CborErrorTooManyItems = 768,
191 CborErrorTooFewItems,
192
193 /* internal implementation errors */
194 CborErrorDataTooLarge = 1024,
195 CborErrorNestingTooDeep,
196 CborErrorUnsupportedType,
197 CborErrorUnimplementedValidation,
198
199 /* errors in converting to JSON */
200 CborErrorJsonObjectKeyIsAggregate = 1280,
201 CborErrorJsonObjectKeyNotString,
202 CborErrorJsonNotImplemented,
203
204 CborErrorOutOfMemory = (int) (~0U / 2 + 1),
205 CborErrorInternalError = (int) (~0U / 2) /* INT_MAX on two's complement machines */
206} CborError;
207
208CBOR_API const char *cbor_error_string(CborError error);
209
210/* Encoder API */
211
212typedef enum CborEncoderAppendType
213{
214 CborEncoderAppendCborData = 0,
215 CborEncoderAppendStringData = 1
216} CborEncoderAppendType;
217
218typedef CborError (*CborEncoderWriteFunction)(void *, const void *, size_t, CborEncoderAppendType);
219
220enum CborEncoderFlags
221{
222 CborIteratorFlag_WriterFunction = 0x01,
223 CborIteratorFlag_ContainerIsMap_ = 0x20
224};
225
227{
228 union {
229 uint8_t *ptr;
230 ptrdiff_t bytes_needed;
231 CborEncoderWriteFunction writer;
232 } data;
233 uint8_t *end;
234 size_t remaining;
235 int flags;
236};
237typedef struct CborEncoder CborEncoder;
238
239static const size_t CborIndefiniteLength = SIZE_MAX;
240
241#ifndef CBOR_NO_ENCODER_API
242CBOR_API void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags);
243CBOR_API void cbor_encoder_init_writer(CborEncoder *encoder, CborEncoderWriteFunction writer, void *);
244CBOR_API CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value);
245CBOR_API CborError cbor_encode_int(CborEncoder *encoder, int64_t value);
246CBOR_API CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value);
247CBOR_API CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value);
248CBOR_API CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag);
249CBOR_API CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length);
250CBOR_INLINE_API CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string)
251{ return cbor_encode_text_string(encoder, string, strlen(string)); }
252CBOR_API CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length);
253CBOR_API CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value);
254
255CBOR_INLINE_API CborError cbor_encode_boolean(CborEncoder *encoder, bool value)
256{ return cbor_encode_simple_value(encoder, (int)value - 1 + (CborBooleanType & 0x1f)); }
257CBOR_INLINE_API CborError cbor_encode_null(CborEncoder *encoder)
258{ return cbor_encode_simple_value(encoder, CborNullType & 0x1f); }
259CBOR_INLINE_API CborError cbor_encode_undefined(CborEncoder *encoder)
260{ return cbor_encode_simple_value(encoder, CborUndefinedType & 0x1f); }
261
262CBOR_INLINE_API CborError cbor_encode_half_float(CborEncoder *encoder, const void *value)
263{ return cbor_encode_floating_point(encoder, CborHalfFloatType, value); }
264CBOR_API CborError cbor_encode_float_as_half_float(CborEncoder *encoder, float value);
265CBOR_INLINE_API CborError cbor_encode_float(CborEncoder *encoder, float value)
266{ return cbor_encode_floating_point(encoder, CborFloatType, &value); }
267CBOR_INLINE_API CborError cbor_encode_double(CborEncoder *encoder, double value)
268{ return cbor_encode_floating_point(encoder, CborDoubleType, &value); }
269
270CBOR_API CborError cbor_encoder_create_array(CborEncoder *parentEncoder, CborEncoder *arrayEncoder, size_t length);
271CBOR_API CborError cbor_encoder_create_map(CborEncoder *parentEncoder, CborEncoder *mapEncoder, size_t length);
272CBOR_API CborError cbor_encoder_close_container(CborEncoder *parentEncoder, const CborEncoder *containerEncoder);
273CBOR_API CborError cbor_encoder_close_container_checked(CborEncoder *parentEncoder, const CborEncoder *containerEncoder);
274
275CBOR_INLINE_API uint8_t *_cbor_encoder_get_buffer_pointer(const CborEncoder *encoder)
276{
277 return encoder->data.ptr;
278}
279
280CBOR_INLINE_API size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer)
281{
282 return (size_t)(encoder->data.ptr - buffer);
283}
284
285CBOR_INLINE_API size_t cbor_encoder_get_extra_bytes_needed(const CborEncoder *encoder)
286{
287 return encoder->end ? 0 : (size_t)encoder->data.bytes_needed;
288}
289#endif /* CBOR_NO_ENCODER_API */
290
291/* Parser API */
292
293enum CborParserGlobalFlags
294{
295 CborParserFlag_ExternalSource = 0x01
296};
297
298enum CborParserIteratorFlags
299{
300 /* used for all types, but not during string chunk iteration
301 * (values are static-asserted, don't change) */
302 CborIteratorFlag_IntegerValueIs64Bit = 0x01,
303 CborIteratorFlag_IntegerValueTooLarge = 0x02,
304
305 /* used only for CborIntegerType */
306 CborIteratorFlag_NegativeInteger = 0x04,
307
308 /* used only during string iteration */
309 CborIteratorFlag_BeforeFirstStringChunk = 0x04,
310 CborIteratorFlag_IteratingStringChunks = 0x08,
311
312 /* used for arrays, maps and strings, including during chunk iteration */
313 CborIteratorFlag_UnknownLength = 0x10,
314
315 /* used for maps, but must be kept for all types
316 * (ContainerIsMap value must be CborMapType - CborArrayType) */
317 CborIteratorFlag_ContainerIsMap = 0x20,
318 CborIteratorFlag_NextIsMapKey = 0x40
319};
320
321struct CborValue;
322struct CborParserOperations
323{
324 bool (*can_read_bytes)(void *token, size_t len);
325 void *(*read_bytes)(void *token, void *dst, size_t offset, size_t len);
326 void (*advance_bytes)(void *token, size_t len);
327 CborError (*transfer_string)(void *token, const void **userptr, size_t offset, size_t len);
328};
329
330struct CborParser
331{
332 union {
333 const uint8_t *end;
334 const struct CborParserOperations *ops;
335 } source;
336 enum CborParserGlobalFlags flags;
337};
338typedef struct CborParser CborParser;
339
341{
342 const CborParser *parser;
343 union {
344 const uint8_t *ptr;
345 void *token;
346 } source;
347 uint32_t remaining;
348 uint16_t extra;
349 uint8_t type;
350 uint8_t flags;
351};
352typedef struct CborValue CborValue;
353
354#ifndef CBOR_NO_PARSER_API
355CBOR_API CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it);
356CBOR_API CborError cbor_parser_init_reader(const struct CborParserOperations *ops, CborParser *parser, CborValue *it, void *token);
357
358CBOR_API CborError cbor_value_validate_basic(const CborValue *it);
359
360CBOR_INLINE_API bool cbor_value_at_end(const CborValue *it)
361{ return it->remaining == 0; }
362CBOR_INLINE_API const uint8_t *cbor_value_get_next_byte(const CborValue *it)
363{ return it->source.ptr; }
364CBOR_API CborError cbor_value_reparse(CborValue *it);
365CBOR_API CborError cbor_value_advance_fixed(CborValue *it);
366CBOR_API CborError cbor_value_advance(CborValue *it);
367CBOR_INLINE_API bool cbor_value_is_container(const CborValue *it)
368{ return it->type == CborArrayType || it->type == CborMapType; }
369CBOR_API CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed);
370CBOR_API CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed);
371
372CBOR_PRIVATE_API uint64_t _cbor_value_decode_int64_internal(const CborValue *value);
373CBOR_INLINE_API uint64_t _cbor_value_extract_int64_helper(const CborValue *value)
374{
375 return value->flags & CborIteratorFlag_IntegerValueTooLarge ?
376 _cbor_value_decode_int64_internal(value) : value->extra;
377}
378
379CBOR_INLINE_API bool cbor_value_is_valid(const CborValue *value)
380{ return value && value->type != CborInvalidType; }
381CBOR_INLINE_API CborType cbor_value_get_type(const CborValue *value)
382{ return (CborType)value->type; }
383
384/* Null & undefined type */
385CBOR_INLINE_API bool cbor_value_is_null(const CborValue *value)
386{ return value->type == CborNullType; }
387CBOR_INLINE_API bool cbor_value_is_undefined(const CborValue *value)
388{ return value->type == CborUndefinedType; }
389
390/* Booleans */
391CBOR_INLINE_API bool cbor_value_is_boolean(const CborValue *value)
392{ return value->type == CborBooleanType; }
393CBOR_INLINE_API CborError cbor_value_get_boolean(const CborValue *value, bool *result)
394{
395 assert(cbor_value_is_boolean(value));
396 *result = !!value->extra;
397 return CborNoError;
398}
399
400/* Simple types */
401CBOR_INLINE_API bool cbor_value_is_simple_type(const CborValue *value)
402{ return value->type == CborSimpleType; }
403CBOR_INLINE_API CborError cbor_value_get_simple_type(const CborValue *value, uint8_t *result)
404{
405 assert(cbor_value_is_simple_type(value));
406 *result = (uint8_t)value->extra;
407 return CborNoError;
408}
409
410/* Integers */
411CBOR_INLINE_API bool cbor_value_is_integer(const CborValue *value)
412{ return value->type == CborIntegerType; }
413CBOR_INLINE_API bool cbor_value_is_unsigned_integer(const CborValue *value)
414{ return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger) == 0; }
415CBOR_INLINE_API bool cbor_value_is_negative_integer(const CborValue *value)
416{ return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger); }
417
418CBOR_INLINE_API CborError cbor_value_get_raw_integer(const CborValue *value, uint64_t *result)
419{
420 assert(cbor_value_is_integer(value));
421 *result = _cbor_value_extract_int64_helper(value);
422 return CborNoError;
423}
424
425CBOR_INLINE_API CborError cbor_value_get_uint64(const CborValue *value, uint64_t *result)
426{
427 assert(cbor_value_is_unsigned_integer(value));
428 *result = _cbor_value_extract_int64_helper(value);
429 return CborNoError;
430}
431
432CBOR_INLINE_API CborError cbor_value_get_int64(const CborValue *value, int64_t *result)
433{
434 assert(cbor_value_is_integer(value));
435 *result = (int64_t) _cbor_value_extract_int64_helper(value);
436 if (value->flags & CborIteratorFlag_NegativeInteger)
437 *result = -*result - 1;
438 return CborNoError;
439}
440
441CBOR_INLINE_API CborError cbor_value_get_int(const CborValue *value, int *result)
442{
443 assert(cbor_value_is_integer(value));
444 *result = (int) _cbor_value_extract_int64_helper(value);
445 if (value->flags & CborIteratorFlag_NegativeInteger)
446 *result = -*result - 1;
447 return CborNoError;
448}
449
450CBOR_API CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result);
451CBOR_API CborError cbor_value_get_int_checked(const CborValue *value, int *result);
452
453CBOR_INLINE_API bool cbor_value_is_length_known(const CborValue *value)
454{ return (value->flags & CborIteratorFlag_UnknownLength) == 0; }
455
456/* Tags */
457CBOR_INLINE_API bool cbor_value_is_tag(const CborValue *value)
458{ return value->type == CborTagType; }
459CBOR_INLINE_API CborError cbor_value_get_tag(const CborValue *value, CborTag *result)
460{
461 assert(cbor_value_is_tag(value));
462 *result = _cbor_value_extract_int64_helper(value);
463 return CborNoError;
464}
465CBOR_API CborError cbor_value_skip_tag(CborValue *it);
466
467/* Strings */
468CBOR_INLINE_API bool cbor_value_is_byte_string(const CborValue *value)
469{ return value->type == CborByteStringType; }
470CBOR_INLINE_API bool cbor_value_is_text_string(const CborValue *value)
471{ return value->type == CborTextStringType; }
472
473CBOR_INLINE_API CborError cbor_value_get_string_length(const CborValue *value, size_t *length)
474{
475 uint64_t v;
476 assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value));
477 if (!cbor_value_is_length_known(value))
478 return CborErrorUnknownLength;
479 v = _cbor_value_extract_int64_helper(value);
480 *length = (size_t)v;
481 if (*length != v)
482 return CborErrorDataTooLarge;
483 return CborNoError;
484}
485
486CBOR_PRIVATE_API CborError _cbor_value_copy_string(const CborValue *value, void *buffer,
487 size_t *buflen, CborValue *next);
488CBOR_PRIVATE_API CborError _cbor_value_dup_string(const CborValue *value, void **buffer,
489 size_t *buflen, CborValue *next);
490
491CBOR_API CborError cbor_value_calculate_string_length(const CborValue *value, size_t *length);
492
493CBOR_INLINE_API CborError cbor_value_copy_text_string(const CborValue *value, char *buffer,
494 size_t *buflen, CborValue *next)
495{
496 assert(cbor_value_is_text_string(value));
497 return _cbor_value_copy_string(value, buffer, buflen, next);
498}
499CBOR_INLINE_API CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer,
500 size_t *buflen, CborValue *next)
501{
502 assert(cbor_value_is_byte_string(value));
503 return _cbor_value_copy_string(value, buffer, buflen, next);
504}
505
506CBOR_INLINE_API CborError cbor_value_dup_text_string(const CborValue *value, char **buffer,
507 size_t *buflen, CborValue *next)
508{
509 assert(cbor_value_is_text_string(value));
510 return _cbor_value_dup_string(value, (void **)buffer, buflen, next);
511}
512CBOR_INLINE_API CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer,
513 size_t *buflen, CborValue *next)
514{
515 assert(cbor_value_is_byte_string(value));
516 return _cbor_value_dup_string(value, (void **)buffer, buflen, next);
517}
518
519CBOR_PRIVATE_API CborError _cbor_value_get_string_chunk_size(const CborValue *value, size_t *len);
520CBOR_INLINE_API CborError cbor_value_get_string_chunk_size(const CborValue *value, size_t *len)
521{
522 assert(value->flags & CborIteratorFlag_IteratingStringChunks);
523 return _cbor_value_get_string_chunk_size(value, len);
524}
525
526CBOR_INLINE_API bool cbor_value_string_iteration_at_end(const CborValue *value)
527{
528 size_t dummy;
529 return cbor_value_get_string_chunk_size(value, &dummy) == CborErrorNoMoreStringChunks;
530}
531
532CBOR_PRIVATE_API CborError _cbor_value_begin_string_iteration(CborValue *value);
533CBOR_INLINE_API CborError cbor_value_begin_string_iteration(CborValue *value)
534{
535 assert(cbor_value_is_text_string(value) || cbor_value_is_byte_string(value));
536 assert(!(value->flags & CborIteratorFlag_IteratingStringChunks));
537 return _cbor_value_begin_string_iteration(value);
538}
539
540CBOR_PRIVATE_API CborError _cbor_value_finish_string_iteration(CborValue *value);
541CBOR_INLINE_API CborError cbor_value_finish_string_iteration(CborValue *value)
542{
543 assert(cbor_value_string_iteration_at_end(value));
544 return _cbor_value_finish_string_iteration(value);
545}
546
547CBOR_PRIVATE_API CborError _cbor_value_get_string_chunk(const CborValue *value, const void **bufferptr,
548 size_t *len, CborValue *next);
549CBOR_INLINE_API CborError cbor_value_get_text_string_chunk(const CborValue *value, const char **bufferptr,
550 size_t *len, CborValue *next)
551{
552 assert(cbor_value_is_text_string(value));
553 return _cbor_value_get_string_chunk(value, (const void **)bufferptr, len, next);
554}
555CBOR_INLINE_API CborError cbor_value_get_byte_string_chunk(const CborValue *value, const uint8_t **bufferptr,
556 size_t *len, CborValue *next)
557{
558 assert(cbor_value_is_byte_string(value));
559 return _cbor_value_get_string_chunk(value, (const void **)bufferptr, len, next);
560}
561
562CBOR_API CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result);
563
564/* Maps and arrays */
565CBOR_INLINE_API bool cbor_value_is_array(const CborValue *value)
566{ return value->type == CborArrayType; }
567CBOR_INLINE_API bool cbor_value_is_map(const CborValue *value)
568{ return value->type == CborMapType; }
569
570CBOR_INLINE_API CborError cbor_value_get_array_length(const CborValue *value, size_t *length)
571{
572 uint64_t v;
573 assert(cbor_value_is_array(value));
574 if (!cbor_value_is_length_known(value))
575 return CborErrorUnknownLength;
576 v = _cbor_value_extract_int64_helper(value);
577 *length = (size_t)v;
578 if (*length != v)
579 return CborErrorDataTooLarge;
580 return CborNoError;
581}
582
583CBOR_INLINE_API CborError cbor_value_get_map_length(const CborValue *value, size_t *length)
584{
585 uint64_t v;
586 assert(cbor_value_is_map(value));
587 if (!cbor_value_is_length_known(value))
588 return CborErrorUnknownLength;
589 v = _cbor_value_extract_int64_helper(value);
590 *length = (size_t)v;
591 if (*length != v)
592 return CborErrorDataTooLarge;
593 return CborNoError;
594}
595
596CBOR_API CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element);
597
598/* Floating point */
599CBOR_INLINE_API bool cbor_value_is_half_float(const CborValue *value)
600{ return value->type == CborHalfFloatType; }
601CBOR_API CborError cbor_value_get_half_float_as_float(const CborValue *value, float *result);
602CBOR_INLINE_API CborError cbor_value_get_half_float(const CborValue *value, void *result)
603{
604 assert(cbor_value_is_half_float(value));
605 assert((value->flags & CborIteratorFlag_IntegerValueTooLarge) == 0);
606
607 /* size has already been computed */
608 memcpy(result, &value->extra, sizeof(value->extra));
609 return CborNoError;
610}
611
612CBOR_INLINE_API bool cbor_value_is_float(const CborValue *value)
613{ return value->type == CborFloatType; }
614CBOR_INLINE_API CborError cbor_value_get_float(const CborValue *value, float *result)
615{
616 uint32_t data;
617 assert(cbor_value_is_float(value));
618 assert(value->flags & CborIteratorFlag_IntegerValueTooLarge);
619 data = (uint32_t)_cbor_value_decode_int64_internal(value);
620 memcpy(result, &data, sizeof(*result));
621 return CborNoError;
622}
623
624CBOR_INLINE_API bool cbor_value_is_double(const CborValue *value)
625{ return value->type == CborDoubleType; }
626CBOR_INLINE_API CborError cbor_value_get_double(const CborValue *value, double *result)
627{
628 uint64_t data;
629 assert(cbor_value_is_double(value));
630 assert(value->flags & CborIteratorFlag_IntegerValueTooLarge);
631 data = _cbor_value_decode_int64_internal(value);
632 memcpy(result, &data, sizeof(*result));
633 return CborNoError;
634}
635
636/* Validation API */
637#ifndef CBOR_NO_VALIDATION_API
638
639enum CborValidationFlags {
640 /* Bit mapping:
641 * bits 0-7 (8 bits): canonical format
642 * bits 8-11 (4 bits): canonical format & strict mode
643 * bits 12-20 (8 bits): strict mode
644 * bits 21-31 (10 bits): other
645 */
646
647 CborValidateShortestIntegrals = 0x0001,
648 CborValidateShortestFloatingPoint = 0x0002,
649 CborValidateShortestNumbers = CborValidateShortestIntegrals | CborValidateShortestFloatingPoint,
650 CborValidateNoIndeterminateLength = 0x0100,
651 CborValidateMapIsSorted = 0x0200 | CborValidateNoIndeterminateLength,
652
653 CborValidateCanonicalFormat = 0x0fff,
654
655 CborValidateMapKeysAreUnique = 0x1000 | CborValidateMapIsSorted,
656 CborValidateTagUse = 0x2000,
657 CborValidateUtf8 = 0x4000,
658
659 CborValidateStrictMode = 0xfff00,
660
661 CborValidateMapKeysAreString = 0x100000,
662 CborValidateNoUndefined = 0x200000,
663 CborValidateNoTags = 0x400000,
664 CborValidateFiniteFloatingPoint = 0x800000,
665 /* unused = 0x1000000, */
666 /* unused = 0x2000000, */
667
668 CborValidateNoUnknownSimpleTypesSA = 0x4000000,
669 CborValidateNoUnknownSimpleTypes = 0x8000000 | CborValidateNoUnknownSimpleTypesSA,
670 CborValidateNoUnknownTagsSA = 0x10000000,
671 CborValidateNoUnknownTagsSR = 0x20000000 | CborValidateNoUnknownTagsSA,
672 CborValidateNoUnknownTags = 0x40000000 | CborValidateNoUnknownTagsSR,
673
674 CborValidateCompleteData = (int)0x80000000,
675
676 CborValidateStrictest = (int)~0U,
677 CborValidateBasic = 0
678};
679
680CBOR_API CborError cbor_value_validate(const CborValue *it, uint32_t flags);
681#endif /* CBOR_NO_VALIDATION_API */
682
683/* Human-readable (dump) API */
684#ifndef CBOR_NO_PRETTY_API
685
686enum CborPrettyFlags {
687 CborPrettyNumericEncodingIndicators = 0x01,
688 CborPrettyTextualEncodingIndicators = 0,
689
690 CborPrettyIndicateIndeterminateLength = 0x02,
691 CborPrettyIndicateIndetermineLength = CborPrettyIndicateIndeterminateLength, /* deprecated */
692 CborPrettyIndicateOverlongNumbers = 0x04,
693
694 CborPrettyShowStringFragments = 0x100,
695 CborPrettyMergeStringFragments = 0,
696
697 CborPrettyDefaultFlags = CborPrettyIndicateIndeterminateLength
698};
699
700typedef CborError (*CborStreamFunction)(void *token, const char *fmt, ...)
701#ifdef __GNUC__
702 __attribute__((__format__(printf, 2, 3)))
703#endif
704;
705
706CBOR_API CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *token, CborValue *value, int flags);
707
708/* The following API requires a hosted C implementation (uses FILE*) */
709#if !defined(__STDC_HOSTED__) || __STDC_HOSTED__-0 == 1
710CBOR_API CborError cbor_value_to_pretty_advance_flags(FILE *out, CborValue *value, int flags);
711CBOR_API CborError cbor_value_to_pretty_advance(FILE *out, CborValue *value);
712CBOR_INLINE_API CborError cbor_value_to_pretty(FILE *out, const CborValue *value)
713{
714 CborValue copy = *value;
715 return cbor_value_to_pretty_advance_flags(out, &copy, CborPrettyDefaultFlags);
716}
717#endif /* __STDC_HOSTED__ check */
718
719#endif /* CBOR_NO_PRETTY_API */
720
721#endif /* CBOR_NO_PARSER_API */
722
723#ifdef __cplusplus
724}
725#endif
726
727#endif /* CBOR_H */
728
CborError cbor_value_to_pretty(FILE *out, const CborValue *value)
Converts the current CBOR type pointed to by value to its textual representation and writes it to the...
Definition cbor.h:712
CborError cbor_value_dup_text_string(const CborValue *value, char **buffer, size_t *buflen, CborValue *next)
Allocates memory for the string pointed by value and copies it into this buffer.
Definition cbor.h:506
CBOR_API CborError cbor_value_get_half_float_as_float(const CborValue *value, float *result)
Retrieves the CBOR half-precision floating point (16-bit) value that value points to,...
Definition cborparser_float.c:45
CBOR_API CborError cbor_value_to_pretty_advance_flags(FILE *out, CborValue *value, int flags)
Converts the current CBOR type pointed to by value to its textual representation and writes it to the...
Definition cborpretty_stdio.c:83
CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer, size_t *buflen, CborValue *next)
Allocates memory for the string pointed by value and copies it into this buffer.
Definition cbor.h:512
CBOR_API CborError cbor_value_to_pretty_advance(FILE *out, CborValue *value)
Converts the current CBOR type pointed to by value to its textual representation and writes it to the...
Definition cborpretty_stdio.c:63
CBOR_API const char * cbor_error_string(CborError error)
Returns the error string corresponding to the CBOR error condition error.
Definition cborerrorstrings.c:80
CBOR_API CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value)
Appends the negative 64-bit integer whose absolute value is absolute_value to the CBOR stream provide...
Definition cborencoder.c:370
CBOR_API CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length)
Appends the byte string string of length length to the CBOR stream provided by encoder.
Definition cborencoder.c:472
CBOR_API void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags)
Initializes a CborEncoder structure encoder by pointing it to buffer buffer of size size.
Definition cborencoder.c:204
CBOR_API CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value)
Appends the unsigned 64-bit integer value to the CBOR stream provided by encoder.
Definition cborencoder.c:357
CBOR_API CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length)
Appends the text string string of length length to the CBOR stream provided by encoder.
Definition cborencoder.c:484
CBOR_API CborError cbor_encoder_close_container(CborEncoder *parentEncoder, const CborEncoder *containerEncoder)
Closes the CBOR container (array or map) provided by containerEncoder and updates the CBOR stream pro...
Definition cborencoder.c:575
CBOR_API CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag)
Appends the CBOR tag tag to the CBOR stream provided by encoder.
Definition cborencoder.c:441
CBOR_API CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value)
Appends the CBOR Simple Type of value value to the CBOR stream provided by encoder.
Definition cborencoder.c:397
CBOR_API CborError cbor_encoder_create_array(CborEncoder *parentEncoder, CborEncoder *arrayEncoder, size_t length)
Creates a CBOR array in the CBOR stream provided by parentEncoder and initializes arrayEncoder so tha...
Definition cborencoder.c:532
CBOR_API CborError cbor_encoder_close_container_checked(CborEncoder *parentEncoder, const CborEncoder *containerEncoder)
Definition cborencoder_close_container_checked.c:53
CBOR_API CborError cbor_encoder_create_map(CborEncoder *parentEncoder, CborEncoder *mapEncoder, size_t length)
Creates a CBOR map in the CBOR stream provided by parentEncoder and initializes mapEncoder so that it...
Definition cborencoder.c:556
CBOR_API CborError cbor_encode_int(CborEncoder *encoder, int64_t value)
Appends the signed 64-bit integer value to the CBOR stream provided by encoder.
Definition cborencoder.c:381
CBOR_API CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value)
Appends the floating-point value of type fpType and pointed to by value to the CBOR stream provided b...
Definition cborencoder.c:418
CBOR_API CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed)
Creates a CborValue iterator pointing to the first element of the container represented by it and sav...
Definition cborparser.c:578
CBOR_API CborError cbor_value_validate_basic(const CborValue *it)
Performs a basic validation of the CBOR stream pointed by it and returns the error it found.
Definition cborparser.c:442
CBOR_API CborError cbor_value_skip_tag(CborValue *it)
Advances the CBOR value it until it no longer points to a tag.
Definition cborparser.c:551
CBOR_API CborError cbor_value_validate(const CborValue *it, uint32_t flags)
Performs a full validation, controlled by the flags options, of the CBOR stream pointed by it and ret...
Definition cborvalidation.c:645
CBOR_API CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed)
Updates it to point to the next element after the container.
Definition cborparser.c:627
CBOR_API CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result)
Retrieves the CBOR integer value that value points to and stores it in result.
Definition cborparser.c:812
CBOR_API CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it)
Initializes the CBOR parser for parsing size bytes beginning at buffer.
Definition cborparser.c:345
CBOR_API CborError cbor_value_advance_fixed(CborValue *it)
Advances the CBOR value it by one fixed-size position.
Definition cborparser.c:463
CBOR_API CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result)
Compares the entry value with the string string and stores the result in result.
Definition cborparser.c:1323
CBOR_API CborError cbor_value_calculate_string_length(const CborValue *value, size_t *length)
Calculates the length of the byte or text string that value points to and stores it in len.
Definition cborparser.c:963
CBOR_API CborError cbor_value_advance(CborValue *it)
Advances the CBOR value it by one element, skipping over containers.
Definition cborparser.c:515
CBOR_API CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element)
Attempts to find the value in map map that corresponds to the text string entry string.
Definition cborparser.c:1411
CBOR_API CborError cbor_value_get_int_checked(const CborValue *value, int *result)
Retrieves the CBOR integer value that value points to and stores it in result.
Definition cborparser.c:852
CBOR_API CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *token, CborValue *value, int flags)
Converts the current CBOR type pointed by value to its textual representation and writes it to the st...
Definition cborpretty.c:578
Structure used to encode to CBOR.
Definition cbor.h:227
This type contains one value parsed from the CBOR stream.
Definition cbor.h:341