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>;
|
|
};
|