1 /* Copyright (C) 2017 the mpv developers 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 */ 15 16 #ifndef TA_H_ 17 #define TA_H_ 18 19 #include <stddef.h> 20 #include <stdbool.h> 21 #include <stdarg.h> 22 23 #ifdef __GNUC__ 24 #define TA_PRF(a1, a2) __attribute__ ((format(printf, a1, a2))) 25 #define TA_TYPEOF(t) __typeof__(t) 26 #else 27 #define TA_PRF(a1, a2) 28 #define TA_TYPEOF(t) void * 29 #endif 30 31 // Broken crap with __USE_MINGW_ANSI_STDIO 32 #if defined(__MINGW32__) && defined(__GNUC__) && !defined(__clang__) 33 #undef TA_PRF 34 #define TA_PRF(a1, a2) __attribute__ ((format (gnu_printf, a1, a2))) 35 #endif 36 37 #define TA_STRINGIFY_(x) # x 38 #define TA_STRINGIFY(x) TA_STRINGIFY_(x) 39 40 #ifdef NDEBUG 41 #define TA_LOC "" 42 #else 43 #define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__) 44 #endif 45 46 // Core functions 47 void *ta_alloc_size(void *ta_parent, size_t size); 48 void *ta_zalloc_size(void *ta_parent, size_t size); 49 void *ta_realloc_size(void *ta_parent, void *ptr, size_t size); 50 size_t ta_get_size(void *ptr); 51 void ta_free(void *ptr); 52 void ta_free_children(void *ptr); 53 void ta_set_destructor(void *ptr, void (*destructor)(void *)); 54 void ta_set_parent(void *ptr, void *ta_parent); 55 void *ta_get_parent(void *ptr); 56 57 // Utility functions 58 size_t ta_calc_array_size(size_t element_size, size_t count); 59 size_t ta_calc_prealloc_elems(size_t nextidx); 60 void *ta_new_context(void *ta_parent); 61 void *ta_steal_(void *ta_parent, void *ptr); 62 void *ta_memdup(void *ta_parent, void *ptr, size_t size); 63 char *ta_strdup(void *ta_parent, const char *str); 64 bool ta_strdup_append(char **str, const char *a); 65 bool ta_strdup_append_buffer(char **str, const char *a); 66 char *ta_strndup(void *ta_parent, const char *str, size_t n); 67 bool ta_strndup_append(char **str, const char *a, size_t n); 68 bool ta_strndup_append_buffer(char **str, const char *a, size_t n); 69 char *ta_asprintf(void *ta_parent, const char *fmt, ...) TA_PRF(2, 3); 70 char *ta_vasprintf(void *ta_parent, const char *fmt, va_list ap) TA_PRF(2, 0); 71 bool ta_asprintf_append(char **str, const char *fmt, ...) TA_PRF(2, 3); 72 bool ta_vasprintf_append(char **str, const char *fmt, va_list ap) TA_PRF(2, 0); 73 bool ta_asprintf_append_buffer(char **str, const char *fmt, ...) TA_PRF(2, 3); 74 bool ta_vasprintf_append_buffer(char **str, const char *fmt, va_list ap) TA_PRF(2, 0); 75 76 #define ta_new(ta_parent, type) (type *)ta_alloc_size(ta_parent, sizeof(type)) 77 #define ta_znew(ta_parent, type) (type *)ta_zalloc_size(ta_parent, sizeof(type)) 78 79 #define ta_new_array(ta_parent, type, count) \ 80 (type *)ta_alloc_size(ta_parent, ta_calc_array_size(sizeof(type), count)) 81 82 #define ta_znew_array(ta_parent, type, count) \ 83 (type *)ta_zalloc_size(ta_parent, ta_calc_array_size(sizeof(type), count)) 84 85 #define ta_new_array_size(ta_parent, element_size, count) \ 86 ta_alloc_size(ta_parent, ta_calc_array_size(element_size, count)) 87 88 #define ta_realloc(ta_parent, ptr, type, count) \ 89 (type *)ta_realloc_size(ta_parent, ptr, ta_calc_array_size(sizeof(type), count)) 90 91 #define ta_new_ptrtype(ta_parent, ptr) \ 92 (TA_TYPEOF(ptr))ta_alloc_size(ta_parent, sizeof(*ptr)) 93 94 #define ta_new_array_ptrtype(ta_parent, ptr, count) \ 95 (TA_TYPEOF(ptr))ta_new_array_size(ta_parent, sizeof(*(ptr)), count) 96 97 #define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr) 98 99 #define ta_dup(ta_parent, ptr) \ 100 (TA_TYPEOF(ptr))ta_memdup(ta_parent, ptr, sizeof(*(ptr))) 101 102 // Ugly macros that crash on OOM. 103 // All of these mirror real functions (with a 'x' added after the 'ta_' 104 // prefix), and the only difference is that they will call abort() on allocation 105 // failures (such as out of memory conditions), instead of returning an error 106 // code. 107 #define ta_xalloc_size(...) ta_oom_p(ta_alloc_size(__VA_ARGS__)) 108 #define ta_xzalloc_size(...) ta_oom_p(ta_zalloc_size(__VA_ARGS__)) 109 #define ta_xnew_context(...) ta_oom_p(ta_new_context(__VA_ARGS__)) 110 #define ta_xstrdup_append(...) ta_oom_b(ta_strdup_append(__VA_ARGS__)) 111 #define ta_xstrdup_append_buffer(...) ta_oom_b(ta_strdup_append_buffer(__VA_ARGS__)) 112 #define ta_xstrndup_append(...) ta_oom_b(ta_strndup_append(__VA_ARGS__)) 113 #define ta_xstrndup_append_buffer(...) ta_oom_b(ta_strndup_append_buffer(__VA_ARGS__)) 114 #define ta_xasprintf(...) ta_oom_s(ta_asprintf(__VA_ARGS__)) 115 #define ta_xvasprintf(...) ta_oom_s(ta_vasprintf(__VA_ARGS__)) 116 #define ta_xasprintf_append(...) ta_oom_b(ta_asprintf_append(__VA_ARGS__)) 117 #define ta_xvasprintf_append(...) ta_oom_b(ta_vasprintf_append(__VA_ARGS__)) 118 #define ta_xasprintf_append_buffer(...) ta_oom_b(ta_asprintf_append_buffer(__VA_ARGS__)) 119 #define ta_xvasprintf_append_buffer(...) ta_oom_b(ta_vasprintf_append_buffer(__VA_ARGS__)) 120 #define ta_xnew(...) ta_oom_g(ta_new(__VA_ARGS__)) 121 #define ta_xznew(...) ta_oom_g(ta_znew(__VA_ARGS__)) 122 #define ta_xnew_array(...) ta_oom_g(ta_new_array(__VA_ARGS__)) 123 #define ta_xznew_array(...) ta_oom_g(ta_znew_array(__VA_ARGS__)) 124 #define ta_xnew_array_size(...) ta_oom_p(ta_new_array_size(__VA_ARGS__)) 125 #define ta_xnew_ptrtype(...) ta_oom_g(ta_new_ptrtype(__VA_ARGS__)) 126 #define ta_xnew_array_ptrtype(...) ta_oom_g(ta_new_array_ptrtype(__VA_ARGS__)) 127 #define ta_xdup(...) ta_oom_g(ta_dup(__VA_ARGS__)) 128 129 #define ta_xrealloc(ta_parent, ptr, type, count) \ 130 (type *)ta_xrealloc_size(ta_parent, ptr, ta_calc_array_size(sizeof(type), count)) 131 132 // Can't be macros, because the OOM logic is slightly less trivial. 133 char *ta_xstrdup(void *ta_parent, const char *str); 134 char *ta_xstrndup(void *ta_parent, const char *str, size_t n); 135 void *ta_xmemdup(void *ta_parent, void *ptr, size_t size); 136 void *ta_xrealloc_size(void *ta_parent, void *ptr, size_t size); 137 138 #ifndef TA_NO_WRAPPERS 139 #define ta_alloc_size(...) ta_dbg_set_loc(ta_alloc_size(__VA_ARGS__), TA_LOC) 140 #define ta_zalloc_size(...) ta_dbg_set_loc(ta_zalloc_size(__VA_ARGS__), TA_LOC) 141 #define ta_realloc_size(...) ta_dbg_set_loc(ta_realloc_size(__VA_ARGS__), TA_LOC) 142 #define ta_memdup(...) ta_dbg_set_loc(ta_memdup(__VA_ARGS__), TA_LOC) 143 #define ta_xmemdup(...) ta_dbg_set_loc(ta_xmemdup(__VA_ARGS__), TA_LOC) 144 #define ta_xrealloc_size(...) ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC) 145 #endif 146 147 void ta_oom_b(bool b); 148 char *ta_oom_s(char *s); 149 void *ta_oom_p(void *p); 150 // Generic pointer 151 #define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr) 152 153 void ta_enable_leak_report(void); 154 void *ta_dbg_set_loc(void *ptr, const char *name); 155 void *ta_dbg_mark_as_string(void *ptr); 156 157 #endif 158