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