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

Commit

Permalink
vector: fix support for odd-sized structures
Browse files Browse the repository at this point in the history
  • Loading branch information
rr- committed Aug 30, 2024
1 parent d655b88 commit eb41cc1
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 48 deletions.
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);
}

0 comments on commit eb41cc1

Please sign in to comment.