1da0d961cSdjm /* 2d3425be1Sdjm * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com> 3da0d961cSdjm * 4da0d961cSdjm * libcbor is free software; you can redistribute it and/or modify 5da0d961cSdjm * it under the terms of the MIT license. See LICENSE for details. 6da0d961cSdjm */ 7da0d961cSdjm 8da0d961cSdjm #ifndef LIBCBOR_COMMON_H 9da0d961cSdjm #define LIBCBOR_COMMON_H 10da0d961cSdjm 119e5c2ddcSdjm #include <assert.h> 129e5c2ddcSdjm #include <stdbool.h> 13da0d961cSdjm #include <stddef.h> 14da0d961cSdjm #include <stdint.h> 159e5c2ddcSdjm #include <stdlib.h> 164dcc46c4Sdjm #include "cbor/cbor_export.h" 17da0d961cSdjm #include "cbor/configuration.h" 189e5c2ddcSdjm #include "data.h" 19da0d961cSdjm 20da0d961cSdjm #ifdef __cplusplus 21da0d961cSdjm extern "C" { 22da0d961cSdjm 239e5c2ddcSdjm /** 244dcc46c4Sdjm * C99 is not a subset of C++ -- 'restrict' qualifier is not a part of the 259e5c2ddcSdjm * language. This is a workaround to keep it in C headers -- compilers allow 269e5c2ddcSdjm * linking non-restrict signatures with restrict implementations. 27da0d961cSdjm * 28da0d961cSdjm * If you know a nicer way, please do let me know. 29da0d961cSdjm */ 30da0d961cSdjm #define CBOR_RESTRICT_POINTER 31da0d961cSdjm 32da0d961cSdjm #else 33da0d961cSdjm 34da0d961cSdjm // MSVC + C++ workaround 35da0d961cSdjm #define CBOR_RESTRICT_POINTER CBOR_RESTRICT_SPECIFIER 36da0d961cSdjm 37da0d961cSdjm #endif 38da0d961cSdjm 39da0d961cSdjm static const uint8_t cbor_major_version = CBOR_MAJOR_VERSION; 40da0d961cSdjm static const uint8_t cbor_minor_version = CBOR_MINOR_VERSION; 41da0d961cSdjm static const uint8_t cbor_patch_version = CBOR_PATCH_VERSION; 42da0d961cSdjm 439e5c2ddcSdjm #define CBOR_VERSION \ 444dcc46c4Sdjm _CBOR_TO_STR(CBOR_MAJOR_VERSION) \ 454dcc46c4Sdjm "." _CBOR_TO_STR(CBOR_MINOR_VERSION) "." _CBOR_TO_STR(CBOR_PATCH_VERSION) 469e5c2ddcSdjm #define CBOR_HEX_VERSION \ 479e5c2ddcSdjm ((CBOR_MAJOR_VERSION << 16) | (CBOR_MINOR_VERSION << 8) | CBOR_PATCH_VERSION) 48da0d961cSdjm 499e5c2ddcSdjm /* http://stackoverflow.com/questions/1644868/c-define-macro-for-debug-printing 509e5c2ddcSdjm */ 51da0d961cSdjm #ifdef DEBUG 52da0d961cSdjm #include <stdio.h> 534dcc46c4Sdjm #define _cbor_debug_print(fmt, ...) \ 549e5c2ddcSdjm do { \ 55da0d961cSdjm if (DEBUG) \ 569e5c2ddcSdjm fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, \ 579e5c2ddcSdjm __VA_ARGS__); \ 58da0d961cSdjm } while (0) 594dcc46c4Sdjm extern bool _cbor_enable_assert; 604dcc46c4Sdjm // Like `assert`, but can be dynamically disabled in tests to allow testing 614dcc46c4Sdjm // invalid behaviors. 624dcc46c4Sdjm #define CBOR_ASSERT(e) assert(!_cbor_enable_assert || (e)) 634dcc46c4Sdjm #define _CBOR_TEST_DISABLE_ASSERT(block) \ 644dcc46c4Sdjm do { \ 654dcc46c4Sdjm _cbor_enable_assert = false; \ 664dcc46c4Sdjm block _cbor_enable_assert = true; \ 674dcc46c4Sdjm } while (0) 68da0d961cSdjm #else 699e5c2ddcSdjm #define debug_print(fmt, ...) \ 709e5c2ddcSdjm do { \ 719e5c2ddcSdjm } while (0) 724dcc46c4Sdjm #define CBOR_ASSERT(e) 734dcc46c4Sdjm #define _CBOR_TEST_DISABLE_ASSERT(block) \ 744dcc46c4Sdjm do { \ 754dcc46c4Sdjm block \ 764dcc46c4Sdjm } while (0) 77da0d961cSdjm #endif 78da0d961cSdjm 794dcc46c4Sdjm #define _CBOR_TO_STR_(x) #x 804dcc46c4Sdjm #define _CBOR_TO_STR(x) _CBOR_TO_STR_(x) /* enables proper double expansion */ 814dcc46c4Sdjm 824dcc46c4Sdjm #ifdef __GNUC__ 834dcc46c4Sdjm #define _CBOR_UNUSED(x) __attribute__((__unused__)) x 844dcc46c4Sdjm // TODO(https://github.com/PJK/libcbor/issues/247): Prefer [[nodiscard]] if 854dcc46c4Sdjm // available 86*196a8b7fSaoyama #if ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ >= 4) 874dcc46c4Sdjm #define _CBOR_NODISCARD __attribute__((warn_unused_result)) 88*196a8b7fSaoyama #else /* gcc3 can not treat warn_unused_result attribute */ 89*196a8b7fSaoyama #define _CBOR_NODISCARD 90*196a8b7fSaoyama #endif 914dcc46c4Sdjm #elif defined(_MSC_VER) 924dcc46c4Sdjm #define _CBOR_UNUSED(x) __pragma(warning(suppress : 4100 4101)) x 934dcc46c4Sdjm #define _CBOR_NODISCARD 944dcc46c4Sdjm #else 954dcc46c4Sdjm #define _CBOR_UNUSED(x) x 964dcc46c4Sdjm #define _CBOR_NODISCARD 974dcc46c4Sdjm #endif 984dcc46c4Sdjm 994dcc46c4Sdjm #if 0 /* custom allocators are not supported on OpenBSD */ 1004dcc46c4Sdjm typedef void *(*_cbor_malloc_t)(size_t); 1014dcc46c4Sdjm typedef void *(*_cbor_realloc_t)(void *, size_t); 1024dcc46c4Sdjm typedef void (*_cbor_free_t)(void *); 1034dcc46c4Sdjm 1044dcc46c4Sdjm CBOR_EXPORT extern _cbor_malloc_t _cbor_malloc; 1054dcc46c4Sdjm CBOR_EXPORT extern _cbor_realloc_t _cbor_realloc; 1064dcc46c4Sdjm CBOR_EXPORT extern _cbor_free_t _cbor_free; 1074dcc46c4Sdjm #endif 108da0d961cSdjm 1099e5c2ddcSdjm // Macro to short-circuit builder functions when memory allocation fails 1109e5c2ddcSdjm #define _CBOR_NOTNULL(cbor_item) \ 1119e5c2ddcSdjm do { \ 1129e5c2ddcSdjm if (cbor_item == NULL) { \ 1139e5c2ddcSdjm return NULL; \ 1149e5c2ddcSdjm } \ 1159e5c2ddcSdjm } while (0) 1169e5c2ddcSdjm 1179e5c2ddcSdjm // Macro to short-circuit builders when memory allocation of nested data fails 1189e5c2ddcSdjm #define _CBOR_DEPENDENT_NOTNULL(cbor_item, pointer) \ 1199e5c2ddcSdjm do { \ 1209e5c2ddcSdjm if (pointer == NULL) { \ 1214dcc46c4Sdjm _cbor_free(cbor_item); \ 1229e5c2ddcSdjm return NULL; \ 1239e5c2ddcSdjm } \ 1249e5c2ddcSdjm } while (0) 1259e5c2ddcSdjm 126da0d961cSdjm /** Sets the memory management routines to use. 127da0d961cSdjm * 128da0d961cSdjm * \rst 1299e5c2ddcSdjm * .. warning:: This function modifies the global state and should therefore be 1309e5c2ddcSdjm * used accordingly. Changing the memory handlers while allocated items exist 1319e5c2ddcSdjm * will result in a ``free``/``malloc`` mismatch. This function is not thread 1329e5c2ddcSdjm * safe with respect to both itself and all the other *libcbor* functions that 1339e5c2ddcSdjm * work with the heap. 1344dcc46c4Sdjm * 135da0d961cSdjm * .. note:: `realloc` implementation must correctly support `NULL` reallocation 1364dcc46c4Sdjm * (see e.g. http://en.cppreference.com/w/c/memory/realloc) 1374dcc46c4Sdjm * \endrst 138da0d961cSdjm * 139da0d961cSdjm * @param custom_malloc malloc implementation 140da0d961cSdjm * @param custom_realloc realloc implementation 141da0d961cSdjm * @param custom_free free implementation 142da0d961cSdjm */ 1434dcc46c4Sdjm #if 0 /* not on OpenBSD */ 1444dcc46c4Sdjm CBOR_EXPORT void cbor_set_allocs(_cbor_malloc_t custom_malloc, 1454dcc46c4Sdjm _cbor_realloc_t custom_realloc, 1464dcc46c4Sdjm _cbor_free_t custom_free); 147da0d961cSdjm #endif 148da0d961cSdjm 149da0d961cSdjm /* 150da0d961cSdjm * ============================================================================ 151da0d961cSdjm * Type manipulation 152da0d961cSdjm * ============================================================================ 153da0d961cSdjm */ 154da0d961cSdjm 155da0d961cSdjm /** Get the type of the item 156da0d961cSdjm * 157da0d961cSdjm * @param item[borrow] 158da0d961cSdjm * @return The type 159da0d961cSdjm */ 1604dcc46c4Sdjm _CBOR_NODISCARD 1614dcc46c4Sdjm CBOR_EXPORT cbor_type cbor_typeof( 1629e5c2ddcSdjm const cbor_item_t *item); /* Will be inlined iff link-time opt is enabled */ 163da0d961cSdjm 164da0d961cSdjm /* Standard item types as described by the RFC */ 165da0d961cSdjm 166da0d961cSdjm /** Does the item have the appropriate major type? 167da0d961cSdjm * @param item[borrow] the item 168da0d961cSdjm * @return Is the item an #CBOR_TYPE_UINT? 169da0d961cSdjm */ 1704dcc46c4Sdjm _CBOR_NODISCARD 1714dcc46c4Sdjm CBOR_EXPORT bool cbor_isa_uint(const cbor_item_t *item); 172da0d961cSdjm 173da0d961cSdjm /** Does the item have the appropriate major type? 174da0d961cSdjm * @param item[borrow] the item 175da0d961cSdjm * @return Is the item a #CBOR_TYPE_NEGINT? 176da0d961cSdjm */ 1774dcc46c4Sdjm _CBOR_NODISCARD 1784dcc46c4Sdjm CBOR_EXPORT bool cbor_isa_negint(const cbor_item_t *item); 179da0d961cSdjm 180da0d961cSdjm /** Does the item have the appropriate major type? 181da0d961cSdjm * @param item[borrow] the item 182da0d961cSdjm * @return Is the item a #CBOR_TYPE_BYTESTRING? 183da0d961cSdjm */ 1844dcc46c4Sdjm _CBOR_NODISCARD 1854dcc46c4Sdjm CBOR_EXPORT bool cbor_isa_bytestring(const cbor_item_t *item); 186da0d961cSdjm 187da0d961cSdjm /** Does the item have the appropriate major type? 188da0d961cSdjm * @param item[borrow] the item 189da0d961cSdjm * @return Is the item a #CBOR_TYPE_STRING? 190da0d961cSdjm */ 1914dcc46c4Sdjm _CBOR_NODISCARD 1924dcc46c4Sdjm CBOR_EXPORT bool cbor_isa_string(const cbor_item_t *item); 193da0d961cSdjm 194da0d961cSdjm /** Does the item have the appropriate major type? 195da0d961cSdjm * @param item[borrow] the item 196da0d961cSdjm * @return Is the item an #CBOR_TYPE_ARRAY? 197da0d961cSdjm */ 1984dcc46c4Sdjm _CBOR_NODISCARD 1994dcc46c4Sdjm CBOR_EXPORT bool cbor_isa_array(const cbor_item_t *item); 200da0d961cSdjm 201da0d961cSdjm /** Does the item have the appropriate major type? 202da0d961cSdjm * @param item[borrow] the item 203da0d961cSdjm * @return Is the item a #CBOR_TYPE_MAP? 204da0d961cSdjm */ 2054dcc46c4Sdjm _CBOR_NODISCARD 2064dcc46c4Sdjm CBOR_EXPORT bool cbor_isa_map(const cbor_item_t *item); 207da0d961cSdjm 208da0d961cSdjm /** Does the item have the appropriate major type? 209da0d961cSdjm * @param item[borrow] the item 210da0d961cSdjm * @return Is the item a #CBOR_TYPE_TAG? 211da0d961cSdjm */ 2124dcc46c4Sdjm _CBOR_NODISCARD 2134dcc46c4Sdjm CBOR_EXPORT bool cbor_isa_tag(const cbor_item_t *item); 214da0d961cSdjm 215da0d961cSdjm /** Does the item have the appropriate major type? 216da0d961cSdjm * @param item[borrow] the item 217da0d961cSdjm * @return Is the item a #CBOR_TYPE_FLOAT_CTRL? 218da0d961cSdjm */ 2194dcc46c4Sdjm _CBOR_NODISCARD 2204dcc46c4Sdjm CBOR_EXPORT bool cbor_isa_float_ctrl(const cbor_item_t *item); 221da0d961cSdjm 222da0d961cSdjm /* Practical types with respect to their semantics (but not tag values) */ 223da0d961cSdjm 224da0d961cSdjm /** Is the item an integer, either positive or negative? 225da0d961cSdjm * @param item[borrow] the item 226da0d961cSdjm * @return Is the item an integer, either positive or negative? 227da0d961cSdjm */ 2284dcc46c4Sdjm _CBOR_NODISCARD 2294dcc46c4Sdjm CBOR_EXPORT bool cbor_is_int(const cbor_item_t *item); 230da0d961cSdjm 231da0d961cSdjm /** Is the item an a floating point number? 232da0d961cSdjm * @param item[borrow] the item 233da0d961cSdjm * @return Is the item a floating point number? 234da0d961cSdjm */ 2354dcc46c4Sdjm _CBOR_NODISCARD 2364dcc46c4Sdjm CBOR_EXPORT bool cbor_is_float(const cbor_item_t *item); 237da0d961cSdjm 238da0d961cSdjm /** Is the item an a boolean? 239da0d961cSdjm * @param item[borrow] the item 240da0d961cSdjm * @return Is the item a boolean? 241da0d961cSdjm */ 2424dcc46c4Sdjm _CBOR_NODISCARD 2434dcc46c4Sdjm CBOR_EXPORT bool cbor_is_bool(const cbor_item_t *item); 244da0d961cSdjm 245da0d961cSdjm /** Does this item represent `null` 2464dcc46c4Sdjm * 247da0d961cSdjm * \rst 2489e5c2ddcSdjm * .. warning:: This is in no way related to the value of the pointer. Passing a 2494dcc46c4Sdjm * null pointer will most likely result in a crash. 2504dcc46c4Sdjm * \endrst 2514dcc46c4Sdjm * 252da0d961cSdjm * @param item[borrow] the item 253da0d961cSdjm * @return Is the item (CBOR logical) null? 254da0d961cSdjm */ 2554dcc46c4Sdjm _CBOR_NODISCARD 2564dcc46c4Sdjm CBOR_EXPORT bool cbor_is_null(const cbor_item_t *item); 257da0d961cSdjm 258da0d961cSdjm /** Does this item represent `undefined` 2594dcc46c4Sdjm * 260da0d961cSdjm * \rst 2619e5c2ddcSdjm * .. warning:: Care must be taken to distinguish nulls and undefined values in 2624dcc46c4Sdjm * C. 2634dcc46c4Sdjm * \endrst 2644dcc46c4Sdjm * 265da0d961cSdjm * @param item[borrow] the item 266da0d961cSdjm * @return Is the item (CBOR logical) undefined? 267da0d961cSdjm */ 2684dcc46c4Sdjm _CBOR_NODISCARD 2694dcc46c4Sdjm CBOR_EXPORT bool cbor_is_undef(const cbor_item_t *item); 270da0d961cSdjm 271da0d961cSdjm /* 272da0d961cSdjm * ============================================================================ 273da0d961cSdjm * Memory management 274da0d961cSdjm * ============================================================================ 275da0d961cSdjm */ 276da0d961cSdjm 277da0d961cSdjm /** Increases the reference count by one 278da0d961cSdjm * 279da0d961cSdjm * No dependent items are affected. 280da0d961cSdjm * 281da0d961cSdjm * @param item[incref] item the item 282da0d961cSdjm * @return the input reference 283da0d961cSdjm */ 2844dcc46c4Sdjm CBOR_EXPORT cbor_item_t *cbor_incref(cbor_item_t *item); 285da0d961cSdjm 286da0d961cSdjm /** Decreases the reference count by one, deallocating the item if needed 287da0d961cSdjm * 288da0d961cSdjm * In case the item is deallocated, the reference count of any dependent items 289da0d961cSdjm * is adjusted accordingly in a recursive manner. 290da0d961cSdjm * 291da0d961cSdjm * @param item[take] the item. Set to `NULL` if deallocated 292da0d961cSdjm */ 2934dcc46c4Sdjm CBOR_EXPORT void cbor_decref(cbor_item_t **item); 294da0d961cSdjm 295da0d961cSdjm /** Decreases the reference count by one, deallocating the item if needed 296da0d961cSdjm * 2979e5c2ddcSdjm * Convenience wrapper for #cbor_decref when its set-to-null behavior is not 2989e5c2ddcSdjm * needed 299da0d961cSdjm * 300da0d961cSdjm * @param item[take] the item 301da0d961cSdjm */ 3024dcc46c4Sdjm CBOR_EXPORT void cbor_intermediate_decref(cbor_item_t *item); 303da0d961cSdjm 304da0d961cSdjm /** Get the reference count 305da0d961cSdjm * 306da0d961cSdjm * \rst 307da0d961cSdjm * .. warning:: This does *not* account for transitive references. 308da0d961cSdjm * \endrst 309da0d961cSdjm * 310da0d961cSdjm * @param item[borrow] the item 311da0d961cSdjm * @return the reference count 312da0d961cSdjm */ 3134dcc46c4Sdjm _CBOR_NODISCARD 3144dcc46c4Sdjm CBOR_EXPORT size_t cbor_refcount(const cbor_item_t *item); 315da0d961cSdjm 316da0d961cSdjm /** Provides CPP-like move construct 317da0d961cSdjm * 3189e5c2ddcSdjm * Decreases the reference count by one, but does not deallocate the item even 3199e5c2ddcSdjm * if its refcount reaches zero. This is useful for passing intermediate values 3209e5c2ddcSdjm * to functions that increase reference count. Should only be used with 3219e5c2ddcSdjm * functions that `incref` their arguments. 322da0d961cSdjm * 323da0d961cSdjm * \rst 3249e5c2ddcSdjm * .. warning:: If the item is moved without correctly increasing the reference 3254dcc46c4Sdjm * count afterwards, the memory will be leaked. 3264dcc46c4Sdjm * \endrst 327da0d961cSdjm * 328da0d961cSdjm * @param item[take] the item 329da0d961cSdjm * @return the item with reference count decreased by one 330da0d961cSdjm */ 3314dcc46c4Sdjm _CBOR_NODISCARD 3324dcc46c4Sdjm CBOR_EXPORT cbor_item_t *cbor_move(cbor_item_t *item); 333da0d961cSdjm 334da0d961cSdjm #ifdef __cplusplus 335da0d961cSdjm } 336da0d961cSdjm #endif 337da0d961cSdjm 338da0d961cSdjm #endif // LIBCBOR_COMMON_H 339