1/* 2 * Copyright (c) 2014-2019 Pavel Kalvoda <me@pavelkalvoda.com> 3 * 4 * libcbor is free software; you can redistribute it and/or modify 5 * it under the terms of the MIT license. See LICENSE for details. 6 */ 7 8#ifndef LIBCBOR_COMMON_H 9#define LIBCBOR_COMMON_H 10 11#include <assert.h> 12#include <stdbool.h> 13#include <stddef.h> 14#include <stdint.h> 15#include <stdlib.h> 16#include "cbor/configuration.h" 17#include "data.h" 18 19#ifdef __cplusplus 20extern "C" { 21 22/** 23 * C++ is not a subset of C99 -- 'restrict' qualifier is not a part of the 24 * language. This is a workaround to keep it in C headers -- compilers allow 25 * linking non-restrict signatures with restrict implementations. 26 * 27 * If you know a nicer way, please do let me know. 28 */ 29#define CBOR_RESTRICT_POINTER 30 31#else 32 33// MSVC + C++ workaround 34#define CBOR_RESTRICT_POINTER CBOR_RESTRICT_SPECIFIER 35 36#endif 37 38static const uint8_t cbor_major_version = CBOR_MAJOR_VERSION; 39static const uint8_t cbor_minor_version = CBOR_MINOR_VERSION; 40static const uint8_t cbor_patch_version = CBOR_PATCH_VERSION; 41 42#define CBOR_VERSION \ 43 TO_STR(CBOR_MAJOR_VERSION) \ 44 "." TO_STR(CBOR_MINOR_VERSION) "." TO_STR(CBOR_PATCH_VERSION) 45#define CBOR_HEX_VERSION \ 46 ((CBOR_MAJOR_VERSION << 16) | (CBOR_MINOR_VERSION << 8) | CBOR_PATCH_VERSION) 47 48/* http://stackoverflow.com/questions/1644868/c-define-macro-for-debug-printing 49 */ 50#ifdef DEBUG 51#include <stdio.h> 52#define debug_print(fmt, ...) \ 53 do { \ 54 if (DEBUG) \ 55 fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, \ 56 __VA_ARGS__); \ 57 } while (0) 58#else 59#define debug_print(fmt, ...) \ 60 do { \ 61 } while (0) 62#endif 63 64#define TO_STR_(x) #x 65#define TO_STR(x) TO_STR_(x) /* enables proper double expansion */ 66 67// Macro to short-circuit builder functions when memory allocation fails 68#define _CBOR_NOTNULL(cbor_item) \ 69 do { \ 70 if (cbor_item == NULL) { \ 71 return NULL; \ 72 } \ 73 } while (0) 74 75// Macro to short-circuit builders when memory allocation of nested data fails 76#define _CBOR_DEPENDENT_NOTNULL(cbor_item, pointer) \ 77 do { \ 78 if (pointer == NULL) { \ 79 _CBOR_FREE(cbor_item); \ 80 return NULL; \ 81 } \ 82 } while (0) 83 84#if CBOR_CUSTOM_ALLOC 85 86typedef void *(*_cbor_malloc_t)(size_t); 87typedef void *(*_cbor_realloc_t)(void *, size_t); 88typedef void (*_cbor_free_t)(void *); 89 90extern _cbor_malloc_t _cbor_malloc; 91extern _cbor_realloc_t _cbor_realloc; 92extern _cbor_free_t _cbor_free; 93 94/** Sets the memory management routines to use. 95 * 96 * Only available when `CBOR_CUSTOM_ALLOC` is truthy 97 * 98 * \rst 99 * .. warning:: This function modifies the global state and should therefore be 100 * used accordingly. Changing the memory handlers while allocated items exist 101 * will result in a ``free``/``malloc`` mismatch. This function is not thread 102 * safe with respect to both itself and all the other *libcbor* functions that 103 * work with the heap. 104 * .. note:: `realloc` implementation must correctly support `NULL` reallocation 105 * (see e.g. http://en.cppreference.com/w/c/memory/realloc) \endrst 106 * 107 * @param custom_malloc malloc implementation 108 * @param custom_realloc realloc implementation 109 * @param custom_free free implementation 110 */ 111void cbor_set_allocs(_cbor_malloc_t custom_malloc, 112 _cbor_realloc_t custom_realloc, _cbor_free_t custom_free); 113 114#define _CBOR_MALLOC _cbor_malloc 115#define _CBOR_REALLOC _cbor_realloc 116#define _CBOR_FREE _cbor_free 117 118#else 119 120#define _CBOR_MALLOC malloc 121#define _CBOR_REALLOC realloc 122#define _CBOR_FREE free 123 124#endif 125 126/* 127 * ============================================================================ 128 * Type manipulation 129 * ============================================================================ 130 */ 131 132/** Get the type of the item 133 * 134 * @param item[borrow] 135 * @return The type 136 */ 137cbor_type cbor_typeof( 138 const cbor_item_t *item); /* Will be inlined iff link-time opt is enabled */ 139 140/* Standard item types as described by the RFC */ 141 142/** Does the item have the appropriate major type? 143 * @param item[borrow] the item 144 * @return Is the item an #CBOR_TYPE_UINT? 145 */ 146bool cbor_isa_uint(const cbor_item_t *item); 147 148/** Does the item have the appropriate major type? 149 * @param item[borrow] the item 150 * @return Is the item a #CBOR_TYPE_NEGINT? 151 */ 152bool cbor_isa_negint(const cbor_item_t *item); 153 154/** Does the item have the appropriate major type? 155 * @param item[borrow] the item 156 * @return Is the item a #CBOR_TYPE_BYTESTRING? 157 */ 158bool cbor_isa_bytestring(const cbor_item_t *item); 159 160/** Does the item have the appropriate major type? 161 * @param item[borrow] the item 162 * @return Is the item a #CBOR_TYPE_STRING? 163 */ 164bool cbor_isa_string(const cbor_item_t *item); 165 166/** Does the item have the appropriate major type? 167 * @param item[borrow] the item 168 * @return Is the item an #CBOR_TYPE_ARRAY? 169 */ 170bool cbor_isa_array(const cbor_item_t *item); 171 172/** Does the item have the appropriate major type? 173 * @param item[borrow] the item 174 * @return Is the item a #CBOR_TYPE_MAP? 175 */ 176bool cbor_isa_map(const cbor_item_t *item); 177 178/** Does the item have the appropriate major type? 179 * @param item[borrow] the item 180 * @return Is the item a #CBOR_TYPE_TAG? 181 */ 182bool cbor_isa_tag(const cbor_item_t *item); 183 184/** Does the item have the appropriate major type? 185 * @param item[borrow] the item 186 * @return Is the item a #CBOR_TYPE_FLOAT_CTRL? 187 */ 188bool cbor_isa_float_ctrl(const cbor_item_t *item); 189 190/* Practical types with respect to their semantics (but not tag values) */ 191 192/** Is the item an integer, either positive or negative? 193 * @param item[borrow] the item 194 * @return Is the item an integer, either positive or negative? 195 */ 196bool cbor_is_int(const cbor_item_t *item); 197 198/** Is the item an a floating point number? 199 * @param item[borrow] the item 200 * @return Is the item a floating point number? 201 */ 202bool cbor_is_float(const cbor_item_t *item); 203 204/** Is the item an a boolean? 205 * @param item[borrow] the item 206 * @return Is the item a boolean? 207 */ 208bool cbor_is_bool(const cbor_item_t *item); 209 210/** Does this item represent `null` 211 * \rst 212 * .. warning:: This is in no way related to the value of the pointer. Passing a 213 * null pointer will most likely result in a crash. \endrst 214 * @param item[borrow] the item 215 * @return Is the item (CBOR logical) null? 216 */ 217bool cbor_is_null(const cbor_item_t *item); 218 219/** Does this item represent `undefined` 220 * \rst 221 * .. warning:: Care must be taken to distinguish nulls and undefined values in 222 * C. \endrst 223 * @param item[borrow] the item 224 * @return Is the item (CBOR logical) undefined? 225 */ 226bool cbor_is_undef(const cbor_item_t *item); 227 228/* 229 * ============================================================================ 230 * Memory management 231 * ============================================================================ 232 */ 233 234/** Increases the reference count by one 235 * 236 * No dependent items are affected. 237 * 238 * @param item[incref] item the item 239 * @return the input reference 240 */ 241cbor_item_t *cbor_incref(cbor_item_t *item); 242 243/** Decreases the reference count by one, deallocating the item if needed 244 * 245 * In case the item is deallocated, the reference count of any dependent items 246 * is adjusted accordingly in a recursive manner. 247 * 248 * @param item[take] the item. Set to `NULL` if deallocated 249 */ 250void cbor_decref(cbor_item_t **item); 251 252/** Decreases the reference count by one, deallocating the item if needed 253 * 254 * Convenience wrapper for #cbor_decref when its set-to-null behavior is not 255 * needed 256 * 257 * @param item[take] the item 258 */ 259void cbor_intermediate_decref(cbor_item_t *item); 260 261/** Get the reference count 262 * 263 * \rst 264 * .. warning:: This does *not* account for transitive references. 265 * \endrst 266 * 267 * @param item[borrow] the item 268 * @return the reference count 269 */ 270size_t cbor_refcount(const cbor_item_t *item); 271 272/** Provides CPP-like move construct 273 * 274 * Decreases the reference count by one, but does not deallocate the item even 275 * if its refcount reaches zero. This is useful for passing intermediate values 276 * to functions that increase reference count. Should only be used with 277 * functions that `incref` their arguments. 278 * 279 * \rst 280 * .. warning:: If the item is moved without correctly increasing the reference 281 * count afterwards, the memory will be leaked. \endrst 282 * 283 * @param item[take] the item 284 * @return the item with reference count decreased by one 285 */ 286cbor_item_t *cbor_move(cbor_item_t *item); 287 288#ifdef __cplusplus 289} 290#endif 291 292#endif // LIBCBOR_COMMON_H 293