From 39bf9c19ad82ad66b2622ca9292dff39ea2e0d99 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Mon, 29 Apr 2024 12:30:49 -0400 Subject: [PATCH] Add narrow and wide reading helpers --- .../Extensions/BinaryReaderExtensions.cs | 108 ++++++++---------- .../Extensions/ByteArrayReaderExtensions.cs | 108 ++++++++---------- .../Extensions/StreamReaderExtensions.cs | 108 ++++++++---------- 3 files changed, 138 insertions(+), 186 deletions(-) diff --git a/SabreTools.IO/Extensions/BinaryReaderExtensions.cs b/SabreTools.IO/Extensions/BinaryReaderExtensions.cs index 36f97de..54b4a62 100644 --- a/SabreTools.IO/Extensions/BinaryReaderExtensions.cs +++ b/SabreTools.IO/Extensions/BinaryReaderExtensions.cs @@ -352,16 +352,8 @@ namespace SabreTools.IO.Extensions if (reader.BaseStream.Position >= reader.BaseStream.Length) return null; - List 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); } /// @@ -372,16 +364,8 @@ namespace SabreTools.IO.Extensions if (reader.BaseStream.Position >= reader.BaseStream.Length) return null; - List 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); } /// @@ -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(); - 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(); - 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(); - 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; } } + + /// + /// Read bytes until a 1-byte null terminator is found + /// + private static byte[] ReadUntilNullNarrow(BinaryReader reader) + { + var bytes = new List(); + while (reader.BaseStream.Position < reader.BaseStream.Length) + { + byte next = reader.ReadByte(); + if (next == 0x00) + break; + + bytes.Add(next); + } + + return [.. bytes]; + } + + /// + /// Read bytes until a 2-byte null terminator is found + /// + private static byte[] ReadUntilNullWide(BinaryReader reader) + { + var bytes = new List(); + while (reader.BaseStream.Position < reader.BaseStream.Length) + { + ushort next = reader.ReadUInt16(); + if (next == 0x0000) + break; + + bytes.AddRange(BitConverter.GetBytes(next)); + } + + return [.. bytes]; + } } } diff --git a/SabreTools.IO/Extensions/ByteArrayReaderExtensions.cs b/SabreTools.IO/Extensions/ByteArrayReaderExtensions.cs index 5b6151f..52b02cc 100644 --- a/SabreTools.IO/Extensions/ByteArrayReaderExtensions.cs +++ b/SabreTools.IO/Extensions/ByteArrayReaderExtensions.cs @@ -480,16 +480,8 @@ namespace SabreTools.IO.Extensions if (offset >= content.Length) return null; - List 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); } /// @@ -500,16 +492,8 @@ namespace SabreTools.IO.Extensions if (offset >= content.Length) return null; - List 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); } /// @@ -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(); - 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(); - 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(); - 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 } } + /// + /// Read bytes until a 1-byte null terminator is found + /// + private static byte[] ReadUntilNullNarrow(byte[] content, ref int offset) + { + var bytes = new List(); + while (offset < content.Length) + { + byte next = content.ReadByte(ref offset); + if (next == 0x00) + break; + + bytes.Add(next); + } + + return [.. bytes]; + } + + /// + /// Read bytes until a 2-byte null terminator is found + /// + private static byte[] ReadUntilNullWide(byte[] content, ref int offset) + { + var bytes = new List(); + while (offset < content.Length) + { + ushort next = content.ReadUInt16(ref offset); + if (next == 0x0000) + break; + + bytes.AddRange(BitConverter.GetBytes(next)); + } + + return [.. bytes]; + } + /// /// Read a number of bytes from the byte array to a buffer /// diff --git a/SabreTools.IO/Extensions/StreamReaderExtensions.cs b/SabreTools.IO/Extensions/StreamReaderExtensions.cs index ff1a310..075b325 100644 --- a/SabreTools.IO/Extensions/StreamReaderExtensions.cs +++ b/SabreTools.IO/Extensions/StreamReaderExtensions.cs @@ -464,16 +464,8 @@ namespace SabreTools.IO.Extensions if (stream.Position >= stream.Length) return null; - List 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); } /// @@ -484,16 +476,8 @@ namespace SabreTools.IO.Extensions if (stream.Position >= stream.Length) return null; - List 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); } /// @@ -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(); - 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(); - 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(); - 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 } } + /// + /// Read bytes until a 1-byte null terminator is found + /// + private static byte[] ReadUntilNullNarrow(Stream stream) + { + var bytes = new List(); + while (stream.Position < stream.Length) + { + byte next = stream.ReadByteValue(); + if (next == 0x00) + break; + + bytes.Add(next); + } + + return [.. bytes]; + } + + /// + /// Read bytes until a 2-byte null terminator is found + /// + private static byte[] ReadUntilNullWide(Stream stream) + { + var bytes = new List(); + while (stream.Position < stream.Length) + { + ushort next = stream.ReadUInt16(); + if (next == 0x0000) + break; + + bytes.AddRange(BitConverter.GetBytes(next)); + } + + return [.. bytes]; + } + /// /// Read a number of bytes from the stream to a buffer ///