using System; using System.Collections.Generic; using System.Text; namespace SabreTools.IO { /// /// Extensions for byte arrays /// /// TODO: Add U/Int24 and U/Int48 methods /// TODO: Add big-endian methods public static class ByteArrayExtensions { /// /// Read a byte and increment the pointer to an array /// public static byte ReadByte(this byte[] content, ref int offset) { return content[offset++]; } /// /// Read a byte array and increment the pointer to an array /// #if NET48 public static byte[] ReadBytes(this byte[] content, ref int offset, int count) #else public static byte[]? ReadBytes(this byte[] content, ref int offset, int count) #endif { // If there's an invalid byte count, don't do anything if (count <= 0) return null; byte[] buffer = new byte[count]; Array.Copy(content, offset, buffer, 0, Math.Min(count, content.Length - offset)); offset += count; return buffer; } /// /// Read an sbyte and increment the pointer to an array /// public static sbyte ReadSByte(this byte[] content, ref int offset) { return (sbyte)content[offset++]; } /// /// Read a char and increment the pointer to an array /// public static char ReadChar(this byte[] content, ref int offset) { return (char)content[offset++]; } /// /// Read a short and increment the pointer to an array /// public static short ReadInt16(this byte[] content, ref int offset) { short value = BitConverter.ToInt16(content, offset); offset += 2; return value; } /// /// Read a ushort and increment the pointer to an array /// public static ushort ReadUInt16(this byte[] content, ref int offset) { ushort value = BitConverter.ToUInt16(content, offset); offset += 2; return value; } /// /// Read a int and increment the pointer to an array /// public static int ReadInt32(this byte[] content, ref int offset) { int value = BitConverter.ToInt32(content, offset); offset += 4; return value; } /// /// Read a uint and increment the pointer to an array /// public static uint ReadUInt32(this byte[] content, ref int offset) { uint value = BitConverter.ToUInt32(content, offset); offset += 4; return value; } /// /// Read a long and increment the pointer to an array /// public static long ReadInt64(this byte[] content, ref int offset) { long value = BitConverter.ToInt64(content, offset); offset += 8; return value; } /// /// Read a ulong and increment the pointer to an array /// public static ulong ReadUInt64(this byte[] content, ref int offset) { ulong value = BitConverter.ToUInt64(content, offset); offset += 8; return value; } /// /// Read a Guid from the stream /// public static Guid ReadGuid(this byte[] content, ref int offset) { byte[] buffer = new byte[16]; Array.Copy(content, offset, buffer, 0, 16); offset += 16; return new Guid(buffer); } /// /// Read a null-terminated string from the stream /// #if NET48 public static string ReadString(this byte[] content, ref int offset) => content.ReadString(ref offset, Encoding.Default); #else public static string? ReadString(this byte[] content, ref int offset) => content.ReadString(ref offset, Encoding.Default); #endif /// /// Read a null-terminated string from the stream /// #if NET48 public static string ReadString(this byte[] content, ref int offset, Encoding encoding) #else public static string? ReadString(this byte[] content, ref int offset, Encoding encoding) #endif { if (offset >= content.Length) return null; byte[] nullTerminator = encoding.GetBytes(new char[] { '\0' }); int charWidth = nullTerminator.Length; List keyChars = new List(); while (offset < content.Length) { char c = encoding.GetChars(content, offset, charWidth)[0]; keyChars.Add(c); offset += charWidth; if (c == '\0') break; } return new string(keyChars.ToArray()).TrimEnd('\0'); } } }