/src/skia/include/private/SkTOptional.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2021 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 SkTOptional_DEFINED |
9 | | #define SkTOptional_DEFINED |
10 | | |
11 | | #include "include/core/SkTypes.h" |
12 | | |
13 | | #include <utility> |
14 | | |
15 | | namespace skstd { |
16 | | |
17 | | /** |
18 | | * An empty optional is represented with `nullopt`. |
19 | | */ |
20 | | struct nullopt_t { |
21 | | struct tag {}; |
22 | | |
23 | | // nullopt_t must not be default-constructible. |
24 | 0 | explicit constexpr nullopt_t(tag) {} |
25 | | }; |
26 | | |
27 | | static constexpr nullopt_t nullopt{nullopt_t::tag{}}; |
28 | | |
29 | | /** |
30 | | * Simple drop-in replacement for std::optional until we move to C++17. This does not have all of |
31 | | * std::optional's capabilities, but it covers our needs for the time being. |
32 | | */ |
33 | | template<typename T> |
34 | | class optional { |
35 | | public: |
36 | | optional(const T& value) |
37 | 1.80M | : fHasValue(true) { |
38 | 1.80M | new(&fPayload.fValue) T(value); |
39 | 1.80M | } |
40 | | |
41 | | optional(T&& value) |
42 | 2.44M | : fHasValue(true) { |
43 | 2.44M | new(&fPayload.fValue) T(std::move(value)); |
44 | 2.44M | } skstd::optional<SkBlendMode>::optional(SkBlendMode&&) Line | Count | Source | 42 | 2.43M | : fHasValue(true) { | 43 | 2.43M | new(&fPayload.fValue) T(std::move(value)); | 44 | 2.43M | } |
skstd::optional<SkRuntimeEffect::ChildType>::optional(SkRuntimeEffect::ChildType&&) Line | Count | Source | 42 | 10.4k | : fHasValue(true) { | 43 | 10.4k | new(&fPayload.fValue) T(std::move(value)); | 44 | 10.4k | } |
|
45 | | |
46 | 243k | optional() {} Unexecuted instantiation: skstd::optional<SkBlendMode>::optional() skstd::optional<SkRuntimeEffect::ChildType>::optional() Line | Count | Source | 46 | 4.04k | optional() {} |
SkSLSwizzle.cpp:skstd::optional<SkSL::validate_swizzle_domain(skstd::string_view)::SwizzleDomain>::optional() Line | Count | Source | 46 | 239k | optional() {} |
|
47 | | |
48 | | optional(const optional& other) { |
49 | | *this = other; |
50 | | } |
51 | | |
52 | | // Construction with nullopt is the same as default construction. |
53 | 4.04k | optional(nullopt_t) : optional() {} |
54 | | |
55 | | // We need a non-const copy constructor because otherwise optional(nonConstSrc) isn't an exact |
56 | | // match for the copy constructor, and we'd end up invoking the Args&&... template by mistake. |
57 | | optional(optional& other) { |
58 | | *this = other; |
59 | | } |
60 | | |
61 | | optional(optional&& other) { |
62 | | *this = std::move(other); |
63 | | } |
64 | | |
65 | | template<typename... Args> |
66 | 236k | optional(Args&&... args) { |
67 | 236k | fHasValue = true; |
68 | 236k | new(&fPayload.fValue) T(std::forward<Args...>(args...)); |
69 | 236k | } |
70 | | |
71 | 4.72M | ~optional() { |
72 | 4.72M | this->reset(); |
73 | 4.72M | } skstd::optional<SkBlendMode>::~optional() Line | Count | Source | 71 | 4.23M | ~optional() { | 72 | 4.23M | this->reset(); | 73 | 4.23M | } |
skstd::optional<SkRuntimeEffect::ChildType>::~optional() Line | Count | Source | 71 | 14.5k | ~optional() { | 72 | 14.5k | this->reset(); | 73 | 14.5k | } |
SkSLSwizzle.cpp:skstd::optional<SkSL::validate_swizzle_domain(skstd::string_view)::SwizzleDomain>::~optional() Line | Count | Source | 71 | 476k | ~optional() { | 72 | 476k | this->reset(); | 73 | 476k | } |
|
74 | | |
75 | | optional& operator=(const optional& other) { |
76 | | if (this != &other) { |
77 | | if (fHasValue) { |
78 | | if (other.fHasValue) { |
79 | | fPayload.fValue = other.fPayload.fValue; |
80 | | } else { |
81 | | this->reset(); |
82 | | } |
83 | | } else { |
84 | | if (other.fHasValue) { |
85 | | fHasValue = true; |
86 | | new (&fPayload.fValue) T(other.fPayload.fValue); |
87 | | } else { |
88 | | // do nothing, no value on either side |
89 | | } |
90 | | } |
91 | | } |
92 | | return *this; |
93 | | } |
94 | | |
95 | 236k | optional& operator=(optional&& other) { |
96 | 236k | if (this != &other) { |
97 | 236k | if (fHasValue) { |
98 | 0 | if (other.fHasValue) { |
99 | 0 | fPayload.fValue = std::move(other.fPayload.fValue); |
100 | 0 | } else { |
101 | 0 | this->reset(); |
102 | 0 | } |
103 | 236k | } else { |
104 | 236k | if (other.fHasValue) { |
105 | 236k | fHasValue = true; |
106 | 236k | new (&fPayload.fValue) T(std::move(other.fPayload.fValue)); |
107 | 0 | } else { |
108 | | // do nothing, no value on either side |
109 | 0 | } |
110 | 236k | } |
111 | 236k | } |
112 | 236k | return *this; |
113 | 236k | } |
114 | | |
115 | | // Assignment to nullopt is the same as reset(). |
116 | | optional& operator=(nullopt_t) { |
117 | | this->reset(); |
118 | | return *this; |
119 | | } |
120 | | |
121 | 2.65M | T& operator*() & { |
122 | 2.65M | SkASSERT(fHasValue); |
123 | 2.65M | return fPayload.fValue; |
124 | 2.65M | } |
125 | | |
126 | 2.04M | const T& operator*() const& { |
127 | 2.04M | SkASSERT(fHasValue); |
128 | 2.04M | return fPayload.fValue; |
129 | 2.04M | } skstd::optional<SkBlendMode>::operator*() const & Line | Count | Source | 126 | 1.78M | const T& operator*() const& { | 127 | 1.78M | SkASSERT(fHasValue); | 128 | 1.78M | return fPayload.fValue; | 129 | 1.78M | } |
skstd::optional<SkRuntimeEffect::ChildType>::operator*() const & Line | Count | Source | 126 | 10.4k | const T& operator*() const& { | 127 | 10.4k | SkASSERT(fHasValue); | 128 | 10.4k | return fPayload.fValue; | 129 | 10.4k | } |
SkSLSwizzle.cpp:skstd::optional<SkSL::validate_swizzle_domain(skstd::string_view)::SwizzleDomain>::operator*() const & Line | Count | Source | 126 | 177 | const T& operator*() const& { | 127 | 177 | SkASSERT(fHasValue); | 128 | 177 | return fPayload.fValue; | 129 | 177 | } |
SkSLSwizzle.cpp:skstd::optional<SkSL::validate_swizzle_domain(skstd::string_view)::SwizzleDomain>::operator*() const & Line | Count | Source | 126 | 246k | const T& operator*() const& { | 127 | 246k | SkASSERT(fHasValue); | 128 | 246k | return fPayload.fValue; | 129 | 246k | } |
|
130 | | |
131 | | T&& operator*() && { |
132 | | SkASSERT(fHasValue); |
133 | | return std::move(fPayload.fValue); |
134 | | } |
135 | | |
136 | | const T&& operator*() const&& { |
137 | | SkASSERT(fHasValue); |
138 | | return std::move(fPayload.fValue); |
139 | | } |
140 | | |
141 | 1.11M | const T& value() const& { |
142 | 1.11M | SkASSERT_RELEASE(fHasValue); |
143 | 1.11M | return **this; |
144 | 1.11M | } |
145 | | |
146 | 2.63M | T& value() & { |
147 | 2.63M | SkASSERT_RELEASE(fHasValue); |
148 | 2.63M | return **this; |
149 | 2.63M | } |
150 | | |
151 | | const T&& value() const&& { |
152 | | SkASSERT_RELEASE(fHasValue); |
153 | | return std::move(**this); |
154 | | } |
155 | | |
156 | | T&& value() && { |
157 | | SkASSERT_RELEASE(fHasValue); |
158 | | return std::move(**this); |
159 | | } |
160 | | |
161 | | T* operator->() { |
162 | | return &**this; |
163 | | } |
164 | | |
165 | | const T* operator->() const { |
166 | | return &**this; |
167 | | } |
168 | | |
169 | | template<typename U> |
170 | | T value_or(U&& value) const& { |
171 | | return this->has_value() ? **this : static_cast<T>(std::forward<U>(value)); |
172 | | } |
173 | | |
174 | | template<typename U> |
175 | 24.3k | T value_or(U&& value) && { |
176 | 24.3k | return this->has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(value)); |
177 | 24.3k | } |
178 | | |
179 | 5.43M | bool has_value() const { |
180 | 5.43M | return fHasValue; |
181 | 5.43M | } skstd::optional<SkBlendMode>::has_value() const Line | Count | Source | 179 | 4.67M | bool has_value() const { | 180 | 4.67M | return fHasValue; | 181 | 4.67M | } |
skstd::optional<SkRuntimeEffect::ChildType>::has_value() const Line | Count | Source | 179 | 25.0k | bool has_value() const { | 180 | 25.0k | return fHasValue; | 181 | 25.0k | } |
SkSLSwizzle.cpp:skstd::optional<SkSL::validate_swizzle_domain(skstd::string_view)::SwizzleDomain>::has_value() const Line | Count | Source | 179 | 730k | bool has_value() const { | 180 | 730k | return fHasValue; | 181 | 730k | } |
|
182 | | |
183 | 3.98M | explicit operator bool() const { |
184 | 3.98M | return this->has_value(); |
185 | 3.98M | } skstd::optional<SkBlendMode>::operator bool() const Line | Count | Source | 183 | 3.97M | explicit operator bool() const { | 184 | 3.97M | return this->has_value(); | 185 | 3.97M | } |
skstd::optional<SkRuntimeEffect::ChildType>::operator bool() const Line | Count | Source | 183 | 14.5k | explicit operator bool() const { | 184 | 14.5k | return this->has_value(); | 185 | 14.5k | } |
|
186 | | |
187 | 4.72M | void reset() { |
188 | 4.72M | if (fHasValue) { |
189 | 4.71M | fPayload.fValue.~T(); |
190 | 4.71M | fHasValue = false; |
191 | 4.71M | } |
192 | 4.72M | } skstd::optional<SkBlendMode>::reset() Line | Count | Source | 187 | 4.23M | void reset() { | 188 | 4.23M | if (fHasValue) { | 189 | 4.23M | fPayload.fValue.~T(); | 190 | 4.23M | fHasValue = false; | 191 | 4.23M | } | 192 | 4.23M | } |
skstd::optional<SkRuntimeEffect::ChildType>::reset() Line | Count | Source | 187 | 14.5k | void reset() { | 188 | 14.5k | if (fHasValue) { | 189 | 10.4k | fPayload.fValue.~T(); | 190 | 10.4k | fHasValue = false; | 191 | 10.4k | } | 192 | 14.5k | } |
Unexecuted instantiation: skstd::optional<unsigned long>::reset() SkSLSwizzle.cpp:skstd::optional<SkSL::validate_swizzle_domain(skstd::string_view)::SwizzleDomain>::reset() Line | Count | Source | 187 | 476k | void reset() { | 188 | 476k | if (fHasValue) { | 189 | 472k | fPayload.fValue.~T(); | 190 | 472k | fHasValue = false; | 191 | 472k | } | 192 | 476k | } |
|
193 | | |
194 | | private: |
195 | | union Payload { |
196 | | T fValue; |
197 | | |
198 | 4.72M | Payload() {} skstd::optional<SkBlendMode>::Payload::Payload() Line | Count | Source | 198 | 4.23M | Payload() {} |
skstd::optional<SkRuntimeEffect::ChildType>::Payload::Payload() Line | Count | Source | 198 | 14.5k | Payload() {} |
SkSLSwizzle.cpp:skstd::optional<SkSL::validate_swizzle_domain(skstd::string_view)::SwizzleDomain>::Payload::Payload() Line | Count | Source | 198 | 476k | Payload() {} |
|
199 | | |
200 | 4.72M | ~Payload() {} skstd::optional<SkBlendMode>::Payload::~Payload() Line | Count | Source | 200 | 4.23M | ~Payload() {} |
skstd::optional<SkRuntimeEffect::ChildType>::Payload::~Payload() Line | Count | Source | 200 | 14.5k | ~Payload() {} |
SkSLSwizzle.cpp:skstd::optional<SkSL::validate_swizzle_domain(skstd::string_view)::SwizzleDomain>::Payload::~Payload() Line | Count | Source | 200 | 476k | ~Payload() {} |
|
201 | | } fPayload; |
202 | | |
203 | | bool fHasValue = false; |
204 | | }; |
205 | | |
206 | | // Comparison operators for optional x optional |
207 | | template <typename T, typename U> bool operator==(const optional<T>& a, const optional<U>& b) { |
208 | | return (a.has_value() != b.has_value()) ? false : |
209 | | !a.has_value() ? true : |
210 | | (*a == *b); |
211 | | } |
212 | | |
213 | | template <typename T, typename U> bool operator!=(const optional<T>& a, const optional<U>& b) { |
214 | | return (a.has_value() != b.has_value()) ? true : |
215 | | !a.has_value() ? false : |
216 | | (*a != *b); |
217 | | } |
218 | | |
219 | | template <typename T, typename U> bool operator<(const optional<T>& a, const optional<U>& b) { |
220 | | return !b.has_value() ? false : |
221 | | !a.has_value() ? true : |
222 | | (*a < *b); |
223 | | } |
224 | | |
225 | | template <typename T, typename U> bool operator<=(const optional<T>& a, const optional<U>& b) { |
226 | | return !a.has_value() ? true : |
227 | | !b.has_value() ? false : |
228 | | (*a <= *b); |
229 | | } |
230 | | |
231 | | template <typename T, typename U> bool operator>(const optional<T>& a, const optional<U>& b) { |
232 | | return !a.has_value() ? false : |
233 | | !b.has_value() ? true : |
234 | | (*a > *b); |
235 | | } |
236 | | |
237 | | template <typename T, typename U> bool operator>=(const optional<T>& a, const optional<U>& b) { |
238 | | return !b.has_value() ? true : |
239 | | !a.has_value() ? false : |
240 | | (*a >= *b); |
241 | | } |
242 | | |
243 | | // Comparison operators for optional x nullopt |
244 | | template <typename T> bool operator==(const optional<T>& a, nullopt_t) { |
245 | | return !a.has_value(); |
246 | | } |
247 | | |
248 | | template <typename T> bool operator!=(const optional<T>& a, nullopt_t) { |
249 | | return a.has_value(); |
250 | | } |
251 | | |
252 | | template <typename T> bool operator<(const optional<T>&, nullopt_t) { |
253 | | return false; |
254 | | } |
255 | | |
256 | | template <typename T> bool operator<=(const optional<T>& a, nullopt_t) { |
257 | | return !a.has_value(); |
258 | | } |
259 | | |
260 | | template <typename T> bool operator>(const optional<T>& a, nullopt_t) { |
261 | | return a.has_value(); |
262 | | } |
263 | | |
264 | | template <typename T> |
265 | | bool operator>=(const optional<T>&, nullopt_t) { |
266 | | return true; |
267 | | } |
268 | | |
269 | | // Comparison operators for nullopt x optional |
270 | | template <typename U> bool operator==(nullopt_t, const optional<U>& b) { |
271 | | return !b.has_value(); |
272 | | } |
273 | | |
274 | | template <typename U> bool operator!=(nullopt_t, const optional<U>& b) { |
275 | | return b.has_value(); |
276 | | } |
277 | | |
278 | | template <typename U> bool operator<(nullopt_t, const optional<U>& b) { |
279 | | return b.has_value(); |
280 | | } |
281 | | |
282 | | template <typename U> bool operator<=(nullopt_t, const optional<U>&) { |
283 | | return true; |
284 | | } |
285 | | |
286 | | template <typename U> bool operator>(nullopt_t, const optional<U>&) { |
287 | | return false; |
288 | | } |
289 | | |
290 | | template <typename U> bool operator>=(nullopt_t, const optional<U>& b) { |
291 | | return !b.has_value(); |
292 | | } |
293 | | |
294 | | // Comparison operators for optional x value |
295 | 298k | template <typename T, typename U> bool operator==(const optional<T>& a, const U& b) { |
296 | 298k | return a.has_value() && (*a == b); |
297 | 298k | } bool skstd::operator==<SkBlendMode, SkBlendMode>(skstd::optional<SkBlendMode> const&, SkBlendMode const&) Line | Count | Source | 295 | 298k | template <typename T, typename U> bool operator==(const optional<T>& a, const U& b) { | 296 | 298k | return a.has_value() && (*a == b); | 297 | 298k | } |
Unexecuted instantiation: bool skstd::operator==<SkRuntimeEffect::ChildType, SkRuntimeEffect::ChildType>(skstd::optional<SkRuntimeEffect::ChildType> const&, SkRuntimeEffect::ChildType const&) |
298 | | |
299 | 634k | template <typename T, typename U> bool operator!=(const optional<T>& a, const U& b) { |
300 | 634k | return !a.has_value() || (*a != b); |
301 | 634k | } bool skstd::operator!=<SkRuntimeEffect::ChildType, SkRuntimeEffect::ChildType>(skstd::optional<SkRuntimeEffect::ChildType> const&, SkRuntimeEffect::ChildType const&) Line | Count | Source | 299 | 10.4k | template <typename T, typename U> bool operator!=(const optional<T>& a, const U& b) { | 300 | 10.4k | return !a.has_value() || (*a != b); | 301 | 10.4k | } |
SkSLSwizzle.cpp:bool skstd::operator!=<SkSL::validate_swizzle_domain(skstd::string_view)::SwizzleDomain, SkSL::validate_swizzle_domain(skstd::string_view)::SwizzleDomain>(skstd::optional<SkSL::validate_swizzle_domain(skstd::string_view)::SwizzleDomain> const&, SkSL::validate_swizzle_domain(skstd::string_view)::SwizzleDomain const&) Line | Count | Source | 299 | 246k | template <typename T, typename U> bool operator!=(const optional<T>& a, const U& b) { | 300 | 246k | return !a.has_value() || (*a != b); | 301 | 246k | } |
bool skstd::operator!=<SkBlendMode, SkBlendMode>(skstd::optional<SkBlendMode> const&, SkBlendMode const&) Line | Count | Source | 299 | 376k | template <typename T, typename U> bool operator!=(const optional<T>& a, const U& b) { | 300 | 376k | return !a.has_value() || (*a != b); | 301 | 376k | } |
|
302 | | |
303 | | template <typename T, typename U> bool operator<(const optional<T>& a, const U& b) { |
304 | | return !a.has_value() || (*a < b); |
305 | | } |
306 | | |
307 | | template <typename T, typename U> bool operator<=(const optional<T>& a, const U& b) { |
308 | | return !a.has_value() || (*a <= b); |
309 | | } |
310 | | |
311 | | template <typename T, typename U> bool operator>(const optional<T>& a, const U& b) { |
312 | | return a.has_value() && (*a > b); |
313 | | } |
314 | | |
315 | | template <typename T, typename U> bool operator>=(const optional<T>& a, const U& b) { |
316 | | return a.has_value() && (*a >= b); |
317 | | } |
318 | | |
319 | | // Comparison operators for value x optional |
320 | 2.39k | template <typename T, typename U> bool operator==(const T& a, const optional<U>& b) { |
321 | 2.39k | return b.has_value() && (a == *b); |
322 | 2.39k | } |
323 | | |
324 | | template <typename T, typename U> bool operator!=(const T& a, const optional<U>& b) { |
325 | | return !b.has_value() || (a != *b); |
326 | | } |
327 | | |
328 | | template <typename T, typename U> bool operator<(const T& a, const optional<U>& b) { |
329 | | return b.has_value() && (a < *b); |
330 | | } |
331 | | |
332 | | template <typename T, typename U> bool operator<=(const T& a, const optional<U>& b) { |
333 | | return b.has_value() && (a <= *b); |
334 | | } |
335 | | |
336 | | template <typename T, typename U> bool operator>(const T& a, const optional<U>& b) { |
337 | | return !b.has_value() || (a > *b); |
338 | | } |
339 | | |
340 | | template <typename T, typename U> bool operator>=(const T& a, const optional<U>& b) { |
341 | | return !b.has_value() || (a >= *b); |
342 | | } |
343 | | |
344 | | } // namespace skstd |
345 | | |
346 | | #endif |