1 /*
2  * Copyright 2020 Google LLC.
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 SKSL_NODEARRAYWRAPPER
9 #define SKSL_NODEARRAYWRAPPER
10 
11 #include "include/private/SkTArray.h"
12 
13 namespace SkSL {
14 
15 class IRNode;
16 
17 // Wraps an SkTArray<std::unique_ptr<Base>> and presents it as a collection of <T>
18 // Once the rearchitecture is complete, Base will always be IRNode and thus we can remove that
19 // parameter, but right now we have to worry about wrapping both ExpressionArray and StatementArray
20 template<typename T, typename Base>
21 class NodeArrayWrapper {
22 public:
23     class iterator {
24     public:
25         T& operator*() {
26             return static_cast<T&>(**fBase);
27         }
28 
29         T* operator->() {
30             return static_cast<T*>(fBase->get());
31         }
32 
33         iterator& operator++() {
34             ++fBase;
35             return *this;
36         }
37 
38         bool operator==(const iterator& other) const {
39             return fBase == other.fBase;
40         }
41 
42         bool operator!=(const iterator& other) const {
43             return fBase != other.fBase;
44         }
45 
46     private:
iterator(const std::unique_ptr<Base> * base)47         iterator(const std::unique_ptr<Base>* base)
48             : fBase(base) {}
49 
50         const std::unique_ptr<Base>* fBase;
51 
52         friend class NodeArrayWrapper;
53     };
54 
55     class const_iterator {
56     public:
57         const T& operator*() {
58             return static_cast<const T&>(**fBase);
59         }
60 
61         const T* operator->() {
62             return static_cast<const T*>(fBase->get());
63         }
64 
65         const_iterator& operator++() {
66             ++fBase;
67             return *this;
68         }
69 
70         bool operator==(const const_iterator& other) const {
71             return fBase == other.fBase;
72         }
73 
74         bool operator!=(const const_iterator& other) const {
75             return fBase != other.fBase;
76         }
77 
78     private:
const_iterator(const std::unique_ptr<Base> * base)79         const_iterator(const std::unique_ptr<Base>* base)
80             : fBase(base) {}
81 
82         const std::unique_ptr<Base>* fBase;
83 
84         friend class NodeArrayWrapper;
85     };
86 
NodeArrayWrapper(SkTArray<std::unique_ptr<Base>> * contents)87     NodeArrayWrapper(SkTArray<std::unique_ptr<Base>>* contents)
88         : fContents(contents) {}
89 
NodeArrayWrapper(const NodeArrayWrapper & other)90     NodeArrayWrapper(const NodeArrayWrapper& other)
91         : fContents(other.fContents) {}
92 
93     NodeArrayWrapper& operator=(const NodeArrayWrapper& other) {
94         fContents = other.fContents;
95     }
96 
reset()97     void reset() {
98         fContents->reset();
99     }
100 
reserve_back(int n)101     void reserve_back(int n) {
102         fContents->reserve_back(n);
103     }
104 
count()105     int count() const {
106         return fContents->count();
107     }
108 
empty()109     bool empty() const {
110         return fContents->empty();
111     }
112 
113 
push_back(T * t)114     T& push_back(T* t) {
115         return static_cast<T&>(*fContents->emplace_back(t));
116     }
117 
emplace_back(Args &&...args)118     template<class... Args> T& emplace_back(Args&&... args) {
119         return static_cast<T&>(*fContents->emplace_back(new T(std::forward<Args>(args)...)));
120     }
121 
pop_back()122     void pop_back() {
123         fContents->pop_back();
124     }
125 
begin()126     iterator begin() {
127         return iterator(fContents->begin());
128     }
129 
end()130     iterator end() {
131         return iterator(fContents->end());
132     }
133 
begin()134     const_iterator begin() const {
135         return const_iterator(fContents->begin());
136     }
137 
end()138     const_iterator end() const {
139         return const_iterator(fContents->end());
140     }
141 
142     T& operator[](int i) {
143         SkASSERT(fContents->at(i));
144         return fContents->at(i)->template as<T>();
145     }
146 
147     const T& operator[](int i) const {
148         SkASSERT(fContents->at(i));
149         return fContents->at(i)->template as<T>();
150     }
151 
front()152     T& front() {
153         return fContents->front()->template as<T>();
154     }
155 
front()156     const T& front() const {
157         return fContents->front()->template as<T>();
158     }
159 
back()160     T& back() {
161         return fContents->back()->template as<T>();
162     }
163 
back()164     const T& back() const {
165         return fContents->back()->template as<T>();
166     }
167 
capacity()168     int capacity() const {
169         return fContents->capacity();
170     }
171 
172 private:
173     SkTArray<std::unique_ptr<Base>>* fContents;
174 };
175 
176 template<typename T, typename Base>
177 class ConstNodeArrayWrapper {
178 public:
179     class iterator {
180     public:
181         const T& operator*() {
182             return static_cast<T&>(**fBase);
183         }
184 
185         const T* operator->() {
186             return static_cast<T*>(fBase->get());
187         }
188 
189         iterator& operator++() {
190             ++fBase;
191             return *this;
192         }
193 
194         bool operator==(const iterator& other) const {
195             return fBase == other.fBase;
196         }
197 
198         bool operator!=(const iterator& other) const {
199             return fBase != other.fBase;
200         }
201 
202     private:
iterator(const std::unique_ptr<Base> * base)203         iterator(const std::unique_ptr<Base>* base)
204             : fBase(base) {}
205 
206         const std::unique_ptr<Base>* fBase;
207 
208         friend class ConstNodeArrayWrapper;
209     };
210 
ConstNodeArrayWrapper(const SkTArray<std::unique_ptr<Base>> * contents)211     ConstNodeArrayWrapper(const SkTArray<std::unique_ptr<Base>>* contents)
212         : fContents(contents) {}
213 
ConstNodeArrayWrapper(const ConstNodeArrayWrapper & other)214     ConstNodeArrayWrapper(const ConstNodeArrayWrapper& other)
215         : fContents(other.fContents) {}
216 
count()217     int count() const {
218         return fContents->count();
219     }
220 
empty()221     bool empty() const {
222         return fContents->empty();
223     }
224 
begin()225     iterator begin() const {
226         return iterator(fContents->begin());
227     }
228 
end()229     iterator end() const {
230         return iterator(fContents->end());
231     }
232 
233     T& operator[](int i) {
234         return fContents->at(i)->template as<T>();
235     }
236 
237     const T& operator[](int i) const {
238         return fContents->at(i)->template as<T>();
239     }
240 
front()241     T& front() {
242         return fContents->front()->template as<T>();
243     }
244 
front()245     const T& front() const {
246         return fContents->front()->template as<T>();
247     }
248 
back()249     T& back() { return fContents->back()->template as<T>(); }
250 
back()251     const T& back() const { return fContents->back()->template as<T>(); }
252 
253 private:
254     const SkTArray<std::unique_ptr<Base>>* fContents;
255 };
256 
257 } // namespace SkSL
258 
259 #endif
260