2023-09-24 14:43:22 +00:00
|
|
|
#if defined(__clang__)
|
|
|
|
#pragma once
|
|
|
|
#include "feely_pona_unity.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct FP_SentinelListLink
|
|
|
|
{
|
|
|
|
T data;
|
|
|
|
FP_SentinelListLink<T> *next;
|
|
|
|
FP_SentinelListLink<T> *prev;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct FP_SentinelList
|
|
|
|
{
|
|
|
|
Dqn_usize size;
|
|
|
|
FP_SentinelListLink<T> *sentinel;
|
|
|
|
};
|
|
|
|
|
2023-09-25 13:06:39 +00:00
|
|
|
template <typename T>
|
|
|
|
FP_SentinelListLink<T> *FP_SentinelList_Front(FP_SentinelList<T> *list)
|
|
|
|
{
|
|
|
|
FP_SentinelListLink<T> *result = nullptr;
|
|
|
|
if (list && list->sentinel && list->sentinel->next)
|
|
|
|
result = list->sentinel->next;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2023-09-24 14:43:22 +00:00
|
|
|
template <typename T>
|
|
|
|
bool FP_SentinelList_Iterate(FP_SentinelList<T> *list, FP_SentinelListLink<T> **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 <typename T>
|
|
|
|
FP_SentinelList<T> FP_SentinelList_Init(TELY_ChunkPool *pool)
|
|
|
|
{
|
|
|
|
FP_SentinelList<T> result = {};
|
|
|
|
result.sentinel = TELY_ChunkPool_New(pool, FP_SentinelListLink<T>);
|
|
|
|
result.sentinel->next = result.sentinel->prev = result.sentinel;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
FP_SentinelListLink<T> *FP_SentinelList_Make(FP_SentinelList<T> *list, TELY_ChunkPool *pool)
|
2023-09-25 13:06:39 +00:00
|
|
|
{
|
|
|
|
FP_SentinelListLink<T> *result = FP_SentinelList_MakeBefore(list, list->sentinel, pool);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2023-09-30 06:11:39 +00:00
|
|
|
template <typename T>
|
|
|
|
FP_SentinelListLink<T> *FP_SentinelList_Add(FP_SentinelList<T> *list, TELY_ChunkPool *pool, const T& data)
|
|
|
|
{
|
|
|
|
FP_SentinelListLink<T> *result = FP_SentinelList_Make(list, pool);
|
|
|
|
result->data = data;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2023-09-25 13:06:39 +00:00
|
|
|
template <typename T>
|
|
|
|
FP_SentinelListLink<T> *FP_SentinelList_MakeBefore(FP_SentinelList<T> *list, FP_SentinelListLink<T> *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<T> *result = TELY_ChunkPool_New(pool, FP_SentinelListLink<T>);
|
|
|
|
result->next = link;
|
|
|
|
result->prev = link->prev;
|
|
|
|
result->next->prev = result;
|
|
|
|
result->prev->next = result;
|
|
|
|
list->size++;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
FP_SentinelListLink<T> *FP_SentinelList_MakeAfter(FP_SentinelList<T> *list, FP_SentinelListLink<T> *link, TELY_ChunkPool *pool)
|
2023-09-24 14:43:22 +00:00
|
|
|
{
|
|
|
|
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<T> *result = TELY_ChunkPool_New(pool, FP_SentinelListLink<T>);
|
2023-09-25 13:06:39 +00:00
|
|
|
result->next = link->next;
|
|
|
|
result->prev = link;
|
2023-09-24 14:43:22 +00:00
|
|
|
result->next->prev = result;
|
|
|
|
result->prev->next = result;
|
|
|
|
list->size++;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
FP_SentinelListLink<T> *FP_SentinelList_Erase(FP_SentinelList<T> *list, FP_SentinelListLink<T> *link, TELY_ChunkPool *pool)
|
|
|
|
{
|
|
|
|
FP_SentinelListLink<T> *result = link->prev;
|
|
|
|
link->next->prev = link->prev;
|
|
|
|
link->prev->next = link->next;
|
|
|
|
TELY_ChunkPool_Dealloc(pool, link);
|
|
|
|
list->size--;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2023-10-14 01:01:22 +00:00
|
|
|
void FP_SentinelList_Clear(FP_SentinelList<T> *list, TELY_ChunkPool *pool)
|
2023-09-24 14:43:22 +00:00
|
|
|
{
|
|
|
|
if (!list || !pool)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (FP_SentinelListLink<T> *link = nullptr; FP_SentinelList_Iterate(list, &link); )
|
|
|
|
link = FP_SentinelList_Erase(list, link, pool);
|
2023-10-14 01:01:22 +00:00
|
|
|
}
|
2023-09-24 14:43:22 +00:00
|
|
|
|
2023-10-14 01:01:22 +00:00
|
|
|
template <typename T>
|
|
|
|
void FP_SentinelList_Deinit(FP_SentinelList<T> *list, TELY_ChunkPool *pool)
|
|
|
|
{
|
|
|
|
if (!list || !pool)
|
|
|
|
return;
|
|
|
|
FP_SentinelList_Clear(list, pool);
|
2023-09-24 14:43:22 +00:00
|
|
|
TELY_ChunkPool_Dealloc(pool, list->sentinel);
|
|
|
|
*list = {};
|
|
|
|
}
|
|
|
|
|
2023-09-30 06:11:39 +00:00
|
|
|
template <typename T>
|
|
|
|
FP_SentinelListLink<T> *FP_SentinelList_Find(FP_SentinelList<T> const *list, T const &find)
|
|
|
|
{
|
|
|
|
FP_SentinelListLink<T> *result = nullptr;
|
|
|
|
for (FP_SentinelListLink<FP_GameEntityHandle> *link = nullptr;
|
|
|
|
!result && FP_SentinelList_Iterate<FP_GameEntityHandle>(DQN_CAST(FP_SentinelList<T> *)list, &link); ) {
|
|
|
|
if (link->data == find)
|
|
|
|
result = link;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|