OLD | NEW |
1 /* | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 * Copyright (C) 2011 Apple Inc. All rights reserved. | 2 // Use of this source code is governed by a BSD-style license that can be |
3 * | 3 // found in the LICENSE file. |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions | |
6 * are met: | |
7 * 1. Redistributions of source code must retain the above copyright | |
8 * notice, this list of conditions and the following disclaimer. | |
9 * 2. Redistributions in binary form must reproduce the above copyright | |
10 * notice, this list of conditions and the following disclaimer in the | |
11 * documentation and/or other materials provided with the distribution. | |
12 * | |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 */ | |
25 | 4 |
26 #ifndef BitVector_h | 5 #include "platform/wtf/BitVector.h" |
27 #define BitVector_h | |
28 | 6 |
29 #include "wtf/Allocator.h" | 7 // The contents of this header was moved to platform/wtf as part of |
30 #include "wtf/Assertions.h" | 8 // WTF migration project. See the following post for details: |
31 #include "wtf/StdLibExtras.h" | 9 // https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gY
CAAJ |
32 #include "wtf/WTFExport.h" | |
33 | |
34 namespace WTF { | |
35 | |
36 class PrintStream; | |
37 | |
38 // This is a space-efficient, resizeable bitvector class. In the common case it | |
39 // occupies one word, but if necessary, it will inflate this one word to point | |
40 // to a single chunk of out-of-line allocated storage to store an arbitrary | |
41 // number of bits. | |
42 // | |
43 // - The bitvector remembers the bound of how many bits can be stored, but this | |
44 // may be slightly greater (by as much as some platform-specific constant) | |
45 // than the last argument passed to ensureSize(). | |
46 // | |
47 // - The bitvector can resize itself automatically (set, clear, get) or can be | |
48 // used in a manual mode, which is faster (quickSet, quickClear, quickGet, | |
49 // ensureSize). | |
50 // | |
51 // - Accesses assert that you are within bounds. | |
52 // | |
53 // - Bits are automatically initialized to zero. | |
54 // | |
55 // On the other hand, this BitVector class may not be the fastest around, since | |
56 // it does conditionals on every get/set/clear. But it is great if you need to | |
57 // juggle a lot of variable-length BitVectors and you're worried about wasting | |
58 // space. | |
59 | |
60 class WTF_EXPORT BitVector { | |
61 DISALLOW_NEW(); | |
62 | |
63 public: | |
64 BitVector() : m_bitsOrPointer(makeInlineBits(0)) {} | |
65 | |
66 explicit BitVector(size_t numBits) : m_bitsOrPointer(makeInlineBits(0)) { | |
67 ensureSize(numBits); | |
68 } | |
69 | |
70 BitVector(const BitVector& other) : m_bitsOrPointer(makeInlineBits(0)) { | |
71 (*this) = other; | |
72 } | |
73 | |
74 ~BitVector() { | |
75 if (isInline()) | |
76 return; | |
77 OutOfLineBits::destroy(outOfLineBits()); | |
78 } | |
79 | |
80 BitVector& operator=(const BitVector& other) { | |
81 if (isInline() && other.isInline()) | |
82 m_bitsOrPointer = other.m_bitsOrPointer; | |
83 else | |
84 setSlow(other); | |
85 return *this; | |
86 } | |
87 | |
88 size_t size() const { | |
89 if (isInline()) | |
90 return maxInlineBits(); | |
91 return outOfLineBits()->numBits(); | |
92 } | |
93 | |
94 void ensureSize(size_t numBits) { | |
95 if (numBits <= size()) | |
96 return; | |
97 resizeOutOfLine(numBits); | |
98 } | |
99 | |
100 // Like ensureSize(), but supports reducing the size of the bitvector. | |
101 void resize(size_t numBits); | |
102 | |
103 void clearAll(); | |
104 | |
105 bool quickGet(size_t bit) const { | |
106 SECURITY_CHECK(bit < size()); | |
107 return !!(bits()[bit / bitsInPointer()] & | |
108 (static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1)))); | |
109 } | |
110 | |
111 void quickSet(size_t bit) { | |
112 SECURITY_CHECK(bit < size()); | |
113 bits()[bit / bitsInPointer()] |= | |
114 (static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1))); | |
115 } | |
116 | |
117 void quickClear(size_t bit) { | |
118 SECURITY_CHECK(bit < size()); | |
119 bits()[bit / bitsInPointer()] &= | |
120 ~(static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1))); | |
121 } | |
122 | |
123 void quickSet(size_t bit, bool value) { | |
124 if (value) | |
125 quickSet(bit); | |
126 else | |
127 quickClear(bit); | |
128 } | |
129 | |
130 bool get(size_t bit) const { | |
131 if (bit >= size()) | |
132 return false; | |
133 return quickGet(bit); | |
134 } | |
135 | |
136 void set(size_t bit) { | |
137 ensureSize(bit + 1); | |
138 quickSet(bit); | |
139 } | |
140 | |
141 void ensureSizeAndSet(size_t bit, size_t size) { | |
142 ensureSize(size); | |
143 quickSet(bit); | |
144 } | |
145 | |
146 void clear(size_t bit) { | |
147 if (bit >= size()) | |
148 return; | |
149 quickClear(bit); | |
150 } | |
151 | |
152 void set(size_t bit, bool value) { | |
153 if (value) | |
154 set(bit); | |
155 else | |
156 clear(bit); | |
157 } | |
158 | |
159 void dump(PrintStream& out); | |
160 | |
161 private: | |
162 static unsigned bitsInPointer() { return sizeof(void*) << 3; } | |
163 | |
164 static unsigned maxInlineBits() { return bitsInPointer() - 1; } | |
165 | |
166 static size_t byteCount(size_t bitCount) { return (bitCount + 7) >> 3; } | |
167 | |
168 static uintptr_t makeInlineBits(uintptr_t bits) { | |
169 DCHECK(!(bits & (static_cast<uintptr_t>(1) << maxInlineBits()))); | |
170 return bits | (static_cast<uintptr_t>(1) << maxInlineBits()); | |
171 } | |
172 | |
173 class WTF_EXPORT OutOfLineBits { | |
174 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | |
175 | |
176 public: | |
177 size_t numBits() const { return m_numBits; } | |
178 size_t numWords() const { | |
179 return (m_numBits + bitsInPointer() - 1) / bitsInPointer(); | |
180 } | |
181 uintptr_t* bits() { return bitwiseCast<uintptr_t*>(this + 1); } | |
182 const uintptr_t* bits() const { | |
183 return bitwiseCast<const uintptr_t*>(this + 1); | |
184 } | |
185 | |
186 static OutOfLineBits* create(size_t numBits); | |
187 | |
188 static void destroy(OutOfLineBits*); | |
189 | |
190 private: | |
191 OutOfLineBits(size_t numBits) : m_numBits(numBits) {} | |
192 | |
193 size_t m_numBits; | |
194 }; | |
195 | |
196 bool isInline() const { return m_bitsOrPointer >> maxInlineBits(); } | |
197 | |
198 const OutOfLineBits* outOfLineBits() const { | |
199 return bitwiseCast<const OutOfLineBits*>(m_bitsOrPointer << 1); | |
200 } | |
201 OutOfLineBits* outOfLineBits() { | |
202 return bitwiseCast<OutOfLineBits*>(m_bitsOrPointer << 1); | |
203 } | |
204 | |
205 void resizeOutOfLine(size_t numBits); | |
206 void setSlow(const BitVector& other); | |
207 | |
208 uintptr_t* bits() { | |
209 if (isInline()) | |
210 return &m_bitsOrPointer; | |
211 return outOfLineBits()->bits(); | |
212 } | |
213 | |
214 const uintptr_t* bits() const { | |
215 if (isInline()) | |
216 return &m_bitsOrPointer; | |
217 return outOfLineBits()->bits(); | |
218 } | |
219 | |
220 uintptr_t m_bitsOrPointer; | |
221 }; | |
222 | |
223 } // namespace WTF | |
224 | |
225 using WTF::BitVector; | |
226 | |
227 #endif // BitVector_h | |
OLD | NEW |