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 | #define DYNAMIC_ARRAY_WITH_INLINE_STORAGE_IMPL(name, type, prefix) \ |
28 | UACPI_MAYBE_UNUSED \ |
29 | prefix uacpi_size name##_inline_capacity(struct name *arr) \ |
30 | { \ |
31 | return sizeof(arr->inline_storage) / sizeof(arr->inline_storage[0]); \ |
32 | } \ |
33 | \ |
34 | prefix type *name##_at(struct name *arr, uacpi_size idx) \ |
35 | { \ |
36 | if (idx >= arr->size_including_inline) \ |
37 | return UACPI_NULL; \ |
38 | \ |
39 | if (idx < name##_inline_capacity(arr)) \ |
40 | return &arr->inline_storage[idx]; \ |
41 | \ |
42 | return &arr->dynamic_storage[idx - name##_inline_capacity(arr)]; \ |
43 | } \ |
44 | \ |
45 | UACPI_MAYBE_UNUSED \ |
46 | prefix type *name##_alloc(struct name *arr) \ |
47 | { \ |
48 | uacpi_size inline_cap; \ |
49 | type *out_ptr; \ |
50 | \ |
51 | inline_cap = name##_inline_capacity(arr); \ |
52 | \ |
53 | if (arr->size_including_inline >= inline_cap) { \ |
54 | uacpi_size dynamic_size; \ |
55 | \ |
56 | dynamic_size = arr->size_including_inline - inline_cap; \ |
57 | if (dynamic_size == arr->dynamic_capacity) { \ |
58 | uacpi_size bytes, type_size; \ |
59 | void *new_buf; \ |
60 | \ |
61 | type_size = sizeof(*arr->dynamic_storage); \ |
62 | bytes = arr->dynamic_capacity * type_size; \ |
63 | bytes += type_size; \ |
64 | \ |
65 | new_buf = uacpi_kernel_alloc(bytes); \ |
66 | if (!new_buf) \ |
67 | return NULL; \ |
68 | arr->dynamic_capacity = bytes / type_size; \ |
69 | \ |
70 | if (arr->dynamic_storage) { \ |
71 | uacpi_memcpy(new_buf, arr->dynamic_storage, \ |
72 | dynamic_size * type_size); \ |
73 | } \ |
74 | uacpi_free(arr->dynamic_storage, dynamic_size * type_size); \ |
75 | arr->dynamic_storage = new_buf; \ |
76 | } \ |
77 | \ |
78 | out_ptr = &arr->dynamic_storage[dynamic_size]; \ |
79 | goto ret; \ |
80 | } \ |
81 | \ |
82 | \ |
83 | out_ptr = &arr->inline_storage[arr->size_including_inline]; \ |
84 | \ |
85 | ret: \ |
86 | arr->size_including_inline++; \ |
87 | return out_ptr; \ |
88 | } \ |
89 | \ |
90 | UACPI_MAYBE_UNUSED \ |
91 | prefix type *name##_calloc(struct name *arr) \ |
92 | { \ |
93 | type *ret; \ |
94 | \ |
95 | ret = name##_alloc(arr); \ |
96 | if (ret) \ |
97 | uacpi_memzero(ret, sizeof(*ret)); \ |
98 | \ |
99 | return ret; \ |
100 | } \ |
101 | \ |
102 | UACPI_MAYBE_UNUSED \ |
103 | prefix void name##_pop(struct name *arr) \ |
104 | { \ |
105 | if (arr->size_including_inline == 0) \ |
106 | return; \ |
107 | \ |
108 | arr->size_including_inline--; \ |
109 | } \ |
110 | \ |
111 | UACPI_MAYBE_UNUSED \ |
112 | prefix uacpi_size name##_size(struct name *arr) \ |
113 | { \ |
114 | return arr->size_including_inline; \ |
115 | } \ |
116 | \ |
117 | UACPI_MAYBE_UNUSED \ |
118 | prefix type *name##_last(struct name *arr) \ |
119 | { \ |
120 | return name##_at(arr, arr->size_including_inline - 1); \ |
121 | } \ |
122 | \ |
123 | prefix void name##_clear(struct name *arr) \ |
124 | { \ |
125 | uacpi_free( \ |
126 | arr->dynamic_storage, \ |
127 | arr->dynamic_capacity * sizeof(*arr->dynamic_storage) \ |
128 | ); \ |
129 | arr->size_including_inline = 0; \ |
130 | arr->dynamic_capacity = 0; \ |
131 | } |
132 | |