You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Framework/AzNetworking/AzNetworking/DataStructures/RingBufferBitset.inl

141 lines
4.4 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
namespace AzNetworking
{
template <uint32_t SIZE>
inline RingbufferBitset<SIZE>::RingbufferBitset()
{
Reset();
}
template <uint32_t SIZE>
inline void RingbufferBitset<SIZE>::Reset()
{
m_headElementOffset = 0;
m_unusedHeadBits = NumBitsetChunkedBits;
for (uint32_t i = 0; i < m_container.size(); ++i)
{
m_container[i] = 0;
}
}
template <uint32_t SIZE>
inline bool RingbufferBitset<SIZE>::GetBit(uint32_t index) const
{
const uint32_t usedHeadBits = NumBitsetChunkedBits - m_unusedHeadBits;
if (index < usedHeadBits)
{
return GetBitHelper(m_container[m_headElementOffset], index);
}
index -= usedHeadBits;
const uint32_t element = (index >> 5) + 1;
const uint32_t bitIndex = index & (NumBitsetChunkedBits - 1);
return GetBitHelper(m_container[GetChunkIndexHelper(element)], bitIndex);
}
template <uint32_t SIZE>
inline void RingbufferBitset<SIZE>::SetBit(uint32_t index, bool value)
{
const uint32_t usedHeadBits = NumBitsetChunkedBits - m_unusedHeadBits;
if (index < usedHeadBits)
{
return SetBitHelper(m_container[m_headElementOffset], index, value);
}
index -= usedHeadBits;
const uint32_t element = (index >> 5) + 1;
const uint32_t bitIndex = index & (NumBitsetChunkedBits - 1);
return SetBitHelper(m_container[GetChunkIndexHelper(element)], bitIndex, value);
}
template <uint32_t SIZE>
inline uint32_t RingbufferBitset<SIZE>::GetValidBitCount() const
{
return SIZE - NumBitsetChunkedBits;
}
template <uint32_t SIZE>
inline void RingbufferBitset<SIZE>::PushBackBits(uint32_t count)
{
const uint32_t headBitsToShift = std::min<uint32_t>(count, m_unusedHeadBits);
m_container[m_headElementOffset] <<= headBitsToShift;
m_unusedHeadBits -= headBitsToShift;
count -= headBitsToShift;
if (m_unusedHeadBits <= 0)
{
IncrementHead();
}
while (count > NumBitsetChunkedBits)
{
count -= NumBitsetChunkedBits;
IncrementHead();
}
m_unusedHeadBits -= count;
}
template <uint32_t SIZE>
inline const BitsetChunk& RingbufferBitset<SIZE>::GetBitsetElement(uint32_t elementIndex) const
{
return m_container[GetChunkIndexHelper(elementIndex)];
}
template <uint32_t SIZE>
inline uint32_t RingbufferBitset<SIZE>::GetUnusedHeadBits() const
{
return m_unusedHeadBits;
}
template <uint32_t SIZE>
inline uint32_t RingbufferBitset<SIZE>::GetChunkIndexHelper(uint32_t absoluteIndex) const
{
AZ_Assert(absoluteIndex < RingbufferContainerSize, "Out of bounds chunk index requested");
return ((m_headElementOffset + RingbufferContainerSize) - absoluteIndex) % RingbufferContainerSize;
}
template <uint32_t SIZE>
inline void RingbufferBitset<SIZE>::IncrementHead()
{
m_headElementOffset = (m_headElementOffset + 1) % RingbufferContainerSize;
m_unusedHeadBits = NumBitsetChunkedBits;
m_container[m_headElementOffset] = 0;
}
template <typename TYPE>
inline bool GetBitHelper(TYPE element, uint32_t bitIndex)
{
AZ_Assert(bitIndex < AZ::Log2(TYPE(~0)), "Out of bounds access (requested %u, size %u)", bitIndex, AZ::Log2(TYPE(~0)));
return ((element >> bitIndex) & 0x01) ? true : false;
}
template <typename TYPE>
inline void SetBitHelper(TYPE &element, uint32_t bitIndex, bool value)
{
AZ_Assert(bitIndex < AZ::Log2(TYPE(~0)), "Out of bounds access (requested %u, size %u)", bitIndex, AZ::Log2(TYPE(~0)));
const TYPE mask = TYPE(0x01 << bitIndex);
element = (value) ? (element | mask) : (element & (TYPE)(~mask));
}
}