2 * Copyright (C) 2008 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * Implementation of an expandable bit vector.
25 #define kBitVectorGrowth 4 /* increase by 4 u4s when limit hit */
29 * Allocate a bit vector with enough space to hold at least the specified
32 BitVector* dvmAllocBitVector(unsigned int startBits, bool expandable)
37 assert(sizeof(bv->storage[0]) == 4); /* assuming 32-bit units */
39 bv = (BitVector*) malloc(sizeof(BitVector));
41 count = (startBits + 31) >> 5;
43 bv->storageSize = count;
44 bv->expandable = expandable;
45 bv->storage = (u4*) calloc(count, sizeof(u4));
52 void dvmFreeBitVector(BitVector* pBits)
62 * "Allocate" the first-available bit in the bitmap.
64 * This is not synchronized. The caller is expected to hold some sort of
65 * lock that prevents multiple threads from executing simultaneously in
66 * dvmAllocBit/dvmFreeBit.
68 int dvmAllocBit(BitVector* pBits)
70 unsigned int word, bit;
73 for (word = 0; word < pBits->storageSize; word++) {
74 if (pBits->storage[word] != 0xffffffff) {
76 * There are unallocated bits in this word. Return the first.
78 bit = ffs(~(pBits->storage[word])) -1;
80 pBits->storage[word] |= 1 << bit;
81 return (word << 5) | bit;
86 * Ran out of space, allocate more if we're allowed to.
88 if (!pBits->expandable)
91 pBits->storage = (u4*)realloc(pBits->storage,
92 (pBits->storageSize + kBitVectorGrowth) * sizeof(u4));
93 memset(&pBits->storage[pBits->storageSize], 0x00,
94 kBitVectorGrowth * sizeof(u4));
95 pBits->storageSize += kBitVectorGrowth;
100 * Mark the specified bit as "set".
102 void dvmSetBit(BitVector* pBits, unsigned int num)
104 if (num >= pBits->storageSize * sizeof(u4) * 8) {
105 if (!pBits->expandable) {
106 ALOGE("Attempt to set bit outside valid range (%d, limit is %d)",
107 num, pBits->storageSize * sizeof(u4) * 8);
111 /* Round up to word boundaries for "num+1" bits */
112 unsigned int newSize = (num + 1 + 31) >> 5;
113 assert(newSize > pBits->storageSize);
114 pBits->storage = (u4*)realloc(pBits->storage, newSize * sizeof(u4));
115 if (pBits->storage == NULL) {
116 ALOGE("BitVector expansion to %d failed", newSize * sizeof(u4));
119 memset(&pBits->storage[pBits->storageSize], 0x00,
120 (newSize - pBits->storageSize) * sizeof(u4));
121 pBits->storageSize = newSize;
124 pBits->storage[num >> 5] |= 1 << (num & 0x1f);
128 * Mark the specified bit as "clear".
130 void dvmClearBit(BitVector* pBits, unsigned int num)
132 assert(num < pBits->storageSize * sizeof(u4) * 8);
134 pBits->storage[num >> 5] &= ~(1 << (num & 0x1f));
138 * Mark all bits bit as "clear".
140 void dvmClearAllBits(BitVector* pBits)
142 unsigned int count = pBits->storageSize;
143 memset(pBits->storage, 0, count * sizeof(u4));
147 * Mark specified number of bits as "set". Cannot set all bits like ClearAll
148 * since there might be unused bits - setting those to one will confuse the
151 void dvmSetInitialBits(BitVector* pBits, unsigned int numBits)
154 assert(((numBits + 31) >> 5) <= pBits->storageSize);
155 for (idx = 0; idx < (numBits >> 5); idx++) {
156 pBits->storage[idx] = -1;
158 unsigned int remNumBits = numBits & 0x1f;
160 pBits->storage[idx] = (1 << remNumBits) - 1;
165 * Determine whether or not the specified bit is set.
167 bool dvmIsBitSet(const BitVector* pBits, unsigned int num)
169 assert(num < pBits->storageSize * sizeof(u4) * 8);
171 unsigned int val = pBits->storage[num >> 5] & (1 << (num & 0x1f));
176 * Count the number of bits that are set.
178 int dvmCountSetBits(const BitVector* pBits)
181 unsigned int count = 0;
183 for (word = 0; word < pBits->storageSize; word++) {
184 u4 val = pBits->storage[word];
187 if (val == 0xffffffff) {
190 /* count the number of '1' bits */
203 * If the vector sizes don't match, log an error and abort.
205 static void checkSizes(const BitVector* bv1, const BitVector* bv2)
207 if (bv1->storageSize != bv2->storageSize) {
208 ALOGE("Mismatched vector sizes (%d, %d)",
209 bv1->storageSize, bv2->storageSize);
215 * Copy a whole vector to the other. Only do that when the both vectors have
218 void dvmCopyBitVector(BitVector *dest, const BitVector *src)
220 /* if dest is expandable and < src, we could expand dest to match */
221 checkSizes(dest, src);
223 memcpy(dest->storage, src->storage, sizeof(u4) * dest->storageSize);
227 * Intersect two bit vectors and store the result to the dest vector.
229 bool dvmIntersectBitVectors(BitVector *dest, const BitVector *src1,
230 const BitVector *src2)
232 if (dest->storageSize != src1->storageSize ||
233 dest->storageSize != src2->storageSize ||
234 dest->expandable != src1->expandable ||
235 dest->expandable != src2->expandable)
239 for (idx = 0; idx < dest->storageSize; idx++) {
240 dest->storage[idx] = src1->storage[idx] & src2->storage[idx];
246 * Unify two bit vectors and store the result to the dest vector.
248 bool dvmUnifyBitVectors(BitVector *dest, const BitVector *src1,
249 const BitVector *src2)
251 if (dest->storageSize != src1->storageSize ||
252 dest->storageSize != src2->storageSize ||
253 dest->expandable != src1->expandable ||
254 dest->expandable != src2->expandable)
258 for (idx = 0; idx < dest->storageSize; idx++) {
259 dest->storage[idx] = src1->storage[idx] | src2->storage[idx];
265 * Compare two bit vectors and return true if difference is seen.
267 bool dvmCompareBitVectors(const BitVector *src1, const BitVector *src2)
269 if (src1->storageSize != src2->storageSize ||
270 src1->expandable != src2->expandable)
274 for (idx = 0; idx < src1->storageSize; idx++) {
275 if (src1->storage[idx] != src2->storage[idx]) return true;
280 /* Initialize the iterator structure */
281 void dvmBitVectorIteratorInit(BitVector* pBits, BitVectorIterator* iterator)
283 iterator->pBits = pBits;
284 iterator->bitSize = pBits->storageSize * sizeof(u4) * 8;
288 /* Return the next position set to 1. -1 means end-of-element reached */
289 int dvmBitVectorIteratorNext(BitVectorIterator* iterator)
291 const BitVector* pBits = iterator->pBits;
292 u4 bitIndex = iterator->idx;
294 assert(iterator->bitSize == pBits->storageSize * sizeof(u4) * 8);
295 if (bitIndex >= iterator->bitSize) return -1;
297 for (; bitIndex < iterator->bitSize; bitIndex++) {
298 unsigned int wordIndex = bitIndex >> 5;
299 unsigned int mask = 1 << (bitIndex & 0x1f);
300 if (pBits->storage[wordIndex] & mask) {
301 iterator->idx = bitIndex+1;
305 /* No more set bits */
311 * Merge the contents of "src" into "dst", checking to see if this causes
312 * any changes to occur. This is a logical OR.
314 * Returns "true" if the contents of the destination vector were modified.
316 bool dvmCheckMergeBitVectors(BitVector* dst, const BitVector* src)
318 bool changed = false;
320 checkSizes(dst, src);
323 for (idx = 0; idx < dst->storageSize; idx++) {
324 u4 merged = src->storage[idx] | dst->storage[idx];
325 if (dst->storage[idx] != merged) {
326 dst->storage[idx] = merged;