diff --git a/src/mobj_list_view.hpp b/src/mobj_list_view.hpp new file mode 100644 index 000000000..638e7d952 --- /dev/null +++ b/src/mobj_list_view.hpp @@ -0,0 +1,74 @@ +// 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_view_hpp +#define mobj_list_view_hpp + +#include +#include +#include + +#include "mobj.hpp" + +namespace srb2 +{ + +// for (T* ptr : MobjList(hnext(), [](T* ptr) { return ptr->hnext(); })) +template , bool> = true> +struct MobjListView +{ + struct Iterator + { + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = T*; + using pointer = value_type; + using reference = value_type; + + Iterator(pointer ptr, F adv) : ptr_(deref(ptr)), adv_(adv) {} + + bool operator==(const Iterator& b) const { return ptr_ == b.ptr_; }; + bool operator!=(const Iterator& b) const { return ptr_ != b.ptr_; }; + + reference operator*() const { return ptr_; } + pointer operator->() { return &ptr_; } + + Iterator& operator++() + { + ptr_ = deref(adv_(ptr_)); + return *this; + } + + Iterator operator++(int) + { + Iterator prev = *this; + ++(*this); + return prev; + } + + private: + pointer ptr_; + F adv_; + + static T* deref(T* ptr) { return ptr && ptr->valid() ? ptr : nullptr; } + }; + + MobjListView(T* ptr, F adv) : ptr_(ptr), adv_(adv) {} + + Iterator begin() const { return {ptr_, adv_}; } + Iterator end() const { return {nullptr, adv_}; } + +private: + T* ptr_; + F adv_; +}; + +}; // namespace srb2 + +#endif/*mobj_list_view_hpp*/