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