xref: /haiku/src/system/kernel/util/Bitmap.cpp (revision 0235c04759eca374fa3998fb9b8934523987372d)
1149c82a8SPawel Dziepak /*
288275138SAugustin 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
788275138SAugustin Cavalier  *		Augustin Cavalier <waddlesplash>
8149c82a8SPawel Dziepak  */
9149c82a8SPawel Dziepak #include <util/Bitmap.h>
10149c82a8SPawel Dziepak 
1188275138SAugustin Cavalier #include <stdlib.h>
12149c82a8SPawel Dziepak #include <string.h>
13149c82a8SPawel Dziepak 
14149c82a8SPawel Dziepak #include <util/BitUtils.h>
15149c82a8SPawel Dziepak 
16149c82a8SPawel Dziepak 
1788275138SAugustin Cavalier namespace BKernel {
18149c82a8SPawel Dziepak 
19149c82a8SPawel Dziepak 
Bitmap(size_t bitCount)2088275138SAugustin Cavalier Bitmap::Bitmap(size_t bitCount)
21149c82a8SPawel Dziepak 	:
22149c82a8SPawel Dziepak 	fElementsCount(0),
2388275138SAugustin Cavalier 	fSize(0),
2488275138SAugustin Cavalier 	fBits(NULL)
25149c82a8SPawel Dziepak {
2688275138SAugustin Cavalier 	Resize(bitCount);
27761714b3SMurai Takashi }
28149c82a8SPawel Dziepak 
29149c82a8SPawel Dziepak 
~Bitmap()30149c82a8SPawel Dziepak Bitmap::~Bitmap()
31149c82a8SPawel Dziepak {
3288275138SAugustin Cavalier 	free(fBits);
33149c82a8SPawel Dziepak }
34149c82a8SPawel Dziepak 
35149c82a8SPawel Dziepak 
3688275138SAugustin Cavalier status_t
InitCheck()3788275138SAugustin Cavalier Bitmap::InitCheck()
3888275138SAugustin Cavalier {
3988275138SAugustin Cavalier 	return (fBits != NULL) ? B_OK : B_NO_MEMORY;
4088275138SAugustin Cavalier }
4188275138SAugustin Cavalier 
4288275138SAugustin Cavalier 
4388275138SAugustin Cavalier status_t
Resize(size_t bitCount)4488275138SAugustin Cavalier Bitmap::Resize(size_t bitCount)
4588275138SAugustin Cavalier {
4688275138SAugustin Cavalier 	const size_t count = (bitCount + kBitsPerElement - 1) / kBitsPerElement;
4788275138SAugustin Cavalier 	if (count == fElementsCount) {
4888275138SAugustin Cavalier 		fSize = bitCount;
4988275138SAugustin Cavalier 		return B_OK;
5088275138SAugustin Cavalier 	}
5188275138SAugustin Cavalier 
5288275138SAugustin Cavalier 	void* bits = realloc(fBits, sizeof(addr_t) * count);
5388275138SAugustin Cavalier 	if (bits == NULL)
5488275138SAugustin Cavalier 		return B_NO_MEMORY;
5588275138SAugustin Cavalier 	fBits = (addr_t*)bits;
5688275138SAugustin Cavalier 
5788275138SAugustin Cavalier 	if (fElementsCount < count)
5888275138SAugustin Cavalier 		memset(&fBits[fElementsCount], 0, sizeof(addr_t) * (count - fElementsCount));
5988275138SAugustin Cavalier 
6088275138SAugustin Cavalier 	fSize = bitCount;
6188275138SAugustin Cavalier 	fElementsCount = count;
6288275138SAugustin Cavalier 	return B_OK;
6388275138SAugustin Cavalier }
6488275138SAugustin Cavalier 
6588275138SAugustin Cavalier 
6688275138SAugustin Cavalier void
Shift(ssize_t bitCount)6788275138SAugustin Cavalier Bitmap::Shift(ssize_t bitCount)
6888275138SAugustin Cavalier {
69bdcc293fSTrung Nguyen 	return bitmap_shift<addr_t>(fBits, fSize, bitCount);
7088275138SAugustin Cavalier }
7188275138SAugustin Cavalier 
7288275138SAugustin Cavalier 
73*0235c047SX512 void
SetRange(size_t index,size_t count)74*0235c047SX512 Bitmap::SetRange(size_t index, size_t count)
75*0235c047SX512 {
76*0235c047SX512 	// TODO: optimize
77*0235c047SX512 	for (; count > 0; count--)
78*0235c047SX512 		Set(index++);
79*0235c047SX512 }
80*0235c047SX512 
81*0235c047SX512 
82*0235c047SX512 void
ClearRange(size_t index,size_t count)83*0235c047SX512 Bitmap::ClearRange(size_t index, size_t count)
84*0235c047SX512 {
85*0235c047SX512 	// TODO: optimize
86*0235c047SX512 	for (; count > 0; count--)
87*0235c047SX512 		Clear(index++);
88*0235c047SX512 }
89*0235c047SX512 
90*0235c047SX512 
91*0235c047SX512 ssize_t
GetLowestClear(size_t fromIndex) const92*0235c047SX512 Bitmap::GetLowestClear(size_t fromIndex) const
93*0235c047SX512 {
94*0235c047SX512 	// TODO: optimize
95*0235c047SX512 
96*0235c047SX512 	for (size_t i = fromIndex; i < fSize; i++) {
97*0235c047SX512 		if (!Get(i))
98*0235c047SX512 			return i;
99*0235c047SX512 	}
100*0235c047SX512 	return -1;
101*0235c047SX512 }
102*0235c047SX512 
103*0235c047SX512 
104*0235c047SX512 ssize_t
GetLowestContiguousClear(size_t count,size_t fromIndex) const105*0235c047SX512 Bitmap::GetLowestContiguousClear(size_t count, size_t fromIndex) const
106*0235c047SX512 {
107*0235c047SX512 	// TODO: optimize
108*0235c047SX512 
109*0235c047SX512 	// nothing to find
110*0235c047SX512 	if (count == 0)
111*0235c047SX512 		return fromIndex;
112*0235c047SX512 
113*0235c047SX512 	for (;;) {
114*0235c047SX512 		ssize_t index = GetLowestClear(fromIndex);
115*0235c047SX512 		if (index < 0)
116*0235c047SX512 			return index;
117*0235c047SX512 
118*0235c047SX512 		// overflow check
119*0235c047SX512 		if ((size_t)index + count - 1 < (size_t)index)
120*0235c047SX512 			return -1;
121*0235c047SX512 
122*0235c047SX512 		size_t curCount = 1;
123*0235c047SX512 		while (curCount < count && Get(index + curCount))
124*0235c047SX512 			curCount++;
125*0235c047SX512 
126*0235c047SX512 		if (curCount == count)
127*0235c047SX512 			return index;
128*0235c047SX512 
129*0235c047SX512 		fromIndex = index + curCount;
130*0235c047SX512 	}
131*0235c047SX512 }
132*0235c047SX512 
133*0235c047SX512 
13488275138SAugustin Cavalier ssize_t
GetHighestSet() const135149c82a8SPawel Dziepak Bitmap::GetHighestSet() const
136149c82a8SPawel Dziepak {
13788275138SAugustin Cavalier 	size_t i = fElementsCount - 1;
138149c82a8SPawel Dziepak 	while (i >= 0 && fBits[i] == 0)
139149c82a8SPawel Dziepak 		i--;
140149c82a8SPawel Dziepak 
141149c82a8SPawel Dziepak 	if (i < 0)
142149c82a8SPawel Dziepak 		return -1;
143149c82a8SPawel Dziepak 
144149c82a8SPawel Dziepak 	STATIC_ASSERT(sizeof(addr_t) == sizeof(uint64)
145149c82a8SPawel Dziepak 		|| sizeof(addr_t) == sizeof(uint32));
146149c82a8SPawel Dziepak 	if (sizeof(addr_t) == sizeof(uint32))
147149c82a8SPawel Dziepak 		return log2(fBits[i]) + i * kBitsPerElement;
148149c82a8SPawel Dziepak 
1495c7f09c4SPawel Dziepak 	uint32 v = (uint64)fBits[i] >> 32;
150149c82a8SPawel Dziepak 	if (v != 0)
151149c82a8SPawel Dziepak 		return log2(v) + sizeof(uint32) * 8 + i * kBitsPerElement;
152149c82a8SPawel Dziepak 	return log2(fBits[i]) + i * kBitsPerElement;
153149c82a8SPawel Dziepak }
154149c82a8SPawel Dziepak 
15588275138SAugustin Cavalier 
15688275138SAugustin Cavalier } // namespace BKernel
157