Skip to content

Commit 6542585

Browse files
Added and write Strings to BitStream
Added tests for reading and writing strings
1 parent 5ce43ae commit 6542585

File tree

2 files changed

+232
-12
lines changed

2 files changed

+232
-12
lines changed

MLAPI.Tests/NetworkingManagerComponents/Binary/BitStreamTest.cs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ namespace MLAPI.Tests.NetworkingManagerComponents.Binary
33
{
44
using MLAPI.NetworkingManagerComponents.Binary;
55
using NUnit.Framework;
6+
using System.Text;
67

78
[TestFixture]
89
public class BitStreamTest
@@ -552,5 +553,81 @@ public void TestArraysPackedDiff()
552553
Assert.That(intInData, Is.EqualTo(intOutData));
553554
Assert.That(doubleInData, Is.EqualTo(doubleOutData));
554555
}
556+
557+
[Test]
558+
public void TestString()
559+
{
560+
string testString = "Hello, World";
561+
BitStream outStream = new BitStream();
562+
outStream.WriteString(testString);
563+
outStream.WriteString(testString, true);
564+
565+
BitStream inStream = new BitStream(outStream.GetBuffer());
566+
StringBuilder readBuilder = inStream.ReadString();
567+
StringBuilder readBuilderSingle = inStream.ReadString(true);
568+
569+
Assert.That(readBuilder.ToString(), Is.EqualTo(testString));
570+
Assert.That(readBuilderSingle.ToString(), Is.EqualTo(testString));
571+
}
572+
573+
[Test]
574+
public void TestStringPacked()
575+
{
576+
string testString = "Hello, World";
577+
BitStream outStream = new BitStream();
578+
outStream.WriteStringPacked(testString);
579+
580+
BitStream inStream = new BitStream(outStream.GetBuffer());
581+
StringBuilder readBuilder = inStream.ReadStringPacked();
582+
583+
Assert.That(readBuilder.ToString(), Is.EqualTo(testString));
584+
}
585+
586+
[Test]
587+
public void TestStringDiff()
588+
{
589+
string testString = "Hello, World"; // The simulated "new" value of testString
590+
string originalString = "Heyo, World"; // This is what testString supposedly changed *from*
591+
BitStream outStream = new BitStream();
592+
outStream.WriteStringDiff(testString, originalString);
593+
outStream.WriteStringDiff(testString, originalString, true);
594+
595+
BitStream inStream = new BitStream(outStream.GetBuffer());
596+
// Read regular diff
597+
StringBuilder readBuilder = inStream.ReadStringDiff(originalString);
598+
599+
// Read diff directly to StringBuilder
600+
inStream.BitPosition = 0;
601+
StringBuilder stringCompare = new StringBuilder(originalString);
602+
inStream.ReadStringDiff(stringCompare);
603+
604+
// Read single-byte diff
605+
StringBuilder byteBuilder = inStream.ReadStringDiff(originalString, true);
606+
607+
Assert.That(readBuilder.ToString(), Is.EqualTo(testString));
608+
Assert.That(stringCompare.ToString(), Is.EqualTo(testString));
609+
Assert.That(byteBuilder.ToString(), Is.EqualTo(testString));
610+
}
611+
612+
[Test]
613+
public void TestStringPackedDiff()
614+
{
615+
string testString = "Hello, World"; // The simulated "new" value of testString
616+
string originalString = "Heyo, World"; // This is what testString supposedly changed *from*
617+
BitStream outStream = new BitStream();
618+
outStream.WriteStringPackedDiff(testString, originalString);
619+
620+
BitStream inStream = new BitStream(outStream.GetBuffer());
621+
// Read regular diff
622+
StringBuilder readBuilder = inStream.ReadStringPackedDiff(originalString);
623+
624+
// Read diff directly to StringBuilder
625+
inStream.BitPosition = 0;
626+
StringBuilder stringCompare = new StringBuilder(originalString);
627+
inStream.ReadStringPackedDiff(stringCompare);
628+
629+
Assert.That(readBuilder.ToString(), Is.EqualTo(testString));
630+
Assert.That(stringCompare.ToString(), Is.EqualTo(testString));
631+
}
555632
}
556633
}

MLAPI/NetworkingManagerComponents/Binary/BitStream.cs

Lines changed: 155 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,14 +1137,16 @@ public override void WriteByte(byte value)
11371137
// As it turns out, strings cannot be treated as char arrays, since strings use pointers to store data rather than C# arrays
11381138
public void WriteString(string s, bool oneByteChars = false)
11391139
{
1140-
WriteUInt64Packed((ulong)s.Length * (oneByteChars ? 1UL : 2UL));
1140+
WriteUInt32Packed((uint)s.Length);
11411141
int target = s.Length;
1142-
for (int i = 0; i < target; ++i) WriteChar(s[i]);
1142+
for (int i = 0; i < target; ++i)
1143+
if (oneByteChars) WriteByte((byte)s[i]);
1144+
else WriteChar(s[i]);
11431145
}
11441146

