7 #ifndef _FCITX_UTILS_INSTRUSIVELIST_H_ 8 #define _FCITX_UTILS_INSTRUSIVELIST_H_ 13 #include <type_traits> 15 #include <fcitx-utils/macros.h> 16 #include <fcitx-utils/misc.h> 20 class IntrusiveListBase;
30 bool isInList()
const {
return !!list_; }
49 operator=(std::forward<IntrusiveListBase>(other));
57 if (size_ == 0 && other.size_ == 0) {
64 auto *node = other.root_.prev_;
66 other.remove(other.root_.prev_);
68 prepend(node, root_.next_);
86 return insertBetween(add, pos, pos->next_);
91 return insertBetween(add, pos->prev_, pos);
95 auto *next_ = pos->next_;
96 auto *prev_ = pos->prev_;
100 pos->next_ =
nullptr;
101 pos->prev_ =
nullptr;
102 pos->list_ =
nullptr;
116 std::size_t size_ = 0;
119 inline void IntrusiveListNode::remove() {
125 template <
typename T>
127 static_assert(std::is_base_of<IntrusiveListNode, T>::value,
128 "T must be a descendant of IntrusiveListNode");
135 return *
static_cast<T *
>(&node);
143 return *
static_cast<const T *
>(&node);
147 template <
typename T, IntrusiveListNode T::*ptrToNode>
150 return value.*ptrToNode;
154 return *parentFromMember(&node, ptrToNode);
158 return value.*ptrToNode;
162 return *parentFromMember(&node, ptrToNode);
166 template <
typename T,
typename NodeGetter>
169 template <
typename T,
typename NodeGetter,
bool isConst>
173 IntrusiveListNode *>;
177 using iterator_category = std::bidirectional_iterator_tag;
178 using value_type = T;
179 using difference_type = std::ptrdiff_t;
181 std::conditional_t<isConst,
typename list_type::const_reference,
182 typename list_type::reference>;
184 std::conditional_t<isConst,
typename list_type::const_pointer,
185 typename list_type::pointer>;
189 : node(node_), nodeGetter(&nodeGetter_) {}
192 template <
bool fromConst>
195 std::enable_if_t<isConst && !fromConst, enabler> = enabler())
196 : IntrusiveListIterator(other.pointed_node(), other.get_nodeGetter()) {}
198 FCITX_INLINE_DEFINE_DEFAULT_DTOR_AND_COPY(IntrusiveListIterator)
200 bool operator==(
const IntrusiveListIterator &other)
const noexcept {
201 return node == other.node;
203 bool operator!=(
const IntrusiveListIterator &other)
const noexcept {
204 return !operator==(other);
206 IntrusiveListIterator &operator++() {
211 IntrusiveListIterator operator++(
int) {
214 return {old, *nodeGetter};
217 reference operator*() {
return nodeGetter->toValue(*node); }
219 pointer operator->() {
return &nodeGetter->toValue(*node); }
221 node_ptr pointed_node()
const {
return node; }
223 const NodeGetter &get_nodeGetter()
const {
return *nodeGetter; }
227 const NodeGetter *nodeGetter;
230 template <
typename T,
typename NodeGetter = IntrusiveListTrivialNodeGetter<T>>
233 using value_type = T;
234 using pointer = value_type *;
235 using const_pointer =
const value_type *;
236 using reference = value_type &;
237 using const_reference =
const value_type &;
240 using reverse_iterator = std::reverse_iterator<iterator>;
241 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
242 using size_type = std::size_t;
245 : nodeGetter(nodeGetter_) {}
249 iterator begin() {
return {root_.next(), nodeGetter}; }
250 iterator end() {
return {&root_, nodeGetter}; }
252 const_iterator begin()
const {
253 return const_iterator{root_.next(), nodeGetter};
256 const_iterator end()
const {
return const_iterator{&root_, nodeGetter}; }
258 const_iterator cbegin()
const {
return {root_.next(), nodeGetter}; }
260 const_iterator cend()
const {
return {&root_, nodeGetter}; }
262 reference front() {
return *begin(); }
264 const_reference front()
const {
return *cbegin(); }
266 reference back() {
return *iterator{root_.prev(), nodeGetter}; }
268 const_reference back()
const {
269 return *const_iterator{root_.prev(), nodeGetter};
272 iterator iterator_to(reference value) {
273 return iterator(&nodeGetter.toNode(value), nodeGetter);
276 const_iterator iterator_to(const_reference value)
const {
277 return const_iterator(&nodeGetter.toNode(value), nodeGetter);
280 bool isInList(const_reference value)
const {
281 return nodeGetter.toNode(value).isInList(
this);
284 void push_back(reference value) {
285 auto &node = nodeGetter.toNode(value);
286 prepend(&node, &root_);
289 void pop_back() {
remove(root_.prev()); }
291 void push_front(reference value) { insert(begin(), value); }
293 void pop_front() { erase(begin()); }
295 iterator erase(iterator pos) {
296 auto node = pos.pointed_node();
297 auto next = node->next();
299 return {next, nodeGetter};
302 iterator erase(iterator start, iterator end) {
304 return {start->pointed_node(), nodeGetter};
308 while ((iter = erase(start)) != end) {
313 size_type size()
const {
return size_; }
315 bool empty()
const {
return root_.next() == &root_; }
317 iterator insert(iterator pos, reference value) {
319 prepend(&nodeGetter.toNode(value), pos.pointed_node());
320 return {pos.pointed_node()->prev(), nodeGetter};
324 NodeGetter nodeGetter;
327 template <
typename T>
331 #endif // _FCITX_UTILS_INSTRUSIVELIST_H_