#if defined(__clang__) #pragma once #include "feely_pona_unity.h" #endif template struct FP_SentinelListLink { T data; FP_SentinelListLink *next; FP_SentinelListLink *prev; }; template struct FP_SentinelList { Dqn_usize size; FP_SentinelListLink *sentinel; }; template FP_SentinelListLink *FP_SentinelList_Front(FP_SentinelList *list) { FP_SentinelListLink *result = nullptr; if (list && list->sentinel && list->sentinel->next) result = list->sentinel->next; return result; } template bool FP_SentinelList_Iterate(FP_SentinelList *list, FP_SentinelListLink **it) { if (!list || !list->sentinel || !it) return false; if (!DQN_CHECK(list->sentinel->next && list->sentinel->prev)) return false; if (!(*it)) *it = list->sentinel; bool result = list && (*it)->next != list->sentinel; if (result) (*it) = (*it)->next; return result; } template FP_SentinelList FP_SentinelList_Init(TELY_ChunkPool *pool) { FP_SentinelList result = {}; result.sentinel = TELY_ChunkPool_New(pool, FP_SentinelListLink); result.sentinel->next = result.sentinel->prev = result.sentinel; return result; } template FP_SentinelListLink *FP_SentinelList_Make(FP_SentinelList *list, TELY_ChunkPool *pool) { FP_SentinelListLink *result = FP_SentinelList_MakeBefore(list, list->sentinel, pool); return result; } template FP_SentinelListLink *FP_SentinelList_Add(FP_SentinelList *list, TELY_ChunkPool *pool, const T& data) { FP_SentinelListLink *result = FP_SentinelList_Make(list, pool); result->data = data; return result; } template FP_SentinelListLink *FP_SentinelList_MakeBefore(FP_SentinelList *list, FP_SentinelListLink *link, TELY_ChunkPool *pool) { DQN_ASSERT(list->sentinel->next); DQN_ASSERT(list->sentinel->prev); DQN_ASSERT(list->sentinel->prev->next == list->sentinel); DQN_ASSERT(list->sentinel->next->prev == list->sentinel); FP_SentinelListLink *result = TELY_ChunkPool_New(pool, FP_SentinelListLink); result->next = link; result->prev = link->prev; result->next->prev = result; result->prev->next = result; list->size++; return result; } template FP_SentinelListLink *FP_SentinelList_MakeAfter(FP_SentinelList *list, FP_SentinelListLink *link, TELY_ChunkPool *pool) { DQN_ASSERT(list->sentinel->next); DQN_ASSERT(list->sentinel->prev); DQN_ASSERT(list->sentinel->prev->next == list->sentinel); DQN_ASSERT(list->sentinel->next->prev == list->sentinel); FP_SentinelListLink *result = TELY_ChunkPool_New(pool, FP_SentinelListLink); result->next = link->next; result->prev = link; result->next->prev = result; result->prev->next = result; list->size++; return result; } template FP_SentinelListLink *FP_SentinelList_Erase(FP_SentinelList *list, FP_SentinelListLink *link, TELY_ChunkPool *pool) { FP_SentinelListLink *result = link->prev; link->next->prev = link->prev; link->prev->next = link->next; TELY_ChunkPool_Dealloc(pool, link); list->size--; return result; } template void FP_SentinelList_Clear(FP_SentinelList *list, TELY_ChunkPool *pool) { if (!list || !pool) return; for (FP_SentinelListLink *link = nullptr; FP_SentinelList_Iterate(list, &link); ) link = FP_SentinelList_Erase(list, link, pool); } template void FP_SentinelList_Deinit(FP_SentinelList *list, TELY_ChunkPool *pool) { if (!list || !pool) return; FP_SentinelList_Clear(list, pool); TELY_ChunkPool_Dealloc(pool, list->sentinel); *list = {}; } template FP_SentinelListLink *FP_SentinelList_Find(FP_SentinelList const *list, T const &find) { FP_SentinelListLink *result = nullptr; for (FP_SentinelListLink *link = nullptr; !result && FP_SentinelList_Iterate(DQN_CAST(FP_SentinelList *)list, &link); ) { if (link->data == find) result = link; } return result; }