diff --git a/SabreTools.IO/Extensions/BinaryReaderExtensions.cs b/SabreTools.IO/Extensions/BinaryReaderExtensions.cs
index 53ed899..5a59f41 100644
--- a/SabreTools.IO/Extensions/BinaryReaderExtensions.cs
+++ b/SabreTools.IO/Extensions/BinaryReaderExtensions.cs
@@ -330,6 +330,8 @@ namespace SabreTools.IO.Extensions
return reader.ReadNullTerminatedUTF8String();
else if (encoding.Equals(Encoding.Unicode))
return reader.ReadNullTerminatedUnicodeString();
+ else if (encoding.Equals(Encoding.UTF32))
+ return reader.ReadNullTerminatedUTF32String();
if (reader.BaseStream.Position >= reader.BaseStream.Length)
return null;
@@ -354,7 +356,7 @@ namespace SabreTools.IO.Extensions
if (reader.BaseStream.Position >= reader.BaseStream.Length)
return null;
- byte[] buffer = ReadUntilNullNarrow(reader);
+ byte[] buffer = ReadUntilNull1Byte(reader);
return Encoding.ASCII.GetString(buffer);
}
@@ -366,7 +368,7 @@ namespace SabreTools.IO.Extensions
if (reader.BaseStream.Position >= reader.BaseStream.Length)
return null;
- byte[] buffer = ReadUntilNullNarrow(reader);
+ byte[] buffer = ReadUntilNull1Byte(reader);
return Encoding.ASCII.GetString(buffer);
}
@@ -378,7 +380,19 @@ namespace SabreTools.IO.Extensions
if (reader.BaseStream.Position >= reader.BaseStream.Length)
return null;
- byte[] buffer = ReadUntilNullWide(reader);
+ byte[] buffer = ReadUntilNull2Byte(reader);
+ return Encoding.Unicode.GetString(buffer);
+ }
+
+ ///
+ /// Read a null-terminated UTF-32 string from the underlying stream
+ ///
+ public static string? ReadNullTerminatedUTF32String(this BinaryReader reader)
+ {
+ if (reader.BaseStream.Position >= reader.BaseStream.Length)
+ return null;
+
+ byte[] buffer = ReadUntilNull4Byte(reader);
return Encoding.Unicode.GetString(buffer);
}
@@ -648,7 +662,7 @@ namespace SabreTools.IO.Extensions
///
/// Read bytes until a 1-byte null terminator is found
///
- private static byte[] ReadUntilNullNarrow(BinaryReader reader)
+ private static byte[] ReadUntilNull1Byte(BinaryReader reader)
{
var bytes = new List();
while (reader.BaseStream.Position < reader.BaseStream.Length)
@@ -666,7 +680,7 @@ namespace SabreTools.IO.Extensions
///
/// Read bytes until a 2-byte null terminator is found
///
- private static byte[] ReadUntilNullWide(BinaryReader reader)
+ private static byte[] ReadUntilNull2Byte(BinaryReader reader)
{
var bytes = new List();
while (reader.BaseStream.Position < reader.BaseStream.Length)
@@ -680,5 +694,23 @@ namespace SabreTools.IO.Extensions
return [.. bytes];
}
+
+ ///
+ /// Read bytes until a 4-byte null terminator is found
+ ///
+ private static byte[] ReadUntilNull4Byte(BinaryReader reader)
+ {
+ var bytes = new List();
+ while (reader.BaseStream.Position < reader.BaseStream.Length)
+ {
+ uint next = reader.ReadUInt32();
+ if (next == 0x00000000)
+ break;
+
+ bytes.AddRange(BitConverter.GetBytes(next));
+ }
+
+ return [.. bytes];
+ }
}
}
diff --git a/SabreTools.IO/Extensions/ByteArrayReaderExtensions.cs b/SabreTools.IO/Extensions/ByteArrayReaderExtensions.cs
index fa1775e..d33ae38 100644
--- a/SabreTools.IO/Extensions/ByteArrayReaderExtensions.cs
+++ b/SabreTools.IO/Extensions/ByteArrayReaderExtensions.cs
@@ -458,6 +458,8 @@ namespace SabreTools.IO.Extensions
return content.ReadNullTerminatedUTF8String(ref offset);
else if (encoding.Equals(Encoding.Unicode))
return content.ReadNullTerminatedUnicodeString(ref offset);
+ else if (encoding.Equals(Encoding.UTF32))
+ return content.ReadNullTerminatedUTF32String(ref offset);
if (offset >= content.Length)
return null;
@@ -482,7 +484,7 @@ namespace SabreTools.IO.Extensions
if (offset >= content.Length)
return null;
- byte[] buffer = ReadUntilNullNarrow(content, ref offset);
+ byte[] buffer = ReadUntilNull1Byte(content, ref offset);
return Encoding.ASCII.GetString(buffer);
}
@@ -494,7 +496,7 @@ namespace SabreTools.IO.Extensions
if (offset >= content.Length)
return null;
- byte[] buffer = ReadUntilNullNarrow(content, ref offset);
+ byte[] buffer = ReadUntilNull1Byte(content, ref offset);
return Encoding.UTF8.GetString(buffer);
}
@@ -506,7 +508,19 @@ namespace SabreTools.IO.Extensions
if (offset >= content.Length)
return null;
- byte[] buffer = ReadUntilNullWide(content, ref offset);
+ byte[] buffer = ReadUntilNull2Byte(content, ref offset);
+ return Encoding.Unicode.GetString(buffer);
+ }
+
+ ///
+ /// Read a null-terminated UTF-32 string from the byte array
+ ///
+ public static string? ReadNullTerminatedUTF32String(this byte[] content, ref int offset)
+ {
+ if (offset >= content.Length)
+ return null;
+
+ byte[] buffer = ReadUntilNull4Byte(content, ref offset);
return Encoding.Unicode.GetString(buffer);
}
@@ -776,7 +790,7 @@ namespace SabreTools.IO.Extensions
///
/// Read bytes until a 1-byte null terminator is found
///
- private static byte[] ReadUntilNullNarrow(byte[] content, ref int offset)
+ private static byte[] ReadUntilNull1Byte(byte[] content, ref int offset)
{
var bytes = new List();
while (offset < content.Length)
@@ -794,7 +808,7 @@ namespace SabreTools.IO.Extensions
///
/// Read bytes until a 2-byte null terminator is found
///
- private static byte[] ReadUntilNullWide(byte[] content, ref int offset)
+ private static byte[] ReadUntilNull2Byte(byte[] content, ref int offset)
{
var bytes = new List();
while (offset < content.Length)
@@ -809,6 +823,24 @@ namespace SabreTools.IO.Extensions
return [.. bytes];
}
+ ///
+ /// Read bytes until a 4-byte null terminator is found
+ ///
+ private static byte[] ReadUntilNull4Byte(byte[] content, ref int offset)
+ {
+ var bytes = new List();
+ while (offset < content.Length)
+ {
+ uint next = content.ReadUInt32(ref offset);
+ if (next == 0x00000000)
+ 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 6ce5ae0..8d23977 100644
--- a/SabreTools.IO/Extensions/StreamReaderExtensions.cs
+++ b/SabreTools.IO/Extensions/StreamReaderExtensions.cs
@@ -442,6 +442,8 @@ namespace SabreTools.IO.Extensions
return stream.ReadNullTerminatedUTF8String();
else if (encoding.Equals(Encoding.Unicode))
return stream.ReadNullTerminatedUnicodeString();
+ else if (encoding.Equals(Encoding.UTF32))
+ return stream.ReadNullTerminatedUTF32String();
if (stream.Position >= stream.Length)
return null;
@@ -466,7 +468,7 @@ namespace SabreTools.IO.Extensions
if (stream.Position >= stream.Length)
return null;
- byte[] buffer = ReadUntilNullNarrow(stream);
+ byte[] buffer = ReadUntilNull1Byte(stream);
return Encoding.ASCII.GetString(buffer);
}
@@ -478,7 +480,7 @@ namespace SabreTools.IO.Extensions
if (stream.Position >= stream.Length)
return null;
- byte[] buffer = ReadUntilNullNarrow(stream);
+ byte[] buffer = ReadUntilNull1Byte(stream);
return Encoding.UTF8.GetString(buffer);
}
@@ -490,7 +492,19 @@ namespace SabreTools.IO.Extensions
if (stream.Position >= stream.Length)
return null;
- byte[] buffer = ReadUntilNullWide(stream);
+ byte[] buffer = ReadUntilNull2Byte(stream);
+ return Encoding.Unicode.GetString(buffer);
+ }
+
+ ///
+ /// Read a null-terminated UTF-32 string from the stream
+ ///
+ public static string? ReadNullTerminatedUTF32String(this Stream stream)
+ {
+ if (stream.Position >= stream.Length)
+ return null;
+
+ byte[] buffer = ReadUntilNull4Byte(stream);
return Encoding.Unicode.GetString(buffer);
}
@@ -760,7 +774,7 @@ namespace SabreTools.IO.Extensions
///
/// Read bytes until a 1-byte null terminator is found
///
- private static byte[] ReadUntilNullNarrow(Stream stream)
+ private static byte[] ReadUntilNull1Byte(Stream stream)
{
var bytes = new List();
while (stream.Position < stream.Length)
@@ -778,7 +792,7 @@ namespace SabreTools.IO.Extensions
///
/// Read bytes until a 2-byte null terminator is found
///
- private static byte[] ReadUntilNullWide(Stream stream)
+ private static byte[] ReadUntilNull2Byte(Stream stream)
{
var bytes = new List();
while (stream.Position < stream.Length)
@@ -814,5 +828,23 @@ namespace SabreTools.IO.Extensions
return buffer;
}
+
+ ///
+ /// Read bytes until a 4-byte null terminator is found
+ ///
+ private static byte[] ReadUntilNull4Byte(Stream stream)
+ {
+ var bytes = new List();
+ while (stream.Position < stream.Length)
+ {
+ uint next = stream.ReadUInt32();
+ if (next == 0x00000000)
+ break;
+
+ bytes.AddRange(BitConverter.GetBytes(next));
+ }
+
+ return [.. bytes];
+ }
}
}