463 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			463 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | #pragma once
 | ||
|  | #include <type_traits>
 | ||
|  | #include <iterator>
 | ||
|  | #include <stdexcept>
 | ||
|  | 
 | ||
|  | /// \~chinese
 | ||
|  | /// @brief 侵入式链表
 | ||
|  | template <typename _PtrTy> | ||
|  | class IntrusiveList | ||
|  | { | ||
|  | public: | ||
|  |     using value_type = typename std::pointer_traits<_PtrTy>::pointer; | ||
|  |     using pointer = value_type *; | ||
|  |     using reference = value_type &; | ||
|  | 
 | ||
|  |     IntrusiveList() | ||
|  |         : first_(), last_() | ||
|  |     { | ||
|  |     } | ||
|  | 
 | ||
|  |     ~IntrusiveList() | ||
|  |     { | ||
|  |         Clear(); | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 获取首元素
 | ||
|  |     const value_type &GetFirst() const | ||
|  |     { | ||
|  |         return first_; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 获取首元素
 | ||
|  |     value_type &GetFirst() | ||
|  |     { | ||
|  |         return first_; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 获取尾元素
 | ||
|  |     const value_type &GetLast() const | ||
|  |     { | ||
|  |         return last_; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 获取尾元素
 | ||
|  |     value_type &GetLast() | ||
|  |     { | ||
|  |         return last_; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 链表是否为空
 | ||
|  |     inline bool IsEmpty() const | ||
|  |     { | ||
|  |         return first_ == nullptr; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 在链表尾部添加对象
 | ||
|  |     void PushBack(reference child) | ||
|  |     { | ||
|  |         if (child->GetPrev()) | ||
|  |             child->GetPrev()->GetNext() = child->GetNext(); | ||
|  |         if (child->GetNext()) | ||
|  |             child->GetNext()->GetPrev() = child->GetPrev(); | ||
|  | 
 | ||
|  |         child->GetPrev() = last_; | ||
|  |         child->GetNext() = nullptr; | ||
|  | 
 | ||
|  |         if (first_) | ||
|  |         { | ||
|  |             last_->GetNext() = child; | ||
|  |         } | ||
|  |         else | ||
|  |         { | ||
|  |             first_ = child; | ||
|  |         } | ||
|  | 
 | ||
|  |         last_ = child; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 在链表头部添加对象
 | ||
|  |     void PushFront(reference child) | ||
|  |     { | ||
|  |         if (child->GetPrev()) | ||
|  |             child->GetPrev()->GetNext() = child->GetNext(); | ||
|  |         if (child->GetNext()) | ||
|  |             child->GetNext()->GetPrev() = child->GetPrev(); | ||
|  | 
 | ||
|  |         child->GetPrev() = nullptr; | ||
|  |         child->GetNext() = first_; | ||
|  | 
 | ||
|  |         if (first_) | ||
|  |         { | ||
|  |             first_->GetPrev() = child; | ||
|  |         } | ||
|  |         else | ||
|  |         { | ||
|  |             last_ = child; | ||
|  |         } | ||
|  | 
 | ||
|  |         first_ = child; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 在链表的对象前插入新对象
 | ||
|  |     void InsertBefore(reference child, reference before) | ||
|  |     { | ||
|  |         if (child->GetPrev()) | ||
|  |             child->GetPrev()->GetNext() = child->GetNext(); | ||
|  |         if (child->GetNext()) | ||
|  |             child->GetNext()->GetPrev() = child->GetPrev(); | ||
|  | 
 | ||
|  |         if (before->GetPrev()) | ||
|  |             before->GetPrev()->GetNext() = child; | ||
|  |         else | ||
|  |             first_ = child; | ||
|  | 
 | ||
|  |         child->GetPrev() = before->GetPrev(); | ||
|  |         child->GetNext() = before; | ||
|  |         before->GetPrev() = child; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 在链表的对象后插入新对象
 | ||
|  |     void InsertAfter(reference child, reference after) | ||
|  |     { | ||
|  |         if (child->GetPrev()) | ||
|  |             child->GetPrev()->GetNext() = child->GetNext(); | ||
|  |         if (child->GetNext()) | ||
|  |             child->GetNext()->GetPrev() = child->GetPrev(); | ||
|  | 
 | ||
|  |         if (after->GetNext()) | ||
|  |             after->GetNext()->GetPrev() = child; | ||
|  |         else | ||
|  |             last_ = child; | ||
|  | 
 | ||
|  |         child->GetNext() = after->GetNext(); | ||
|  |         child->GetPrev() = after; | ||
|  |         after->GetNext() = child; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 移除对象
 | ||
|  |     void Remove(reference child) | ||
|  |     { | ||
|  |         if (child->GetNext()) | ||
|  |         { | ||
|  |             child->GetNext()->GetPrev() = child->GetPrev(); | ||
|  |         } | ||
|  |         else | ||
|  |         { | ||
|  |             last_ = child->GetPrev(); | ||
|  |         } | ||
|  | 
 | ||
|  |         if (child->GetPrev()) | ||
|  |         { | ||
|  |             child->GetPrev()->GetNext() = child->GetNext(); | ||
|  |         } | ||
|  |         else | ||
|  |         { | ||
|  |             first_ = child->GetNext(); | ||
|  |         } | ||
|  | 
 | ||
|  |         child->GetPrev() = nullptr; | ||
|  |         child->GetNext() = nullptr; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 清空所有对象
 | ||
|  |     void Clear() | ||
|  |     { | ||
|  |         value_type p = first_; | ||
|  |         while (p) | ||
|  |         { | ||
|  |             value_type tmp = p; | ||
|  |             p = p->GetNext(); | ||
|  |             if (tmp) | ||
|  |             { | ||
|  |                 tmp->GetNext() = nullptr; | ||
|  |                 tmp->GetPrev() = nullptr; | ||
|  |             } | ||
|  |         } | ||
|  |         first_ = nullptr; | ||
|  |         last_ = nullptr; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 检查链表是否有效
 | ||
|  |     bool CheckValid() | ||
|  |     { | ||
|  |         if (!first_) | ||
|  |             return true; | ||
|  | 
 | ||
|  |         int pos = 0; | ||
|  | 
 | ||
|  |         value_type p = first_; | ||
|  |         value_type tmp = p; | ||
|  |         do | ||
|  |         { | ||
|  |             tmp = p; | ||
|  |             p = p->GetNext(); | ||
|  |             ++pos; | ||
|  | 
 | ||
|  |             if (p) | ||
|  |             { | ||
|  |                 if (p->GetPrev() != tmp) | ||
|  |                     return false; | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  |                 if (tmp != last_) | ||
|  |                     return false; | ||
|  |             } | ||
|  |         } while (p); | ||
|  |         return true; | ||
|  |     } | ||
|  | 
 | ||
|  | public: | ||
|  |     template <typename _IterPtrTy> | ||
|  |     struct Iterator | ||
|  |     { | ||
|  |         using iterator_category = std::bidirectional_iterator_tag; | ||
|  |         using value_type = _IterPtrTy; | ||
|  |         using pointer = _IterPtrTy *; | ||
|  |         using reference = _IterPtrTy &; | ||
|  |         using difference_type = ptrdiff_t; | ||
|  | 
 | ||
|  |         inline Iterator(value_type ptr = nullptr, bool is_end = false) | ||
|  |             : base_(ptr), is_end_(is_end) | ||
|  |         { | ||
|  |         } | ||
|  | 
 | ||
|  |         inline reference operator*() const | ||
|  |         { | ||
|  |             KGE_ASSERT(base_ && !is_end_); | ||
|  |             return const_cast<reference>(base_); | ||
|  |         } | ||
|  | 
 | ||
|  |         inline pointer operator->() const | ||
|  |         { | ||
|  |             return std::pointer_traits<pointer>::pointer_to(**this); | ||
|  |         } | ||
|  | 
 | ||
|  |         inline Iterator &operator++() | ||
|  |         { | ||
|  |             KGE_ASSERT(base_ && !is_end_); | ||
|  |             value_type next = base_->GetNext(); | ||
|  |             if (next) | ||
|  |                 base_ = next; | ||
|  |             else | ||
|  |                 is_end_ = true; | ||
|  |             return (*this); | ||
|  |         } | ||
|  | 
 | ||
|  |         inline Iterator operator++(int) | ||
|  |         { | ||
|  |             Iterator old = (*this); | ||
|  |             ++(*this); | ||
|  |             return old; | ||
|  |         } | ||
|  | 
 | ||
|  |         inline Iterator &operator--() | ||
|  |         { | ||
|  |             KGE_ASSERT(base_); | ||
|  |             if (is_end_) | ||
|  |                 is_end_ = false; | ||
|  |             else | ||
|  |                 base_ = base_->GetPrev(); | ||
|  |             return (*this); | ||
|  |         } | ||
|  | 
 | ||
|  |         inline Iterator operator--(int) | ||
|  |         { | ||
|  |             Iterator old = (*this); | ||
|  |             --(*this); | ||
|  |             return old; | ||
|  |         } | ||
|  | 
 | ||
|  |         inline bool operator==(const Iterator &other) const | ||
|  |         { | ||
|  |             return base_ == other.base_ && is_end_ == other.is_end_; | ||
|  |         } | ||
|  | 
 | ||
|  |         inline bool operator!=(const Iterator &other) const | ||
|  |         { | ||
|  |             return !(*this == other); | ||
|  |         } | ||
|  | 
 | ||
|  |         inline operator bool() const | ||
|  |         { | ||
|  |             return base_ != nullptr && !is_end_; | ||
|  |         } | ||
|  | 
 | ||
|  |     private: | ||
|  |         bool is_end_; | ||
|  | 
 | ||
|  |         typename std::remove_const<value_type>::type base_; | ||
|  |     }; | ||
|  | 
 | ||
|  | public: | ||
|  |     using iterator = Iterator<value_type>; | ||
|  |     using const_iterator = Iterator<const value_type>; | ||
|  |     using reverse_iterator = std::reverse_iterator<iterator>; | ||
|  |     using const_reverse_iterator = std::reverse_iterator<const_iterator>; | ||
|  | 
 | ||
|  |     inline iterator begin() | ||
|  |     { | ||
|  |         return iterator(first_, first_ == nullptr); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline const_iterator begin() const | ||
|  |     { | ||
|  |         return const_iterator(first_, first_ == nullptr); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline const_iterator cbegin() const | ||
|  |     { | ||
|  |         return begin(); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline iterator end() | ||
|  |     { | ||
|  |         return iterator(last_, true); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline const_iterator end() const | ||
|  |     { | ||
|  |         return const_iterator(last_, true); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline const_iterator cend() const | ||
|  |     { | ||
|  |         return end(); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline reverse_iterator rbegin() | ||
|  |     { | ||
|  |         return reverse_iterator(end()); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline const_reverse_iterator rbegin() const | ||
|  |     { | ||
|  |         return const_reverse_iterator(end()); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline const_reverse_iterator crbegin() const | ||
|  |     { | ||
|  |         return rbegin(); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline reverse_iterator rend() | ||
|  |     { | ||
|  |         return reverse_iterator(begin()); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline const_reverse_iterator rend() const | ||
|  |     { | ||
|  |         return const_reverse_iterator(begin()); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline const_reverse_iterator crend() const | ||
|  |     { | ||
|  |         return rend(); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline value_type &front() | ||
|  |     { | ||
|  |         if (IsEmpty()) | ||
|  |             throw std::out_of_range("front() called on empty list"); | ||
|  |         return first_; | ||
|  |     } | ||
|  | 
 | ||
|  |     inline const value_type &front() const | ||
|  |     { | ||
|  |         if (IsEmpty()) | ||
|  |             throw std::out_of_range("front() called on empty list"); | ||
|  |         return first_; | ||
|  |     } | ||
|  | 
 | ||
|  |     inline value_type &back() | ||
|  |     { | ||
|  |         if (IsEmpty()) | ||
|  |             throw std::out_of_range("back() called on empty list"); | ||
|  |         return last_; | ||
|  |     } | ||
|  | 
 | ||
|  |     inline const value_type &back() const | ||
|  |     { | ||
|  |         if (IsEmpty()) | ||
|  |             throw std::out_of_range("back() called on empty list"); | ||
|  |         return last_; | ||
|  |     } | ||
|  | 
 | ||
|  | private: | ||
|  |     value_type first_; | ||
|  |     value_type last_; | ||
|  | }; | ||
|  | 
 | ||
|  | /// \~chinese
 | ||
|  | /// @brief 侵入式链表元素
 | ||
|  | template <typename _PtrTy> | ||
|  | class IntrusiveListValue | ||
|  | { | ||
|  | public: | ||
|  |     using value_type = typename std::pointer_traits<_PtrTy>::pointer; | ||
|  |     using reference = value_type &; | ||
|  |     using pointer = value_type *; | ||
|  | 
 | ||
|  |     IntrusiveListValue() | ||
|  |         : prev_(nullptr), next_(nullptr) | ||
|  |     { | ||
|  |     } | ||
|  | 
 | ||
|  |     IntrusiveListValue(value_type rhs) | ||
|  |         : prev_(nullptr), next_(nullptr) | ||
|  |     { | ||
|  |         if (rhs) | ||
|  |         { | ||
|  |             prev_ = rhs->GetPrev(); | ||
|  |             next_ = rhs->GetNext(); | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 获取前一元素
 | ||
|  |     const value_type &GetPrev() const | ||
|  |     { | ||
|  |         return prev_; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 获取前一元素
 | ||
|  |     value_type &GetPrev() | ||
|  |     { | ||
|  |         return prev_; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 获取下一元素
 | ||
|  |     const value_type &GetNext() const | ||
|  |     { | ||
|  |         return next_; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// \~chinese
 | ||
|  |     /// @brief 获取下一元素
 | ||
|  |     value_type &GetNext() | ||
|  |     { | ||
|  |         return next_; | ||
|  |     } | ||
|  | 
 | ||
|  | private: | ||
|  |     value_type prev_; | ||
|  |     value_type next_; | ||
|  | 
 | ||
|  |     friend class IntrusiveList<_PtrTy>; | ||
|  | }; |