diff --git a/Lidgren.Network/NetBitWriter.cs b/Lidgren.Network/NetBitWriter.cs
index 08ffe25..44e4cbf 100644
--- a/Lidgren.Network/NetBitWriter.cs
+++ b/Lidgren.Network/NetBitWriter.cs
@@ -97,44 +97,54 @@ namespace Lidgren.Network
return;
}
- ///
- /// Write a byte consisting of 1-8 bits to a buffer; assumes buffer is previously allocated
- ///
public static void WriteByte(byte source, int numberOfBits, byte[] destination, int destBitOffset)
{
- NetException.Assert(((numberOfBits >= 1) && (numberOfBits <= 8)), "Must write between 1 and 8 bits!");
+ if (numberOfBits == 0)
+ return;
- // mask out unwanted bits in the source
- byte isrc = (byte)(source & (0x000000FF >> (8 - numberOfBits)));
+ NetException.Assert(((numberOfBits >= 0) && (numberOfBits <= 8)), "Must write between 0 and 8 bits!");
- int bytePtr = destBitOffset >> 3;
+ // Mask out all the bits we dont want
+ source = (byte)(source & (0xFF >> (8 - numberOfBits)));
- int localBitLen = (destBitOffset % 8);
- if (localBitLen == 0)
+ int p = destBitOffset >> 3;
+ int bitsUsed = destBitOffset & 0x7; // mod 8
+ int bitsFree = 8 - bitsUsed;
+ int bitsLeft = bitsFree - numberOfBits;
+
+ // Fast path, everything fits in the first byte
+ if (bitsLeft >= 0)
{
- destination[bytePtr] = (byte)isrc;
+ int mask = (0xFF >> bitsFree) | (0xFF << (8 - bitsLeft));
+
+ destination[p] = (byte)(
+ // Mask out lower and upper bits
+ (destination[p] & mask) |
+
+ // Insert new bits
+ (source << bitsUsed)
+ );
+
return;
}
- //destination[bytePtr] &= (byte)(255 >> (8 - localBitLen)); // clear before writing
- //destination[bytePtr] |= (byte)(isrc << localBitLen); // write first half
- destination[bytePtr] = (byte)(
- (uint)(destination[bytePtr] & (255 >> (8 - localBitLen))) |
- (uint)(isrc << localBitLen)
+ destination[p] = (byte)(
+ // Mask out upper bits
+ (destination[p] & (0xFF >> bitsFree)) |
+
+ // Write the lower bits to the upper bits in the first byte
+ (source << bitsUsed)
);
- // need write into next byte?
- if (localBitLen + numberOfBits > 8)
- {
- //destination[bytePtr + 1] &= (byte)(255 << localBitLen); // clear before writing
- //destination[bytePtr + 1] |= (byte)(isrc >> (8 - localBitLen)); // write second half
- destination[bytePtr + 1] = (byte)(
- (uint)(destination[bytePtr + 1] & (255 << localBitLen)) |
- (uint)(isrc >> (8 - localBitLen))
- );
- }
+ p += 1;
- return;
+ destination[p] = (byte)(
+ // Mask out lower bits
+ (destination[p] & (0xFF << (numberOfBits - bitsFree))) |
+
+ // Write the upper bits to the lower bits of the second byte
+ (source >> bitsFree)
+ );
}
///
@@ -287,35 +297,32 @@ namespace Lidgren.Network
//public static ulong ReadUInt64(byte[] fromBuffer, int numberOfBits, int readBitOffset)
///
- /// Writes un unsigned 16 bit integer
+ /// Writes an unsigned 16 bit integer
///
[CLSCompliant(false)]
- public static int WriteUInt16(ushort source, int numberOfBits, byte[] destination, int destinationBitOffset)
+ public static void WriteUInt16(ushort source, int numberOfBits, byte[] destination, int destinationBitOffset)
{
+ if (numberOfBits == 0)
+ return;
+
+ NetException.Assert((numberOfBits >= 0 && numberOfBits <= 16), "numberOfBits must be between 0 and 16");
#if BIGENDIAN
// reorder bytes
uint intSource = source;
intSource = ((intSource & 0x0000ff00) >> 8) | ((intSource & 0x000000ff) << 8);
source = (ushort)intSource;
#endif
-
- int returnValue = destinationBitOffset + numberOfBits;
if (numberOfBits <= 8)
{
NetBitWriter.WriteByte((byte)source, numberOfBits, destination, destinationBitOffset);
- return returnValue;
+ return;
}
+
NetBitWriter.WriteByte((byte)source, 8, destination, destinationBitOffset);
- destinationBitOffset += 8;
+
numberOfBits -= 8;
-
- if (numberOfBits <= 8)
- {
- NetBitWriter.WriteByte((byte)(source >> 8), numberOfBits, destination, destinationBitOffset);
- return returnValue;
- }
-
- return returnValue;
+ if (numberOfBits > 0)
+ NetBitWriter.WriteByte((byte)(source >> 8), numberOfBits, destination, destinationBitOffset + 8);
}
///
diff --git a/UnitTests/ReadWriteTests.cs b/UnitTests/ReadWriteTests.cs
index fb27ced..8682ccf 100644
--- a/UnitTests/ReadWriteTests.cs
+++ b/UnitTests/ReadWriteTests.cs
@@ -52,6 +52,7 @@ namespace UnitTests
msg.Write(567845.0f);
msg.WriteVariableInt32(2115998022);
msg.Write(46.0);
+ msg.Write((ushort)14, 9);
bcnt += msg.WriteVariableInt32(-47);
msg.WriteVariableInt32(470000);
msg.WriteVariableUInt32(48);
@@ -89,12 +90,13 @@ namespace UnitTests
bdr.Append(inc.ReadSingle());
bdr.Append(inc.ReadVariableInt32());
bdr.Append(inc.ReadDouble());
+ bdr.Append(inc.ReadUInt32(9));
bdr.Append(inc.ReadVariableInt32());
bdr.Append(inc.ReadVariableInt32());
bdr.Append(inc.ReadVariableUInt32());
bdr.Append(inc.ReadVariableInt64());
- if (bdr.ToString().Equals("False-342duke of earl4344True567845211599802246-4747000048-49"))
+ if (bdr.ToString().Equals("False-342duke of earl4344True56784521159980224614-4747000048-49"))
Console.WriteLine("Read/write tests OK");
else
throw new NetException("Read/write tests FAILED!");