/* * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef UpdateMask_h__ #define UpdateMask_h__ #include "Define.h" #include #include // std::memset namespace UpdateMaskHelpers { inline constexpr std::size_t GetBlockIndex(std::size_t bit) { return bit / 32u; } inline constexpr uint32 GetBlockFlag(std::size_t bit) { return 1u << (bit % 32u); } } template class UpdateMask { public: static constexpr uint32 BlockCount = (Bits + 31) / 32; static constexpr uint32 BlocksMaskCount = (BlockCount + 31) / 32; constexpr UpdateMask() : _blocksMask(), _blocks() { } constexpr UpdateMask(std::array const& init) { _blocksMask.back() = 0; // only last value of blocksMask will not be written fully for (uint32 block = 0; block < BlockCount; ++block) { if ((_blocks[block] = init[block]) != 0) _blocksMask[UpdateMaskHelpers::GetBlockIndex(block)] |= UpdateMaskHelpers::GetBlockFlag(block); else _blocksMask[UpdateMaskHelpers::GetBlockIndex(block)] &= ~UpdateMaskHelpers::GetBlockFlag(block); } } constexpr uint32 GetBlocksMask(uint32 index) const { return _blocksMask[index]; } constexpr uint32 GetBlock(uint32 index) const { return _blocks[index]; } constexpr bool operator[](uint32 index) const { return (_blocks[UpdateMaskHelpers::GetBlockIndex(index)] & UpdateMaskHelpers::GetBlockFlag(index)) != 0; } constexpr bool IsAnySet() const { return std::ranges::any_of(_blocksMask, [](uint32 blockMask) { return blockMask != 0; }); } constexpr void Reset(uint32 index) { std::size_t blockIndex = UpdateMaskHelpers::GetBlockIndex(index); if (!(_blocks[blockIndex] &= ~UpdateMaskHelpers::GetBlockFlag(index))) _blocksMask[UpdateMaskHelpers::GetBlockIndex(blockIndex)] &= ~UpdateMaskHelpers::GetBlockFlag(blockIndex); } constexpr void ResetAll() { _blocksMask = { }; _blocks = { }; } constexpr void Set(uint32 index) { std::size_t blockIndex = UpdateMaskHelpers::GetBlockIndex(index); _blocks[blockIndex] |= UpdateMaskHelpers::GetBlockFlag(index); _blocksMask[UpdateMaskHelpers::GetBlockIndex(blockIndex)] |= UpdateMaskHelpers::GetBlockFlag(blockIndex); } constexpr void SetAll() { std::memset(_blocksMask.data(), 0xFF, _blocksMask.size() * sizeof(typename decltype(_blocksMask)::value_type)); if constexpr (BlocksMaskCount % 32) { constexpr uint32 unused = 32 - (BlocksMaskCount % 32); _blocksMask.back() &= (0xFFFFFFFF >> unused); } std::memset(_blocks.data(), 0xFF, _blocks.size() * sizeof(typename decltype(_blocks)::value_type)); if constexpr (BlockCount % 32) { constexpr uint32 unused = 32 - (BlockCount % 32); _blocks.back() &= (0xFFFFFFFF >> unused); } } constexpr UpdateMask& operator&=(UpdateMask const& right) { for (uint32 i = 0; i < BlocksMaskCount; ++i) _blocksMask[i] &= right._blocksMask[i]; for (uint32 i = 0; i < BlockCount; ++i) if (!(_blocks[i] &= right._blocks[i])) _blocksMask[UpdateMaskHelpers::GetBlockIndex(i)] &= ~UpdateMaskHelpers::GetBlockFlag(i); return *this; } constexpr UpdateMask& operator|=(UpdateMask const& right) { for (std::size_t i = 0; i < BlocksMaskCount; ++i) _blocksMask[i] |= right._blocksMask[i]; for (std::size_t i = 0; i < BlockCount; ++i) _blocks[i] |= right._blocks[i]; return *this; } private: std::array _blocksMask; std::array _blocks; }; template constexpr UpdateMask operator&(UpdateMask const& left, UpdateMask const& right) { UpdateMask result = left; result &= right; return result; } template constexpr UpdateMask operator|(UpdateMask const& left, UpdateMask const& right) { UpdateMask result = left; result |= right; return result; } #endif // UpdateMask_h__