1 /* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2022 Intel Corporation. All rights reserved.
4 */
5
6 #ifndef DSP_FW_FW_ARRAY_H_
7 #define DSP_FW_FW_ARRAY_H_
8
9 #include <stdint.h>
10 #include <stddef.h>
11
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15
16 /*! Wrapper for buffer descriptor. */
17 typedef struct byte_array {
18 /*! Pointer to buffer begin. */
19 uint8_t *data;
20 /*! Size of buffer (in number of elements, typically bytes). */
21 size_t size;
22 } byte_array_t;
23
array_get_data(const byte_array_t * ba)24 static inline uint8_t *array_get_data(const byte_array_t *ba)
25 {
26 return (uint8_t *)ba->data;
27 }
28
array_get_data_end(const byte_array_t * ba)29 static inline uint8_t *array_get_data_end(const byte_array_t *ba)
30 {
31 return array_get_data(ba) + ba->size;
32 }
33
34
array_get_size(const byte_array_t * ba)35 static inline size_t array_get_size(const byte_array_t *ba)
36 {
37 return ba->size;
38 }
39
array_alloc_from(byte_array_t * ba,size_t required_size)40 static inline uint8_t *array_alloc_from(byte_array_t *ba,
41 size_t required_size)
42 {
43 /* TODO: add alignment */
44 /* TODO: validate inputs */
45 /* TODO: move this to more appropriate file */
46
47 uint8_t *cached_data = array_get_data(ba);
48
49 ba->data += required_size;
50 ba->size -= required_size;
51
52 return cached_data;
53 }
54 #ifdef __cplusplus
55 } /* extern "C" */
56 #endif
57
58 #ifdef __cplusplus
59 /* clang-format off */
60 #define assert(cond)
61
array_get_data(const byte_array_t & ba)62 static inline uint8_t *array_get_data(const byte_array_t &ba)
63 {
64 return (uint8_t *)ba.data;
65 }
66
array_get_size(const byte_array_t & ba)67 static inline size_t array_get_size(const byte_array_t &ba)
68 {
69 return ba.size;
70 }
71
72 namespace dsp_fw
73 {
74 /*!
75 * Provides a safe wrapper around array allocated in continuous memory.
76 * Size of the array specified by the client is checked on any attempt
77 * to access the array data.
78 *
79 * \note Wrapper does not take over ownership of the array. The array
80 * must be deallocated elsewhere by its proper owner.
81 *
82 * \note All copy operations are shallow bit copies of the array.
83 * The array is expected to keep built-in types or pointers, so
84 * there is no assignment operator called for each copied entry.
85 *
86 * \note Array (especially Array<uint8_t>/ByteArray) can be casted to
87 * byte_array_t as there are binary compatible
88 */
89 template < class T >
90 class Array /*: public byte_array*/
91 {
92 public:
93
94 /*!
95 * Default ctor to provide two-stage initialization completed by Init() call.
96 */
Array()97 Array()
98 {
99 data_ = NULL;
100 size_ = 0;
101 }
102
103 /*!
104 * Constructs the object and initializes pointer and size to the provided
105 * values.
106 *
107 * \param ptr - Pointer to the array.
108 * \param size - Size of the array pointed by the ptr.
109 */
Array(T * ptr,size_t size)110 Array(T * ptr, size_t size)
111 {
112 data_ = (T *)ptr;
113 size_ = size;
114 }
115
116 /*!
117 * Completes two-stage object initialization when initialized by the default
118 * ctor.
119 *
120 * \param ptr - Pointer to the array.
121 * \param size - Size of the array pointed by the ptr.
122 */
Init(T * ptr,size_t size)123 void Init(T *ptr, size_t size)
124 {
125 data_ = (T *)ptr;
126 size_ = size;
127 }
128
129 /*!
130 * Completes two-stage object initialization when initialized by the default
131 * ctor.
132 *
133 * \param ptr - Pointer to the array.
134 * \param end - Pointer to the end of the array.
135 */
InitWithRange(T * ptr,T * ptr_end)136 void InitWithRange(T *ptr, T *ptr_end)
137 {
138 assert(ptr_end >= ptr);
139 data_ = (T *)ptr;
140 size_ = ptr_end - ptr;
141 }
142
143 /*!
144 * Detaches the wrapper from the array object. Provided for the sake of
145 * completeness since array lifetime is not bound to the wrapper lifetime.
146 */
Detach(void)147 void Detach(void) { data_ = NULL; size_ = 0; }
148 /*!
149 * Retrieves the size of the array.
150 *
151 * \return Size of the array. It may be zero if the wrapper is not fully
152 * initialized.
153 */
size(void)154 size_t size(void) const { return size_; }
155 /*!
156 * Retrieves allocated size of buffer in bytes.
157 */
alloc_size(void)158 size_t alloc_size(void) const { return size()*sizeof(T); }
159 /*!
160 * Resizes the array.
161 */
Resize(size_t new_size)162 void Resize(size_t new_size) { size_ = new_size; }
163 /*!
164 * Retrieves address of the array (const version).
165 * \return Address of the array. It may be null if the wrapper is not fully
166 * initialized.
167 */
data(void)168 const T *data(void) const { return (const T *)data_; }
169 /*!
170 * Retrieves address of the array (modifiable version).
171 *
172 * \return Address of the array. It may be null if the wrapper is not fully
173 * initialized.
174 */
data(void)175 T *data(void) { return (T *)data_; }
176 /*!
177 * Retrieves address of end of the array (const version).
178 * \return Address of the array.
179 */
data_end(void)180 const T *data_end(void) const { return data() + size_; }
181 /*!
182 * Retrieves address of end of the array (modifiable version).
183 * \return Address of end of the array.
184 */
data_end(void)185 T *data_end(void) { return data() + size_; }
186 /*!
187 * Safe (in debug) operator to access element of the array (const version).
188 *
189 * \param idx Index of the element to be accessed.
190 * \return Reference to the element.
191 */
192 const T & operator[](size_t idx) const {
193 /*assert(idx < size()); //TODO: no exceptions, release err handling req */
194 return data()[idx];
195 }
196
197 /*!
198 * Safe (in debug) operator to access element of the array (modifiable version).
199 *
200 * \param idx Index of the element to be accessed.
201 * \return Reference to the element.
202 */
203 T & operator[](size_t idx) {
204 /*assert(idx < size()); //TODO: no exceptions, release err handling req */
205 return data()[idx];
206 }
207
208 /*!
209 * Safe copy-from operation that verifies size of source and this.
210 *
211 * \param src Address of the source array to be copied into this.
212 * \param srcSize Size of the source array.
213 * \param dst_offset Offset in the destination array to start copying data at
214 * (expressed in number of items).
215 */
216 void copyFrom(const T *src, size_t srcSize, size_t dst_offset = 0)
217 {
218 assert(data() != NULL);
219 assert(size() > dst_offset);
220 assert((size() - dst_offset) >= srcSize);
221 memcpy_s(data() + dst_offset, alloc_size() - dst_offset * sizeof(T),
222 src, srcSize * sizeof(T));
223 }
224
225 /*!
226 * Safe copy-from operation that verifies size of source and this.
227 *
228 * \param src The source array to be copied into this.
229 * \param dst_offset Offset in the destination array to start copying data at
230 * (expressed in number of items).
231 */
232 void copyFrom(const Array < T > &src, size_t dst_offset = 0)
233 {
234 assert(data() != 0);
235 assert(size() > dst_offset);
236 assert((size() - dst_offset) >= src.size());
237 memcpy_s(data() + dst_offset, alloc_size() - dst_offset * sizeof(T),
238 src.data(), src.alloc_size());
239 }
240
241 /*!
242 * Safe copy-to operation that verifies size of the destination and this.
243 * \param dst Address of the destination array to be overwritten by this.
244 * \param dstSize Size of the destination array.
245 */
copyTo(T * dst,size_t dstSize)246 void copyTo(T *dst, size_t dstSize) const {
247 assert(data() != 0);
248 assert(size() <= dstSize);
249 memcpy_s(dst, dstSize * sizeof(T), data(), alloc_size());
250 }
251
252 /*!
253 * Safe copy-to operation that verifies size of the destination and this.
254 * \param dst The destination array to be overwritten by this.
255 */
copyTo(Array<T> & dst)256 void copyTo(Array < T > &dst) const {
257 assert(data() != 0);
258 assert(size() <= dst.size());
259 memcpy_s(dst.data(), dst.alloc_size(), data(), alloc_size());
260 }
261
262 /*!
263 * Copies as much as specified size starting from specified offset.
264 * \param dst Destination buffer.
265 * \param copy_size Number of items to be copied.
266 * \param src_offset Offset in the source buffer (in number of items).
267 */
268 void copyFragmentTo(Array < T > &dst, size_t copy_size, size_t src_offset = 0) const {
269 assert(data() != 0);
270 assert((src_offset + copy_size) <= size());
271 assert(copy_size <= dst.size());
272 memcpy_s(dst.data(), dst.alloc_size(), data() + src_offset, copy_size * sizeof(T));
273 }
274
275 /*!
276 * Safe cast of the content of the array to the specified type (modifiable
277 * version).
278 * \return Pointer to the requested type if array is large enough to be
279 * casted, NULL otherwise.
280 */
281 template < class TC >
dataAs(void)282 TC *dataAs(void)
283 {
284 if (alloc_size() < sizeof(TC)) {
285 assert(false);
286 return NULL;
287 }
288 return reinterpret_cast < TC * > (data());
289 }
290
291 template < class TC >
dataAsArray(size_t size)292 TC *dataAsArray(size_t size)
293 {
294 if (alloc_size() < sizeof(TC)*size) {
295 assert(false);
296 return NULL;
297 }
298 return reinterpret_cast < TC * > (data());
299 }
300
301 /*!
302 * Safe cast of the content of the array to the specified type (const version).
303 * \return Pointer to the requested type if array is large enough to be
304 * casted, NULL otherwise.
305 */
306 template < class TC >
dataAs(void)307 const TC *dataAs(void) const {
308 if (alloc_size() < sizeof(TC)) {
309 assert(false);
310 return NULL;
311 }
312 return reinterpret_cast < const TC * > (data());
313 }
314
315 /*!
316 * Inserts object of specified type into the buffer.
317 * Use this explicit call instead of operator=(TC) or stream-like <<.
318 */
319 template < class TC >
setDataAs(const TC & d)320 void setDataAs(const TC & d)
321 {
322 TC *t = dataAs < TC > ();
323
324 if (t == NULL) {
325 assert(false);
326 return;
327 }
328 *t = d; /* using operator=, not shallow copy */
329 Resize(sizeof(TC));
330 }
331
332 /*!
333 * Safe zero-memory on the underlying buffer.
334 */
clear(void)335 void clear(void)
336 {
337 memset(data(), 0x00, alloc_size());
338 }
339
Swap(Array<T> * array)340 void Swap(Array < T > *array)
341 {
342 Array < T > temp(*array);
343 array->data_ = data_;
344 array->size_ = size_;
345 this->data_ = temp.data_;
346 this->size_ = temp.size_;
347 }
348
Swap(Array<T> & array)349 void Swap(Array < T > &array)
350 {
351 Array < T > temp(array);
352 array.data_ = data_;
353 array.size_ = size_;
354 this->data_ = temp.data_;
355 this->size_ = temp.size_;
356 }
357 private:
358 T *data_;
359 size_t size_;
360 };
361
362 /*!
363 * Predefined type of array of bytes.
364 */
365 typedef Array < uint8_t > ByteArray;
366
367 /*!
368 * Predefined type of array of dwords.
369 */
370 typedef Array < uint32_t > DwordArray;
371
372 } /* end of namespace dsp_fw */
373
374 #endif /* __cplusplus */
375 /* clang-format on */
376 #endif /* #ifndef DSP_FW_FW_ARRAY_H_ */
377