1 /****************************************************************************
3 ** Copyright (C) 2015 Intel Corporation
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:
12 ** The above copyright notice and this permission notice shall be included in
13 ** all copies or substantial portions of the Software.
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
23 ****************************************************************************/
42 /* Some systems fail to define SIZE_MAX in <stdint.h>, even though C99 requires it...
43 * Conversion from signed to unsigned is defined in 6.3.1.3 (Signed and unsigned integers) p2,
44 * which says: "the value is converted by repeatedly adding or subtracting one more than the
45 * maximum value that can be represented in the new type until the value is in the range of the
47 * So -1 gets converted to size_t by adding SIZE_MAX + 1, which results in SIZE_MAX.
49 # define SIZE_MAX ((size_t)-1)
55 #ifndef CBOR_PRIVATE_API
56 # define CBOR_PRIVATE_API
58 #ifndef CBOR_INLINE_API
59 # if defined(__cplusplus)
60 # define CBOR_INLINE_API inline
62 # define CBOR_INLINE_API static inline
66 typedef enum CborType {
67 CborIntegerType = 0x00,
68 CborByteStringType = 0x40,
69 CborTextStringType = 0x60,
73 CborSimpleType = 0xe0,
74 CborBooleanType = 0xf5,
76 CborUndefinedType = 0xf7,
77 CborHalfFloatType = 0xf9,
79 CborDoubleType = 0xfb,
81 CborInvalidType = 0xff /* equivalent to the break byte, so it will never be used */
84 typedef uint64_t CborTag;
85 typedef enum CborKnownTags {
86 CborDateTimeStringTag = 0, /* RFC 3339 format: YYYY-MM-DD hh:mm:ss+zzzz */
87 CborUnixTime_tTag = 1,
88 CborPositiveBignumTag = 2,
89 CborNegativeBignumTag = 3,
92 CborExpectedBase64urlTag = 21,
93 CborExpectedBase64Tag = 22,
94 CborExpectedBase16Tag = 23,
96 CborBase64urlTag = 33,
98 CborRegularExpressionTag = 35,
99 CborMimeMessageTag = 36, /* RFC 2045-2047 */
100 CborSignatureTag = 55799
105 typedef enum CborError {
108 /* errors in all modes */
110 CborErrorUnknownLength, /* request for length in array, map, or string with indeterminate length */
111 CborErrorAdvancePastEOF,
114 /* parser errors streaming errors */
115 CborErrorGarbageAtEnd = 256,
116 CborErrorUnexpectedEOF,
117 CborErrorUnexpectedBreak,
118 CborErrorUnknownType, /* can only heppen in major type 7 */
119 CborErrorIllegalType, /* type not allowed here */
120 CborErrorIllegalNumber,
121 CborErrorIllegalSimpleType, /* types of value less than 32 encoded in two bytes */
123 /* parser errors in strict mode parsing only */
124 CborErrorUnknownSimpleType = 512,
126 CborErrorInappropriateTagForType,
127 CborErrorDuplicateObjectKeys,
128 CborErrorInvalidUtf8TextString,
131 CborErrorTooManyItems = 768,
132 CborErrorTooFewItems,
134 /* internal implementation errors */
135 CborErrorDataTooLarge = 1024,
136 CborErrorNestingTooDeep,
137 CborErrorUnsupportedType,
139 /* errors in converting to JSON */
140 CborErrorJsonObjectKeyIsAggregate,
141 CborErrorJsonObjectKeyNotString,
143 CborErrorOutOfMemory = ~0U / 2 + 1,
144 CborErrorInternalError = ~0U
147 CBOR_API const char *cbor_error_string(CborError error);
154 ptrdiff_t bytes_needed;
160 typedef struct CborEncoder CborEncoder;
162 static const size_t CborIndefiniteLength = SIZE_MAX;
164 CBOR_API void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags);
165 CBOR_API CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value);
166 CBOR_API CborError cbor_encode_int(CborEncoder *encoder, int64_t value);
167 CBOR_API CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value);
168 CBOR_API CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value);
169 CBOR_API CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag);
170 CBOR_API CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length);
171 CBOR_INLINE_API CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string)
172 { return cbor_encode_text_string(encoder, string, strlen(string)); }
173 CBOR_API CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length);
174 CBOR_API CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value);
176 CBOR_INLINE_API CborError cbor_encode_boolean(CborEncoder *encoder, bool value)
177 { return cbor_encode_simple_value(encoder, (int)value - 1 + (CborBooleanType & 0x1f)); }
178 CBOR_INLINE_API CborError cbor_encode_null(CborEncoder *encoder)
179 { return cbor_encode_simple_value(encoder, CborNullType & 0x1f); }
180 CBOR_INLINE_API CborError cbor_encode_undefined(CborEncoder *encoder)
181 { return cbor_encode_simple_value(encoder, CborUndefinedType & 0x1f); }
183 CBOR_INLINE_API CborError cbor_encode_half_float(CborEncoder *encoder, const void *value)
184 { return cbor_encode_floating_point(encoder, CborHalfFloatType, value); }
185 CBOR_INLINE_API CborError cbor_encode_float(CborEncoder *encoder, float value)
186 { return cbor_encode_floating_point(encoder, CborFloatType, &value); }
187 CBOR_INLINE_API CborError cbor_encode_double(CborEncoder *encoder, double value)
188 { return cbor_encode_floating_point(encoder, CborDoubleType, &value); }
190 CBOR_API CborError cbor_encoder_create_array(CborEncoder *encoder, CborEncoder *arrayEncoder, size_t length);
191 CBOR_API CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length);
192 CBOR_API CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder);
193 CBOR_API CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder);
197 enum CborParserIteratorFlags
199 CborIteratorFlag_IntegerValueTooLarge = 0x01,
200 CborIteratorFlag_NegativeInteger = 0x02,
201 CborIteratorFlag_UnknownLength = 0x04,
202 CborIteratorFlag_ContainerIsMap = 0x20
210 typedef struct CborParser CborParser;
214 const CborParser *parser;
221 typedef struct CborValue CborValue;
223 CBOR_API CborError cbor_parser_init(const uint8_t *buffer, size_t size, int flags, CborParser *parser, CborValue *it);
225 CBOR_INLINE_API bool cbor_value_at_end(const CborValue *it)
226 { return it->remaining == 0; }
227 CBOR_API CborError cbor_value_advance_fixed(CborValue *it);
228 CBOR_API CborError cbor_value_advance(CborValue *it);
229 CBOR_INLINE_API bool cbor_value_is_container(const CborValue *it)
230 { return it->type == CborArrayType || it->type == CborMapType; }
231 CBOR_API CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed);
232 CBOR_API CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed);
234 CBOR_PRIVATE_API uint64_t _cbor_value_decode_int64_internal(const CborValue *value);
235 CBOR_INLINE_API uint64_t _cbor_value_extract_int64_helper(const CborValue *value)
237 return value->flags & CborIteratorFlag_IntegerValueTooLarge ?
238 _cbor_value_decode_int64_internal(value) : value->extra;
241 CBOR_INLINE_API bool cbor_value_is_valid(const CborValue *value)
242 { return value && value->type != CborInvalidType; }
243 CBOR_INLINE_API CborType cbor_value_get_type(const CborValue *value)
244 { return (CborType)value->type; }
246 /* Null & undefined type */
247 CBOR_INLINE_API bool cbor_type_is_null(const CborValue *value)
248 { return value->type == CborNullType; }
249 CBOR_INLINE_API bool cbor_type_is_undefined(const CborValue *value)
250 { return value->type == CborUndefinedType; }
253 CBOR_INLINE_API bool cbor_value_is_boolean(const CborValue *value)
254 { return value->type == CborBooleanType; }
255 CBOR_INLINE_API CborError cbor_value_get_boolean(const CborValue *value, bool *result)
257 assert(cbor_value_is_boolean(value));
258 *result = value->extra;
263 CBOR_INLINE_API bool cbor_value_is_simple_type(const CborValue *value)
264 { return value->type == CborSimpleType; }
265 CBOR_INLINE_API CborError cbor_value_get_simple_type(const CborValue *value, uint8_t *result)
267 assert(cbor_value_is_simple_type(value));
268 *result = value->extra;
273 CBOR_INLINE_API bool cbor_value_is_integer(const CborValue *value)
274 { return value->type == CborIntegerType; }
275 CBOR_INLINE_API bool cbor_value_is_unsigned_integer(const CborValue *value)
276 { return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger) == 0; }
277 CBOR_INLINE_API bool cbor_value_is_negative_integer(const CborValue *value)
278 { return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger); }
280 CBOR_INLINE_API CborError cbor_value_get_raw_integer(const CborValue *value, uint64_t *result)
282 assert(cbor_value_is_integer(value));
283 *result = _cbor_value_extract_int64_helper(value);
287 CBOR_INLINE_API CborError cbor_value_get_uint64(const CborValue *value, uint64_t *result)
289 assert(cbor_value_is_unsigned_integer(value));
290 *result = _cbor_value_extract_int64_helper(value);
294 CBOR_INLINE_API CborError cbor_value_get_int64(const CborValue *value, int64_t *result)
296 assert(cbor_value_is_integer(value));
297 *result = (int64_t) _cbor_value_extract_int64_helper(value);
298 if (value->flags & CborIteratorFlag_NegativeInteger)
299 *result = -*result - 1;
303 CBOR_INLINE_API CborError cbor_value_get_int(const CborValue *value, int *result)
305 assert(cbor_value_is_integer(value));
306 *result = (int) _cbor_value_extract_int64_helper(value);
307 if (value->flags & CborIteratorFlag_NegativeInteger)
308 *result = -*result - 1;
312 CBOR_API CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result);
313 CBOR_API CborError cbor_value_get_int_checked(const CborValue *value, int *result);
315 CBOR_INLINE_API bool cbor_value_is_length_known(const CborValue *value)
316 { return (value->flags & CborIteratorFlag_UnknownLength) == 0; }
319 CBOR_INLINE_API bool cbor_value_is_tag(const CborValue *value)
320 { return value->type == CborTagType; }
321 CBOR_INLINE_API CborError cbor_value_get_tag(const CborValue *value, CborTag *result)
323 assert(cbor_value_is_tag(value));
324 *result = _cbor_value_extract_int64_helper(value);
327 CBOR_API CborError cbor_value_skip_tag(CborValue *it);
330 CBOR_INLINE_API bool cbor_value_is_byte_string(const CborValue *value)
331 { return value->type == CborByteStringType; }
332 CBOR_INLINE_API bool cbor_value_is_text_string(const CborValue *value)
333 { return value->type == CborTextStringType; }
335 CBOR_INLINE_API CborError cbor_value_get_string_length(const CborValue *value, size_t *length)
337 assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value));
338 if (!cbor_value_is_length_known(value))
339 return CborErrorUnknownLength;
340 uint64_t v = _cbor_value_extract_int64_helper(value);
343 return CborErrorDataTooLarge;
347 CBOR_PRIVATE_API CborError _cbor_value_copy_string(const CborValue *value, void *buffer,
348 size_t *buflen, CborValue *next);
349 CBOR_PRIVATE_API CborError _cbor_value_dup_string(const CborValue *value, void **buffer,
350 size_t *buflen, CborValue *next);
352 CBOR_API CborError cbor_value_calculate_string_length(const CborValue *value, size_t *length);
354 CBOR_INLINE_API CborError cbor_value_copy_text_string(const CborValue *value, char *buffer,
355 size_t *buflen, CborValue *next)
357 assert(cbor_value_is_text_string(value));
358 return _cbor_value_copy_string(value, buffer, buflen, next);
360 CBOR_INLINE_API CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer,
361 size_t *buflen, CborValue *next)
363 assert(cbor_value_is_byte_string(value));
364 return _cbor_value_copy_string(value, buffer, buflen, next);
367 CBOR_INLINE_API CborError cbor_value_dup_text_string(const CborValue *value, char **buffer,
368 size_t *buflen, CborValue *next)
370 assert(cbor_value_is_text_string(value));
371 return _cbor_value_dup_string(value, (void **)buffer, buflen, next);
373 CBOR_INLINE_API CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer,
374 size_t *buflen, CborValue *next)
376 assert(cbor_value_is_byte_string(value));
377 return _cbor_value_dup_string(value, (void **)buffer, buflen, next);
380 /* ### TBD: partial reading API */
382 CBOR_API CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result);
384 /* Maps and arrays */
385 CBOR_INLINE_API bool cbor_value_is_array(const CborValue *value)
386 { return value->type == CborArrayType; }
387 CBOR_INLINE_API bool cbor_value_is_map(const CborValue *value)
388 { return value->type == CborMapType; }
390 CBOR_INLINE_API CborError cbor_value_get_array_length(const CborValue *value, size_t *length)
392 assert(cbor_value_is_array(value));
393 if (!cbor_value_is_length_known(value))
394 return CborErrorUnknownLength;
395 uint64_t v = _cbor_value_extract_int64_helper(value);
398 return CborErrorDataTooLarge;
402 CBOR_INLINE_API CborError cbor_value_get_map_length(const CborValue *value, size_t *length)
404 assert(cbor_value_is_map(value));
405 if (!cbor_value_is_length_known(value))
406 return CborErrorUnknownLength;
407 uint64_t v = _cbor_value_extract_int64_helper(value);
410 return CborErrorDataTooLarge;
414 CBOR_API CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element);
417 CBOR_API CborError cbor_value_get_half_float(const CborValue *value, void *result);
418 CBOR_INLINE_API CborError cbor_value_get_float(const CborValue *value, float *result)
420 assert(value->type == CborFloatType);
421 assert(value->flags & CborIteratorFlag_IntegerValueTooLarge);
422 uint32_t data = _cbor_value_decode_int64_internal(value);
423 memcpy(result, &data, sizeof(*result));
427 CBOR_INLINE_API CborError cbor_value_get_double(const CborValue *value, double *result)
429 assert(value->type == CborDoubleType);
430 assert(value->flags & CborIteratorFlag_IntegerValueTooLarge);
431 uint64_t data = _cbor_value_decode_int64_internal(value);
432 memcpy(result, &data, sizeof(*result));
436 /* Human-readable (dump) API */
437 CBOR_API CborError cbor_value_to_pretty_advance(FILE *out, CborValue *value);
438 CBOR_INLINE_API CborError cbor_value_to_pretty(FILE *out, const CborValue *value)
440 CborValue copy = *value;
441 return cbor_value_to_pretty_advance(out, ©);