1 /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 #ifndef CRAS_ARRAY_H_
7 #define CRAS_ARRAY_H_
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 #include <string.h>
14 
15 /*
16 
17 Sample usage:
18 
19 DECLARE_ARRAY_TYPE(double, double_array);
20 
21 void f()
22 {
23 	int i;
24 	double *p;
25 	double_array a = ARRAY_INIT;
26 
27 	ARRAY_APPEND(&a, 1.0);
28 	*ARRAY_APPEND_ZERO(&a) = 2.0;
29 
30 	ARRAY_ELEMENT_FOREACH(&a, i, p) {
31 		printf("%f\n", *p);  // prints 1.0 2.0
32 	}
33 
34 	ARRAY_FREE(&a);
35 }
36 
37 */
38 
39 /* Define a type for the array given the element type */
40 #define DECLARE_ARRAY_TYPE(element_type, array_type)                           \
41 	typedef struct {                                                       \
42 		int count;                                                     \
43 		int size;                                                      \
44 		element_type *element;                                         \
45 	} array_type;
46 
47 /* The initializer for an empty array is the zero value. */
48 #define ARRAY_INIT                                                             \
49 	{                                                                      \
50 	}
51 
52 #define _ARRAY_EXTEND(a)                                                       \
53 	({                                                                     \
54 		if ((a)->count >= (a)->size) {                                 \
55 			if ((a)->size == 0)                                    \
56 				(a)->size = 4;                                 \
57 			else                                                   \
58 				(a)->size *= 2;                                \
59 			(a)->element = (__typeof((a)->element))realloc(        \
60 				(a)->element,                                  \
61 				(a)->size * sizeof((a)->element[0]));          \
62 		}                                                              \
63 		&(a)->element[((a)->count)++];                                 \
64 	})
65 
66 /* Append an element with the given value to the array a */
67 #define ARRAY_APPEND(a, value)                                                 \
68 	do {                                                                   \
69 		*_ARRAY_EXTEND(a) = (value);                                   \
70 	} while (0)
71 
72 /* Append a zero element to the array a and return the pointer to the element */
73 #define ARRAY_APPEND_ZERO(a)                                                   \
74 	({                                                                     \
75 		typeof((a)->element) _tmp_ptr = _ARRAY_EXTEND(a);              \
76 		memset(_tmp_ptr, 0, sizeof(*_tmp_ptr));                        \
77 		_tmp_ptr;                                                      \
78 	})
79 
80 /* Return the number of elements in the array a */
81 #define ARRAY_COUNT(a) ((a)->count)
82 
83 /* Return a pointer to the i-th element in the array a */
84 #define ARRAY_ELEMENT(a, i) ((a)->element + (i))
85 
86 /* Return the index of the element pointed by p in the array a */
87 #define ARRAY_INDEX(a, p) ((p) - (a)->element)
88 
89 /* Go through each element in the array a and assign index and pointer
90    to the element to the variable i and ptr */
91 #define ARRAY_ELEMENT_FOREACH(a, i, ptr)                                       \
92 	for ((i) = 0, (ptr) = (a)->element; (i) < (a)->count; (i)++, (ptr)++)
93 
94 /* Free the memory used by the array a. The array becomes an empty array. */
95 #define ARRAY_FREE(a)                                                          \
96 	do {                                                                   \
97 		free((a)->element);                                            \
98 		(a)->element = NULL;                                           \
99 		(a)->size = 0;                                                 \
100 		(a)->count = 0;                                                \
101 	} while (0)
102 
103 /* Return the index of the element with the value x. -1 if not found */
104 #define ARRAY_FIND(a, x)                                                       \
105 	({                                                                     \
106 		typeof((a)->element) _bptr = (a)->element;                     \
107 		typeof((a)->element) _eptr = (a)->element + (a)->count;        \
108 		for (; _bptr != _eptr && *_bptr != x; _bptr++)                 \
109 			;                                                      \
110 		(_bptr == _eptr) ? -1 : (_bptr - (a)->element);                \
111 	})
112 
113 #ifdef __cplusplus
114 } /* extern "C" */
115 #endif
116 
117 #endif /* CRAS_ARRAY_H_ */
118