Home | History | Annotate | Download | only in common
      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 	FOR_ARRAY_ELEMENT(&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 #define _ARRAY_EXTEND(a)						\
     51 	({								\
     52 		if ((a)->count >= (a)->size) {				\
     53 			if ((a)->size == 0)				\
     54 				(a)->size = 4;				\
     55 			else						\
     56 				(a)->size *= 2;				\
     57 			(a)->element = (__typeof((a)->element))		\
     58 				realloc((a)->element,			\
     59 					(a)->size *			\
     60 					sizeof((a)->element[0]));	\
     61 		}							\
     62 		&(a)->element[((a)->count)++];				\
     63 	})
     64 
     65 /* Append an element with the given value to the array a */
     66 #define ARRAY_APPEND(a, value)						\
     67 	do {								\
     68 		*_ARRAY_EXTEND(a) = (value);				\
     69 	} while (0)
     70 
     71 /* Append a zero element to the array a and return the pointer to the element */
     72 #define ARRAY_APPEND_ZERO(a)					    \
     73 	({							    \
     74 		typeof((a)->element) _tmp_ptr = _ARRAY_EXTEND(a);   \
     75 		memset(_tmp_ptr, 0, sizeof(*_tmp_ptr));		    \
     76 		_tmp_ptr;					    \
     77 	})
     78 
     79 /* Return the number of elements in the array a */
     80 #define ARRAY_COUNT(a) ((a)->count)
     81 
     82 /* Return a pointer to the i-th element in the array a */
     83 #define ARRAY_ELEMENT(a, i) ((a)->element + (i))
     84 
     85 /* Return the index of the element pointed by p in the array a */
     86 #define ARRAY_INDEX(a, p) ((p) - (a)->element)
     87 
     88 /* Go through each element in the array a and assign index and pointer
     89    to the element to the variable i and ptr */
     90 #define FOR_ARRAY_ELEMENT(a, i, ptr)				    \
     91 	for ((i) = 0, (ptr) = (a)->element; (i) < (a)->count;	    \
     92 	     (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 
    104 /* Return the index of the element with the value x. -1 if not found */
    105 #define ARRAY_FIND(a, x)						\
    106 	({								\
    107 		typeof((a)->element) _bptr = (a)->element;		\
    108 		typeof((a)->element) _eptr = (a)->element + (a)->count; \
    109 		for (; _bptr != _eptr && *_bptr != x; _bptr++)		\
    110 			;						\
    111 		(_bptr == _eptr) ? -1 : (_bptr - (a)->element);		\
    112 	})
    113 
    114 #ifdef __cplusplus
    115 } /* extern "C" */
    116 #endif
    117 
    118 #endif /* CRAS_ARRAY_H_ */
    119