Skip to content

Commit fc63b03

Browse files
Fixed CeilingExact functions
Added sign bit constants for all signed types Fixed Length Fixed Grow? Added Grow call where necessary Added some necessary methods
1 parent 5f8c306 commit fc63b03

File tree

2 files changed

+37
-11
lines changed

2 files changed

+37
-11
lines changed

MLAPI/NetworkingManagerComponents/Binary/Arithmetic.cs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,36 @@
22
{
33
public static class Arithmetic
44
{
5+
// Sign bits for different data types
6+
public const long SIGN_BIT_64 = -9223372036854775808;
7+
public const int SIGN_BIT_32 = -2147483648;
8+
public const short SIGN_BIT_16 = -32768;
9+
public const sbyte SIGN_BIT_8 = -128;
10+
11+
// Ceiling function that doesn't deal with floating point values
512
public static ulong CeilingExact(ulong u1, ulong u2) => (u1 / u2) + (u1 % u2 == 0 ? 0UL : 1UL);
6-
public static long CeilingExact(long u1, long u2) => (u1 / u2) + (u1 % u2 == 0 ? 0L : 1L);
13+
public static long CeilingExact(long u1, long u2) => (u1 / u2) + (u1 % u2 == 0 ? 0L : 1L | ((u1&SIGN_BIT_64)^(u2&SIGN_BIT_64)));
714
public static uint CeilingExact(uint u1, uint u2) => (u1 / u2) + (u1 % u2 == 0 ? 0U : 1U);
8-
public static int CeilingExact(int u1, int u2) => (u1 / u2) + (u1 % u2 == 0 ? 0 : 1);
15+
public static int CeilingExact(int u1, int u2) => (u1 / u2) + (u1 % u2 == 0 ? 0 : 1 | ((u1 & SIGN_BIT_32) ^ (u2 & SIGN_BIT_32)));
916
public static ushort CeilingExact(ushort u1, ushort u2) => (ushort)((u1 / u2) + (u1 % u2 == 0 ? 0 : 1));
10-
public static short CeilingExact(short u1, short u2) => (short)((u1 / u2) + (u1 % u2 == 0 ? 0 : 1));
17+
public static short CeilingExact(short u1, short u2) => (short)((u1 / u2) + (u1 % u2 == 0 ? 0 : 1 | ((u1 & SIGN_BIT_32) ^ (u2 & SIGN_BIT_32))));
1118
public static byte CeilingExact(byte u1, byte u2) => (byte)((u1 / u2) + (u1 % u2 == 0 ? 0 : 1));
12-
public static sbyte CeilingExact(sbyte u1, sbyte u2) => (sbyte)((u1 / u2) + (u1 % u2 == 0 ? 0 : 1));
19+
public static sbyte CeilingExact(sbyte u1, sbyte u2) => (sbyte)((u1 / u2) + (u1 % u2 == 0 ? 0 : 1 | ((u1 & SIGN_BIT_32) ^ (u2 & SIGN_BIT_32))));
20+
21+
// ZigZag
1322
public static ulong ZigZagEncode(long value) => (ulong)((value >> 63) ^ (value << 1));
1423
public static long ZigZagDecode(ulong value) => (((long)(value >> 1) & 0x7FFFFFFFFFFFFFFFL) ^ ((long)(value << 63) >> 63));
24+
25+
// Var int helper stuff
26+
public static int VarIntSize(ulong value) =>
27+
value <= 240 ? 1 :
28+
value <= 2287 ? 2 :
29+
value <= 67823 ? 3 :
30+
value <= 16777215 ? 4 :
31+
value <= 4294967295 ? 5 :
32+
value <= 1099511627775 ? 6 :
33+
value <= 281474976710655 ? 7 :
34+
value <= 72057594037927935 ? 8 :
35+
9;
1536
}
1637
}

