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