1145-
public void WriteStringPacked(string s, bool oneByteChars = false)
1147+
public void WriteStringPacked(string s)
11461148
{
1147-
WriteUInt64Packed((ulong)s.Length * (oneByteChars ? 1UL : 2UL));
1149+
WriteUInt32Packed((uint)s.Length);
11481150
int target = s.Length;
11491151
for (int i = 0; i < target; ++i) WriteCharPacked(s[i]);
11501152
}
@@ -1154,7 +1156,7 @@ public void WriteStringDiff(string write, string compare, bool oneByteChars = fa
11541156
#if !ARRAY_DIFF_ALLOW_RESIZE
11551157
if (write.Length != compare.Length) throw new ArgumentException("Mismatched string lengths");
11561158
#endif
1157-
WriteUInt64Packed((ulong)write.Length * (oneByteChars ? 1UL : 2UL));
1159+
WriteUInt32Packed((uint)write.Length);
11581160

11591161
// Premapping
11601162
#if ARRAY_WRITE_PREMAP
@@ -1181,13 +1183,13 @@ public void WriteStringDiff(string write, string compare, bool oneByteChars = fa
11811183
}
11821184
}
11831185

1184-
public void WriteStringPackedDiff(string write, string compare, bool oneByteChars = false)
1186+
public void WriteStringPackedDiff(string write, string compare)
11851187
{
11861188

11871189
#if !ARRAY_DIFF_ALLOW_RESIZE
11881190
if (write.Length != compare.Length) throw new ArgumentException("Mismatched string lengths");
11891191
#endif
1190-
WriteUInt64Packed((ulong)write.Length * (oneByteChars ? 1UL : 2UL));
1192+
WriteUInt32Packed((uint)write.Length);
11911193

11921194
// Premapping
11931195
#if ARRAY_WRITE_PREMAP
@@ -1206,11 +1208,7 @@ public void WriteStringPackedDiff(string write, string compare, bool oneByteChar
12061208
#if !ARRAY_WRITE_PREMAP
12071209
WriteBit(!b);
12081210
#endif
1209-
if (b)
1210-
{
1211-
if (oneByteChars) WriteByte((byte)write[i]);
1212-
else WriteCharPacked(write[i]);
1213-
}
1211+
if (b) WriteCharPacked(write[i]);
12141212
}
12151213
}
12161214