MLAPI/NetworkingManagerComponents/Binary/BitStream.cs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,14 @@ namespace MLAPI.NetworkingManagerComponents.Binary
99
{
1010
public sealed class BitStream : Stream
1111
{
12-
private const long SIGN_BIT = -9223372036854775808;
13-
14-
1512
private readonly double growthFactor;
1613
private readonly byte[] target;
1714

1815
public BitStream(byte[] target, double growthFactor = 2.0)
1916
{
2017
this.target = target;
2118
this.growthFactor = growthFactor <= 1 ? 1.5 : growthFactor;
19+
BitLength = (ulong)target.LongLength << 3;
2220
}
2321

2422
public override bool CanRead => BitPosition < (ulong) target.LongLength;
@@ -27,8 +25,9 @@ public BitStream(byte[] target, double growthFactor = 2.0)
2725

2826
public override bool CanWrite => true;
2927

30-
public override long Length => (long) (BitLength>>3);
28+
public override long Length => (long) ((BitLength>>3) + ((BitLength&1UL)|((BitLength>>1)&1UL)|((BitLength>>2)&1UL))); // Optimized CeilingExact
3129

30+
private long BitWriteIndex { get => (long)((BitPosition >> 3) + ((BitPosition & 1UL) | ((BitPosition >> 1) & 1UL) | ((BitPosition >> 2) & 1UL))); }
3231
public override long Position { get => (long)(BitPosition>>3); set => BitPosition = (ulong)value << 3; }
3332
public ulong BitPosition { get; set; }
3433
public ulong BitLength { get; private set; }
@@ -60,9 +59,9 @@ public override long Seek(long offset, SeekOrigin origin)
6059
origin == SeekOrigin.Current ?
6160
offset > 0 ?
6261
Math.Min(BitPosition + ((ulong)offset << 3), (ulong)target.Length << 3) :
63-
(offset ^ SIGN_BIT) > Position ?
62+
(offset ^ SIGN_BIT_64) > Position ?
6463
0UL :
65-
BitPosition - (ulong)((offset ^ SIGN_BIT) << 3) :
64+
BitPosition - (ulong)((offset ^ SIGN_BIT_64) << 3) :
6665
origin == SeekOrigin.Begin ?
6766
(ulong)Math.Max(0, offset) << 3 :
6867
(ulong)Math.Max(target.Length - offset, 0) << 3
@@ -93,7 +92,7 @@ public override void Write(byte[] buffer, int offset, int count)
9392
}
9493
}
9594

96-
private void Grow(int newContent) => SetLength(target.LongLength * (long)Math.Pow(growthFactor, CeilingExact(newContent, target.Length)));
95+
private void Grow(int newContent) => SetLength(Math.Max(target.LongLength, 1) * (long)Math.Pow(growthFactor, CeilingExact(newContent, Math.Max(target.Length, 1))));
9796

9897
public void WriteBit(bool bit)
9998
{
@@ -138,6 +137,8 @@ public void WriteUInt64(ulong value)
138137
public void WriteInt64Packed(long value) => WriteUInt64(ZigZagEncode(value));
139138
public void WriteUInt64Packed(ulong value)
140139
{
140+
int grow = VarIntSize(value);
141+
if (BitWriteIndex + grow >= target.LongLength) Grow(grow);
141142
if (value <= 240) WriteULongByte(value);
142143
else if (value <= 2287)
143144
{
@@ -206,6 +207,7 @@ public ulong ReadUInt64Packed()
206207
while (hdr > ++cmp) res |= (ulong)_ReadByte() << (cmp << 3);
207208
return res;
208209
}
210+
public bool ReadBit() => (target[Position] & (1 << (int)(BitPosition++ & 7))) != 0;
209211

210212

211213
private void WriteULongByteMisaligned(ulong value) => WriteMisaligned((byte)value);
@@ -222,12 +224,15 @@ private void WriteMisaligned(byte value)
222224
private void WriteULongByte(ulong byteValue) => WriteByte((byte)byteValue);
223225
public override void WriteByte(byte value)
224226
{
227+
if (Position == target.LongLength) Grow(1);
225228
if (BitAligned)
226229
{
227230
target[Position] = value;
228231
++Position;
229232
}
230233
else WriteMisaligned(value);
231234
}
235+
236+
public byte[] GetBuffer() => target;
232237
}
233238
}

0 commit comments

Comments
 (0)