src/array.c
  1#include <stdio.h>
  2
  3#include "alba.h"
  4
  5#include <stdlib.h>
  6#include <string.h>
  7
  8AlbaArray alba_create_array(const uint64_t element_size, const uint64_t capacity)
  9{
 10    AlbaArray array = {0};
 11    array.element_size = element_size;
 12    if (capacity > 0)
 13    {
 14        array.capacity = capacity;
 15        array.data = reallocarray(array.data, capacity, element_size);
 16    }
 17    return array;
 18}
 19
 20void alba_array_reserve(AlbaArray* array, const uint64_t request)
 21{
 22    if (array->capacity > request) return;
 23    if (array->capacity == 0) array->capacity = 16;
 24    while (request > array->capacity)
 25    {
 26        array->capacity *= 2;
 27    }
 28    array->data = reallocarray(array->data, array->capacity, array->element_size);
 29}
 30
 31void alba_array_append(AlbaArray* array, const void* value)
 32{
 33    alba_array_extend(array, 1, value);
 34}
 35
 36void alba_array_extend(AlbaArray* array, const uint64_t size, const void* data)
 37{
 38    alba_array_reserve(array, array->length + size);
 39    memcpy(array->data + array->length * array->element_size, data, size * array->element_size);
 40    array->length += size;
 41}
 42
 43void alba_array_release(const AlbaArray* array)
 44{
 45    free(array->data);
 46}
 47
 48void alba_array_clear(AlbaArray* array)
 49{
 50    array->length = 0;
 51}
 52
 53static void swap(const uint64_t element_size, void* a, void* b, void* temp)
 54{
 55    memcpy(temp, a, element_size);
 56    memcpy(a, b, element_size);
 57    memcpy(b, temp, element_size);
 58}
 59
 60static void quicksort(
 61    const uint64_t element_size, const uint64_t length, void* data,
 62    uint32_t (*is_before_pivot)(void* pivot, void* elem), void* temp
 63)
 64{
 65    if (length < 2) return;
 66
 67    void* pivot = data + (length - 1) * element_size;
 68    void* larger = NULL;
 69    for (uint64_t i = 0; i < length; i++)
 70    {
 71        void* current = data + i * element_size;
 72        if (is_before_pivot(pivot, current))
 73        {
 74            if (larger == NULL) continue;
 75            swap(element_size, larger, current, temp);
 76            larger += element_size;
 77        }
 78        else if (larger == NULL)
 79        {
 80            larger = current;
 81        }
 82    }
 83
 84    if (larger != NULL)
 85    {
 86        swap(element_size, larger, pivot, temp);
 87        pivot = larger;
 88    }
 89
 90    const uint64_t size_before = (pivot - data);
 91    const uint64_t num_elem_before = size_before / element_size;
 92    quicksort(element_size, num_elem_before, data, is_before_pivot, temp);
 93    quicksort(element_size, length - num_elem_before - 1, data + size_before + element_size, is_before_pivot, temp);
 94}
 95
 96void alba_array_sort(const AlbaArray* array, uint32_t (*is_before_pivot)(void* pivot, void* elem))
 97{
 98    void* temp = malloc(array->element_size);
 99    quicksort(array->element_size, array->length, array->data, is_before_pivot, temp);
100    free(temp);
101}
102
103void alba_array_print(const AlbaArray* array, void (*print_element)(void* element))
104{
105    printf("len: %lu\n", array->length);
106    for (uint64_t i = 0; i < array->length; i++)
107    {
108        print_element(array->data + i * array->element_size);
109    }
110}
111
112void* alba_array_last(const AlbaArray* array)
113{
114    return array->data + array->length - 1;
115}