xref: /freebsd/contrib/libcbor/src/cbor/common.h (revision abd872540f24cfc7dbd1ea29b6918c7082a22108)
110ff414cSEd Maste /*
210ff414cSEd Maste  * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
310ff414cSEd Maste  *
410ff414cSEd Maste  * libcbor is free software; you can redistribute it and/or modify
510ff414cSEd Maste  * it under the terms of the MIT license. See LICENSE for details.
610ff414cSEd Maste  */
710ff414cSEd Maste 
810ff414cSEd Maste #ifndef LIBCBOR_COMMON_H
910ff414cSEd Maste #define LIBCBOR_COMMON_H
1010ff414cSEd Maste 
1110ff414cSEd Maste #include <assert.h>
1210ff414cSEd Maste #include <stdbool.h>
1310ff414cSEd Maste #include <stddef.h>
1410ff414cSEd Maste #include <stdint.h>
1510ff414cSEd Maste #include <stdlib.h>
165d3e7166SEd Maste 
1710ff414cSEd Maste #include "cbor/cbor_export.h"
1810ff414cSEd Maste #include "cbor/configuration.h"
1910ff414cSEd Maste #include "data.h"
2010ff414cSEd Maste 
2110ff414cSEd Maste #ifdef __cplusplus
2210ff414cSEd Maste extern "C" {
2310ff414cSEd Maste 
2410ff414cSEd Maste /**
255d3e7166SEd Maste  * C99 is not a subset of C++ -- 'restrict' qualifier is not a part of the
2610ff414cSEd Maste  * language. This is a workaround to keep it in C headers -- compilers allow
2710ff414cSEd Maste  * linking non-restrict signatures with restrict implementations.
2810ff414cSEd Maste  *
2910ff414cSEd Maste  * If you know a nicer way, please do let me know.
3010ff414cSEd Maste  */
3110ff414cSEd Maste #define CBOR_RESTRICT_POINTER
3210ff414cSEd Maste 
3310ff414cSEd Maste #else
3410ff414cSEd Maste 
3510ff414cSEd Maste // MSVC + C++ workaround
3610ff414cSEd Maste #define CBOR_RESTRICT_POINTER CBOR_RESTRICT_SPECIFIER
3710ff414cSEd Maste 
3810ff414cSEd Maste #endif
3910ff414cSEd Maste 
4010ff414cSEd Maste static const uint8_t cbor_major_version = CBOR_MAJOR_VERSION;
4110ff414cSEd Maste static const uint8_t cbor_minor_version = CBOR_MINOR_VERSION;
4210ff414cSEd Maste static const uint8_t cbor_patch_version = CBOR_PATCH_VERSION;
4310ff414cSEd Maste 
4410ff414cSEd Maste #define CBOR_VERSION               \
455d3e7166SEd Maste   _CBOR_TO_STR(CBOR_MAJOR_VERSION) \
465d3e7166SEd Maste   "." _CBOR_TO_STR(CBOR_MINOR_VERSION) "." _CBOR_TO_STR(CBOR_PATCH_VERSION)
4710ff414cSEd Maste #define CBOR_HEX_VERSION \
4810ff414cSEd Maste   ((CBOR_MAJOR_VERSION << 16) | (CBOR_MINOR_VERSION << 8) | CBOR_PATCH_VERSION)
4910ff414cSEd Maste 
5010ff414cSEd Maste /* http://stackoverflow.com/questions/1644868/c-define-macro-for-debug-printing
5110ff414cSEd Maste  */
5210ff414cSEd Maste #ifdef DEBUG
5310ff414cSEd Maste #include <stdio.h>
545d3e7166SEd Maste #define _cbor_debug_print(fmt, ...)                                     \
5510ff414cSEd Maste   do {                                                                  \
5610ff414cSEd Maste     if (DEBUG)                                                          \
5710ff414cSEd Maste       fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, \
5810ff414cSEd Maste               __VA_ARGS__);                                             \
5910ff414cSEd Maste   } while (0)
605d3e7166SEd Maste extern bool _cbor_enable_assert;
615d3e7166SEd Maste // Like `assert`, but can be dynamically disabled in tests to allow testing
625d3e7166SEd Maste // invalid behaviors.
635d3e7166SEd Maste #define CBOR_ASSERT(e) assert(!_cbor_enable_assert || (e))
645d3e7166SEd Maste #define _CBOR_TEST_DISABLE_ASSERT(block) \
655d3e7166SEd Maste   do {                                   \
665d3e7166SEd Maste     _cbor_enable_assert = false;         \
675d3e7166SEd Maste     block _cbor_enable_assert = true;    \
685d3e7166SEd Maste   } while (0)
6910ff414cSEd Maste #else
7010ff414cSEd Maste #define debug_print(fmt, ...) \
7110ff414cSEd Maste   do {                        \
7210ff414cSEd Maste   } while (0)
735d3e7166SEd Maste #define CBOR_ASSERT(e)
745d3e7166SEd Maste #define _CBOR_TEST_DISABLE_ASSERT(block) \
755d3e7166SEd Maste   do {                                   \
765d3e7166SEd Maste     block                                \
775d3e7166SEd Maste   } while (0)
7810ff414cSEd Maste #endif
7910ff414cSEd Maste 
805d3e7166SEd Maste #define _CBOR_TO_STR_(x) #x
815d3e7166SEd Maste #define _CBOR_TO_STR(x) _CBOR_TO_STR_(x) /* enables proper double expansion */
825d3e7166SEd Maste 
835d3e7166SEd Maste #ifdef __GNUC__
845d3e7166SEd Maste #define _CBOR_UNUSED(x) __attribute__((__unused__)) x
855d3e7166SEd Maste // TODO(https://github.com/PJK/libcbor/issues/247): Prefer [[nodiscard]] if
865d3e7166SEd Maste // available
875d3e7166SEd Maste #define _CBOR_NODISCARD __attribute__((warn_unused_result))
885d3e7166SEd Maste #elif defined(_MSC_VER)
895d3e7166SEd Maste #define _CBOR_UNUSED(x) __pragma(warning(suppress : 4100 4101)) x
905d3e7166SEd Maste #define _CBOR_NODISCARD
915d3e7166SEd Maste #else
925d3e7166SEd Maste #define _CBOR_UNUSED(x) x
935d3e7166SEd Maste #define _CBOR_NODISCARD
945d3e7166SEd Maste #endif
955d3e7166SEd Maste 
965d3e7166SEd Maste typedef void *(*_cbor_malloc_t)(size_t);
975d3e7166SEd Maste typedef void *(*_cbor_realloc_t)(void *, size_t);
985d3e7166SEd Maste typedef void (*_cbor_free_t)(void *);
995d3e7166SEd Maste 
1005d3e7166SEd Maste CBOR_EXPORT extern _cbor_malloc_t _cbor_malloc;
1015d3e7166SEd Maste CBOR_EXPORT extern _cbor_realloc_t _cbor_realloc;
1025d3e7166SEd Maste CBOR_EXPORT extern _cbor_free_t _cbor_free;
10310ff414cSEd Maste 
10410ff414cSEd Maste // Macro to short-circuit builder functions when memory allocation fails
10510ff414cSEd Maste #define _CBOR_NOTNULL(cbor_item) \
10610ff414cSEd Maste   do {                           \
10710ff414cSEd Maste     if (cbor_item == NULL) {     \
10810ff414cSEd Maste       return NULL;               \
10910ff414cSEd Maste     }                            \
11010ff414cSEd Maste   } while (0)
11110ff414cSEd Maste 
11210ff414cSEd Maste // Macro to short-circuit builders when memory allocation of nested data fails
11310ff414cSEd Maste #define _CBOR_DEPENDENT_NOTNULL(cbor_item, pointer) \
11410ff414cSEd Maste   do {                                              \
11510ff414cSEd Maste     if (pointer == NULL) {                          \
1165d3e7166SEd Maste       _cbor_free(cbor_item);                        \
11710ff414cSEd Maste       return NULL;                                  \
11810ff414cSEd Maste     }                                               \
11910ff414cSEd Maste   } while (0)
12010ff414cSEd Maste 
12110ff414cSEd Maste /** Sets the memory management routines to use.
12210ff414cSEd Maste  *
1235d3e7166SEd Maste  * By default, libcbor will use the standard library `malloc`, `realloc`, and
1245d3e7166SEd Maste  * `free`.
12510ff414cSEd Maste  *
12610ff414cSEd Maste  * \rst
12710ff414cSEd Maste  * .. warning:: This function modifies the global state and should therefore be
12810ff414cSEd Maste  *  used accordingly. Changing the memory handlers while allocated items exist
12910ff414cSEd Maste  *  will result in a ``free``/``malloc`` mismatch. This function is not thread
13010ff414cSEd Maste  *  safe with respect to both itself and all the other *libcbor* functions that
13110ff414cSEd Maste  *  work with the heap.
13210ff414cSEd Maste  *
13310ff414cSEd Maste  * .. note:: `realloc` implementation must correctly support `NULL` reallocation
13410ff414cSEd Maste  *  (see e.g. http://en.cppreference.com/w/c/memory/realloc)
13510ff414cSEd Maste  * \endrst
13610ff414cSEd Maste  *
13710ff414cSEd Maste  * @param custom_malloc malloc implementation
13810ff414cSEd Maste  * @param custom_realloc realloc implementation
13910ff414cSEd Maste  * @param custom_free free implementation
14010ff414cSEd Maste  */
14110ff414cSEd Maste CBOR_EXPORT void cbor_set_allocs(_cbor_malloc_t custom_malloc,
14210ff414cSEd Maste                                  _cbor_realloc_t custom_realloc,
14310ff414cSEd Maste                                  _cbor_free_t custom_free);
14410ff414cSEd Maste 
14510ff414cSEd Maste /*
14610ff414cSEd Maste  * ============================================================================
14710ff414cSEd Maste  * Type manipulation
14810ff414cSEd Maste  * ============================================================================
14910ff414cSEd Maste  */
15010ff414cSEd Maste 
15110ff414cSEd Maste /** Get the type of the item
15210ff414cSEd Maste  *
1535d3e7166SEd Maste  * @param item
15410ff414cSEd Maste  * @return The type
15510ff414cSEd Maste  */
1565d3e7166SEd Maste _CBOR_NODISCARD
15710ff414cSEd Maste CBOR_EXPORT cbor_type cbor_typeof(
15810ff414cSEd Maste     const cbor_item_t *item); /* Will be inlined iff link-time opt is enabled */
15910ff414cSEd Maste 
160*abd87254SEd Maste /* Standard CBOR Major item types */
16110ff414cSEd Maste 
16210ff414cSEd Maste /** Does the item have the appropriate major type?
1635d3e7166SEd Maste  * @param item the item
16410ff414cSEd Maste  * @return Is the item an #CBOR_TYPE_UINT?
16510ff414cSEd Maste  */
1665d3e7166SEd Maste _CBOR_NODISCARD
16710ff414cSEd Maste CBOR_EXPORT bool cbor_isa_uint(const cbor_item_t *item);
16810ff414cSEd Maste 
16910ff414cSEd Maste /** Does the item have the appropriate major type?
1705d3e7166SEd Maste  * @param item the item
17110ff414cSEd Maste  * @return Is the item a #CBOR_TYPE_NEGINT?
17210ff414cSEd Maste  */
1735d3e7166SEd Maste _CBOR_NODISCARD
17410ff414cSEd Maste CBOR_EXPORT bool cbor_isa_negint(const cbor_item_t *item);
17510ff414cSEd Maste 
17610ff414cSEd Maste /** Does the item have the appropriate major type?
1775d3e7166SEd Maste  * @param item the item
17810ff414cSEd Maste  * @return Is the item a #CBOR_TYPE_BYTESTRING?
17910ff414cSEd Maste  */
1805d3e7166SEd Maste _CBOR_NODISCARD
18110ff414cSEd Maste CBOR_EXPORT bool cbor_isa_bytestring(const cbor_item_t *item);
18210ff414cSEd Maste 
18310ff414cSEd Maste /** Does the item have the appropriate major type?
1845d3e7166SEd Maste  * @param item the item
18510ff414cSEd Maste  * @return Is the item a #CBOR_TYPE_STRING?
18610ff414cSEd Maste  */
1875d3e7166SEd Maste _CBOR_NODISCARD
18810ff414cSEd Maste CBOR_EXPORT bool cbor_isa_string(const cbor_item_t *item);
18910ff414cSEd Maste 
19010ff414cSEd Maste /** Does the item have the appropriate major type?
1915d3e7166SEd Maste  * @param item the item
19210ff414cSEd Maste  * @return Is the item an #CBOR_TYPE_ARRAY?
19310ff414cSEd Maste  */
1945d3e7166SEd Maste _CBOR_NODISCARD
19510ff414cSEd Maste CBOR_EXPORT bool cbor_isa_array(const cbor_item_t *item);
19610ff414cSEd Maste 
19710ff414cSEd Maste /** Does the item have the appropriate major type?
1985d3e7166SEd Maste  * @param item the item
19910ff414cSEd Maste  * @return Is the item a #CBOR_TYPE_MAP?
20010ff414cSEd Maste  */
2015d3e7166SEd Maste _CBOR_NODISCARD
20210ff414cSEd Maste CBOR_EXPORT bool cbor_isa_map(const cbor_item_t *item);
20310ff414cSEd Maste 
20410ff414cSEd Maste /** Does the item have the appropriate major type?
2055d3e7166SEd Maste  * @param item the item
20610ff414cSEd Maste  * @return Is the item a #CBOR_TYPE_TAG?
20710ff414cSEd Maste  */
2085d3e7166SEd Maste _CBOR_NODISCARD
20910ff414cSEd Maste CBOR_EXPORT bool cbor_isa_tag(const cbor_item_t *item);
21010ff414cSEd Maste 
21110ff414cSEd Maste /** Does the item have the appropriate major type?
2125d3e7166SEd Maste  * @param item the item
21310ff414cSEd Maste  * @return Is the item a #CBOR_TYPE_FLOAT_CTRL?
21410ff414cSEd Maste  */
2155d3e7166SEd Maste _CBOR_NODISCARD
21610ff414cSEd Maste CBOR_EXPORT bool cbor_isa_float_ctrl(const cbor_item_t *item);
21710ff414cSEd Maste 
21810ff414cSEd Maste /* Practical types with respect to their semantics (but not tag values) */
21910ff414cSEd Maste 
22010ff414cSEd Maste /** Is the item an integer, either positive or negative?
2215d3e7166SEd Maste  * @param item the item
22210ff414cSEd Maste  * @return  Is the item an integer, either positive or negative?
22310ff414cSEd Maste  */
2245d3e7166SEd Maste _CBOR_NODISCARD
22510ff414cSEd Maste CBOR_EXPORT bool cbor_is_int(const cbor_item_t *item);
22610ff414cSEd Maste 
22710ff414cSEd Maste /** Is the item an a floating point number?
2285d3e7166SEd Maste  * @param item the item
22910ff414cSEd Maste  * @return  Is the item a floating point number?
23010ff414cSEd Maste  */
2315d3e7166SEd Maste _CBOR_NODISCARD
23210ff414cSEd Maste CBOR_EXPORT bool cbor_is_float(const cbor_item_t *item);
23310ff414cSEd Maste 
23410ff414cSEd Maste /** Is the item an a boolean?
2355d3e7166SEd Maste  * @param item the item
23610ff414cSEd Maste  * @return  Is the item a boolean?
23710ff414cSEd Maste  */
2385d3e7166SEd Maste _CBOR_NODISCARD
23910ff414cSEd Maste CBOR_EXPORT bool cbor_is_bool(const cbor_item_t *item);
24010ff414cSEd Maste 
24110ff414cSEd Maste /** Does this item represent `null`
24210ff414cSEd Maste  *
24310ff414cSEd Maste  * \rst
24410ff414cSEd Maste  * .. warning:: This is in no way related to the value of the pointer. Passing a
24510ff414cSEd Maste  *  null pointer will most likely result in a crash.
24610ff414cSEd Maste  * \endrst
24710ff414cSEd Maste  *
2485d3e7166SEd Maste  * @param item the item
24910ff414cSEd Maste  * @return  Is the item (CBOR logical) null?
25010ff414cSEd Maste  */
2515d3e7166SEd Maste _CBOR_NODISCARD
25210ff414cSEd Maste CBOR_EXPORT bool cbor_is_null(const cbor_item_t *item);
25310ff414cSEd Maste 
25410ff414cSEd Maste /** Does this item represent `undefined`
25510ff414cSEd Maste  *
25610ff414cSEd Maste  * \rst
25710ff414cSEd Maste  * .. warning:: Care must be taken to distinguish nulls and undefined values in
25810ff414cSEd Maste  *  C.
25910ff414cSEd Maste  * \endrst
26010ff414cSEd Maste  *
2615d3e7166SEd Maste  * @param item the item
26210ff414cSEd Maste  * @return Is the item (CBOR logical) undefined?
26310ff414cSEd Maste  */
2645d3e7166SEd Maste _CBOR_NODISCARD
26510ff414cSEd Maste CBOR_EXPORT bool cbor_is_undef(const cbor_item_t *item);
26610ff414cSEd Maste 
26710ff414cSEd Maste /*
26810ff414cSEd Maste  * ============================================================================
26910ff414cSEd Maste  * Memory management
27010ff414cSEd Maste  * ============================================================================
27110ff414cSEd Maste  */
27210ff414cSEd Maste 
2735d3e7166SEd Maste /** Increases the item's reference count by one
27410ff414cSEd Maste  *
2755d3e7166SEd Maste  * Constant complexity; items referring to this one or items being referred to
2765d3e7166SEd Maste  * are not updated.
27710ff414cSEd Maste  *
2785d3e7166SEd Maste  * This function can be used to extend reference counting to client code.
2795d3e7166SEd Maste  *
2805d3e7166SEd Maste  * @param item Reference to an item
2815d3e7166SEd Maste  * @return The input \p item
28210ff414cSEd Maste  */
28310ff414cSEd Maste CBOR_EXPORT cbor_item_t *cbor_incref(cbor_item_t *item);
28410ff414cSEd Maste 
2855d3e7166SEd Maste /** Decreases the item's reference count by one, deallocating the item if needed
28610ff414cSEd Maste  *
2875d3e7166SEd Maste  * In case the item is deallocated, the reference count of all items this item
2885d3e7166SEd Maste  * references will also be #cbor_decref 'ed recursively.
28910ff414cSEd Maste  *
2905d3e7166SEd Maste  * @param item Reference to an item. Will be set to `NULL` if deallocated
29110ff414cSEd Maste  */
29210ff414cSEd Maste CBOR_EXPORT void cbor_decref(cbor_item_t **item);
29310ff414cSEd Maste 
2945d3e7166SEd Maste /** Decreases the item's reference count by one, deallocating the item if needed
29510ff414cSEd Maste  *
29610ff414cSEd Maste  * Convenience wrapper for #cbor_decref when its set-to-null behavior is not
29710ff414cSEd Maste  * needed
29810ff414cSEd Maste  *
2995d3e7166SEd Maste  * @param item Reference to an item
30010ff414cSEd Maste  */
30110ff414cSEd Maste CBOR_EXPORT void cbor_intermediate_decref(cbor_item_t *item);
30210ff414cSEd Maste 
3035d3e7166SEd Maste /** Get the item's reference count
30410ff414cSEd Maste  *
30510ff414cSEd Maste  * \rst
30610ff414cSEd Maste  * .. warning:: This does *not* account for transitive references.
30710ff414cSEd Maste  * \endrst
30810ff414cSEd Maste  *
3095d3e7166SEd Maste  * @todo Add some inline examples for reference counting
3105d3e7166SEd Maste  *
3115d3e7166SEd Maste  * @param item the item
31210ff414cSEd Maste  * @return the reference count
31310ff414cSEd Maste  */
3145d3e7166SEd Maste _CBOR_NODISCARD
31510ff414cSEd Maste CBOR_EXPORT size_t cbor_refcount(const cbor_item_t *item);
31610ff414cSEd Maste 
31710ff414cSEd Maste /** Provides CPP-like move construct
31810ff414cSEd Maste  *
31910ff414cSEd Maste  * Decreases the reference count by one, but does not deallocate the item even
32010ff414cSEd Maste  * if its refcount reaches zero. This is useful for passing intermediate values
32110ff414cSEd Maste  * to functions that increase reference count. Should only be used with
32210ff414cSEd Maste  * functions that `incref` their arguments.
32310ff414cSEd Maste  *
32410ff414cSEd Maste  * \rst
32510ff414cSEd Maste  * .. warning:: If the item is moved without correctly increasing the reference
32610ff414cSEd Maste  *  count afterwards, the memory will be leaked.
32710ff414cSEd Maste  * \endrst
32810ff414cSEd Maste  *
3295d3e7166SEd Maste  * @param item Reference to an item
33010ff414cSEd Maste  * @return the item with reference count decreased by one
33110ff414cSEd Maste  */
3325d3e7166SEd Maste _CBOR_NODISCARD
33310ff414cSEd Maste CBOR_EXPORT cbor_item_t *cbor_move(cbor_item_t *item);
33410ff414cSEd Maste 
33510ff414cSEd Maste #ifdef __cplusplus
33610ff414cSEd Maste }
33710ff414cSEd Maste #endif
33810ff414cSEd Maste 
33910ff414cSEd Maste #endif  // LIBCBOR_COMMON_H
340