Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkBitSet.h
Go to the documentation of this file.
1/*
2 * Copyright 2011 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 SkBitSet_DEFINED
9#define SkBitSet_DEFINED
10
13#include "src/base/SkMathPriv.h"
14
15#include <climits>
16#include <cstring>
17#include <limits>
18#include <memory>
19#include <optional>
20
21class SkBitSet {
22public:
23 explicit SkBitSet(size_t size)
24 : fSize(size)
25 , fChunks((Chunk*)sk_calloc_throw(NumChunksFor(fSize) * sizeof(Chunk))) {}
26
27 SkBitSet(const SkBitSet&) = delete;
28 SkBitSet& operator=(const SkBitSet&) = delete;
29 SkBitSet(SkBitSet&& that) { *this = std::move(that); }
31 if (this != &that) {
32 this->fSize = that.fSize;
33 this->fChunks = std::move(that.fChunks);
34 that.fSize = 0;
35 }
36 return *this;
37 }
38 ~SkBitSet() = default;
39
40 /** Set the value of the index-th bit to true. */
41 void set(size_t index) {
42 SkASSERT(index < fSize);
43 *this->chunkFor(index) |= ChunkMaskFor(index);
44 }
45
46 /** Sets every bit in the bitset to true. */
47 void set() {
48 Chunk* chunks = fChunks.get();
49 const size_t numChunks = NumChunksFor(fSize);
50 std::memset(chunks, 0xFF, sizeof(Chunk) * numChunks);
51 }
52
53 /** Set the value of the index-th bit to false. */
54 void reset(size_t index) {
55 SkASSERT(index < fSize);
56 *this->chunkFor(index) &= ~ChunkMaskFor(index);
57 }
58
59 /** Sets every bit in the bitset to false. */
60 void reset() {
61 Chunk* chunks = fChunks.get();
62 const size_t numChunks = NumChunksFor(fSize);
63 std::memset(chunks, 0, sizeof(Chunk) * numChunks);
64 }
65
66 bool test(size_t index) const {
67 SkASSERT(index < fSize);
68 return SkToBool(*this->chunkFor(index) & ChunkMaskFor(index));
69 }
70
71 size_t size() const {
72 return fSize;
73 }
74
75 // Calls f(size_t index) for each set index.
76 template<typename FN>
77 void forEachSetIndex(FN f) const {
78 const Chunk* chunks = fChunks.get();
79 const size_t numChunks = NumChunksFor(fSize);
80 for (size_t i = 0; i < numChunks; ++i) {
81 if (Chunk chunk = chunks[i]) { // There are set bits
82 const size_t index = i * kChunkBits;
83 for (size_t j = 0; j < kChunkBits; ++j) {
84 if (0x1 & (chunk >> j)) {
85 f(index + j);
86 }
87 }
88 }
89 }
90 }
91
92 using OptionalIndex = std::optional<size_t>;
93
94 // If any bits are set, returns the index of the first.
96 const Chunk* chunks = fChunks.get();
97 const size_t numChunks = NumChunksFor(fSize);
98 for (size_t i = 0; i < numChunks; ++i) {
99 if (Chunk chunk = chunks[i]) { // There are set bits
100 static_assert(kChunkBits <= std::numeric_limits<uint32_t>::digits, "SkCTZ");
101 const size_t bitIndex = i * kChunkBits + SkCTZ(chunk);
102 return OptionalIndex(bitIndex);
103 }
104 }
105 return OptionalIndex();
106 }
107
108 // If any bits are not set, returns the index of the first.
110 const Chunk* chunks = fChunks.get();
111 const size_t numChunks = NumChunksFor(fSize);
112 for (size_t i = 0; i < numChunks; ++i) {
113 if (Chunk chunk = ~chunks[i]) { // if there are unset bits ...
114 static_assert(kChunkBits <= std::numeric_limits<uint32_t>::digits, "SkCTZ");
115 const size_t bitIndex = i * kChunkBits + SkCTZ(chunk);
116 if (bitIndex >= fSize) {
117 break;
118 }
119 return OptionalIndex(bitIndex);
120 }
121 }
122 return OptionalIndex();
123 }
124
125private:
126 size_t fSize;
127
128 using Chunk = uint32_t;
129 static_assert(std::numeric_limits<Chunk>::radix == 2);
130 inline static constexpr size_t kChunkBits = std::numeric_limits<Chunk>::digits;
131 static_assert(kChunkBits == sizeof(Chunk)*CHAR_BIT, "SkBitSet must use every bit in a Chunk");
132 std::unique_ptr<Chunk, SkOverloadedFunctionObject<void(void*), sk_free>> fChunks;
133
134 Chunk* chunkFor(size_t index) const {
135 return fChunks.get() + (index / kChunkBits);
136 }
137
138 static constexpr Chunk ChunkMaskFor(size_t index) {
139 return (Chunk)1 << (index & (kChunkBits-1));
140 }
141
142 static constexpr size_t NumChunksFor(size_t size) {
143 return (size + (kChunkBits-1)) / kChunkBits;
144 }
145};
146
147#endif
#define SkASSERT(cond)
Definition SkAssert.h:116
static void * sk_calloc_throw(size_t size)
Definition SkMalloc.h:71
SK_API void sk_free(void *)
static int SkCTZ(uint32_t mask)
Definition SkMathPriv.h:224
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
SkBitSet & operator=(const SkBitSet &)=delete
OptionalIndex findFirst()
Definition SkBitSet.h:95
void set(size_t index)
Definition SkBitSet.h:41
void reset()
Definition SkBitSet.h:60
SkBitSet(const SkBitSet &)=delete
bool test(size_t index) const
Definition SkBitSet.h:66
~SkBitSet()=default
void set()
Definition SkBitSet.h:47
std::optional< size_t > OptionalIndex
Definition SkBitSet.h:92
void forEachSetIndex(FN f) const
Definition SkBitSet.h:77
SkBitSet(SkBitSet &&that)
Definition SkBitSet.h:29
size_t size() const
Definition SkBitSet.h:71
SkBitSet & operator=(SkBitSet &&that)
Definition SkBitSet.h:30
void reset(size_t index)
Definition SkBitSet.h:54
OptionalIndex findFirstUnset()
Definition SkBitSet.h:109
SkBitSet(size_t size)
Definition SkBitSet.h:23