diff --git a/include/libtrx/vector.h b/include/libtrx/vector.h index 63ba658..68bb9a1 100644 --- a/include/libtrx/vector.h +++ b/include/libtrx/vector.h @@ -4,11 +4,14 @@ #include #include -typedef struct VECTOR { +struct VECTOR_PRIV; + +typedef struct { int32_t count; int32_t capacity; size_t item_size; - void **items; + + struct VECTOR_PRIV *priv; } VECTOR; VECTOR *Vector_Create(size_t item_size); @@ -19,8 +22,10 @@ int32_t Vector_IndexOf(const VECTOR *vector, const void *item); int32_t Vector_LastIndexOf(const VECTOR *vector, const void *item); bool Vector_Contains(const VECTOR *vector, const void *item); +void *Vector_Get(VECTOR *vector, int32_t index); void Vector_Add(VECTOR *vector, void *item); void Vector_Insert(VECTOR *vector, int32_t index, void *item); +void Vector_Swap(VECTOR *vector, int32_t index1, int32_t index2); bool Vector_Remove(VECTOR *vector, const void *item); void Vector_RemoveAt(VECTOR *vector, int32_t index); diff --git a/src/vector.c b/src/vector.c index bc1e06c..146f6b5 100644 --- a/src/vector.c +++ b/src/vector.c @@ -4,11 +4,17 @@ #include #include +#include #include #include #define VECTOR_DEFAULT_CAPACITY 4 #define VECTOR_GROWTH_RATE 2 +#define P(obj) ((*obj->priv)) + +struct VECTOR_PRIV { + char *items; +}; static void Vector_EnsureCapacity(VECTOR *vector); @@ -23,116 +29,149 @@ VECTOR *Vector_CreateAtCapacity(const size_t item_size, const int32_t capacity) vector->count = 0; vector->capacity = capacity; vector->item_size = item_size; - vector->items = Memory_Alloc(item_size * capacity); + vector->priv = Memory_Alloc(sizeof(struct VECTOR_PRIV)); + P(vector).items = Memory_Alloc(item_size * capacity); return vector; } void Vector_Free(VECTOR *vector) { - Memory_FreePointer(&vector->items); + Memory_FreePointer(&P(vector).items); + Memory_FreePointer(&vector->priv); Memory_FreePointer(&vector); } -static void Vector_EnsureCapacity(VECTOR *vector) +static void Vector_EnsureCapacity(VECTOR *const vector) { if (vector->count + 1 <= vector->capacity) { return; } vector->capacity *= VECTOR_GROWTH_RATE; - vector->items = - Memory_Realloc(vector->items, vector->item_size * vector->capacity); + P(vector).items = + Memory_Realloc(P(vector).items, vector->item_size * vector->capacity); } -int32_t Vector_IndexOf(const VECTOR *vector, const void *item) +int32_t Vector_IndexOf(const VECTOR *const vector, const void *const item) { for (int32_t i = 0; i < vector->count; i++) { - if (vector->items[i] == item) { + if (memcmp( + P(vector).items + i * vector->item_size, item, + vector->item_size) + == 0) { return i; } } return -1; } -int32_t Vector_LastIndexOf(const VECTOR *vector, const void *item) +int32_t Vector_LastIndexOf(const VECTOR *const vector, const void *const item) { + const char *const items = P(vector).items; for (int32_t i = vector->count - 1; i >= 0; i--) { - if (vector->items[i] == item) { + if (memcmp(items + i * vector->item_size, item, vector->item_size) + == 0) { return i; } } return -1; } -bool Vector_Contains(const VECTOR *vector, const void *item) +bool Vector_Contains(const VECTOR *const vector, const void *const item) { return Vector_IndexOf(vector, item) != -1; } -void Vector_Add(VECTOR *vector, void *item) +void *Vector_Get(VECTOR *const vector, const int32_t index) +{ + assert(index >= 0 && index <= vector->count); + char *const items = P(vector).items; + return (void *)(items + index * vector->item_size); +} + +void Vector_Add(VECTOR *const vector, void *const item) { Vector_EnsureCapacity(vector); - vector->items[vector->count++] = item; + Vector_Insert(vector, vector->count, item); } -void Vector_Insert(VECTOR *vector, const int32_t index, void *item) +void Vector_Insert(VECTOR *const vector, const int32_t index, void *const item) { assert(index >= 0 && index <= vector->count); - Vector_EnsureCapacity(vector); - - for (int32_t i = vector->count - 1; i >= index; i--) { - vector->items[i + 1] = vector->items[i]; + char *const items = P(vector).items; + if (index < vector->count) { + memmove( + items + (index + 1) * vector->item_size, + items + index * vector->item_size, + (vector->count - (index + 1)) * vector->item_size); } - - vector->items[index] = item; + memcpy(items + index * vector->item_size, item, vector->item_size); vector->count++; } -bool Vector_Remove(VECTOR *vector, const void *item) +void Vector_Swap( + VECTOR *const vector, const int32_t index1, const int32_t index2) +{ + assert(index1 >= 0 && index1 <= vector->count); + assert(index2 >= 0 && index2 <= vector->count); + if (index1 == index2) { + return; + } + char *const items = P(vector).items; + void *tmp = Memory_Alloc(vector->item_size); + memcpy(tmp, items + index1 * vector->item_size, vector->item_size); + memcpy( + items + index1 * vector->item_size, items + index2 * vector->item_size, + vector->item_size); + memcpy(items + index2 * vector->item_size, tmp, vector->item_size); + Memory_FreePointer(&tmp); +} + +bool Vector_Remove(VECTOR *const vector, const void *item) { const int32_t index = Vector_IndexOf(vector, item); if (index == -1) { return false; } - Vector_RemoveAt(vector, index); return true; } -void Vector_RemoveAt(VECTOR *vector, const int32_t index) +void Vector_RemoveAt(VECTOR *const vector, const int32_t index) { assert(index >= 0 && index < vector->count); - - vector->items[index] = NULL; - for (int32_t i = index + 1; i < vector->count; i++) { - vector->items[i - 1] = vector->items[i]; - vector->items[i] = NULL; - } - + char *const items = P(vector).items; + memset(items + index * vector->item_size, 0, vector->item_size); + memmove( + items + index * vector->item_size, + items + (index + 1) * vector->item_size, + (vector->count - (index + 1)) * vector->item_size); vector->count--; } -void Vector_Reverse(VECTOR *vector) +void Vector_Reverse(VECTOR *const vector) { int32_t i = 0; int32_t j = vector->count - 1; + void *tmp = Memory_Alloc(vector->item_size); + char *const items = P(vector).items; for (; i < j; i++, j--) { - void *temp = vector->items[i]; - vector->items[i] = vector->items[j]; - vector->items[j] = temp; + memcpy(tmp, items + i * vector->item_size, vector->item_size); + memcpy( + items + i * vector->item_size, items + j * vector->item_size, + vector->item_size); + memcpy(items + j * vector->item_size, tmp, vector->item_size); } + Memory_FreePointer(&tmp); } -void Vector_Clear(VECTOR *vector) +void Vector_Clear(VECTOR *const vector) { - for (int32_t i = 0; i < vector->count; i++) { - vector->items[i] = NULL; - } - vector->count = 0; vector->capacity = VECTOR_DEFAULT_CAPACITY; - vector->items = - Memory_Realloc(vector->items, vector->item_size * vector->capacity); + P(vector).items = + Memory_Realloc(P(vector).items, vector->item_size * vector->capacity); + memset(P(vector).items, 0, vector->item_size * vector->count); }