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); |
246 | CBOR_INLINE_API CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string) |
247 | { return cbor_encode_text_string(encoder, string, length: strlen(s: 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 | |
251 | CBOR_INLINE_API CborError cbor_encode_boolean(CborEncoder *encoder, bool value) |
252 | { return cbor_encode_simple_value(encoder, value: (int)value - 1 + (CborBooleanType & 0x1f)); } |
253 | CBOR_INLINE_API CborError cbor_encode_null(CborEncoder *encoder) |
254 | { return cbor_encode_simple_value(encoder, value: CborNullType & 0x1f); } |
255 | CBOR_INLINE_API CborError cbor_encode_undefined(CborEncoder *encoder) |
256 | { return cbor_encode_simple_value(encoder, value: CborUndefinedType & 0x1f); } |
257 | |
258 | CBOR_INLINE_API CborError cbor_encode_half_float(CborEncoder *encoder, const void *value) |
259 | { return cbor_encode_floating_point(encoder, fpType: CborHalfFloatType, value); } |
260 | CBOR_API CborError cbor_encode_float_as_half_float(CborEncoder *encoder, float value); |
261 | CBOR_INLINE_API CborError cbor_encode_float(CborEncoder *encoder, float value) |
262 | { return cbor_encode_floating_point(encoder, fpType: CborFloatType, value: &value); } |
263 | CBOR_INLINE_API CborError cbor_encode_double(CborEncoder *encoder, double value) |
264 | { return cbor_encode_floating_point(encoder, fpType: CborDoubleType, value: &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 | |
271 | CBOR_INLINE_API uint8_t *_cbor_encoder_get_buffer_pointer(const CborEncoder *encoder) |
272 | { |
273 | return encoder->data.ptr; |
274 | } |
275 | |
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 | |
281 | CBOR_INLINE_API size_t (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 ; |
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 | |
356 | CBOR_INLINE_API bool cbor_value_at_end(const CborValue *it) |
357 | { return it->remaining == 0; } |
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); |
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); |
369 | CBOR_INLINE_API uint64_t (const CborValue *value) |
370 | { |
371 | return value->flags & CborIteratorFlag_IntegerValueTooLarge ? |
372 | _cbor_value_decode_int64_internal(value) : value->extra; |
373 | } |
374 | |
375 | CBOR_INLINE_API bool cbor_value_is_valid(const CborValue *value) |
376 | { return value && value->type != CborInvalidType; } |
377 | CBOR_INLINE_API CborType cbor_value_get_type(const CborValue *value) |
378 | { return (CborType)value->type; } |
379 | |
380 | /* Null & undefined type */ |
381 | CBOR_INLINE_API bool cbor_value_is_null(const CborValue *value) |
382 | { return value->type == CborNullType; } |
383 | CBOR_INLINE_API bool cbor_value_is_undefined(const CborValue *value) |
384 | { return value->type == CborUndefinedType; } |
385 | |
386 | /* Booleans */ |
387 | CBOR_INLINE_API bool cbor_value_is_boolean(const CborValue *value) |
388 | { return value->type == CborBooleanType; } |
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 */ |
397 | CBOR_INLINE_API bool cbor_value_is_simple_type(const CborValue *value) |
398 | { return value->type == CborSimpleType; } |
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 */ |
407 | CBOR_INLINE_API bool cbor_value_is_integer(const CborValue *value) |
408 | { return value->type == CborIntegerType; } |
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; } |
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 | |
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 | |
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 | |
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 | |
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 | |
449 | CBOR_INLINE_API bool cbor_value_is_length_known(const CborValue *value) |
450 | { return (value->flags & CborIteratorFlag_UnknownLength) == 0; } |
451 | |
452 | /* Tags */ |
453 | CBOR_INLINE_API bool cbor_value_is_tag(const CborValue *value) |
454 | { return value->type == CborTagType; } |
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 */ |
464 | CBOR_INLINE_API bool cbor_value_is_byte_string(const CborValue *value) |
465 | { return value->type == CborByteStringType; } |
466 | CBOR_INLINE_API bool cbor_value_is_text_string(const CborValue *value) |
467 | { return value->type == CborTextStringType; } |
468 | |
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 | |
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 | } |
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 | |
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, buffer: (void **)buffer, buflen, next); |
507 | } |
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, buffer: (void **)buffer, buflen, next); |
513 | } |
514 | |
515 | CBOR_PRIVATE_API CborError _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 | |
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, len: &dummy) == CborErrorNoMoreStringChunks; |
526 | } |
527 | |
528 | CBOR_PRIVATE_API CborError _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); |
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); |
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, bufferptr: (const void **)bufferptr, len, next); |
550 | } |
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, bufferptr: (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 */ |
561 | CBOR_INLINE_API bool cbor_value_is_array(const CborValue *value) |
562 | { return value->type == CborArrayType; } |
563 | CBOR_INLINE_API bool cbor_value_is_map(const CborValue *value) |
564 | { return value->type == CborMapType; } |
565 | |
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 | |
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 */ |
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); |
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(dest: result, src: &value->extra, n: sizeof(value->extra)); |
605 | return CborNoError; |
606 | } |
607 | |
608 | CBOR_INLINE_API bool cbor_value_is_float(const CborValue *value) |
609 | { return value->type == CborFloatType; } |
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(dest: result, src: &data, n: sizeof(*result)); |
617 | return CborNoError; |
618 | } |
619 | |
620 | CBOR_INLINE_API bool cbor_value_is_double(const CborValue *value) |
621 | { return value->type == CborDoubleType; } |
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(dest: result, src: &data, n: 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); |
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, value: ©, flags: 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 | |