Skip to content

Commit 48d4560

Browse files
committed
Optimize reading binary strings
Fixes #98
1 parent 9e78198 commit 48d4560

File tree

1 file changed

+35
-9
lines changed

1 file changed

+35
-9
lines changed

ValveKeyValue/ValveKeyValue/Deserialization/KeyValues1/KV1BinaryReader.cs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Buffers;
12
using System.Text;
23
using ValveKeyValue.Abstraction;
34
using ValveKeyValue.KeyValues1;
@@ -84,7 +85,7 @@ string ReadKeyForNextValue()
8485
return stringTable[index];
8586
}
8687

87-
return Encoding.UTF8.GetString(ReadNullTerminatedBytes());
88+
return ReadNullTerminatedUtf8String();
8889
}
8990

9091
void ReadValue(KV1BinaryNodeType type)
@@ -102,7 +103,7 @@ void ReadValue(KV1BinaryNodeType type)
102103

103104
case KV1BinaryNodeType.String:
104105
// UTF8 encoding is used for string values
105-
value = new KVObjectValue<string>(Encoding.UTF8.GetString(ReadNullTerminatedBytes()), KVValueType.String);
106+
value = new KVObjectValue<string>(ReadNullTerminatedUtf8String(), KVValueType.String);
106107
break;
107108

108109
case KV1BinaryNodeType.WideString:
@@ -137,16 +138,41 @@ void ReadValue(KV1BinaryNodeType type)
137138
listener.OnKeyValuePair(name, value);
138139
}
139140

140-
byte[] ReadNullTerminatedBytes()
141+
string ReadNullTerminatedUtf8String()
141142
{
142-
using var mem = new MemoryStream();
143-
byte nextByte;
144-
while ((nextByte = reader.ReadByte()) != 0)
143+
var buffer = ArrayPool<byte>.Shared.Rent(32);
144+
145+
try
145146
{
146-
mem.WriteByte(nextByte);
147+
var position = 0;
148+
149+
do
150+
{
151+
var b = reader.ReadByte();
152+
153+
if (b <= 0) // null byte or stream ended
154+
{
155+
break;
156+
}
157+
158+
if (position >= buffer.Length)
159+
{
160+
var newBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length * 2);
161+
Buffer.BlockCopy(buffer, 0, newBuffer, 0, buffer.Length);
162+
ArrayPool<byte>.Shared.Return(buffer);
163+
buffer = newBuffer;
164+
}
165+
166+
buffer[position++] = b;
167+
}
168+
while (true);
169+
170+
return Encoding.UTF8.GetString(buffer[..position]);
171+
}
172+
finally
173+
{
174+
ArrayPool<byte>.Shared.Return(buffer);
147175
}
148-
149-
return mem.ToArray();
150176
}
151177

152178
void DetectMagicHeader()

0 commit comments

Comments
 (0)