ReactOS 0.4.16-dev-1946-g52006dd
dynamic_array.h
Go to the documentation of this file.
1#pragma once
2
3#include <uacpi/types.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)