| /* |
| * Copyright 2017 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SkArenaAllocList_DEFINED |
| #define SkArenaAllocList_DEFINED |
| |
| #include "include/core/SkTypes.h" |
| #include "src/core/SkArenaAlloc.h" |
| |
| /** |
| * A singly linked list of Ts stored in a SkArenaAlloc. The arena rather than the list owns |
| * the elements. This supports forward iteration and range based for loops. |
| */ |
| template <typename T> |
| class SkArenaAllocList { |
| private: |
| struct Node; |
| |
| public: |
| SkArenaAllocList() = default; |
| |
| void reset() { fHead = fTail = nullptr; } |
| |
| template <typename... Args> |
| inline T& append(SkArenaAlloc* arena, Args... args); |
| |
| class Iter { |
| public: |
| Iter() = default; |
| inline Iter& operator++(); |
| T& operator*() const { return fCurr->fT; } |
| T* operator->() const { return &fCurr->fT; } |
| bool operator==(const Iter& that) const { return fCurr == that.fCurr; } |
| bool operator!=(const Iter& that) const { return !(*this == that); } |
| |
| private: |
| friend class SkArenaAllocList; |
| explicit Iter(Node* node) : fCurr(node) {} |
| Node* fCurr = nullptr; |
| }; |
| |
| Iter begin() { return Iter(fHead); } |
| Iter end() { return Iter(); } |
| Iter tail() { return Iter(fTail); } |
| |
| private: |
| struct Node { |
| template <typename... Args> |
| Node(Args... args) : fT(std::forward<Args>(args)...) {} |
| T fT; |
| Node* fNext = nullptr; |
| }; |
| Node* fHead = nullptr; |
| Node* fTail = nullptr; |
| }; |
| |
| template <typename T> |
| template <typename... Args> |
| T& SkArenaAllocList<T>::append(SkArenaAlloc* arena, Args... args) { |
| SkASSERT(!fHead == !fTail); |
| auto* n = arena->make<Node>(std::forward<Args>(args)...); |
| if (!fTail) { |
| fHead = fTail = n; |
| } else { |
| fTail = fTail->fNext = n; |
| } |
| return fTail->fT; |
| } |
| |
| template <typename T> |
| typename SkArenaAllocList<T>::Iter& SkArenaAllocList<T>::Iter::operator++() { |
| fCurr = fCurr->fNext; |
| return *this; |
| } |
| |
| #endif |