v->alloced = size;
v->active = 0;
v->count = 0;
+ v->dynamic = true;
v->index = XCALLOC(MTYPE_VECTOR_INDEX, sizeof(void *) * size);
return v;
}
void vector_free(vector v)
{
- XFREE(MTYPE_VECTOR_INDEX, v->index);
- XFREE(MTYPE_VECTOR, v);
+ if (v->alloced)
+ XFREE(MTYPE_VECTOR_INDEX, v->index);
+ if (v->dynamic)
+ XFREE(MTYPE_VECTOR, v);
}
-/* Check assigned index, and if it runs short double index pointer */
+/* resize vector to a minimum of num
+ * may resize larger to avoid excessive realloc overhead
+ */
void vector_ensure(vector v, unsigned int num)
{
+ unsigned int newsz;
+
if (v->alloced > num)
return;
- v->index = XREALLOC(MTYPE_VECTOR_INDEX, v->index,
- sizeof(void *) * (v->alloced * 2));
- memset(&v->index[v->alloced], 0, sizeof(void *) * v->alloced);
- v->alloced *= 2;
+ newsz = MAX(v->active * 2, num + 1);
+
+ if (!v->alloced && v->index) {
+ /* currently using global variable, not malloc'd memory */
+ void **orig_index = v->index;
- if (v->alloced <= num)
- vector_ensure(v, num);
+ v->index = XMALLOC(MTYPE_VECTOR_INDEX, sizeof(void *) * newsz);
+ memcpy(v->index, orig_index, v->active * sizeof(void *));
+ v->alloced = v->active;
+ } else
+ v->index = XREALLOC(MTYPE_VECTOR_INDEX, v->index,
+ sizeof(void *) * newsz);
+
+ memset(&v->index[v->alloced], 0, sizeof(void *) * (newsz - v->alloced));
+ v->alloced = newsz;
}
/* This function only returns next empty slot index. It dose not mean
/* Unset value at specified index slot. */
void vector_unset(vector v, unsigned int i)
{
- if (i >= v->alloced)
+ if (i >= v->active)
return;
if (v->index[i])
/* struct for vector */
struct _vector {
- unsigned int active; /* number of active slots */
- unsigned int alloced; /* number of allocated slot */
+ /* active: index of last non-NULL item (+1)
+ * count: number of non-NULL items (+1)
+ *
+ * the two will be different if a slot is set to NULL (without pulling
+ * up later items in the array). Whether this happens depends on
+ * which vector functions are used. If no empty slots are used, the
+ * two fields will be identical.
+ *
+ * alloced: size of array pointed to by index. If this is 0, index
+ * points at a global variable rather than a malloc'd bit of memory.
+ * The vector code will convert to malloc'd memory if necessary to
+ * perform updates.
+ */
+ unsigned int active;
+ unsigned int alloced;
unsigned int count;
+
+ /* whether struct _vector itself is dynamically allocated */
+ bool dynamic;
+
void **index; /* index to data */
};
typedef struct _vector *vector;