Coverage Report

Created: 2021-08-22 09:07

/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