Add narrow and wide reading helpers

This commit is contained in:
Matt Nadareski
2024-04-29 12:30:49 -04:00
parent 32cab49bae
commit 39bf9c19ad
3 changed files with 138 additions and 186 deletions

View File

@@ -352,16 +352,8 @@ namespace SabreTools.IO.Extensions
if (reader.BaseStream.Position >= reader.BaseStream.Length)
return null;
List<byte> buffer = [];
while (reader.BaseStream.Position < reader.BaseStream.Length)
{
byte ch = reader.ReadByte();
buffer.Add(ch);
if (ch == '\0')
break;
}
return Encoding.ASCII.GetString([.. buffer]);
byte[] buffer = ReadUntilNullNarrow(reader);
return Encoding.ASCII.GetString(buffer);
}
/// <summary>
@@ -372,16 +364,8 @@ namespace SabreTools.IO.Extensions
if (reader.BaseStream.Position >= reader.BaseStream.Length)
return null;
List<byte> buffer = [];
while (reader.BaseStream.Position < reader.BaseStream.Length)
{
byte[] ch = reader.ReadBytes(2);
buffer.AddRange(ch);
if (ch[0] == '\0' && ch[1] == '\0')
break;
}
return Encoding.Unicode.GetString([.. buffer]);
byte[] buffer = ReadUntilNullWide(reader);
return Encoding.Unicode.GetString(buffer);
}
/// <summary>
@@ -635,59 +619,59 @@ namespace SabreTools.IO.Extensions
case UnmanagedType.LPStr:
case UnmanagedType.LPTStr: // Technically distinct; possibly not null-terminated
case null:
var lpstrBytes = new List<byte>();
while (true)
{
byte next = reader.ReadByte();
if (next == 0x00)
break;
lpstrBytes.Add(next);
if (reader.BaseStream.Position >= reader.BaseStream.Length)
break;
}
return Encoding.ASCII.GetString([.. lpstrBytes]);
var lpstrBytes = ReadUntilNullNarrow(reader);
return Encoding.ASCII.GetString(lpstrBytes);
#if NET472_OR_GREATER || NETCOREAPP
case UnmanagedType.LPUTF8Str:
var lputf8Str = new List<byte>();
while (true)
{
byte next = reader.ReadByte();
if (next == 0x00)
break;
lputf8Str.Add(next);
if (reader.BaseStream.Position >= reader.BaseStream.Length)
break;
}
return Encoding.UTF8.GetString([.. lputf8Str]);
var lputf8Str = ReadUntilNullNarrow(reader);
return Encoding.UTF8.GetString(lputf8Str);
#endif
case UnmanagedType.LPWStr:
var lpwstrBytes = new List<byte>();
while (true)
{
ushort next = reader.ReadUInt16();
if (next == 0x0000)
break;
lpwstrBytes.AddRange(BitConverter.GetBytes(next));
if (reader.BaseStream.Position >= reader.BaseStream.Length)
break;
}
return Encoding.Unicode.GetString([.. lpwstrBytes]);
var lpwstrBytes = ReadUntilNullWide(reader);
return Encoding.Unicode.GetString(lpwstrBytes);
// No other string types are recognized
default:
return null;
}
}
/// <summary>
/// Read bytes until a 1-byte null terminator is found
/// </summary>
private static byte[] ReadUntilNullNarrow(BinaryReader reader)
{
var bytes = new List<byte>();
while (reader.BaseStream.Position < reader.BaseStream.Length)
{
byte next = reader.ReadByte();
if (next == 0x00)
break;
bytes.Add(next);
}
return [.. bytes];
}
/// <summary>
/// Read bytes until a 2-byte null terminator is found
/// </summary>
private static byte[] ReadUntilNullWide(BinaryReader reader)
{
var bytes = new List<byte>();
while (reader.BaseStream.Position < reader.BaseStream.Length)
{
ushort next = reader.ReadUInt16();
if (next == 0x0000)
break;
bytes.AddRange(BitConverter.GetBytes(next));
}
return [.. bytes];
}
}
}

View File

