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