mirror of
https://github.com/slendidev/lunar.git
synced 2026-01-30 16:28:58 +02:00
Add useful wayland RAII wrappers
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
286
src/wayland/List.h
Normal file
286
src/wayland/List.h
Normal file
@@ -0,0 +1,286 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
||||
#include <wayland-server-core.h>
|
||||
|
||||
namespace Lunar::Wayland {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T, wl_list T::*Member>
|
||||
constexpr std::ptrdiff_t member_offset() noexcept
|
||||
{
|
||||
return reinterpret_cast<std::ptrdiff_t>(
|
||||
&(reinterpret_cast<T const volatile *>(0)->*Member));
|
||||
}
|
||||
|
||||
template<typename T, wl_list T::*Member>
|
||||
inline T *container_of(wl_list *node) noexcept
|
||||
{
|
||||
auto *p = reinterpret_cast<std::byte *>(node) - member_offset<T, Member>();
|
||||
return reinterpret_cast<T *>(p);
|
||||
}
|
||||
|
||||
template<typename T, wl_list T::*Member>
|
||||
inline T const *container_of(wl_list const *node) noexcept
|
||||
{
|
||||
auto *p = reinterpret_cast<std::byte const *>(node)
|
||||
- member_offset<T, Member>();
|
||||
return reinterpret_cast<T const *>(p);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename T, wl_list T::*Member> 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<T, Member>(m_cur);
|
||||
}
|
||||
auto operator->() const -> pointer
|
||||
{
|
||||
return detail::container_of<T, Member>(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<T, Member>(m_cur);
|
||||
}
|
||||
auto operator->() const -> pointer
|
||||
{
|
||||
return detail::container_of<T, Member>(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
|
||||
Reference in New Issue
Block a user