diff --git a/src/mobj_list.hpp b/src/mobj_list.hpp new file mode 100644 index 000000000..ad9ac8964 --- /dev/null +++ b/src/mobj_list.hpp @@ -0,0 +1,86 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by James Robert Roman +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#ifndef mobj_list_hpp +#define mobj_list_hpp + +#include + +#include "cxxutil.hpp" +#include "mobj.hpp" +#include "mobj_list_view.hpp" + +namespace srb2 +{ + +// Requires: +// void T::next(T*) +// T* T::next() const +template +struct MobjList +{ + static_assert(std::is_convertible_v); + + MobjList() {} + + T* front() const { return static_cast(Head); } + bool empty() const { return !front(); } + + void push_front(T* ptr) + { + ptr->next(front()); + front(ptr); + } + + void erase(T* node) + { + if (front() == node) + { + front(node->next()); + node->next(nullptr); + return; + } + + auto view = this->view(); + auto end = view.end(); + auto it = view.begin(); + + SRB2_ASSERT(it != end); + + for (;;) + { + T* prev = *it; + + it++; + + if (it == end) + { + break; + } + + if (*it == node) + { + prev->next(node->next()); + node->next(nullptr); + break; + } + } + } + + auto begin() const { return view().begin(); } + auto end() const { return view().end(); } + +private: + void front(T* ptr) { Mobj::ManagedPtr {Head} = ptr; } + auto view() const { return MobjListView(front(), [](T* node) { return node->next(); }); } +}; + +}; // namespace srb2 + +#endif/*mobj_list_hpp*/