/** * MaNGOS is a full featured server for World of Warcraft, supporting * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 * * Copyright (C) 2005-2015 MaNGOS project * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * World of Warcraft, and all World of Warcraft or Warcraft art, images, * and lore are copyrighted by Blizzard Entertainment, Inc. */ #ifndef MANGOS_H_UPDATEMASK #define MANGOS_H_UPDATEMASK #include "UpdateFields.h" #include "Errors.h" #ifdef WIN32 #include #endif class UpdateMask { public: UpdateMask() : mCount(0), mBlocks(0), mUpdateMask(0) { } UpdateMask(const UpdateMask& mask) : mUpdateMask(0) { *this = mask; } ~UpdateMask() { delete[] mUpdateMask; } void SetBit(uint32 index) { ((uint8*)mUpdateMask)[ index >> 3 ] |= 1 << (index & 0x7); } void UnsetBit(uint32 index) { ((uint8*)mUpdateMask)[ index >> 3 ] &= (0xff ^(1 << (index & 0x7))); } bool GetBit(uint32 index) const { return (((uint8*)mUpdateMask)[ index >> 3 ] & (1 << (index & 0x7))) != 0; } uint32 GetNextSetIndex(uint32 start) const { uint32 index = start; while (index <= mCount) { uint32 offset = ctz(mUpdateMask[index >> 5] >> (index & 0x1F)); if (offset < (32 - (index & 0x1F))) return index + offset; else index += (32 - (index & 0x1F)); } return mCount; } uint32 GetBlockCount() const { return mBlocks; } uint32 GetLength() const { return mBlocks << 2; } uint32 GetCount() const { return mCount; } uint8* GetMask() { return (uint8*)mUpdateMask; } void SetCount(uint32 valuesCount) { delete[] mUpdateMask; mCount = valuesCount; mBlocks = (valuesCount + 31) / 32; mUpdateMask = new uint32[mBlocks]; memset(mUpdateMask, 0, mBlocks << 2); } void Clear() { if (mUpdateMask) { memset(mUpdateMask, 0, mBlocks << 2); } } UpdateMask& operator = (const UpdateMask& mask) { SetCount(mask.mCount); memcpy(mUpdateMask, mask.mUpdateMask, mBlocks << 2); return *this; } void operator &= (const UpdateMask& mask) { MANGOS_ASSERT(mask.mCount <= mCount); for (uint32 i = 0; i < mBlocks; ++i) { mUpdateMask[i] &= mask.mUpdateMask[i]; } } void operator |= (const UpdateMask& mask) { MANGOS_ASSERT(mask.mCount <= mCount); for (uint32 i = 0; i < mBlocks; ++i) { mUpdateMask[i] |= mask.mUpdateMask[i]; } } UpdateMask operator & (const UpdateMask& mask) const { MANGOS_ASSERT(mask.mCount <= mCount); UpdateMask newmask; newmask = *this; newmask &= mask; return newmask; } UpdateMask operator | (const UpdateMask& mask) const { MANGOS_ASSERT(mask.mCount <= mCount); UpdateMask newmask; newmask = *this; newmask |= mask; return newmask; } private: uint32 mCount; uint32 mBlocks; uint32* mUpdateMask; #ifdef WIN32 static uint32 __inline __builtin_ctz(uint32 x) { unsigned long r = 0; _BitScanForward(&r, x); return r; } #endif static inline uint32 ctz(const uint32 x) { return x ? __builtin_ctz(x) : 32; } }; #endif