#ifndef PK_PKARR_H #define PK_PKARR_H #include #include "pkmem.h" /* deleteme */ struct pk_arr { uint32_t next; uint32_t reserved; uint32_t stride; uint32_t alignment; struct pk_membucket *bkt; void *data; }; typedef bool(pk_arr_item_compare)(void *user_data, void *item); void pk_arr_clear(struct pk_arr *arr); void pk_arr_reset(struct pk_arr *arr); void pk_arr_reserve(struct pk_arr *arr, uint32_t count); void pk_arr_resize(struct pk_arr *arr, uint32_t count); void pk_arr_move_to_back(struct pk_arr *arr, uint32_t index); void pk_arr_append(struct pk_arr *arr, void *data); void pk_arr_remove_at(struct pk_arr *arr, uint32_t index); uint32_t pk_arr_find_first_index(struct pk_arr *arr, void *user_data, pk_arr_item_compare *fn); #endif /* PK_PKARR_H */ #ifdef PK_IMPL_ARR #include "./pkmacros.h" /* deleteme */ #ifndef PK_ARR_GROW_RATIO #define PK_ARR_GROW_RATIO 1.5 #endif #ifndef PK_ARR_INITIAL_COUNT #define PK_ARR_INITIAL_COUNT 16 #endif void pk_arr_clear(struct pk_arr *arr) { arr->next = 0; } void pk_arr_reset(struct pk_arr *arr) { if (arr->data != NULL) pk_delete(arr->data, arr->stride * arr->reserved, arr->bkt); arr->data = NULL; arr->next = 0; arr->reserved = 0; } void pk_arr_reserve(struct pk_arr *arr, uint32_t count) { if (arr->reserved >= count) return; void *new_data = pk_new(arr->stride * count, arr->alignment, arr->bkt); if (arr->data != NULL) { if (arr->next != 0) { memcpy(new_data, arr->data, arr->stride * arr->reserved); } pk_delete(arr->data, arr->stride * arr->reserved, arr->bkt); } arr->reserved = count; arr->data = new_data; } void pk_arr_resize(struct pk_arr *arr, uint32_t count) { pk_arr_reserve(arr, count); arr->next = count; } void pk_arr_move_to_back(struct pk_arr *arr, uint32_t index) { if (arr->reserved == 0) return; if (arr->next <= 1) return; #ifdef PK_ARR_MOVE_IN_PLACE uint32_t i, ii; uint8_t *target = (uint8_t *)pk_new(arr->stride, arr->alignment, arr->bkt); uint8_t *buffer = (uint8_t *)arr->data; for (ii = 0, i = arr->stride * index; ii < arr->stride; ++ii, ++i) { target[ii] = buffer[i]; } for (i = arr->stride * index; i < (arr->stride * (arr->next - 1)); ++i) { buffer[i] = buffer[i + arr->stride]; } for (ii = 0, i = arr->stride * (arr->next - 1); ii < arr->stride; ++ii, ++i) { buffer[i] = target[ii]; } pk_delete(target, arr->stride, arr->bkt); #else char *new_data = (char *)pk_new(arr->stride * arr->reserved, arr->alignment, arr->bkt); if (index > 0) { memcpy(new_data, arr->data, arr->stride * index); } memcpy( new_data + (arr->stride * (arr->next - 1)), ((char *)arr->data) + (arr->stride * index), arr->stride); memcpy( new_data + (arr->stride * index), ((char *)arr->data) + (arr->stride * (index + 1)), arr->stride * (arr->next - index - 1)); pk_delete(arr->data, arr->stride * arr->reserved, arr->bkt); arr->data = (void *)new_data; #endif } void pk_arr_append(struct pk_arr *arr, void *data) { if (arr->reserved == arr->next) { uint32_t new_count = PK_MAX(arr->reserved == 0 ? PK_ARR_INITIAL_COUNT : arr->reserved * PK_ARR_GROW_RATIO, arr->reserved + 1); void *new_data = pk_new(arr->stride * new_count, arr->alignment, arr->bkt); if (arr->data != NULL) { memcpy(new_data, arr->data, arr->stride * arr->reserved); pk_delete(arr->data, arr->stride * arr->reserved, arr->bkt); } arr->data = new_data; arr->reserved = new_count; } memcpy(((char *)arr->data) + (arr->stride * arr->next), data, arr->stride); arr->next += 1; return; } void pk_arr_remove_at(struct pk_arr *arr, uint32_t index) { if (arr->reserved == 0) return; if (index == arr->next - 1) { arr->next -=1; return; } #ifdef PK_ARR_MOVE_IN_PLACE uint32_t i; uint8_t *buffer = (uint8_t *)arr->data; for (i = arr->stride * index; i < (arr->stride * (arr->next - 1)); ++i) { buffer[i] = buffer[i + arr->stride]; } #else char *new_data = (char *)pk_new(arr->stride * arr->reserved, arr->alignment, arr->bkt); if (index > 0) { memcpy(new_data, arr->data, arr->stride * index); } memcpy( new_data + (arr->stride * index), ((char *)arr->data) + (arr->stride * (index + 1)), arr->stride * (arr->next - index - 1)); pk_delete(arr->data, arr->stride * arr->reserved, arr->bkt); arr->data = (void *)new_data; #endif arr->next -= 1; } uint32_t pk_arr_find_first_index(struct pk_arr *arr, void *user_data, pk_arr_item_compare *fn) { uint32_t i; char *char_data = (char *)arr->data; for (i = 0; i < arr->next; ++i) { if (fn(user_data, char_data + (arr->stride * i))) return i; } return -1; } #endif /* PK_IMPL_ARR */