+
+/************************************************************************
+ * Dynamic arrays with progressive allocation
+ ************************************************************************/
+
+/* Internal functions */
+#define _ARRAY_ALLOC(array, newsize) { \
+ (array).i_alloc = newsize; \
+ (array).p_elems = VLCCVP realloc( (array).p_elems, (array).i_alloc * \
+ sizeof(*(array).p_elems) ); \
+ if( !(array).p_elems ) abort(); \
+}
+
+#define _ARRAY_GROW1(array) { \
+ if( (array).i_alloc < 10 ) \
+ _ARRAY_ALLOC(array, 10 ) \
+ else if( (array).i_alloc == (array).i_size ) \
+ _ARRAY_ALLOC(array, (int)(array.i_alloc * 1.5) ) \
+}
+
+#define _ARRAY_GROW(array,additional) { \
+ int i_first = (array).i_alloc; \
+ while( (array).i_alloc - i_first < additional ) \
+ { \
+ if( (array).i_alloc < 10 ) \
+ _ARRAY_ALLOC(array, 10 ) \
+ else if( (array).i_alloc == (array).i_size ) \
+ _ARRAY_ALLOC(array, (int)((array).i_alloc * 1.5) ) \
+ else break; \
+ } \
+}
+
+#define _ARRAY_SHRINK(array) { \
+ if( (array).i_size > 10 && (array).i_size < (int)((array).i_alloc / 1.5) ) { \
+ _ARRAY_ALLOC(array, (array).i_size + 5); \
+ } \
+}
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/* API */
+#define DECL_ARRAY(type) struct { \
+ int i_alloc; \
+ int i_size; \
+ type *p_elems; \
+}
+
+#define TYPEDEF_ARRAY(type, name) typedef DECL_ARRAY(type) name;
+
+#define ARRAY_INIT(array) \
+ do { \
+ (array).i_alloc = 0; \
+ (array).i_size = 0; \
+ (array).p_elems = NULL; \
+ } while(0)
+
+#define ARRAY_RESET(array) \
+ do { \
+ (array).i_alloc = 0; \
+ (array).i_size = 0; \
+ free( (array).p_elems ); (array).p_elems = NULL; \
+ } while(0)
+
+#define ARRAY_APPEND(array, elem) \
+ do { \
+ _ARRAY_GROW1(array); \
+ (array).p_elems[(array).i_size] = elem; \
+ (array).i_size++; \
+ } while(0)
+
+#define ARRAY_INSERT(array,elem,pos) \
+ do { \
+ _ARRAY_GROW1(array); \
+ if( (array).i_size - pos ) { \
+ memmove( (array).p_elems + pos + 1, (array).p_elems + pos, \
+ ((array).i_size-pos) * sizeof(*(array).p_elems) ); \
+ } \
+ (array).p_elems[pos] = elem; \
+ (array).i_size++; \
+ } while(0)
+
+#define ARRAY_REMOVE(array,pos) \
+ do { \
+ if( (array).i_size - (pos) - 1 ) \
+ { \
+ memmove( (array).p_elems + pos, (array).p_elems + pos + 1, \
+ ( (array).i_size - pos - 1 ) *sizeof(*(array).p_elems) ); \
+ } \
+ (array).i_size--; \
+ _ARRAY_SHRINK(array); \
+ } while(0)
+
+#define ARRAY_VAL(array, pos) array.p_elems[pos]
+
+#define ARRAY_BSEARCH(array, elem, zetype, key, answer) \
+ BSEARCH( (array).p_elems, (array).i_size, elem, zetype, key, answer)
+
+#define FOREACH_ARRAY( item, array ) { \
+ int fe_idx; \
+ for( fe_idx = 0 ; fe_idx < (array).i_size ; fe_idx++ ) \
+ { \
+ item = (array).p_elems[fe_idx];
+
+#define FOREACH_END() } }
+
+
+/************************************************************************
+ * Dynamic arrays with progressive allocation (Preferred API)
+ ************************************************************************/
+typedef struct vlc_array_t
+{
+ int i_count;
+ void ** pp_elems;
+} vlc_array_t;
+
+static inline void vlc_array_init( vlc_array_t * p_array )
+{
+ memset( p_array, 0, sizeof(vlc_array_t) );
+}
+
+static inline void vlc_array_clear( vlc_array_t * p_array )
+{
+ free( p_array->pp_elems );
+ memset( p_array, 0, sizeof(vlc_array_t) );
+}
+
+static inline vlc_array_t * vlc_array_new( void )
+{
+ vlc_array_t * ret = (vlc_array_t *)malloc( sizeof(vlc_array_t) );
+ if( ret ) vlc_array_init( ret );
+ return ret;
+}
+
+static inline void vlc_array_destroy( vlc_array_t * p_array )
+{
+ if( !p_array )
+ return;
+ vlc_array_clear( p_array );
+ free( p_array );
+}
+
+
+/* Read */
+static inline int
+vlc_array_count( vlc_array_t * p_array )
+{
+ return p_array->i_count;
+}
+
+static inline void *
+vlc_array_item_at_index( vlc_array_t * p_array, int i_index )
+{
+ return p_array->pp_elems[i_index];
+}
+
+static inline int
+vlc_array_index_of_item( vlc_array_t * p_array, void * item )
+{
+ int i;
+ for( i = 0; i < p_array->i_count; i++)
+ {
+ if( p_array->pp_elems[i] == item )
+ return i;
+ }
+ return -1;
+}
+
+/* Write */
+static inline void
+vlc_array_insert( vlc_array_t * p_array, void * p_elem, int i_index )
+{
+ TAB_INSERT_CAST( (void **), p_array->i_count, p_array->pp_elems, p_elem, i_index );
+}
+
+static inline void
+vlc_array_append( vlc_array_t * p_array, void * p_elem )
+{
+ vlc_array_insert( p_array, p_elem, p_array->i_count );
+}
+
+static inline void
+vlc_array_remove( vlc_array_t * p_array, int i_index )
+{
+ if( i_index >= 0 )
+ {
+ if( p_array->i_count > 1 )
+ {
+ memmove( p_array->pp_elems + i_index,
+ p_array->pp_elems + i_index+1,
+ ( p_array->i_count - i_index - 1 ) * sizeof( void* ) );
+ }
+ p_array->i_count--;
+ if( p_array->i_count == 0 )
+ {
+ free( p_array->pp_elems );
+ p_array->pp_elems = NULL;
+ }
+ }
+}
+
+