Skip to content
This repository has been archived by the owner on Oct 4, 2024. It is now read-only.

vector: fix support for odd-sized structures #21

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions include/libtrx/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
#include <stddef.h>
#include <stdint.h>

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);
Expand All @@ -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);
Expand Down
131 changes: 85 additions & 46 deletions src/vector.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>

#define VECTOR_DEFAULT_CAPACITY 4
#define VECTOR_GROWTH_RATE 2
#define P(obj) ((*obj->priv))

static void Vector_EnsureCapacity(VECTOR *vector);
struct VECTOR_PRIV {
char *items;
};

static void Vector_EnsureCapacity(VECTOR *vector, int32_t n);

VECTOR *Vector_Create(const size_t item_size)
{
Expand All @@ -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, const int32_t n)
{
if (vector->count + 1 <= vector->capacity) {
return;
while (vector->count + n > vector->capacity) {
vector->capacity *= VECTOR_GROWTH_RATE;
P(vector).items = Memory_Realloc(
P(vector).items, vector->item_size * vector->capacity);
}

vector->capacity *= VECTOR_GROWTH_RATE;
vector->items =
Memory_Realloc(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)
{
Vector_EnsureCapacity(vector);
vector->items[vector->count++] = item;
assert(index >= 0 && index < vector->count);
char *const items = P(vector).items;
return (void *)(items + index * vector->item_size);
}

void Vector_Insert(VECTOR *vector, const int32_t index, void *item)
void Vector_Add(VECTOR *const vector, void *const item)
{
assert(index >= 0 && index <= vector->count);

Vector_EnsureCapacity(vector);
Vector_EnsureCapacity(vector, 1);
Vector_Insert(vector, vector->count, item);
}

for (int32_t i = vector->count - 1; i >= index; i--) {
vector->items[i + 1] = vector->items[i];
void Vector_Insert(VECTOR *const vector, const int32_t index, void *const item)
{
assert(index >= 0 && index <= vector->count);
Vector_EnsureCapacity(vector, 1);
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) * 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);
if (index + 1 < vector->count) {
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);
}