/src/skia/src/core/SkEnumerate.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2019 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 SkEnumerate_DEFINED |
9 | | #define SkEnumerate_DEFINED |
10 | | |
11 | | #include <cstddef> |
12 | | #include <iterator> |
13 | | #include <tuple> |
14 | | #include <variant> |
15 | | |
16 | | template <typename Iter, typename C = std::monostate> |
17 | | class SkEnumerate { |
18 | | using Captured = decltype(*std::declval<Iter>()); |
19 | | template <typename> struct is_tuple : std::false_type {}; |
20 | | template <typename... T> struct is_tuple<std::tuple<T...>> : std::true_type {}; |
21 | | |
22 | | // v must be a r-value to bind to temporary non-const references. |
23 | 959k | static constexpr auto MakeResult(size_t i, Captured&& v) { |
24 | 959k | if constexpr (is_tuple<Captured>::value) { |
25 | 957k | return std::tuple_cat(std::tuple<size_t>{i}, v); |
26 | 957k | } else { |
27 | | // Capture v by reference instead of by value by using std::tie. |
28 | 1.91k | return std::tuple_cat(std::tuple<size_t>{i}, std::tie(v)); |
29 | 1.91k | } |
30 | 959k | } SkEnumerate<SkZip<unsigned short const, SkPoint const>::Iterator, SkZip<unsigned short const, SkPoint const> >::MakeResult(unsigned long, std::__1::tuple<unsigned short const&, SkPoint const&>&&) Line | Count | Source | 23 | 957k | static constexpr auto MakeResult(size_t i, Captured&& v) { | 24 | 957k | if constexpr (is_tuple<Captured>::value) { | 25 | 957k | return std::tuple_cat(std::tuple<size_t>{i}, v); | 26 | | } else { | 27 | | // Capture v by reference instead of by value by using std::tie. | 28 | | return std::tuple_cat(std::tuple<size_t>{i}, std::tie(v)); | 29 | | } | 30 | 957k | } |
SkEnumerate<SkPoint*, std::__1::monostate>::MakeResult(unsigned long, SkPoint&) Line | Count | Source | 23 | 1.91k | static constexpr auto MakeResult(size_t i, Captured&& v) { | 24 | | if constexpr (is_tuple<Captured>::value) { | 25 | | return std::tuple_cat(std::tuple<size_t>{i}, v); | 26 | 1.91k | } else { | 27 | | // Capture v by reference instead of by value by using std::tie. | 28 | 1.91k | return std::tuple_cat(std::tuple<size_t>{i}, std::tie(v)); | 29 | 1.91k | } | 30 | 1.91k | } |
|
31 | | |
32 | | using Result = decltype(MakeResult(0, std::declval<Captured>())); |
33 | | |
34 | | class Iterator { |
35 | | public: |
36 | | using value_type = Result; |
37 | | using difference_type = ptrdiff_t; |
38 | | using pointer = value_type*; |
39 | | using reference = value_type; |
40 | | using iterator_category = std::input_iterator_tag; |
41 | 22.3k | constexpr Iterator(ptrdiff_t index, Iter it) : fIndex{index}, fIt{it} { } SkEnumerate<SkZip<unsigned short const, SkPoint const>::Iterator, SkZip<unsigned short const, SkPoint const> >::Iterator::Iterator(long, SkZip<unsigned short const, SkPoint const>::Iterator) Line | Count | Source | 41 | 22.1k | constexpr Iterator(ptrdiff_t index, Iter it) : fIndex{index}, fIt{it} { } |
SkEnumerate<SkPoint*, std::__1::monostate>::Iterator::Iterator(long, SkPoint*) Line | Count | Source | 41 | 218 | constexpr Iterator(ptrdiff_t index, Iter it) : fIndex{index}, fIt{it} { } |
|
42 | 957k | constexpr Iterator(const Iterator&) = default; |
43 | 959k | constexpr Iterator operator++() { ++fIndex; ++fIt; return *this; } SkEnumerate<SkZip<unsigned short const, SkPoint const>::Iterator, SkZip<unsigned short const, SkPoint const> >::Iterator::operator++() Line | Count | Source | 43 | 957k | constexpr Iterator operator++() { ++fIndex; ++fIt; return *this; } |
SkEnumerate<SkPoint*, std::__1::monostate>::Iterator::operator++() Line | Count | Source | 43 | 1.91k | constexpr Iterator operator++() { ++fIndex; ++fIt; return *this; } |
|
44 | | constexpr Iterator operator++(int) { Iterator tmp(*this); operator++(); return tmp; } |
45 | | constexpr bool operator==(const Iterator& rhs) const { return fIt == rhs.fIt; } |
46 | 970k | constexpr bool operator!=(const Iterator& rhs) const { return fIt != rhs.fIt; } SkEnumerate<SkZip<unsigned short const, SkPoint const>::Iterator, SkZip<unsigned short const, SkPoint const> >::Iterator::operator!=(SkEnumerate<SkZip<unsigned short const, SkPoint const>::Iterator, SkZip<unsigned short const, SkPoint const> >::Iterator const&) const Line | Count | Source | 46 | 968k | constexpr bool operator!=(const Iterator& rhs) const { return fIt != rhs.fIt; } |
SkEnumerate<SkPoint*, std::__1::monostate>::Iterator::operator!=(SkEnumerate<SkPoint*, std::__1::monostate>::Iterator const&) const Line | Count | Source | 46 | 2.02k | constexpr bool operator!=(const Iterator& rhs) const { return fIt != rhs.fIt; } |
|
47 | 959k | constexpr reference operator*() { return MakeResult(fIndex, *fIt); } SkEnumerate<SkZip<unsigned short const, SkPoint const>::Iterator, SkZip<unsigned short const, SkPoint const> >::Iterator::operator*() Line | Count | Source | 47 | 957k | constexpr reference operator*() { return MakeResult(fIndex, *fIt); } |
SkEnumerate<SkPoint*, std::__1::monostate>::Iterator::operator*() Line | Count | Source | 47 | 1.91k | constexpr reference operator*() { return MakeResult(fIndex, *fIt); } |
|
48 | | |
49 | | private: |
50 | | ptrdiff_t fIndex; |
51 | | Iter fIt; |
52 | | }; |
53 | | |
54 | | public: |
55 | 109 | constexpr SkEnumerate(Iter begin, Iter end) : SkEnumerate{0, begin, end} {} |
56 | | explicit constexpr SkEnumerate(C&& c) |
57 | 11.0k | : fCollection{std::move(c)} |
58 | 11.0k | , fBeginIndex{0} |
59 | 11.0k | , fBegin{std::begin(fCollection)} |
60 | 11.0k | , fEnd{std::end(fCollection)} { } |
61 | | constexpr SkEnumerate(const SkEnumerate& that) = default; |
62 | | constexpr SkEnumerate& operator=(const SkEnumerate& that) { |
63 | | fBegin = that.fBegin; |
64 | | fEnd = that.fEnd; |
65 | | return *this; |
66 | | } |
67 | 11.1k | constexpr Iterator begin() const { return Iterator{fBeginIndex, fBegin}; } SkEnumerate<SkZip<unsigned short const, SkPoint const>::Iterator, SkZip<unsigned short const, SkPoint const> >::begin() const Line | Count | Source | 67 | 11.0k | constexpr Iterator begin() const { return Iterator{fBeginIndex, fBegin}; } |
SkEnumerate<SkPoint*, std::__1::monostate>::begin() const Line | Count | Source | 67 | 109 | constexpr Iterator begin() const { return Iterator{fBeginIndex, fBegin}; } |
|
68 | 11.1k | constexpr Iterator end() const { return Iterator{fBeginIndex + this->ssize(), fEnd}; } SkEnumerate<SkZip<unsigned short const, SkPoint const>::Iterator, SkZip<unsigned short const, SkPoint const> >::end() const Line | Count | Source | 68 | 11.0k | constexpr Iterator end() const { return Iterator{fBeginIndex + this->ssize(), fEnd}; } |
SkEnumerate<SkPoint*, std::__1::monostate>::end() const Line | Count | Source | 68 | 109 | constexpr Iterator end() const { return Iterator{fBeginIndex + this->ssize(), fEnd}; } |
|
69 | | constexpr bool empty() const { return fBegin == fEnd; } |
70 | | constexpr size_t size() const { return std::distance(fBegin, fEnd); } |
71 | 11.1k | constexpr ptrdiff_t ssize() const { return std::distance(fBegin, fEnd); } SkEnumerate<SkZip<unsigned short const, SkPoint const>::Iterator, SkZip<unsigned short const, SkPoint const> >::ssize() const Line | Count | Source | 71 | 11.0k | constexpr ptrdiff_t ssize() const { return std::distance(fBegin, fEnd); } |
SkEnumerate<SkPoint*, std::__1::monostate>::ssize() const Line | Count | Source | 71 | 109 | constexpr ptrdiff_t ssize() const { return std::distance(fBegin, fEnd); } |
|
72 | | constexpr SkEnumerate first(size_t n) { |
73 | | SkASSERT(n <= this->size()); |
74 | | ptrdiff_t deltaEnd = this->ssize() - n; |
75 | | return SkEnumerate{fBeginIndex, fBegin, std::prev(fEnd, deltaEnd)}; |
76 | | } |
77 | | constexpr SkEnumerate last(size_t n) { |
78 | | SkASSERT(n <= this->size()); |
79 | | ptrdiff_t deltaBegin = this->ssize() - n; |
80 | | return SkEnumerate{fBeginIndex + deltaBegin, std::next(fBegin, deltaBegin), fEnd}; |
81 | | } |
82 | | constexpr SkEnumerate subspan(size_t offset, size_t count) { |
83 | | SkASSERT(offset < this->size()); |
84 | | SkASSERT(count <= this->size() - offset); |
85 | | auto newBegin = std::next(fBegin, offset); |
86 | | return SkEnumerate(fBeginIndex + offset, newBegin, std::next(newBegin, count)); |
87 | | } |
88 | | |
89 | | private: |
90 | | constexpr SkEnumerate(ptrdiff_t beginIndex, Iter begin, Iter end) |
91 | 109 | : fBeginIndex{beginIndex} |
92 | 109 | , fBegin(begin) |
93 | 109 | , fEnd(end) {} |
94 | | |
95 | | C fCollection; |
96 | | const ptrdiff_t fBeginIndex; |
97 | | Iter fBegin; |
98 | | Iter fEnd; |
99 | | }; |
100 | | |
101 | | template <typename C, typename Iter = decltype(std::begin(std::declval<C>()))> |
102 | 109 | inline constexpr SkEnumerate<Iter> SkMakeEnumerate(C& c) { |
103 | 109 | return SkEnumerate<Iter>{std::begin(c), std::end(c)}; |
104 | 109 | } |
105 | | template <typename C, typename Iter = decltype(std::begin(std::declval<C>()))> |
106 | 11.0k | inline constexpr SkEnumerate<Iter, C> SkMakeEnumerate(C&& c) { |
107 | 11.0k | return SkEnumerate<Iter, C>{std::forward<C>(c)}; |
108 | 11.0k | } |
109 | | |
110 | | template <class T, std::size_t N, typename Iter = decltype(std::begin(std::declval<T(&)[N]>()))> |
111 | | inline constexpr SkEnumerate<Iter> SkMakeEnumerate(T (&a)[N]) { |
112 | | return SkEnumerate<Iter>{std::begin(a), std::end(a)}; |
113 | | } |
114 | | #endif // SkEnumerate_DEFINED |