@@ -480,16 +480,8 @@ namespace SabreTools.IO.Extensions
if (offset >= content.Length)
return null;
List<byte> buffer = [];
while (offset < content.Length)
{
byte ch = content.ReadByteValue(ref offset);
buffer.Add(ch);
if (ch == '\0')
break;
}
return Encoding.ASCII.GetString([.. buffer]);
byte[] buffer = ReadUntilNullNarrow(content, ref offset);
return Encoding.ASCII.GetString(buffer);
}
/// <summary>
@@ -500,16 +492,8 @@ namespace SabreTools.IO.Extensions
if (offset >= content.Length)
return null;
List<byte> buffer = [];
while (offset < content.Length)
{
byte[] ch = content.ReadBytes(ref offset, 2);
buffer.AddRange(ch);
if (ch[0] == '\0' && ch[1] == '\0')
break;
}
return Encoding.Unicode.GetString([.. buffer]);
byte[] buffer = ReadUntilNullWide(content, ref offset);
return Encoding.Unicode.GetString(buffer);
}
/// <summary>
@@ -763,54 +747,18 @@ namespace SabreTools.IO.Extensions
case UnmanagedType.LPStr:
case UnmanagedType.LPTStr: // Technically distinct; possibly not null-terminated
case null:
var lpstrBytes = new List<byte>();
while (true)
{
byte next = content.ReadByteValue(ref offset);
if (next == 0x00)
break;
lpstrBytes.Add(next);
if (offset >= content.Length)
break;
}
return Encoding.ASCII.GetString([.. lpstrBytes]);
var lpstrBytes = ReadUntilNullNarrow(content, ref offset);
return Encoding.ASCII.GetString(lpstrBytes);
#if NET472_OR_GREATER || NETCOREAPP
case UnmanagedType.LPUTF8Str:
var lputf8Str = new List<byte>();
while (true)
{
byte next = content.ReadByteValue(ref offset);
if (next == 0x00)
break;
lputf8Str.Add(next);
if (offset >= content.Length)
break;
}
return Encoding.UTF8.GetString([.. lputf8Str]);
var lputf8Str = ReadUntilNullNarrow(content, ref offset);
return Encoding.UTF8.GetString(lputf8Str);
#endif
case UnmanagedType.LPWStr:
var lpwstrBytes = new List<byte>();
while (true)
{
ushort next = content.ReadUInt16(ref offset);
if (next == 0x0000)
break;
lpwstrBytes.AddRange(BitConverter.GetBytes(next));
if (offset >= content.Length)
break;
}
return Encoding.Unicode.GetString([.. lpwstrBytes]);
var lpwstrBytes = ReadUntilNullWide(content, ref offset);
return Encoding.Unicode.GetString(lpwstrBytes);
// No other string types are recognized
default:
@@ -818,6 +766,42 @@ namespace SabreTools.IO.Extensions
}
}
/// <summary>
/// Read bytes until a 1-byte null terminator is found
/// </summary>
private static byte[] ReadUntilNullNarrow(byte[] content, ref int offset)
{
var bytes = new List<byte>();
while (offset < content.Length)
{
byte next = content.ReadByte(ref offset);
if (next == 0x00)
break;
bytes.Add(next);
}
return [.. bytes];
}
/// <summary>
/// Read bytes until a 2-byte null terminator is found
/// </summary>
private static byte[] ReadUntilNullWide(byte[] content, ref int offset)
{
var bytes = new List<byte>();
while (offset < content.Length)
{
ushort next = content.ReadUInt16(ref offset);
if (next == 0x0000)
break;
bytes.AddRange(BitConverter.GetBytes(next));
}
return [.. bytes];
}
/// <summary>
/// Read a number of bytes from the byte array to a buffer
/// </summary>

View File

@@ -464,16 +464,8 @@ namespace SabreTools.IO.Extensions
if (stream.Position >= stream.Length)
return null;
List<byte> buffer = [];
while (stream.Position < stream.Length)
{
byte ch = stream.ReadByteValue();
buffer.Add(ch);
if (ch == '\0')
break;
}
return Encoding.ASCII.GetString([.. buffer]);
byte[] buffer = ReadUntilNullNarrow(stream);
return Encoding.ASCII.GetString(buffer);
}
/// <summary>
@@ -484,16 +476,8 @@ namespace SabreTools.IO.Extensions
if (stream.Position >= stream.Length)
return null;
List<byte> buffer = [];
while (stream.Position < stream.Length)
{
byte[] ch = stream.ReadBytes(2);
buffer.AddRange(ch);
if (ch[0] == '\0' && ch[1] == '\0')
break;
}
return Encoding.Unicode.GetString([.. buffer]);
byte[] buffer = ReadUntilNullWide(stream);
return Encoding.Unicode.GetString(buffer);
}
/// <summary>
@@ -747,54 +731,18 @@ namespace SabreTools.IO.Extensions
case UnmanagedType.LPStr:
case UnmanagedType.LPTStr: // Technically distinct; possibly not null-terminated
case null:
var lpstrBytes = new List<byte>();
while (true)
{
byte next = stream.ReadByteValue();
if (next == 0x00)
break;
lpstrBytes.Add(next);
if (stream.Position >= stream.Length)
break;
}
return Encoding.ASCII.GetString([.. lpstrBytes]);
var lpstrBytes = ReadUntilNullNarrow(stream);
return Encoding.ASCII.GetString(lpstrBytes);
#if NET472_OR_GREATER || NETCOREAPP
case UnmanagedType.LPUTF8Str:
var lputf8Str = new List<byte>();
while (true)
{
byte next = stream.ReadByteValue();
if (next == 0x00)
break;
lputf8Str.Add(next);
if (stream.Position >= stream.Length)
break;
}
return Encoding.UTF8.GetString([.. lputf8Str]);
var lputf8Str = ReadUntilNullNarrow(stream);
return Encoding.UTF8.GetString(lputf8Str);
#endif
case UnmanagedType.LPWStr:
var lpwstrBytes = new List<byte>();
while (true)
{
ushort next = stream.ReadUInt16();
if (next == 0x0000)
break;
lpwstrBytes.AddRange(BitConverter.GetBytes(next));
if (stream.Position >= stream.Length)
break;
}
return Encoding.Unicode.GetString([.. lpwstrBytes]);
var lpwstrBytes = ReadUntilNullWide(stream);
return Encoding.Unicode.GetString(lpwstrBytes);
// No other string types are recognized
default:
@@ -802,6 +750,42 @@ namespace SabreTools.IO.Extensions
}
}
/// <summary>
/// Read bytes until a 1-byte null terminator is found
/// </summary>
private static byte[] ReadUntilNullNarrow(Stream stream)
{
var bytes = new List<byte>();
while (stream.Position < stream.Length)
{
byte next = stream.ReadByteValue();
if (next == 0x00)
break;
bytes.Add(next);
}
return [.. bytes];
}
/// <summary>
/// Read bytes until a 2-byte null terminator is found
/// </summary>
private static byte[] ReadUntilNullWide(Stream stream)
{
var bytes = new List<byte>();
while (stream.Position < stream.Length)
{
ushort next = stream.ReadUInt16();
if (next == 0x0000)
break;
bytes.AddRange(BitConverter.GetBytes(next));
}
return [.. bytes];
}
/// <summary>
/// Read a number of bytes from the stream to a buffer
/// </summary>