Files
nt-lite/code/kernel/include/kernel/ke_util.h
T

75 lines
3.7 KiB
C

// Kernel ke util declarations shared by implementation files and kernel clients.
#pragma once
#include <string.h>
#include <kernel/mm_virt.h>
// Dynamic array (stretchy-buffer style)
// T *buf = NULL;
// arr_push(buf, value); // appends; grows automatically
// arr_push_front(buf, value); // prepends
// arr_remove(buf, i); // removes index i, shifts tail left
// size_t n = arr_len(buf); // element count (0 if buf == NULL)
// arr_free(buf); // frees header + data
// The allocation layout is:
// [ Header (count, capacity) ][ T[0] ][ T[1] ] ...
// buf always points at T[0]; the Header lives one slot before it.
typedef struct {
size_t count;
size_t capacity;
} _ArrHeader;
#define _ARR_INIT_CAPACITY 2
#define _arr_header(arr) ((_ArrHeader *)(arr) - 1)
#define arr_len(arr) ((arr) ? _arr_header(arr)->count : 0u)
#define _arr_maybe_grow(arr) \
do { \
if (!(arr)) { \
_ArrHeader *_h = MmAllocatePool(sizeof(_ArrHeader) + \
sizeof(*(arr)) * _ARR_INIT_CAPACITY); \
_h->count = 0; \
_h->capacity = _ARR_INIT_CAPACITY; \
(arr) = (void *)(_h + 1); \
} \
_ArrHeader *_h = _arr_header(arr); \
if (_h->count >= _h->capacity) { \
_h->capacity *= 2; \
_h = MmReallocatePool(_h, sizeof(_ArrHeader) + \
sizeof(*(arr)) * _h->capacity); \
(arr) = (void *)(_h + 1); \
} \
} while (0)
#define arr_push(arr, x) \
do { \
_arr_maybe_grow(arr); \
(arr)[_arr_header(arr)->count++] = (x); \
} while (0)
#define arr_push_front(arr, x) \
do { \
_arr_maybe_grow(arr); \
_ArrHeader *_h = _arr_header(arr); \
memmove(&(arr)[1], &(arr)[0], sizeof(*(arr)) * _h->count); \
(arr)[0] = (x); \
_h->count++; \
} while (0)
#define arr_remove(arr, index) \
do { \
if ((arr) && (size_t)(index) < arr_len(arr)) { \
_ArrHeader *_h = _arr_header(arr); \
memmove(&(arr)[index], &(arr)[(index) + 1], \
sizeof(*(arr)) * (_h->count - (size_t)(index) - 1)); \
_h->count--; \
} \
} while (0)
#define arr_free(arr) MmFreePool(_arr_header(arr))