Skip to content
Merged
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
1 change: 1 addition & 0 deletions javascript/packages/node/binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"./extension/libherb/util.c",
"./extension/libherb/util/hb_arena.c",
"./extension/libherb/util/hb_array.c",
"./extension/libherb/util/hb_narray.c",
"./extension/libherb/util/hb_buffer.c",
"./extension/libherb/util/hb_string.c",
"./extension/libherb/util/hb_system.c",
Expand Down
29 changes: 29 additions & 0 deletions src/include/util/hb_narray.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef HERB_NARRAY_H
#define HERB_NARRAY_H

#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct HB_NARRAY_STRUCT {
uint8_t* items;
size_t item_size;
size_t size;
size_t capacity;
} hb_narray_T;

void hb_narray_init(hb_narray_T* array, size_t item_size, size_t initial_capacity);
#define hb_narray_pointer_init(array, initial_capacity) (hb_narray_init(array, sizeof(void*), initial_capacity))

void* hb_narray_get(const hb_narray_T* array, size_t index);
void* hb_narray_first(hb_narray_T* array);
void* hb_narray_last(hb_narray_T* array);

void hb_narray_append(hb_narray_T* array, void* item);
void hb_narray_remove(hb_narray_T* array, size_t index);
void hb_narray_deinit(hb_narray_T* array);

#define hb_narray_push(array, item) (hb_narray_append(array, item))
bool hb_narray_pop(hb_narray_T* array, void* item);

#endif
75 changes: 75 additions & 0 deletions src/util/hb_narray.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include "../include/util/hb_narray.h"

#include <assert.h>
#include <stdbool.h>
#include <string.h>

void hb_narray_init(hb_narray_T* array, size_t item_size, size_t initial_capacity) {
assert(initial_capacity != 0);

array->item_size = item_size;
array->capacity = initial_capacity;
array->size = 0;
array->items = malloc(array->capacity * array->item_size);
}

void hb_narray_append(hb_narray_T* array, void* item) {
if (array->size + 1 > array->capacity) {
array->capacity *= 2;
void* new_buffer = realloc(array->items, array->capacity * array->item_size);
assert(new_buffer != NULL);
array->items = new_buffer;
}

memcpy(array->items + (array->size * array->item_size), item, array->item_size);
array->size += 1;
}

static inline uint8_t* hb_narray_memory_position(const hb_narray_T* array, size_t index) {
return array->items + (array->item_size * index);
}

void hb_narray_remove(hb_narray_T* array, size_t index) {
assert(index < array->size);

if (array->size - 1 > index) {
size_t elements_to_shift = (array->size - 1) - index;
size_t bytes_to_shift = array->item_size * elements_to_shift;

memcpy(hb_narray_memory_position(array, index), hb_narray_memory_position(array, index + 1), bytes_to_shift);
}

array->size -= 1;
}

void* hb_narray_get(const hb_narray_T* array, size_t index) {
assert(index < array->size);

return hb_narray_memory_position(array, index);
}

void* hb_narray_first(hb_narray_T* array) {
if (array->size == 0) { return NULL; }

return hb_narray_get(array, 0);
}

void* hb_narray_last(hb_narray_T* array) {
if (array->size == 0) { return NULL; }
return hb_narray_get(array, array->size - 1);
}

bool hb_narray_pop(hb_narray_T* array, void* item) {
if (array->size == 0) { return false; }
memcpy(item, hb_narray_last(array), array->item_size);
array->size -= 1;

return true;
}

void hb_narray_deinit(hb_narray_T* array) {
array->item_size = 0;
array->capacity = 0;
array->size = 0;
free(array->items);
}
2 changes: 2 additions & 0 deletions test/c/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

