+ * 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)