xref: /haiku/src/system/kernel/util/Bitmap.cpp (revision 88275138bae13f25a33a610ba51d116f4a593b81)
1149c82a8SPawel Dziepak /*
2*88275138SAugustin Cavalier  * Copyright 2013-2022, Haiku, Inc. All rights reserved.
3149c82a8SPawel Dziepak  * Distributed under the terms of the MIT License.
4149c82a8SPawel Dziepak  *
5149c82a8SPawel Dziepak  * Authors:
6149c82a8SPawel Dziepak  *		Paweł Dziepak, pdziepak@quarnos.org
7*88275138SAugustin Cavalier  *		Augustin Cavalier <waddlesplash>
8149c82a8SPawel Dziepak  */
9149c82a8SPawel Dziepak #include <util/Bitmap.h>
10149c82a8SPawel Dziepak 
11*88275138SAugustin Cavalier #include <stdlib.h>
12149c82a8SPawel Dziepak #include <string.h>
13149c82a8SPawel Dziepak 
14149c82a8SPawel Dziepak #include <util/BitUtils.h>
15149c82a8SPawel Dziepak 
16149c82a8SPawel Dziepak 
17*88275138SAugustin Cavalier namespace BKernel {
18149c82a8SPawel Dziepak 
19149c82a8SPawel Dziepak 
20*88275138SAugustin Cavalier Bitmap::Bitmap(size_t bitCount)
21149c82a8SPawel Dziepak 	:
22149c82a8SPawel Dziepak 	fElementsCount(0),
23*88275138SAugustin Cavalier 	fSize(0),
24*88275138SAugustin Cavalier 	fBits(NULL)
25149c82a8SPawel Dziepak {
26*88275138SAugustin Cavalier 	Resize(bitCount);
27761714b3SMurai Takashi }
28149c82a8SPawel Dziepak 
29149c82a8SPawel Dziepak 
30149c82a8SPawel Dziepak Bitmap::~Bitmap()
31149c82a8SPawel Dziepak {
32*88275138SAugustin Cavalier 	free(fBits);
33149c82a8SPawel Dziepak }
34149c82a8SPawel Dziepak 
35149c82a8SPawel Dziepak 
36*88275138SAugustin Cavalier status_t
37*88275138SAugustin Cavalier Bitmap::InitCheck()
38*88275138SAugustin Cavalier {
39*88275138SAugustin Cavalier 	return (fBits != NULL) ? B_OK : B_NO_MEMORY;
40*88275138SAugustin Cavalier }
41*88275138SAugustin Cavalier 
42*88275138SAugustin Cavalier 
43*88275138SAugustin Cavalier status_t
44*88275138SAugustin Cavalier Bitmap::Resize(size_t bitCount)
45*88275138SAugustin Cavalier {
46*88275138SAugustin Cavalier 	const size_t count = (bitCount + kBitsPerElement - 1) / kBitsPerElement;
47*88275138SAugustin Cavalier 	if (count == fElementsCount) {
48*88275138SAugustin Cavalier 		fSize = bitCount;
49*88275138SAugustin Cavalier 		return B_OK;
50*88275138SAugustin Cavalier 	}
51*88275138SAugustin Cavalier 
52*88275138SAugustin Cavalier 	void* bits = realloc(fBits, sizeof(addr_t) * count);
53*88275138SAugustin Cavalier 	if (bits == NULL)
54*88275138SAugustin Cavalier 		return B_NO_MEMORY;
55*88275138SAugustin Cavalier 	fBits = (addr_t*)bits;
56*88275138SAugustin Cavalier 
57*88275138SAugustin Cavalier 	if (fElementsCount < count)
58*88275138SAugustin Cavalier 		memset(&fBits[fElementsCount], 0, sizeof(addr_t) * (count - fElementsCount));
59*88275138SAugustin Cavalier 
60*88275138SAugustin Cavalier 	fSize = bitCount;
61*88275138SAugustin Cavalier 	fElementsCount = count;
62*88275138SAugustin Cavalier 	return B_OK;
63*88275138SAugustin Cavalier }
64*88275138SAugustin Cavalier 
65*88275138SAugustin Cavalier 
66*88275138SAugustin Cavalier void
67*88275138SAugustin Cavalier Bitmap::Shift(ssize_t bitCount)
68*88275138SAugustin Cavalier {
69*88275138SAugustin Cavalier 	if (bitCount == 0)
70*88275138SAugustin Cavalier 		return;
71*88275138SAugustin Cavalier 
72*88275138SAugustin Cavalier 	const size_t shift = (bitCount > 0) ? bitCount : -bitCount;
73*88275138SAugustin Cavalier 	const size_t nElements = shift / kBitsPerElement, nBits = shift % kBitsPerElement;
74*88275138SAugustin Cavalier 	if (nElements != 0) {
75*88275138SAugustin Cavalier 		if (bitCount > 0) {
76*88275138SAugustin Cavalier 			// "Left" shift.
77*88275138SAugustin Cavalier 			memmove(&fBits[nElements], fBits, sizeof(addr_t) * (fElementsCount - nElements));
78*88275138SAugustin Cavalier 			memset(fBits, 0, sizeof(addr_t) * nElements);
79*88275138SAugustin Cavalier 		} else if (bitCount < 0) {
80*88275138SAugustin Cavalier 			// "Right" shift.
81*88275138SAugustin Cavalier 			memmove(fBits, &fBits[nElements], sizeof(addr_t) * (fElementsCount - nElements));
82*88275138SAugustin Cavalier 			memset(&fBits[fElementsCount - nElements], 0, sizeof(addr_t) * nElements);
83*88275138SAugustin Cavalier 		}
84*88275138SAugustin Cavalier 	}
85*88275138SAugustin Cavalier 
86*88275138SAugustin Cavalier 	// If the shift was by a multiple of the element size, nothing more to do.
87*88275138SAugustin Cavalier 	if (nBits == 0)
88*88275138SAugustin Cavalier 		return;
89*88275138SAugustin Cavalier 
90*88275138SAugustin Cavalier 	// One set of bits comes from the "current" element and are shifted in the
91*88275138SAugustin Cavalier 	// direction of the shift; the other set comes from the next-processed
92*88275138SAugustin Cavalier 	// element and are shifted in the opposite direction.
93*88275138SAugustin Cavalier 	if (bitCount > 0) {
94*88275138SAugustin Cavalier 		// "Left" shift.
95*88275138SAugustin Cavalier 		for (ssize_t i = fElementsCount - 1; i >= 0; i--) {
96*88275138SAugustin Cavalier 			addr_t low = 0;
97*88275138SAugustin Cavalier 			if (i != 0)
98*88275138SAugustin Cavalier 				low = fBits[i - 1] >> (kBitsPerElement - nBits);
99*88275138SAugustin Cavalier 			const addr_t high = fBits[i] << nBits;
100*88275138SAugustin Cavalier 			fBits[i] = low | high;
101*88275138SAugustin Cavalier 		}
102*88275138SAugustin Cavalier 	} else if (bitCount < 0) {
103*88275138SAugustin Cavalier 		// "Right" shift.
104*88275138SAugustin Cavalier 		for (size_t i = 0; i < fElementsCount; i++) {
105*88275138SAugustin Cavalier 			const addr_t low = fBits[i] >> nBits;
106*88275138SAugustin Cavalier 			addr_t high = 0;
107*88275138SAugustin Cavalier 			if (i != (fElementsCount - 1))
108*88275138SAugustin Cavalier 				high = fBits[i + 1] << (kBitsPerElement - nBits);
109*88275138SAugustin Cavalier 			fBits[i] = low | high;
110*88275138SAugustin Cavalier 		}
111*88275138SAugustin Cavalier 	}
112*88275138SAugustin Cavalier }
113*88275138SAugustin Cavalier 
114*88275138SAugustin Cavalier 
115*88275138SAugustin Cavalier ssize_t
116149c82a8SPawel Dziepak Bitmap::GetHighestSet() const
117149c82a8SPawel Dziepak {
118*88275138SAugustin Cavalier 	size_t i = fElementsCount - 1;
119149c82a8SPawel Dziepak 	while (i >= 0 && fBits[i] == 0)
120149c82a8SPawel Dziepak 		i--;
121149c82a8SPawel Dziepak 
122149c82a8SPawel Dziepak 	if (i < 0)
123149c82a8SPawel Dziepak 		return -1;
124149c82a8SPawel Dziepak 
125149c82a8SPawel Dziepak 	STATIC_ASSERT(sizeof(addr_t) == sizeof(uint64)
126149c82a8SPawel Dziepak 		|| sizeof(addr_t) == sizeof(uint32));
127149c82a8SPawel Dziepak 	if (sizeof(addr_t) == sizeof(uint32))
128149c82a8SPawel Dziepak 		return log2(fBits[i]) + i * kBitsPerElement;
129149c82a8SPawel Dziepak 
1305c7f09c4SPawel Dziepak 	uint32 v = (uint64)fBits[i] >> 32;
131149c82a8SPawel Dziepak 	if (v != 0)
132149c82a8SPawel Dziepak 		return log2(v) + sizeof(uint32) * 8 + i * kBitsPerElement;
133149c82a8SPawel Dziepak 	return log2(fBits[i]) + i * kBitsPerElement;
134149c82a8SPawel Dziepak }
135149c82a8SPawel Dziepak 
136*88275138SAugustin Cavalier 
137*88275138SAugustin Cavalier } // namespace BKernel
138