1/*
2 * Copyright 2020 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrSTArenaList_DEFINED
9#define GrSTArenaList_DEFINED
10
11#include "src/core/SkArenaAlloc.h"
12
13// A singly-linked list whose head element is a "stack allocated" class member and whose subsequent
14// elements are allocated in an SkArenaAlloc.
15template<typename T> class GrSTArenaList {
16public:
17 struct Node {
18 template <typename... Args>
19 Node(Args&&... elementArgs) : fElement(std::forward<Args>(elementArgs)...) {}
20 T fElement;
21 Node* fNext = nullptr;
22 };
23
24 template <typename... Args>
25 GrSTArenaList(Args&&... headArgs) : fHead(std::forward<Args>(headArgs)...) {}
26
27 const T& head() const { return fHead.fElement; }
28 T& head() { return fHead.fElement; }
29
30 void concat(GrSTArenaList&& list, SkArenaAlloc* allocator) {
31 Node* listHeadCopy = allocator->make<Node>(std::move(list.fHead));
32 fTail->fNext = listHeadCopy;
33 // If the list's fTail pointed to its locally allocated head element, then point our fTail
34 // at the copy we just made in the arena. Otherwise the list's fTail already points at an
35 // arena-allocated element, so keep it.
36 fTail = (list.fTail == &list.fHead) ? listHeadCopy : list.fTail;
37 }
38
39 struct Iter {
40 bool operator!=(const Iter& it) const { return fCurr != it.fCurr; }
41 bool operator==(const Iter& it) const { return fCurr == it.fCurr; }
42 void operator++() { fCurr = fCurr->fNext; }
43 T& operator*() { return fCurr->fElement; }
44 Node* fCurr;
45 };
46
47 Iter begin() { return Iter{&fHead}; }
48 Iter end() { return Iter{nullptr}; }
49
50private:
51 Node fHead;
52 Node* fTail = &fHead;
53};
54
55#endif
56