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