cOMS/memory/Heap.h
Dennis Eichhorn 39fbcf4300
Some checks are pending
CodeQL / Analyze (${{ matrix.language }}) (autobuild, c-cpp) (push) Waiting to run
Microsoft C++ Code Analysis / Analyze (push) Waiting to run
linux bug fixes
2025-03-22 01:10:19 +00:00

149 lines
4.0 KiB
C
Executable File

/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef COMS_MEMORY_HEAP_H
#define COMS_MEMORY_HEAP_H
#include <stdio.h>
#include <string.h>
#include "../stdlib/Types.h"
#include "../log/DebugMemory.h"
#include "BufferMemory.h"
#include "../system/Allocator.h"
struct Heap {
byte* elements;
byte* helper_mem;
uint32 element_size;
uint64 capacity;
uint64 size;
int32 (*compare) (const void*, const void*);
};
void heap_alloc(Heap* heap, uint32 element_size, uint64 capacity, int32 (*compare)(const void*, const void*)) {
ASSERT_SIMPLE(element_size * capacity);
heap->elements = (byte *) platform_alloc(element_size * capacity + element_size);
if (!heap->elements) {
return;
}
heap->element_size = element_size;
heap->capacity = capacity;
heap->size = 0;
heap->compare = compare;
heap->helper_mem = heap->elements + element_size;
}
void heap_free(Heap* heap)
{
DEBUG_MEMORY_DELETE((uintptr_t) heap->elements, heap->element_size * heap->capacity);
platform_free((void **) &heap->elements);
}
void heap_init(Heap* heap, BufferMemory* buf, uint32 element_size, uint64 capacity, int32 (*compare)(const void*, const void*)) {
ASSERT_SIMPLE(element_size * capacity);
heap->elements = buffer_get_memory(buf, element_size * capacity, 8, true);
if (!heap->elements) {
return;
}
heap->element_size = element_size;
heap->capacity = capacity;
heap->size = 0;
heap->compare = compare;
}
void heapify_down(Heap* heap, uint64 index) {
uint64 left_child = 2 * index + 1;
uint64 right_child = left_child + 1;
uint64 largest = index;
void* largest_element = heap->elements + (largest * heap->element_size);
if (left_child < heap->size) {
void* left = heap->elements + (left_child * heap->element_size);
if (heap->compare(left, largest_element) > 0) {
largest = left_child;
}
}
if (right_child < heap->size) {
void* right = heap->elements + (right_child * heap->element_size);
void* current_largest = heap->elements + (largest * heap->element_size);
if (heap->compare(right, current_largest) > 0) {
largest = right_child;
}
}
if (largest != index) {
heap_swap(
heap->elements + (index * heap->element_size),
heap->elements + (largest * heap->element_size),
heap->element_size, heap->helper_mem
);
heapify_down(heap, largest);
}
}
void heapify_up(Heap* heap, uint64 index) {
if (index == 0) {
return; // Root node
}
uint64 parent_index = (index - 1) / 2;
void* current = heap->elements + (index * heap->element_size);
void* parent = heap->elements + (parent_index * heap->element_size);
if (heap->compare(current, parent) > 0) {
heap_swap(current, parent, heap->element_size, heap->helper_mem);
heapify_up(heap, parent_index);
}
}
void heap_push(Heap* heap, const void* element) {
if (heap->size >= heap->capacity) {
return;
}
void* target = heap->elements + (heap->size * heap->element_size);
memcpy(target, element, heap->element_size);
heapify_up(heap, heap->size);
++heap->size;
}
void heap_pop(Heap* heap, void* out) {
if (heap->size == 0) {
return;
}
DEBUG_MEMORY_READ((uintptr_t) heap->elements, heap->element_size);
memcpy(out, heap->elements, heap->element_size);
void* last_element = heap->elements + ((heap->size - 1) * heap->element_size);
memcpy(heap->elements, last_element, heap->element_size);
--heap->size;
heapify_down(heap, 0);
}
inline
void* heap_peek(Heap* heap) {
DEBUG_MEMORY_READ((uintptr_t) heap->elements, heap->element_size);
return heap->elements;
}
inline
void heap_swap(void* a, void* b, uint32 size, void* helper_mem) {
memcpy(helper_mem, a, size);
memcpy(a, b, size);
memcpy(b, helper_mem, size);
}
#endif