mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 21:32:44 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			270 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			270 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #pragma once
 | |
| 
 | |
| namespace AK {
 | |
| 
 | |
| class IntrusiveListNode;
 | |
| class IntrusiveListStorage {
 | |
| private:
 | |
|     friend class IntrusiveListNode;
 | |
|     template<class T, IntrusiveListNode T::*member>
 | |
|     friend class IntrusiveList;
 | |
|     IntrusiveListNode* m_first { nullptr };
 | |
|     IntrusiveListNode* m_last { nullptr };
 | |
| };
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| class IntrusiveList {
 | |
| public:
 | |
|     IntrusiveList();
 | |
|     ~IntrusiveList();
 | |
| 
 | |
|     void clear();
 | |
|     bool is_empty() const;
 | |
|     void append(T& n);
 | |
|     void prepend(T& n);
 | |
|     void remove(T& n);
 | |
|     bool contains(const T&) const;
 | |
|     T* first() const;
 | |
|     T* last() const;
 | |
| 
 | |
|     T* take_first();
 | |
| 
 | |
|     class Iterator {
 | |
|     public:
 | |
|         Iterator();
 | |
|         Iterator(T* value);
 | |
| 
 | |
|         T& operator*() const;
 | |
|         T* operator->() const;
 | |
|         bool operator==(const Iterator& other) const;
 | |
|         bool operator!=(const Iterator& other) const { return !(*this == other); }
 | |
|         Iterator& operator++();
 | |
|         Iterator& erase();
 | |
| 
 | |
|     private:
 | |
|         T* m_value { nullptr };
 | |
|     };
 | |
| 
 | |
|     Iterator begin();
 | |
|     Iterator end();
 | |
| 
 | |
| private:
 | |
|     static T* next(T* current);
 | |
|     static T* node_to_value(IntrusiveListNode& node);
 | |
|     IntrusiveListStorage m_storage;
 | |
| };
 | |
| 
 | |
| class IntrusiveListNode {
 | |
| public:
 | |
|     ~IntrusiveListNode();
 | |
|     void remove();
 | |
|     bool is_in_list() const;
 | |
| 
 | |
| private:
 | |
|     template<class T, IntrusiveListNode T::*member>
 | |
|     friend class IntrusiveList;
 | |
|     IntrusiveListStorage* m_storage = nullptr;
 | |
|     IntrusiveListNode* m_next = nullptr;
 | |
|     IntrusiveListNode* m_prev = nullptr;
 | |
| };
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline IntrusiveList<T, member>::Iterator::Iterator()
 | |
| {
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline IntrusiveList<T, member>::Iterator::Iterator(T* value)
 | |
|     : m_value(value)
 | |
| {
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline T& IntrusiveList<T, member>::Iterator::operator*() const
 | |
| {
 | |
|     return *m_value;
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline T* IntrusiveList<T, member>::Iterator::operator->() const
 | |
| {
 | |
|     return m_value;
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline bool IntrusiveList<T, member>::Iterator::operator==(const Iterator& other) const
 | |
| {
 | |
|     return other.m_value == m_value;
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline typename IntrusiveList<T, member>::Iterator& IntrusiveList<T, member>::Iterator::operator++()
 | |
| {
 | |
|     m_value = IntrusiveList<T, member>::next(m_value);
 | |
|     return *this;
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline typename IntrusiveList<T, member>::Iterator& IntrusiveList<T, member>::Iterator::erase()
 | |
| {
 | |
|     T* old = m_value;
 | |
|     m_value = IntrusiveList<T, member>::next(m_value);
 | |
|     (old->*member).remove();
 | |
|     return *this;
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline IntrusiveList<T, member>::IntrusiveList()
 | |
| 
 | |
| {
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline IntrusiveList<T, member>::~IntrusiveList()
 | |
| {
 | |
|     clear();
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline void IntrusiveList<T, member>::clear()
 | |
| {
 | |
|     while (m_storage.m_first)
 | |
|         m_storage.m_first->remove();
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline bool IntrusiveList<T, member>::is_empty() const
 | |
| {
 | |
|     return m_storage.m_first == nullptr;
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline void IntrusiveList<T, member>::append(T& n)
 | |
| {
 | |
|     auto& nnode = n.*member;
 | |
|     if (nnode.m_storage)
 | |
|         nnode.remove();
 | |
| 
 | |
|     nnode.m_storage = &m_storage;
 | |
|     nnode.m_prev = m_storage.m_last;
 | |
|     nnode.m_next = nullptr;
 | |
| 
 | |
|     if (m_storage.m_last)
 | |
|         m_storage.m_last->m_next = &nnode;
 | |
|     m_storage.m_last = &nnode;
 | |
|     if (!m_storage.m_first)
 | |
|         m_storage.m_first = &nnode;
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline void IntrusiveList<T, member>::prepend(T& n)
 | |
| {
 | |
|     auto& nnode = n.*member;
 | |
|     if (nnode.m_storage)
 | |
|         nnode.remove();
 | |
| 
 | |
|     nnode.m_storage = &m_storage;
 | |
|     nnode.m_prev = nullptr;
 | |
|     nnode.m_next = m_storage.m_first;
 | |
| 
 | |
|     if (m_storage.m_first)
 | |
|         m_storage.m_first->m_prev = &nnode;
 | |
|     m_storage.m_first = &nnode;
 | |
|     if (!m_storage.m_last)
 | |
|         m_storage.m_last = &nnode;
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline void IntrusiveList<T, member>::remove(T& n)
 | |
| {
 | |
|     auto& nnode = n.*member;
 | |
|     if (nnode.m_storage)
 | |
|         nnode.remove();
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline bool IntrusiveList<T, member>::contains(const T& n) const
 | |
| {
 | |
|     auto& nnode = n.*member;
 | |
|     return nnode.m_storage == &m_storage;
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline T* IntrusiveList<T, member>::first() const
 | |
| {
 | |
|     return m_storage.m_first ? node_to_value(*m_storage.m_first) : nullptr;
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline T* IntrusiveList<T, member>::take_first()
 | |
| {
 | |
|     if (auto* ptr = first()) {
 | |
|         remove(*ptr);
 | |
|         return ptr;
 | |
|     }
 | |
|     return nullptr;
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline T* IntrusiveList<T, member>::last() const
 | |
| {
 | |
|     return m_storage.m_last ? node_to_value(*m_storage.m_last) : nullptr;
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline T* IntrusiveList<T, member>::next(T* current)
 | |
| {
 | |
|     auto& nextnode = (current->*member).m_next;
 | |
|     T* nextstruct = nextnode ? node_to_value(*nextnode) : nullptr;
 | |
|     return nextstruct;
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline typename IntrusiveList<T, member>::Iterator IntrusiveList<T, member>::begin()
 | |
| {
 | |
|     return m_storage.m_first ? Iterator(node_to_value(*m_storage.m_first)) : Iterator();
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline typename IntrusiveList<T, member>::Iterator IntrusiveList<T, member>::end()
 | |
| {
 | |
|     return Iterator();
 | |
| }
 | |
| 
 | |
| template<class T, IntrusiveListNode T::*member>
 | |
| inline T* IntrusiveList<T, member>::node_to_value(IntrusiveListNode& node)
 | |
| {
 | |
|     return (T*)((char*)&node - ((char*)&(((T*)nullptr)->*member) - (char*)nullptr));
 | |
| }
 | |
| 
 | |
| inline IntrusiveListNode::~IntrusiveListNode()
 | |
| {
 | |
|     if (m_storage)
 | |
|         remove();
 | |
| }
 | |
| 
 | |
| inline void IntrusiveListNode::remove()
 | |
| {
 | |
|     ASSERT(m_storage);
 | |
|     if (m_storage->m_first == this)
 | |
|         m_storage->m_first = m_next;
 | |
|     if (m_storage->m_last == this)
 | |
|         m_storage->m_last = m_prev;
 | |
|     if (m_prev)
 | |
|         m_prev->m_next = m_next;
 | |
|     if (m_next)
 | |
|         m_next->m_prev = m_prev;
 | |
|     m_prev = nullptr;
 | |
|     m_next = nullptr;
 | |
|     m_storage = nullptr;
 | |
| }
 | |
| 
 | |
| inline bool IntrusiveListNode::is_in_list() const
 | |
| {
 | |
|     return m_storage != nullptr;
 | |
| }
 | |
| 
 | |
| }
 | |
| 
 | |
| using AK::IntrusiveList;
 | |
| using AK::IntrusiveListNode;
 | 
