#pragma once #include #include #include namespace Lunar::Wayland { namespace detail { template constexpr std::ptrdiff_t member_offset() noexcept { return reinterpret_cast( &(reinterpret_cast(0)->*Member)); } template inline T *container_of(wl_list *node) noexcept { auto *p { reinterpret_cast(node) - member_offset() }; return reinterpret_cast(p); } template inline T const *container_of(wl_list const *node) noexcept { auto *p { reinterpret_cast(node) - member_offset() }; return reinterpret_cast(p); } } // namespace detail template struct List { struct Iterator { using iterator_category = std::bidirectional_iterator_tag; using value_type = T; using difference_type = std::ptrdiff_t; using pointer = T *; using reference = T &; Iterator() = default; Iterator(wl_list *cur, wl_list *head) : m_cur(cur) , m_head(head) { } auto operator*() const -> reference { return *detail::container_of(m_cur); } auto operator->() const -> pointer { return detail::container_of(m_cur); } auto operator++() -> Iterator & { m_cur = m_cur->next; return *this; } auto operator++(int) -> Iterator { auto t { *this }; ++(*this); return t; } auto operator--() -> Iterator & { m_cur = (m_cur == m_head) ? m_head->prev : m_cur->prev; return *this; } auto operator--(int) -> Iterator { auto t { *this }; --(*this); return t; } friend auto operator==(Iterator a, Iterator b) -> bool { return a.m_cur == b.m_cur; } friend auto operator!=(Iterator a, Iterator b) -> bool { return !(a == b); } private: wl_list *m_cur { nullptr }; wl_list *m_head { nullptr }; }; struct ConstIterator { using iterator_category = std::bidirectional_iterator_tag; using value_type = T const; using difference_type = std::ptrdiff_t; using pointer = T const *; using reference = T const &; ConstIterator() = default; ConstIterator(wl_list const *cur, wl_list const *head) : m_cur(cur) , m_head(head) { } auto operator*() const -> reference { return *detail::container_of(m_cur); } auto operator->() const -> pointer { return detail::container_of(m_cur); } auto operator++() -> ConstIterator & { m_cur = m_cur->next; return *this; } auto operator++(int) -> ConstIterator { auto t { *this }; ++(*this); return t; } auto operator--() -> ConstIterator & { m_cur = (m_cur == m_head) ? m_head->prev : m_cur->prev; return *this; } auto operator--(int) -> ConstIterator { auto t { *this }; --(*this); return t; } friend auto operator==(ConstIterator a, ConstIterator b) -> bool { return a.m_cur == b.m_cur; } friend auto operator!=(ConstIterator a, ConstIterator b) -> bool { return !(a == b); } private: wl_list const *m_cur { nullptr }; wl_list const *m_head { nullptr }; }; List() : m_head {} , m_external_head { nullptr } , m_should_cleanup { true } { wl_list_init(&m_head); } explicit List( wl_list *existing_head, bool should_cleanup = false, bool init = false) : m_head {} , m_external_head { existing_head } , m_should_cleanup { should_cleanup } { if (init && m_external_head) wl_list_init(m_external_head); } ~List() { if (!m_should_cleanup) return; clear(); if (auto *h { head_ptr() }; h) wl_list_init(h); } List(List const &) = delete; auto operator=(List const &) -> List & = delete; List(List &&other) noexcept { move_from(other); } auto operator=(List &&other) noexcept -> List & { if (this != &other) { this->~List(); move_from(other); } return *this; } inline auto c_ptr() -> wl_list * { return head_ptr(); } inline auto c_ptr() const -> wl_list const * { return head_ptr(); } auto empty() const noexcept -> bool { return wl_list_empty(head_ptr()); } auto length() const noexcept -> int { return wl_list_length(head_ptr()); } auto push_front(T *elem) noexcept -> void { wl_list_insert(head_ptr(), &(elem->*Member)); } auto push_back(T *elem) noexcept -> void { auto *h { head_ptr() }; wl_list_insert(h->prev, &(elem->*Member)); } auto remove(T *elem) noexcept -> void { wl_list_remove(&(elem->*Member)); wl_list_init(&(elem->*Member)); } auto clear() noexcept -> void { auto *h { head_ptr() }; while (!wl_list_empty(h)) { auto *node { h->next }; wl_list_remove(node); wl_list_init(node); } } auto begin() noexcept -> Iterator { auto *h { head_ptr() }; return Iterator(h->next, h); } auto end() noexcept -> Iterator { auto *h { head_ptr() }; return Iterator(h, h); } auto begin() const noexcept -> ConstIterator { auto const *h { head_ptr() }; return ConstIterator(h->next, h); } auto end() const noexcept -> ConstIterator { auto const *h { head_ptr() }; return ConstIterator(h, h); } private: auto head_ptr() noexcept -> wl_list * { return m_external_head ? m_external_head : &m_head; } auto head_ptr() const noexcept -> wl_list const * { return m_external_head ? m_external_head : &m_head; } auto move_from(List &other) noexcept -> void { m_head = other.m_head; m_external_head = other.m_external_head; m_should_cleanup = other.m_should_cleanup; other.m_external_head = nullptr; other.m_should_cleanup = false; wl_list_init(&other.m_head); } private: wl_list m_head {}; wl_list *m_external_head { nullptr }; bool m_should_cleanup { true }; }; } // namespace Lunar::Wayland