/* * Copyright (c) 2018-2020 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #pragma once #include #include #include namespace ams::kern { class KLinkedListNode : public util::IntrusiveListBaseNode, public KSlabAllocated { private: void *item; public: constexpr KLinkedListNode() : util::IntrusiveListBaseNode(), item(nullptr) { MESOSPHERE_ASSERT_THIS(); } constexpr void Initialize(void *it) { MESOSPHERE_ASSERT_THIS(); this->item = it; } constexpr void *GetItem() const { return this->item; } }; static_assert(sizeof(KLinkedListNode) == sizeof(util::IntrusiveListNode) + sizeof(void *)); template class KLinkedList : private util::IntrusiveListBaseTraits::ListType { private: using BaseList = util::IntrusiveListBaseTraits::ListType; public: template class Iterator; using value_type = T; using size_type = size_t; using difference_type = ptrdiff_t; using pointer = value_type *; using const_pointer = const value_type *; using reference = value_type &; using const_reference = const value_type &; using iterator = Iterator; using const_iterator = Iterator; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; template class Iterator { private: using BaseIterator = BaseList::Iterator; friend class KLinkedList; public: using iterator_category = std::bidirectional_iterator_tag; using value_type = typename KLinkedList::value_type; using difference_type = typename KLinkedList::difference_type; using pointer = typename std::conditional::type; using reference = typename std::conditional::type; private: BaseIterator base_it; public: explicit Iterator(BaseIterator it) : base_it(it) { /* ... */ } pointer GetItem() const { return static_cast(this->base_it->GetItem()); } bool operator==(const Iterator &rhs) const { return this->base_it == rhs.base_it; } bool operator!=(const Iterator &rhs) const { return !(*this == rhs); } pointer operator->() const { return this->GetItem(); } reference operator*() const { return *this->GetItem(); } Iterator &operator++() { ++this->base_it; return *this; } Iterator &operator--() { --this->base_it; return *this; } Iterator operator++(int) { const Iterator it{*this}; ++(*this); return it; } Iterator operator--(int) { const Iterator it{*this}; --(*this); return it; } operator Iterator() const { return Iterator(this->base_it); } }; public: constexpr KLinkedList() : BaseList() { /* ... */ } ~KLinkedList() { /* Erase all elements. */ for (auto it = this->begin(); it != this->end(); it = this->erase(it)) { /* ... */ } /* Ensure we succeeded. */ MESOSPHERE_ASSERT(this->empty()); } /* Iterator accessors. */ iterator begin() { return iterator(BaseList::begin()); } const_iterator begin() const { return const_iterator(BaseList::begin()); } iterator end() { return iterator(BaseList::end()); } const_iterator end() const { return const_iterator(BaseList::end()); } const_iterator cbegin() const { return this->begin(); } const_iterator cend() const { return this->end(); } reverse_iterator rbegin() { return reverse_iterator(this->end()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(this->end()); } reverse_iterator rend() { return reverse_iterator(this->begin()); } const_reverse_iterator rend() const { return const_reverse_iterator(this->begin()); } const_reverse_iterator crbegin() const { return this->rbegin(); } const_reverse_iterator crend() const { return this->rend(); } /* Content management. */ using BaseList::empty; using BaseList::size; reference back() { return *(--this->end()); } const_reference back() const { return *(--this->end()); } reference front() { return *this->begin(); } const_reference front() const { return *this->begin(); } iterator insert(const_iterator pos, reference ref) { KLinkedListNode *node = KLinkedListNode::Allocate(); MESOSPHERE_ABORT_UNLESS(node != nullptr); node->Initialize(std::addressof(ref)); return iterator(BaseList::insert(pos.base_it, *node)); } void push_back(reference ref) { this->insert(this->end(), ref); } void push_front(reference ref) { this->insert(this->begin(), ref); } void pop_back() { this->erase(--this->end()); } void pop_front() { this->erase(this->begin()); } iterator erase(const iterator pos) { KLinkedListNode *freed_node = std::addressof(*pos.base_it); iterator ret = iterator(BaseList::erase(pos.base_it)); KLinkedListNode::Free(freed_node); return ret; } }; }