Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- * * Copyright (c) 2023 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #ifndef Bitmap_h #define Bitmap_h #include <bit> #include <span> #include "Allocator.h" //FIXME: Should we get rid of the size tracking and make this dynamically grow as necessary? namespace lsl { struct VIS_HIDDEN Bitmap { Bitmap() = default; Bitmap(Allocator& allocator, size_t size) : _allocator(&allocator), _size(size) { _sizeInBytes = (_size + (kBitsPerByte-1)) / kBitsPerByte; void* buffer = _allocator->malloc(_sizeInBytes); bzero(buffer, _sizeInBytes); _bitmap = UniquePtr<std::byte>((std::byte*)buffer); } Bitmap(Allocator& allocator, size_t size, std::span<std::byte>& data) : Bitmap(allocator, size) { _bitmap.withUnsafe([&](std::byte* bitmap) { std::copy(data.begin(), data.begin()+_sizeInBytes, &bitmap[0]); }); data = data.last((size_t)(data.size()-_sizeInBytes)); } Bitmap(const Bitmap& other) : Bitmap(*other._allocator, other._size) { _bitmap.withUnsafe([&](std::byte* bitmap) { std::copy(other.bytes().begin(), other.bytes().end(), &bitmap[0]); }); } Bitmap& operator=(const Bitmap& other) { auto temp = other; swap(temp); return *this; } Bitmap(Bitmap&& other) { swap(other); } Bitmap& operator=(Bitmap&& other) { swap(other); return *this; } ~Bitmap() { clear(); } void setBit(size_t bit) { assert(bit < _size); _bitmap.withUnsafe([&](std::byte* bitmap) { std::byte* byte = &bitmap[bit / kBitsPerByte]; *byte |= (std::byte)(1 << (bit % kBitsPerByte)); }); } bool checkBit(size_t bit) const { assert(bit < _size); return ((std::byte)0 != _bitmap.withUnsafe([&](std::byte* bitmap) { std::byte* byte = &bitmap[bit / kBitsPerByte]; return *byte & (std::byte)(1 << (bit % kBitsPerByte)); })); } size_t size() const { return _size; } size_t sizeInBytes() const { return _sizeInBytes; } friend void swap(Bitmap& x, Bitmap& y) { x.swap(y); } std::span<std::byte> bytes() const { return _bitmap.withUnsafe([&](std::byte* bitmap) { return std::span<std::byte>(&bitmap[0], sizeInBytes()); }); } void clear() { _size = 0; _sizeInBytes = 0; _bitmap = nullptr; } size_t getBitCount() const { return _bitmap.withUnsafe([&](std::byte* bitmap) { uint64_t wordCount = roundUpToPowerOf2<kBitsPerWord>(_size) / kBitsPerWord; size_t result = 0; for (auto i = 0; i < wordCount; ++i) { result += std::popcount(((uint64_t*)bitmap)[i]); } return result; }); } explicit operator bool() const { return (bool)_bitmap; } private: static const uint64_t kBitsPerByte = 8; static const uint64_t kBitsPerWord = 64; template<uint64_t n> static inline uint64_t roundUpToPowerOf2(uint64_t value) { static_assert(std::popcount(n) == 1 && "Can only align to powers of 2"); return ((value + (n-1)) & (-1*n)); } void swap(Bitmap& other) { if (this == &other) { return; } using std::swap; swap(_allocator, other._allocator); swap(_bitmap, other._bitmap); swap(_size, other._size); swap(_sizeInBytes, other._sizeInBytes); } Allocator* _allocator = nullptr; UniquePtr<std::byte> _bitmap = nullptr; size_t _size = 0; size_t _sizeInBytes = 0; }; }; #endif /* Bitmap_h */ |