| 1 | #pragma once |
| 2 | |
| 3 | #include <uacpi/types.h> |
| 4 | #include <uacpi/internal/stdlib.h> |
| 5 | #include <uacpi/kernel_api.h> |
| 6 | |
| 7 | #define DYNAMIC_ARRAY_WITH_INLINE_STORAGE(name, type, inline_capacity) \ |
| 8 | struct name { \ |
| 9 | type inline_storage[inline_capacity]; \ |
| 10 | type *dynamic_storage; \ |
| 11 | uacpi_size dynamic_capacity; \ |
| 12 | uacpi_size size_including_inline; \ |
| 13 | }; \ |
| 14 | |
| 15 | #define DYNAMIC_ARRAY_SIZE(arr) ((arr)->size_including_inline) |
| 16 | |
| 17 | #define DYNAMIC_ARRAY_WITH_INLINE_STORAGE_EXPORTS(name, type, prefix) \ |
| 18 | prefix uacpi_size name##_inline_capacity(struct name *arr); \ |
| 19 | prefix type *name##_at(struct name *arr, uacpi_size idx); \ |
| 20 | prefix type *name##_alloc(struct name *arr); \ |
| 21 | prefix type *name##_calloc(struct name *arr); \ |
| 22 | prefix void name##_pop(struct name *arr); \ |
| 23 | prefix uacpi_size name##_size(struct name *arr); \ |
| 24 | prefix type *name##_last(struct name *arr) \ |
| 25 | prefix void name##_clear(struct name *arr); |
| 26 | |
| 27 | #ifndef UACPI_BAREBONES_MODE |
| 28 | #define DYNAMIC_ARRAY_ALLOC_FN(name, type, prefix) \ |
| 29 | UACPI_MAYBE_UNUSED \ |
| 30 | prefix type *name##_alloc(struct name *arr) \ |
| 31 | { \ |
| 32 | uacpi_size inline_cap; \ |
| 33 | type *out_ptr; \ |
| 34 | \ |
| 35 | inline_cap = name##_inline_capacity(arr); \ |
| 36 | \ |
| 37 | if (arr->size_including_inline >= inline_cap) { \ |
| 38 | uacpi_size dynamic_size; \ |
| 39 | \ |
| 40 | dynamic_size = arr->size_including_inline - inline_cap; \ |
| 41 | if (dynamic_size == arr->dynamic_capacity) { \ |
| 42 | uacpi_size bytes, type_size; \ |
| 43 | void *new_buf; \ |
| 44 | \ |
| 45 | type_size = sizeof(*arr->dynamic_storage); \ |
| 46 | \ |
| 47 | if (arr->dynamic_capacity == 0) { \ |
| 48 | bytes = type_size * inline_cap; \ |
| 49 | } else { \ |
| 50 | bytes = (arr->dynamic_capacity / 2) * type_size; \ |
| 51 | if (bytes == 0) \ |
| 52 | bytes += type_size; \ |
| 53 | \ |
| 54 | bytes += arr->dynamic_capacity * type_size; \ |
| 55 | } \ |
| 56 | \ |
| 57 | new_buf = uacpi_kernel_alloc(bytes); \ |
| 58 | if (uacpi_unlikely(new_buf == UACPI_NULL)) \ |
| 59 | return UACPI_NULL; \ |
| 60 | \ |
| 61 | arr->dynamic_capacity = bytes / type_size; \ |
| 62 | \ |
| 63 | if (arr->dynamic_storage) { \ |
| 64 | uacpi_memcpy(new_buf, arr->dynamic_storage, \ |
| 65 | dynamic_size * type_size); \ |
| 66 | } \ |
| 67 | uacpi_free(arr->dynamic_storage, dynamic_size * type_size); \ |
| 68 | arr->dynamic_storage = new_buf; \ |
| 69 | } \ |
| 70 | \ |
| 71 | out_ptr = &arr->dynamic_storage[dynamic_size]; \ |
| 72 | goto ret; \ |
| 73 | } \ |
| 74 | out_ptr = &arr->inline_storage[arr->size_including_inline]; \ |
| 75 | ret: \ |
| 76 | arr->size_including_inline++; \ |
| 77 | return out_ptr; \ |
| 78 | } |
| 79 | |
| 80 | #define DYNAMIC_ARRAY_CLEAR_FN(name, type, prefix) \ |
| 81 | prefix void name##_clear(struct name *arr) \ |
| 82 | { \ |
| 83 | uacpi_free( \ |
| 84 | arr->dynamic_storage, \ |
| 85 | arr->dynamic_capacity * sizeof(*arr->dynamic_storage) \ |
| 86 | ); \ |
| 87 | arr->size_including_inline = 0; \ |
| 88 | arr->dynamic_capacity = 0; \ |
| 89 | arr->dynamic_storage = UACPI_NULL; \ |
| 90 | } |
| 91 | #else |
| 92 | #define DYNAMIC_ARRAY_ALLOC_FN(name, type, prefix) \ |
| 93 | UACPI_MAYBE_UNUSED \ |
| 94 | prefix type *name##_alloc(struct name *arr) \ |
| 95 | { \ |
| 96 | uacpi_size inline_cap; \ |
| 97 | type *out_ptr; \ |
| 98 | \ |
| 99 | inline_cap = name##_inline_capacity(arr); \ |
| 100 | \ |
| 101 | if (arr->size_including_inline >= inline_cap) { \ |
| 102 | uacpi_size dynamic_size; \ |
| 103 | \ |
| 104 | dynamic_size = arr->size_including_inline - inline_cap; \ |
| 105 | if (uacpi_unlikely(dynamic_size == arr->dynamic_capacity)) \ |
| 106 | return UACPI_NULL; \ |
| 107 | \ |
| 108 | out_ptr = &arr->dynamic_storage[dynamic_size]; \ |
| 109 | goto ret; \ |
| 110 | } \ |
| 111 | out_ptr = &arr->inline_storage[arr->size_including_inline]; \ |
| 112 | ret: \ |
| 113 | arr->size_including_inline++; \ |
| 114 | return out_ptr; \ |
| 115 | } |
| 116 | |
| 117 | #define DYNAMIC_ARRAY_CLEAR_FN(name, type, prefix) \ |
| 118 | prefix void name##_clear(struct name *arr) \ |
| 119 | { \ |
| 120 | arr->size_including_inline = 0; \ |
| 121 | arr->dynamic_capacity = 0; \ |
| 122 | arr->dynamic_storage = UACPI_NULL; \ |
| 123 | } |
| 124 | #endif |
| 125 | |
| 126 | #define DYNAMIC_ARRAY_WITH_INLINE_STORAGE_IMPL(name, type, prefix) \ |
| 127 | UACPI_MAYBE_UNUSED \ |
| 128 | prefix uacpi_size name##_inline_capacity(struct name *arr) \ |
| 129 | { \ |
| 130 | return sizeof(arr->inline_storage) / sizeof(arr->inline_storage[0]); \ |
| 131 | } \ |
| 132 | \ |
| 133 | UACPI_MAYBE_UNUSED \ |
| 134 | prefix uacpi_size name##_capacity(struct name *arr) \ |
| 135 | { \ |
| 136 | return name##_inline_capacity(arr) + arr->dynamic_capacity; \ |
| 137 | } \ |
| 138 | \ |
| 139 | prefix type *name##_at(struct name *arr, uacpi_size idx) \ |
| 140 | { \ |
| 141 | if (idx >= arr->size_including_inline) \ |
| 142 | return UACPI_NULL; \ |
| 143 | \ |
| 144 | if (idx < name##_inline_capacity(arr)) \ |
| 145 | return &arr->inline_storage[idx]; \ |
| 146 | \ |
| 147 | return &arr->dynamic_storage[idx - name##_inline_capacity(arr)]; \ |
| 148 | } \ |
| 149 | \ |
| 150 | DYNAMIC_ARRAY_ALLOC_FN(name, type, prefix) \ |
| 151 | \ |
| 152 | UACPI_MAYBE_UNUSED \ |
| 153 | prefix type *name##_calloc(struct name *arr) \ |
| 154 | { \ |
| 155 | type *ret; \ |
| 156 | \ |
| 157 | ret = name##_alloc(arr); \ |
| 158 | if (ret) \ |
| 159 | uacpi_memzero(ret, sizeof(*ret)); \ |
| 160 | \ |
| 161 | return ret; \ |
| 162 | } \ |
| 163 | \ |
| 164 | UACPI_MAYBE_UNUSED \ |
| 165 | prefix void name##_pop(struct name *arr) \ |
| 166 | { \ |
| 167 | if (arr->size_including_inline == 0) \ |
| 168 | return; \ |
| 169 | \ |
| 170 | arr->size_including_inline--; \ |
| 171 | } \ |
| 172 | \ |
| 173 | UACPI_MAYBE_UNUSED \ |
| 174 | prefix uacpi_size name##_size(struct name *arr) \ |
| 175 | { \ |
| 176 | return arr->size_including_inline; \ |
| 177 | } \ |
| 178 | \ |
| 179 | UACPI_MAYBE_UNUSED \ |
| 180 | prefix type *name##_last(struct name *arr) \ |
| 181 | { \ |
| 182 | return name##_at(arr, arr->size_including_inline - 1); \ |
| 183 | } \ |
| 184 | \ |
| 185 | DYNAMIC_ARRAY_CLEAR_FN(name, type, prefix) |
| 186 | |