src/dynarray.c
  1#include <stdio.h>
  2
  3#include "alba.h"
  4
  5#include <stdlib.h>
  6#include <string.h>
  7
  8DynArray dynarray_new(const uint64_t element_size, const uint64_t capacity)
  9{
 10    DynArray array = {0};
 11    array.element_size = element_size;
 12    if (capacity > 0)
 13    {
 14        dynarray_reserve(&array, capacity);
 15    }
 16    return array;
 17}
 18
 19void dynarray_reserve(DynArray* array, const uint64_t request)
 20{
 21    if (array->capacity > request) return;
 22    if (array->capacity == 0) array->capacity = 16;
 23    while (request > array->capacity)
 24    {
 25        array->capacity *= 2;
 26    }
 27    array->data = reallocarray(array->data, array->capacity, array->element_size);
 28}
 29
 30void dynarray_append(DynArray* array, const void* value)
 31{
 32    dynarray_extend(array, 1, value);
 33}
 34
 35void dynarray_extend(DynArray* array, const uint64_t size, const void* data)
 36{
 37    dynarray_reserve(array, array->length + size);
 38    memcpy(array->data + array->length * array->element_size, data, size * array->element_size);
 39    array->length += size;
 40}
 41
 42void dynarray_release(const DynArray* array)
 43{
 44    free(array->data);
 45}
 46
 47void dynarray_clear(DynArray* array)
 48{
 49    array->length = 0;
 50}
 51
 52static void swap(const uint64_t element_size, void* a, void* b, void* temp)
 53{
 54    memcpy(temp, a, element_size);
 55    memcpy(a, b, element_size);
 56    memcpy(b, temp, element_size);
 57}
 58
 59static void quicksort(
 60    const uint64_t element_size, const uint64_t length, void* data,
 61    uint32_t (*is_before_pivot)(void* pivot, void* elem), void* temp
 62)
 63{
 64    if (length < 2) return;
 65
 66    void* pivot = data + (length - 1) * element_size;
 67    void* larger = NULL;
 68    for (uint64_t i = 0; i < length; i++)
 69    {
 70        void* current = data + i * element_size;
 71        if (is_before_pivot(pivot, current))
 72        {
 73            if (larger == NULL) continue;
 74            swap(element_size, larger, current, temp);
 75            larger += element_size;
 76        }
 77        else if (larger == NULL)
 78        {
 79            larger = current;
 80        }
 81    }
 82
 83    if (larger != NULL)
 84    {
 85        swap(element_size, larger, pivot, temp);
 86        pivot = larger;
 87    }
 88
 89    const uint64_t size_before = (pivot - data);
 90    const uint64_t num_elem_before = size_before / element_size;
 91    quicksort(element_size, num_elem_before, data, is_before_pivot, temp);
 92    quicksort(element_size, length - num_elem_before - 1, data + size_before + element_size, is_before_pivot, temp);
 93}
 94
 95void dynarray_sort(const DynArray* array, uint32_t (*is_before_pivot)(void* pivot, void* elem))
 96{
 97    void* temp = malloc(array->element_size);
 98    quicksort(array->element_size, array->length, array->data, is_before_pivot, temp);
 99    free(temp);
100}