TCase *hb_arena_tests(void);
TCase *hb_array_tests(void);
TCase *hb_narray_tests(void);
TCase *hb_buffer_tests(void);
TCase *hb_string_tests(void);
TCase *herb_tests(void);
Expand All @@ -18,6 +19,7 @@ Suite *herb_suite(void) {

suite_add_tcase(suite, hb_arena_tests());
suite_add_tcase(suite, hb_array_tests());
suite_add_tcase(suite, hb_narray_tests());
suite_add_tcase(suite, hb_buffer_tests());
suite_add_tcase(suite, hb_string_tests());
suite_add_tcase(suite, herb_tests());
Expand Down
152 changes: 152 additions & 0 deletions test/c/test_hb_narray.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#include "include/test.h"
#include "../../src/include/util/hb_narray.h"

TEST(test_hb_narray_init)
hb_narray_T array;

hb_narray_init(&array, sizeof(uint64_t), 1024);

ck_assert_int_eq(array.item_size, sizeof(uint64_t));
ck_assert_int_eq(array.capacity, 1024);
ck_assert_int_eq(array.size, 0);
ck_assert_ptr_nonnull(array.items);

hb_narray_deinit(&array);
END

TEST(test_hb_narray_pointer_init)
hb_narray_T array;

hb_narray_pointer_init(&array, 1024);

ck_assert_int_eq(array.item_size, sizeof(void *));
ck_assert_int_eq(array.capacity, 1024);
ck_assert_int_eq(array.size, 0);
ck_assert_ptr_nonnull(array.items);

hb_narray_deinit(&array);
END

TEST(test_hb_narray_append)
hb_narray_T array;

hb_narray_init(&array, sizeof(uint64_t), 2);

uint64_t number = 1;
hb_narray_append(&array, &number);
ck_assert_int_eq(array.capacity, 2);

number = 2;
hb_narray_append(&array, &number);
ck_assert_int_eq(array.capacity, 2);

number = 3;
hb_narray_append(&array, &number);
ck_assert_int_eq(array.capacity, 4);

ck_assert_int_eq(*(uint64_t *)hb_narray_get(&array, 0), 1);
ck_assert_int_eq(*(uint64_t *)hb_narray_get(&array, 1), 2);
ck_assert_int_eq(*(uint64_t *)hb_narray_get(&array, 2), 3);

ck_assert_int_eq(array.size, 3);

hb_narray_deinit(&array);
END

TEST(test_hb_narray_first_last)
hb_narray_T array;

hb_narray_init(&array, sizeof(uint64_t), 2);

ck_assert_ptr_null(hb_narray_first(&array));
ck_assert_ptr_null(hb_narray_last(&array));

uint64_t number = 1;
hb_narray_append(&array, &number);

ck_assert_int_eq(*(uint64_t *)hb_narray_first(&array), 1);
ck_assert_int_eq(*(uint64_t *)hb_narray_last(&array), 1);

number = 2;
hb_narray_append(&array, &number);

ck_assert_int_eq(*(uint64_t *)hb_narray_first(&array), 1);
ck_assert_int_eq(*(uint64_t *)hb_narray_last(&array), 2);

hb_narray_deinit(&array);
END

TEST(test_hb_narray_stack_behavior)
hb_narray_T array;

hb_narray_init(&array, sizeof(uint64_t), 2);

for(uint64_t i = 0; i < 4; i++) {
hb_narray_push(&array, &i);
}

uint64_t number;

ck_assert(hb_narray_pop(&array, &number));
ck_assert_int_eq(number, 3);
ck_assert_int_eq(array.size, 3);

ck_assert(hb_narray_pop(&array, &number));
ck_assert_int_eq(number, 2);
ck_assert_int_eq(array.size, 2);

ck_assert(hb_narray_pop(&array, &number));
ck_assert_int_eq(number, 1);
ck_assert_int_eq(array.size, 1);

ck_assert(hb_narray_pop(&array, &number));
ck_assert_int_eq(number, 0);
ck_assert_int_eq(array.size, 0);

ck_assert(!hb_narray_pop(&array, &number));

hb_narray_deinit(&array);
END

TEST(test_hb_narray_remove)
hb_narray_T array;

hb_narray_init(&array, sizeof(uint64_t), 2);

for(uint64_t i = 0; i < 4; i++) {
hb_narray_push(&array, &i);
}

hb_narray_remove(&array, 0);
ck_assert_int_eq(array.size, 3);
ck_assert_int_eq(*(uint64_t *)hb_narray_get(&array, 0), 1);
ck_assert_int_eq(*(uint64_t *)hb_narray_get(&array, 1), 2);
ck_assert_int_eq(*(uint64_t *)hb_narray_get(&array, 2), 3);

hb_narray_remove(&array, 1);
ck_assert_int_eq(array.size, 2);
ck_assert_int_eq(*(uint64_t *)hb_narray_get(&array, 0), 1);
ck_assert_int_eq(*(uint64_t *)hb_narray_get(&array, 1), 3);

hb_narray_remove(&array, 1);
ck_assert_int_eq(array.size, 1);
ck_assert_int_eq(*(uint64_t *)hb_narray_get(&array, 0), 1);

hb_narray_remove(&array, 0);
ck_assert_int_eq(array.size, 0);

hb_narray_deinit(&array);
END

TCase *hb_narray_tests(void) {
TCase *buffer = tcase_create("Herb (New) Array");

tcase_add_test(buffer, test_hb_narray_init);
tcase_add_test(buffer, test_hb_narray_pointer_init);
tcase_add_test(buffer, test_hb_narray_append);
tcase_add_test(buffer, test_hb_narray_first_last);
tcase_add_test(buffer, test_hb_narray_stack_behavior);
tcase_add_test(buffer, test_hb_narray_remove);

return buffer;
}
Loading