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