@@ -1691,6 +1689,151 @@ public void WriteDoubleArrayPackedDiff(double[] write, double[] compare, long co
16911689

16921690

16931691
// Read arrays
1692+
public StringBuilder ReadString(bool oneByteChars) => ReadString(null, oneByteChars);
1693+
public StringBuilder ReadString(StringBuilder builder = null, bool oneByteChars = false)
1694+
{
1695+
int expectedLength = (int)ReadUInt32Packed();
1696+
if (builder == null) builder = new StringBuilder(expectedLength);
1697+
else if (builder.Capacity + builder.Length < expectedLength) builder.Capacity = expectedLength + builder.Length;
1698+
for (int i = 0; i < expectedLength; ++i)
1699+
builder.Insert(i, oneByteChars ? (char)_ReadByte() : ReadChar());
1700+
return builder;
1701+
}
1702+
1703+
public StringBuilder ReadStringPacked(StringBuilder builder = null)
1704+
{
1705+
int expectedLength = (int)ReadUInt32Packed();
1706+
if (builder == null) builder = new StringBuilder(expectedLength);
1707+
else if (builder.Capacity + builder.Length < expectedLength) builder.Capacity = expectedLength + builder.Length;
1708+
for (int i = 0; i < expectedLength; ++i)
1709+
builder.Insert(i, ReadCharPacked());
1710+
return builder;
1711+
}
1712+
1713+
public StringBuilder ReadStringDiff(string compare, bool oneByteChars = false) => ReadStringDiff(null, compare, oneByteChars);
1714+
public StringBuilder ReadStringDiff(StringBuilder builder, string compare, bool oneByteChars = false)
1715+
{
1716+
int expectedLength = (int)ReadUInt32Packed();
1717+
if (builder == null) builder = new StringBuilder(expectedLength);
1718+
else if (builder.Capacity < expectedLength) builder.Capacity = expectedLength;
1719+
ulong dBlockStart = BitPosition + (ulong)(compare == null ? 0 : Math.Min(expectedLength, compare.Length));
1720+
ulong mapStart;
1721+
int compareLength = compare == null ? 0 : compare.Length;
1722+
for (int i = 0; i < expectedLength; ++i)
1723+
{
1724+
if (i >= compareLength || ReadBit())
1725+
{
1726+
#if ARRAY_WRITE_PREMAP
1727+
// Move to data section
1728+
mapStart = BitPosition;
1729+
BitPosition = dBlockStart;
1730+
#endif
1731+
// Read datum
1732+
builder.Insert(i, oneByteChars ? (char)_ReadByte() : ReadChar());
1733+
#if ARRAY_WRITE_PREMAP
1734+
dBlockStart = BitPosition;
1735+
// Return to mapping section
1736+
BitPosition = mapStart;
1737+
#endif
1738+
}
1739+
else if (i < compareLength) builder.Insert(i, compare[i]);
1740+
}
1741+
BitPosition = dBlockStart;
1742+
return builder;
1743+
}
1744+
1745+
public StringBuilder ReadStringDiff(StringBuilder compareAndBuffer, bool oneByteChars = false)
1746+
{
1747+
int expectedLength = (int)ReadUInt32Packed();
1748+
if (compareAndBuffer == null) throw new ArgumentNullException("Buffer cannot be null");
1749+
else if (compareAndBuffer.Capacity < expectedLength) compareAndBuffer.Capacity = expectedLength;
1750+
ulong dBlockStart = BitPosition + (ulong)Math.Min(expectedLength, compareAndBuffer.Length);
1751+
ulong mapStart;
1752+
for (int i = 0; i < expectedLength; ++i)
1753+
{
1754+
if (i >= compareAndBuffer.Length || ReadBit())
1755+
{
1756+
#if ARRAY_WRITE_PREMAP
1757+
// Move to data section
1758+
mapStart = BitPosition;
1759+
BitPosition = dBlockStart;
1760+
#endif
1761+
// Read datum
1762+
compareAndBuffer.Remove(i, 1);
1763+
compareAndBuffer.Insert(i, oneByteChars ? (char)_ReadByte() : ReadChar());
1764+
#if ARRAY_WRITE_PREMAP
1765+
dBlockStart = BitPosition;
1766+
// Return to mapping section
1767+
BitPosition = mapStart;
1768+
#endif
1769+
}
1770+
}
1771+
BitPosition = dBlockStart;
1772+
return compareAndBuffer;
1773+
}
1774+
1775+
public StringBuilder ReadStringPackedDiff(string compare) => ReadStringPackedDiff(null, compare);
1776+
public StringBuilder ReadStringPackedDiff(StringBuilder builder, string compare)
1777+
{
1778+
int expectedLength = (int)ReadUInt32Packed();
1779+
if (builder == null) builder = new StringBuilder(expectedLength);
1780+
else if (builder.Capacity < expectedLength) builder.Capacity = expectedLength;
1781+
ulong dBlockStart = BitPosition + (ulong)(compare == null ? 0 : Math.Min(expectedLength, compare.Length));
1782+
ulong mapStart;
1783+
int compareLength = compare == null ? 0 : compare.Length;
1784+
for (int i = 0; i < expectedLength; ++i)
1785+
{
1786+
if (i >= compareLength || ReadBit())
1787+
{
1788+
#if ARRAY_WRITE_PREMAP
1789+
// Move to data section
1790+
mapStart = BitPosition;
1791+
BitPosition = dBlockStart;
1792+
#endif
1793+
// Read datum
1794+
builder.Insert(i, ReadCharPacked());
1795+
#if ARRAY_WRITE_PREMAP
1796+
dBlockStart = BitPosition;
1797+
// Return to mapping section
1798+
BitPosition = mapStart;
1799+
#endif
1800+
}
1801+
else if (i < compareLength) builder.Insert(i, compare[i]);
1802+
}
1803+
BitPosition = dBlockStart;
1804+
return builder;
1805+
}
1806+
1807+
public StringBuilder ReadStringPackedDiff(StringBuilder compareAndBuffer)
1808+
{
1809+
int expectedLength = (int)ReadUInt32Packed();
1810+
if (compareAndBuffer == null) throw new ArgumentNullException("Buffer cannot be null");
1811+
else if (compareAndBuffer.Capacity < expectedLength) compareAndBuffer.Capacity = expectedLength;
1812+
ulong dBlockStart = BitPosition + (ulong)Math.Min(expectedLength, compareAndBuffer.Length);
1813+
ulong mapStart;
1814+
for (int i = 0; i < expectedLength; ++i)
1815+
{
1816+
if (i >= compareAndBuffer.Length || ReadBit())
1817+
{
1818+
#if ARRAY_WRITE_PREMAP
1819+
// Move to data section
1820+
mapStart = BitPosition;
1821+
BitPosition = dBlockStart;
1822+
#endif
1823+
// Read datum
1824+
compareAndBuffer.Remove(i, 1);
1825+
compareAndBuffer.Insert(i, ReadCharPacked());
1826+
#if ARRAY_WRITE_PREMAP
1827+
dBlockStart = BitPosition;
1828+
// Return to mapping section
1829+
BitPosition = mapStart;
1830+
#endif
1831+
}
1832+
}
1833+
BitPosition = dBlockStart;
1834+
return compareAndBuffer;
1835+
}
1836+
16941837
public byte[] ReadByteArray(byte[] readTo = null, long knownLength = -1)
16951838
{
16961839
if (knownLength < 0) knownLength = (long)ReadUInt64Packed();

0 commit comments

Comments
 (0)