From c485a2d02c6c05fccc5c956a2955c99d1662f0d8 Mon Sep 17 00:00:00 2001 From: lidgren Date: Fri, 24 Sep 2010 18:26:01 +0000 Subject: [PATCH] NetBitVector enhanced --- Lidgren.Network/NetBitVector.cs | 52 +++++++++++++++++++++++++-------- UnitTests/BitVectorTests.cs | 31 +++++++++++++++++++- 2 files changed, 70 insertions(+), 13 deletions(-) diff --git a/Lidgren.Network/NetBitVector.cs b/Lidgren.Network/NetBitVector.cs index c72a53b..a14c8ca 100644 --- a/Lidgren.Network/NetBitVector.cs +++ b/Lidgren.Network/NetBitVector.cs @@ -18,35 +18,57 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. */ using System; +using System.Text; namespace Lidgren.Network { public sealed class NetBitVector { private readonly int m_capacity; - private readonly uint[] m_data; + private readonly int[] m_data; public int Capacity { get { return m_capacity; } } public NetBitVector(int bitsCapacity) { m_capacity = bitsCapacity; - m_data = new uint[(bitsCapacity + 31) / 32]; + m_data = new int[(bitsCapacity + 31) / 32]; } public bool IsEmpty() { - foreach (uint v in m_data) + foreach (int v in m_data) if (v != 0) return false; return true; } + /// + /// Shift all bits one step down, cycling the first bit to the top + /// + public void RotateDown() + { + int lenMinusOne = m_data.Length - 1; + + int firstBit = m_data[0] & 1; + for (int i = 0; i < lenMinusOne; i++) + m_data[i] = ((m_data[i] >> 1) & ~(1 << 31)) | m_data[i + 1] << 31; + + int lastIndex = m_capacity - 1 - (32 * lenMinusOne); + + // special handling of last int + int cur = m_data[lenMinusOne]; + cur = cur >> 1; + cur |= firstBit << lastIndex; + + m_data[lenMinusOne] = cur; + } + public int GetFirstSetIndex() { int idx = 0; - uint data = m_data[0]; + int data = m_data[0]; while (data == 0) { idx++; @@ -62,24 +84,20 @@ namespace Lidgren.Network public bool Get(int bitIndex) { - int idx = bitIndex / 32; - uint data = m_data[idx]; - int bitNr = bitIndex - (idx * 32); - return (data & (1 << bitNr)) != 0; + return (m_data[bitIndex / 32] & (1 << (bitIndex % 32))) != 0; } public void Set(int bitIndex, bool value) { int idx = bitIndex / 32; - int bitNr = bitIndex - (idx * 32); if (value) - m_data[idx] |= (uint)(1 << bitNr); + m_data[idx] |= (1 << (bitIndex % 32)); else - m_data[idx] &= (uint)(~(1 << bitNr)); + m_data[idx] &= (~(1 << (bitIndex % 32))); } [System.Runtime.CompilerServices.IndexerName("Bit")] - public bool this [int index] + public bool this[int index] { get { return Get(index); } set { Set(index, value); } @@ -89,5 +107,15 @@ namespace Lidgren.Network { Array.Clear(m_data, 0, m_data.Length); } + + public override string ToString() + { + StringBuilder bdr = new StringBuilder(m_capacity + 2); + bdr.Append('['); + for (int i = 0; i < m_capacity; i++) + bdr.Append(Get(m_capacity - i - 1) ? '1' : '0'); + bdr.Append(']'); + return bdr.ToString(); + } } } diff --git a/UnitTests/BitVectorTests.cs b/UnitTests/BitVectorTests.cs index d5d20dd..57ac7d2 100644 --- a/UnitTests/BitVectorTests.cs +++ b/UnitTests/BitVectorTests.cs @@ -32,7 +32,36 @@ namespace UnitTests if (f != i) throw new NetException("bit vector fail 4"); } - + + v = new NetBitVector(9); + v.Clear(); + v.Set(3, true); + if (v.ToString() != "[000001000]") + throw new NetException("NetBitVector.RotateDown failed"); + v.RotateDown(); + if (v.Get(3) == true || v.Get(2) == false || v.Get(4) == true) + throw new NetException("NetBitVector.RotateDown failed 2"); + if (v.ToString() != "[000000100]") + throw new NetException("NetBitVector.RotateDown failed 3"); + + v.Set(0, true); + v.RotateDown(); + if (v.ToString() != "[100000010]") + throw new NetException("NetBitVector.RotateDown failed 4"); + + v = new NetBitVector(38); + v.Set(0, true); + v.Set(1, true); + v.Set(31, true); + + if (v.ToString() != "[00000010000000000000000000000000000011]") + throw new NetException("NetBitVector.RotateDown failed 5"); + + v.RotateDown(); + + if (v.ToString() != "[10000001000000000000000000000000000001]") + throw new NetException("NetBitVector.RotateDown failed 5"); + Console.WriteLine("NetBitVector tests OK"); } }