1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 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 #include "tinycbor/config.h"
29 
30 #include <assert.h>
31 #include <limits.h>
32 #include <stddef.h>
33 #include <stdint.h>
34 #include <string.h>
35 #include <stdio.h>
36 
37 #ifdef __cplusplus
38 extern "C" {
39 #else
40 #include <stdbool.h>
41 #endif
42 
43 #ifndef SIZE_MAX
44 /* Some systems fail to define SIZE_MAX in <stdint.h>, even though C99 requires it...
45  * Conversion from signed to unsigned is defined in 6.3.1.3 (Signed and unsigned integers) p2,
46  * which says: "the value is converted by repeatedly adding or subtracting one more than the
47  * maximum value that can be represented in the new type until the value is in the range of the
48  * new type."
49  * So -1 gets converted to size_t by adding SIZE_MAX + 1, which results in SIZE_MAX.
50  */
51 #  define SIZE_MAX ((size_t)-1)
52 #endif
53 
54 #ifndef CBOR_API
55 #  define CBOR_API
56 #endif
57 #ifndef CBOR_PRIVATE_API
58 #  define CBOR_PRIVATE_API
59 #endif
60 #ifndef CBOR_INLINE_API
61 #  if defined(__cplusplus)
62 #    define CBOR_INLINE inline
63 #    define CBOR_INLINE_API inline
64 #  else
65 #    define CBOR_INLINE_API static CBOR_INLINE
66 #    if defined(_MSC_VER)
67 #      define CBOR_INLINE __inline
68 #    elif defined(__GNUC__)
69 #      define CBOR_INLINE __inline__
70 #    elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
71 #      define CBOR_INLINE inline
72 #    else
73 #      define CBOR_INLINE
74 #    endif
75 #  endif
76 #endif
77 
78 typedef enum CborType {
79     CborIntegerType     = 0x00,
80     CborByteStringType  = 0x40,
81     CborTextStringType  = 0x60,
82     CborArrayType       = 0x80,
83     CborMapType         = 0xa0,
84     CborTagType         = 0xc0,
85     CborSimpleType      = 0xe0,
86     CborBooleanType     = 0xf5,
87     CborNullType        = 0xf6,
88     CborUndefinedType   = 0xf7,
89     CborHalfFloatType   = 0xf9,
90     CborFloatType       = 0xfa,
91     CborDoubleType      = 0xfb,
92 
93     CborInvalidType     = 0xff              /* equivalent to the break byte, so it will never be used */
94 } CborType;
95 
96 typedef uint64_t CborTag;
97 typedef enum CborKnownTags {
98     CborDateTimeStringTag          = 0,        /* RFC 3339 format: YYYY-MM-DD hh:mm:ss+zzzz */
99     CborUnixTime_tTag              = 1,
100     CborPositiveBignumTag          = 2,
101     CborNegativeBignumTag          = 3,
102     CborDecimalTag                 = 4,
103     CborBigfloatTag                = 5,
104     CborExpectedBase64urlTag       = 21,
105     CborExpectedBase64Tag          = 22,
106     CborExpectedBase16Tag          = 23,
107     CborUriTag                     = 32,
108     CborBase64urlTag               = 33,
109     CborBase64Tag                  = 34,
110     CborRegularExpressionTag       = 35,
111     CborMimeMessageTag             = 36,       /* RFC 2045-2047 */
112     CborSignatureTag               = 55799
113 } CborKnownTags;
114 
115 /* Error API */
116 
117 typedef enum CborError {
118     CborNoError = 0,
119 
120     /* errors in all modes */
121     CborUnknownError,
122     CborErrorUnknownLength,         /* request for length in array, map, or string with indeterminate length */
123     CborErrorAdvancePastEOF,
124     CborErrorIO,
125 
126     /* parser errors streaming errors */
127     CborErrorGarbageAtEnd = 256,
128     CborErrorUnexpectedEOF,
129     CborErrorUnexpectedBreak,
130     CborErrorUnknownType,           /* can only heppen in major type 7 */
131     CborErrorIllegalType,           /* type not allowed here */
132     CborErrorIllegalNumber,
133     CborErrorIllegalSimpleType,     /* types of value less than 32 encoded in two bytes */
134 
135     /* parser errors in strict mode parsing only */
136     CborErrorUnknownSimpleType = 512,
137     CborErrorUnknownTag,
138     CborErrorInappropriateTagForType,
139     CborErrorDuplicateObjectKeys,
140     CborErrorInvalidUtf8TextString,
141 
142     /* encoder errors */
143     CborErrorTooManyItems = 768,
144     CborErrorTooFewItems,
145 
146     /* internal implementation errors */
147     CborErrorDataTooLarge = 1024,
148     CborErrorNestingTooDeep,
149     CborErrorUnsupportedType,
150 
151     /* errors in converting to JSON */
152     CborErrorJsonObjectKeyIsAggregate,
153     CborErrorJsonObjectKeyNotString,
154     CborErrorJsonNotImplemented,
155 
156     CborErrorOutOfMemory = ~0U / 2 + 1,
157     CborErrorInternalError = ~0U
158 } CborError;
159 
160 CBOR_API const char *cbor_error_string(CborError error);
161 
162 struct cbor_encoder_writer;
163 
164 typedef int (cbor_encoder_write)(struct cbor_encoder_writer *, const char *data, int len);
165 
166 typedef struct cbor_encoder_writer {
167     cbor_encoder_write *write;
168     int                 bytes_written;
169 } cbor_encoder_writer;
170 
171 struct cbor_iovec {
172     void   *iov_base;
173     size_t iov_len;
174 };
175 
176 /* Encoder API */
177 struct CborEncoder {
178     cbor_encoder_writer *writer;
179     void *writer_arg;
180     size_t added;
181     int flags;
182 };
183 typedef struct CborEncoder CborEncoder;
184 
185 static const size_t CborIndefiniteLength = SIZE_MAX;
186 
187 
188 CBOR_API void cbor_encoder_init(CborEncoder *encoder, cbor_encoder_writer *pwriter, int flags);
189 CBOR_API CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value);
190 CBOR_API CborError cbor_encode_int(CborEncoder *encoder, int64_t value);
191 CBOR_API CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value);
192 CBOR_API CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value);
193 CBOR_API CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag);
194 CBOR_API CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length);
cbor_encode_text_stringz(CborEncoder * encoder,const char * string)195 CBOR_INLINE_API CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string)
196 { return cbor_encode_text_string(encoder, string, strlen(string)); }
197 CBOR_API CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length);
198 CBOR_API CborError cbor_encode_byte_iovec(CborEncoder *encoder,
199                                           const struct cbor_iovec iov[],
200                                           int iov_len);
201 CBOR_API CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value);
cbor_encode_bytes_written(CborEncoder * encoder)202 CBOR_INLINE_API int cbor_encode_bytes_written(CborEncoder *encoder)
203 {   return encoder->writer->bytes_written; }
cbor_encode_boolean(CborEncoder * encoder,bool value)204 CBOR_INLINE_API CborError cbor_encode_boolean(CborEncoder *encoder, bool value)
205 { return cbor_encode_simple_value(encoder, (int)value - 1 + (CborBooleanType & 0x1f)); }
cbor_encode_null(CborEncoder * encoder)206 CBOR_INLINE_API CborError cbor_encode_null(CborEncoder *encoder)
207 { return cbor_encode_simple_value(encoder, CborNullType & 0x1f); }
cbor_encode_undefined(CborEncoder * encoder)208 CBOR_INLINE_API CborError cbor_encode_undefined(CborEncoder *encoder)
209 { return cbor_encode_simple_value(encoder, CborUndefinedType & 0x1f); }
210 
cbor_encode_half_float(CborEncoder * encoder,const void * value)211 CBOR_INLINE_API CborError cbor_encode_half_float(CborEncoder *encoder, const void *value)
212 { return cbor_encode_floating_point(encoder, CborHalfFloatType, value); }
cbor_encode_float(CborEncoder * encoder,float value)213 CBOR_INLINE_API CborError cbor_encode_float(CborEncoder *encoder, float value)
214 { return cbor_encode_floating_point(encoder, CborFloatType, &value); }
cbor_encode_double(CborEncoder * encoder,double value)215 CBOR_INLINE_API CborError cbor_encode_double(CborEncoder *encoder, double value)
216 { return cbor_encode_floating_point(encoder, CborDoubleType, &value); }
217 
218 CBOR_API CborError cbor_encoder_create_array(CborEncoder *encoder, CborEncoder *arrayEncoder, size_t length);
219 CBOR_API CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length);
220 CBOR_API CborError cbor_encoder_create_indef_text_string(CborEncoder *encoder, CborEncoder *stringEncoder);
221 CBOR_API CborError cbor_encoder_create_indef_byte_string(CborEncoder *encoder, CborEncoder *stringEncoder);
222 CBOR_API CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder);
223 CBOR_API CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder);
224 
225 /* Parser API */
226 
227 enum CborParserIteratorFlags
228 {
229     CborIteratorFlag_IntegerValueTooLarge   = 0x01,
230     CborIteratorFlag_NegativeInteger        = 0x02,
231     CborIteratorFlag_UnknownLength          = 0x04,
232     CborIteratorFlag_ContainerIsMap         = 0x20
233 };
234 
235 struct cbor_decoder_reader;
236 
237 typedef uint8_t (cbor_reader_get8)(struct cbor_decoder_reader *d, int offset);
238 typedef uint16_t (cbor_reader_get16)(struct cbor_decoder_reader *d, int offset);
239 typedef uint32_t (cbor_reader_get32)(struct cbor_decoder_reader *d, int offset);
240 typedef uint64_t (cbor_reader_get64)(struct cbor_decoder_reader *d, int offset);
241 typedef uintptr_t (cbor_memcmp)(struct cbor_decoder_reader *d, char *buf, int offset, size_t len);
242 typedef uintptr_t (cbor_memcpy)(struct cbor_decoder_reader *d, char *buf, int offset, size_t len);
243 
244 struct cbor_decoder_reader {
245     cbor_reader_get8  *get8;
246     cbor_reader_get16 *get16;
247     cbor_reader_get32 *get32;
248     cbor_reader_get64 *get64;
249     cbor_memcmp       *cmp;
250     cbor_memcpy       *cpy;
251     size_t             message_size;
252 };
253 
254 struct CborParser
255 {
256     struct cbor_decoder_reader *d;
257     int end;
258     int flags;
259 };
260 typedef struct CborParser CborParser;
261 
262 struct CborValue
263 {
264     const CborParser *parser;
265     int offset;
266     uint32_t remaining;
267     uint16_t extra;
268     uint8_t type;
269     uint8_t flags;
270 };
271 typedef struct CborValue CborValue;
272 
273 CBOR_API CborError cbor_parser_init(struct cbor_decoder_reader *d, int flags, CborParser *parser, CborValue *it);
274 
cbor_value_at_end(const CborValue * it)275 CBOR_INLINE_API bool cbor_value_at_end(const CborValue *it)
276 { return it->remaining == 0; }
277 CBOR_API CborError cbor_value_advance_fixed(CborValue *it);
278 CBOR_API CborError cbor_value_advance(CborValue *it);
cbor_value_is_container(const CborValue * it)279 CBOR_INLINE_API bool cbor_value_is_container(const CborValue *it)
280 { return it->type == CborArrayType || it->type == CborMapType; }
281 CBOR_API CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed);
282 CBOR_API CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed);
283 
284 CBOR_PRIVATE_API uint64_t _cbor_value_decode_int64_internal(const CborValue *value);
_cbor_value_extract_int64_helper(const CborValue * value)285 CBOR_INLINE_API uint64_t _cbor_value_extract_int64_helper(const CborValue *value)
286 {
287     return value->flags & CborIteratorFlag_IntegerValueTooLarge ?
288                 _cbor_value_decode_int64_internal(value) : value->extra;
289 }
290 
cbor_value_is_valid(const CborValue * value)291 CBOR_INLINE_API bool cbor_value_is_valid(const CborValue *value)
292 { return value && value->type != CborInvalidType; }
cbor_value_get_type(const CborValue * value)293 CBOR_INLINE_API CborType cbor_value_get_type(const CborValue *value)
294 { return (CborType)value->type; }
295 
296 /* Null & undefined type */
cbor_value_is_null(const CborValue * value)297 CBOR_INLINE_API bool cbor_value_is_null(const CborValue *value)
298 { return value->type == CborNullType; }
cbor_value_is_undefined(const CborValue * value)299 CBOR_INLINE_API bool cbor_value_is_undefined(const CborValue *value)
300 { return value->type == CborUndefinedType; }
301 
302 /* Booleans */
cbor_value_is_boolean(const CborValue * value)303 CBOR_INLINE_API bool cbor_value_is_boolean(const CborValue *value)
304 { return value->type == CborBooleanType; }
cbor_value_get_boolean(const CborValue * value,bool * result)305 CBOR_INLINE_API CborError cbor_value_get_boolean(const CborValue *value, bool *result)
306 {
307     assert(cbor_value_is_boolean(value));
308     *result = !!value->extra;
309     return CborNoError;
310 }
311 
312 /* Simple types */
cbor_value_is_simple_type(const CborValue * value)313 CBOR_INLINE_API bool cbor_value_is_simple_type(const CborValue *value)
314 { return value->type == CborSimpleType; }
cbor_value_get_simple_type(const CborValue * value,uint8_t * result)315 CBOR_INLINE_API CborError cbor_value_get_simple_type(const CborValue *value, uint8_t *result)
316 {
317     assert(cbor_value_is_simple_type(value));
318     *result = (uint8_t)value->extra;
319     return CborNoError;
320 }
321 
322 /* Integers */
cbor_value_is_integer(const CborValue * value)323 CBOR_INLINE_API bool cbor_value_is_integer(const CborValue *value)
324 { return value->type == CborIntegerType; }
cbor_value_is_unsigned_integer(const CborValue * value)325 CBOR_INLINE_API bool cbor_value_is_unsigned_integer(const CborValue *value)
326 { return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger) == 0; }
cbor_value_is_negative_integer(const CborValue * value)327 CBOR_INLINE_API bool cbor_value_is_negative_integer(const CborValue *value)
328 { return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger); }
329 
cbor_value_get_raw_integer(const CborValue * value,uint64_t * result)330 CBOR_INLINE_API CborError cbor_value_get_raw_integer(const CborValue *value, uint64_t *result)
331 {
332     assert(cbor_value_is_integer(value));
333     *result = _cbor_value_extract_int64_helper(value);
334     return CborNoError;
335 }
336 
cbor_value_get_uint64(const CborValue * value,uint64_t * result)337 CBOR_INLINE_API CborError cbor_value_get_uint64(const CborValue *value, uint64_t *result)
338 {
339     assert(cbor_value_is_unsigned_integer(value));
340     *result = _cbor_value_extract_int64_helper(value);
341     return CborNoError;
342 }
343 
cbor_value_get_int64(const CborValue * value,int64_t * result)344 CBOR_INLINE_API CborError cbor_value_get_int64(const CborValue *value, int64_t *result)
345 {
346     assert(cbor_value_is_integer(value));
347     *result = (int64_t) _cbor_value_extract_int64_helper(value);
348     if (value->flags & CborIteratorFlag_NegativeInteger)
349         *result = -*result - 1;
350     return CborNoError;
351 }
352 
cbor_value_get_int(const CborValue * value,int * result)353 CBOR_INLINE_API CborError cbor_value_get_int(const CborValue *value, int *result)
354 {
355     assert(cbor_value_is_integer(value));
356     *result = (int) _cbor_value_extract_int64_helper(value);
357     if (value->flags & CborIteratorFlag_NegativeInteger)
358         *result = -*result - 1;
359     return CborNoError;
360 }
361 
362 CBOR_API CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result);
363 CBOR_API CborError cbor_value_get_int_checked(const CborValue *value, int *result);
364 
cbor_value_is_length_known(const CborValue * value)365 CBOR_INLINE_API bool cbor_value_is_length_known(const CborValue *value)
366 { return (value->flags & CborIteratorFlag_UnknownLength) == 0; }
367 
368 /* Tags */
cbor_value_is_tag(const CborValue * value)369 CBOR_INLINE_API bool cbor_value_is_tag(const CborValue *value)
370 { return value->type == CborTagType; }
cbor_value_get_tag(const CborValue * value,CborTag * result)371 CBOR_INLINE_API CborError cbor_value_get_tag(const CborValue *value, CborTag *result)
372 {
373     assert(cbor_value_is_tag(value));
374     *result = _cbor_value_extract_int64_helper(value);
375     return CborNoError;
376 }
377 CBOR_API CborError cbor_value_skip_tag(CborValue *it);
378 
379 /* Strings */
cbor_value_is_byte_string(const CborValue * value)380 CBOR_INLINE_API bool cbor_value_is_byte_string(const CborValue *value)
381 { return value->type == CborByteStringType; }
cbor_value_is_text_string(const CborValue * value)382 CBOR_INLINE_API bool cbor_value_is_text_string(const CborValue *value)
383 { return value->type == CborTextStringType; }
384 
cbor_value_get_string_length(const CborValue * value,size_t * length)385 CBOR_INLINE_API CborError cbor_value_get_string_length(const CborValue *value, size_t *length)
386 {
387     assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value));
388     if (!cbor_value_is_length_known(value))
389         return CborErrorUnknownLength;
390     uint64_t v = _cbor_value_extract_int64_helper(value);
391     *length = v;
392     if (*length != v)
393         return CborErrorDataTooLarge;
394     return CborNoError;
395 }
396 
397 CBOR_PRIVATE_API CborError _cbor_value_copy_string(const CborValue *value, void *buffer,
398                                                    size_t *buflen, CborValue *next);
399 CBOR_PRIVATE_API CborError _cbor_value_dup_string(const CborValue *value, void **buffer,
400                                                   size_t *buflen, CborValue *next);
401 
402 CBOR_API CborError cbor_value_calculate_string_length(const CborValue *value, size_t *length);
403 
cbor_value_copy_text_string(const CborValue * value,char * buffer,size_t * buflen,CborValue * next)404 CBOR_INLINE_API CborError cbor_value_copy_text_string(const CborValue *value, char *buffer,
405                                                       size_t *buflen, CborValue *next)
406 {
407     assert(cbor_value_is_text_string(value));
408     return _cbor_value_copy_string(value, buffer, buflen, next);
409 }
cbor_value_copy_byte_string(const CborValue * value,uint8_t * buffer,size_t * buflen,CborValue * next)410 CBOR_INLINE_API CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer,
411                                                       size_t *buflen, CborValue *next)
412 {
413     assert(cbor_value_is_byte_string(value));
414     return _cbor_value_copy_string(value, buffer, buflen, next);
415 }
416 
cbor_value_dup_text_string(const CborValue * value,char ** buffer,size_t * buflen,CborValue * next)417 CBOR_INLINE_API CborError cbor_value_dup_text_string(const CborValue *value, char **buffer,
418                                                      size_t *buflen, CborValue *next)
419 {
420     assert(cbor_value_is_text_string(value));
421     return _cbor_value_dup_string(value, (void **)buffer, buflen, next);
422 }
cbor_value_dup_byte_string(const CborValue * value,uint8_t ** buffer,size_t * buflen,CborValue * next)423 CBOR_INLINE_API CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer,
424                                                      size_t *buflen, CborValue *next)
425 {
426     assert(cbor_value_is_byte_string(value));
427     return _cbor_value_dup_string(value, (void **)buffer, buflen, next);
428 }
429 
430 /* ### TBD: partial reading API */
431 
432 CBOR_API CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result);
433 
434 /* Maps and arrays */
cbor_value_is_array(const CborValue * value)435 CBOR_INLINE_API bool cbor_value_is_array(const CborValue *value)
436 { return value->type == CborArrayType; }
cbor_value_is_map(const CborValue * value)437 CBOR_INLINE_API bool cbor_value_is_map(const CborValue *value)
438 { return value->type == CborMapType; }
439 
cbor_value_get_array_length(const CborValue * value,size_t * length)440 CBOR_INLINE_API CborError cbor_value_get_array_length(const CborValue *value, size_t *length)
441 {
442     assert(cbor_value_is_array(value));
443     if (!cbor_value_is_length_known(value))
444         return CborErrorUnknownLength;
445     uint64_t v = _cbor_value_extract_int64_helper(value);
446     *length = v;
447     if (*length != v)
448         return CborErrorDataTooLarge;
449     return CborNoError;
450 }
451 
cbor_value_get_map_length(const CborValue * value,size_t * length)452 CBOR_INLINE_API CborError cbor_value_get_map_length(const CborValue *value, size_t *length)
453 {
454     assert(cbor_value_is_map(value));
455     if (!cbor_value_is_length_known(value))
456         return CborErrorUnknownLength;
457     uint64_t v = _cbor_value_extract_int64_helper(value);
458     *length = v;
459     if (*length != v)
460         return CborErrorDataTooLarge;
461     return CborNoError;
462 }
463 
464 CBOR_API CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element);
465 
466 /* Floating point */
cbor_value_is_half_float(const CborValue * value)467 CBOR_INLINE_API bool cbor_value_is_half_float(const CborValue *value)
468 { return value->type == CborHalfFloatType; }
469 CBOR_API CborError cbor_value_get_half_float(const CborValue *value, void *result);
470 
cbor_value_is_float(const CborValue * value)471 CBOR_INLINE_API bool cbor_value_is_float(const CborValue *value)
472 { return value->type == CborFloatType; }
cbor_value_get_float(const CborValue * value,float * result)473 CBOR_INLINE_API CborError cbor_value_get_float(const CborValue *value, float *result)
474 {
475     assert(cbor_value_is_float(value));
476     assert(value->flags & CborIteratorFlag_IntegerValueTooLarge);
477     uint32_t data = (uint32_t)_cbor_value_decode_int64_internal(value);
478     memcpy(result, &data, sizeof(*result));
479     return CborNoError;
480 }
481 
cbor_value_is_double(const CborValue * value)482 CBOR_INLINE_API bool cbor_value_is_double(const CborValue *value)
483 { return value->type == CborDoubleType; }
cbor_value_get_double(const CborValue * value,double * result)484 CBOR_INLINE_API CborError cbor_value_get_double(const CborValue *value, double *result)
485 {
486     assert(cbor_value_is_double(value));
487     assert(value->flags & CborIteratorFlag_IntegerValueTooLarge);
488     uint64_t data = _cbor_value_decode_int64_internal(value);
489     memcpy(result, &data, sizeof(*result));
490     return CborNoError;
491 }
492 
493 /* Human-readable (dump) API */
494 CBOR_API CborError cbor_value_to_pretty_advance(FILE *out, CborValue *value);
cbor_value_to_pretty(FILE * out,const CborValue * value)495 CBOR_INLINE_API CborError cbor_value_to_pretty(FILE *out, const CborValue *value)
496 {
497     CborValue copy = *value;
498     return cbor_value_to_pretty_advance(out, &copy);
499 }
500 
501 struct mgmt_cbuf {
502     struct CborParser  parser;
503     struct CborEncoder encoder;
504     struct CborValue   it;
505 };
506 
507 #ifdef __cplusplus
508 }
509 #endif
510 
511 #endif /* CBOR_H */
512 
513