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 20 extern "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 38 static const uint8_t cbor_major_version = CBOR_MAJOR_VERSION; 39 static const uint8_t cbor_minor_version = CBOR_MINOR_VERSION; 40 static 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 86 typedef void *(*_cbor_malloc_t)(size_t); 87 typedef void *(*_cbor_realloc_t)(void *, size_t); 88 typedef void (*_cbor_free_t)(void *); 89 90 extern _cbor_malloc_t _cbor_malloc; 91 extern _cbor_realloc_t _cbor_realloc; 92 extern _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 */ 111 void 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 */ 137 cbor_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 */ 146 bool 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 */ 152 bool 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 */ 158 bool 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 */ 164 bool 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 */ 170 bool 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 */ 176 bool 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 */ 182 bool 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 */ 188 bool 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 */ 196 bool 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 */ 202 bool 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 */ 208 bool 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 */ 217 bool 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 */ 226 bool 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 */ 241 cbor_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 */ 250 void 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 */ 259 void 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 */ 270 size_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 */ 286 cbor_item_t *cbor_move(cbor_item_t *item); 287 288 #ifdef __cplusplus 289 } 290 #endif 291 292 #endif // LIBCBOR_COMMON_H 293