110 lines
2.6 KiB
C
110 lines
2.6 KiB
C
#pragma once
|
|
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
|
|
#include "base/memory.h"
|
|
|
|
static constexpr size_t INIT_CAPACITY = 4;
|
|
static inline size_t next_capacity(size_t capacity) {
|
|
if (capacity) return capacity * 2;
|
|
return INIT_CAPACITY;
|
|
}
|
|
|
|
/**
|
|
* @file array.h
|
|
* @brief 动态数组基础操作。
|
|
*/
|
|
|
|
/**
|
|
* @brief 确保数组容量至少为 need。
|
|
*
|
|
* @param items 数组指针地址
|
|
* @param item_size 单个元素大小
|
|
* @param capacity 当前容量地址
|
|
* @param need 目标容量
|
|
*/
|
|
static inline void array_reserve_impl(
|
|
void **items,
|
|
size_t item_size,
|
|
size_t *capacity,
|
|
size_t need
|
|
) {
|
|
if (*capacity >= need) return;
|
|
|
|
size_t new_capacity = next_capacity(*capacity);
|
|
while (new_capacity < need) {
|
|
new_capacity = next_capacity(new_capacity);
|
|
}
|
|
|
|
if (*items) {
|
|
xrealloc(items, item_size * new_capacity);
|
|
} else {
|
|
*items = xmalloc(item_size * new_capacity);
|
|
}
|
|
*capacity = new_capacity;
|
|
}
|
|
|
|
/**
|
|
* @brief 追加一个槽位并返回其地址。
|
|
*
|
|
* @param items 数组指针地址
|
|
* @param item_size 单个元素大小
|
|
* @param count 元素个数地址
|
|
* @param capacity 容量地址
|
|
*
|
|
* @return void* 新槽位地址
|
|
*/
|
|
static inline void *array_push_impl(
|
|
void **items,
|
|
size_t item_size,
|
|
size_t *count,
|
|
size_t *capacity
|
|
) {
|
|
array_reserve_impl(items, item_size, capacity, *count + 1);
|
|
|
|
void *slot = (char *)*items + *count * item_size;
|
|
(*count)++;
|
|
return slot;
|
|
}
|
|
|
|
/**
|
|
* @brief 删除指定下标元素,并将后续元素左移。
|
|
*
|
|
* @param items 数组首地址
|
|
* @param item_size 单个元素大小
|
|
* @param count 元素个数地址
|
|
* @param index 要删除的下标
|
|
*
|
|
* @return true 删除成功
|
|
* @return false 下标越界
|
|
*/
|
|
static inline bool
|
|
array_erase_impl(void *items, size_t item_size, size_t *count, size_t index) {
|
|
if (index >= *count) return false;
|
|
|
|
size_t tail_count = *count - index - 1;
|
|
if (tail_count > 0) {
|
|
char *dest = (char *)items + index * item_size;
|
|
char *src = dest + item_size;
|
|
memmove(dest, src, tail_count * item_size);
|
|
}
|
|
|
|
(*count)--;
|
|
return true;
|
|
}
|
|
|
|
/** @brief 为具体类型数组预留容量。 */
|
|
#define array_reserve(items, capacity, need) \
|
|
array_reserve_impl((void **)&(items), sizeof(*(items)), &(capacity), (need))
|
|
|
|
/* clang-format off */
|
|
/** @brief 为具体类型数组追加一个槽位。 */
|
|
#define array_push(items, count, capacity)\
|
|
(typeof(items))array_push_impl((void **)&(items), sizeof(*(items)), &(count), &(capacity))
|
|
/* clang-format on */
|
|
|
|
/** @brief 删除具体类型数组中指定下标的元素。 */
|
|
#define array_erase(items, count, index) \
|
|
array_erase_impl((items), sizeof(*(items)), &(count), (index))
|