using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace BurnOutSharp.Builder { internal static class Extensions { #region Byte Arrays /// /// 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 /// public static byte[] ReadBytes(this byte[] content, ref int offset, int count) { byte[] buffer = new byte[count]; Array.Copy(content, offset, buffer, 0, Math.Min(count, content.Length - offset)); offset += count; return buffer; } /// /// 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 character array and increment the pointer to an array /// public static char[] ReadChars(this byte[] content, ref int offset, int count) => content.ReadChars(ref offset, count, Encoding.Default); /// /// Read a character array and increment the pointer to an array /// public static char[] ReadChars(this byte[] content, ref int offset, int count, Encoding encoding) { // TODO: Fix the code below to make it work with byte arrays and not streams return null; // byte[] buffer = new byte[count]; // stream.Read(buffer, 0, count); // return encoding.GetString(buffer).ToCharArray(); } /// /// 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 null-terminated string from the stream /// public static string ReadString(this byte[] content, ref int offset) => content.ReadString(ref offset, Encoding.Default); /// /// Read a null-terminated string from the stream /// public static string ReadString(this byte[] content, ref int offset, Encoding encoding) { byte[] nullTerminator = encoding.GetBytes(new char[] { '\0' }); int charWidth = nullTerminator.Length; List keyChars = new List(); while (BitConverter.ToUInt16(content, offset) != 0x0000) { keyChars.Add(encoding.GetChars(content, offset, charWidth)[0]); offset += charWidth; } offset += 2; return new string(keyChars.ToArray()); } #endregion #region Streams /// /// Read a byte from the stream /// public static byte ReadByteValue(this Stream stream) { byte[] buffer = new byte[1]; stream.Read(buffer, 0, 1); return buffer[0]; } /// /// Read a byte array from the stream /// public static byte[] ReadBytes(this Stream stream, int count) { byte[] buffer = new byte[count]; stream.Read(buffer, 0, count); return buffer; } /// /// Read a character from the stream /// public static char ReadChar(this Stream stream) { byte[] buffer = new byte[1]; stream.Read(buffer, 0, 1); return (char)buffer[0]; } /// /// Read a character array from the stream /// public static char[] ReadChars(this Stream stream, int count) => stream.ReadChars(count, Encoding.Default); /// /// Read a character array from the stream /// public static char[] ReadChars(this Stream stream, int count, Encoding encoding) { byte[] buffer = new byte[count]; stream.Read(buffer, 0, count); return encoding.GetString(buffer).ToCharArray(); } /// /// Read a short from the stream /// public static short ReadInt16(this Stream stream) { byte[] buffer = new byte[2]; stream.Read(buffer, 0, 2); return BitConverter.ToInt16(buffer, 0); } /// /// Read a ushort from the stream /// public static ushort ReadUInt16(this Stream stream) { byte[] buffer = new byte[2]; stream.Read(buffer, 0, 2); return BitConverter.ToUInt16(buffer, 0); } /// /// Read an int from the stream /// public static int ReadInt32(this Stream stream) { byte[] buffer = new byte[4]; stream.Read(buffer, 0, 4); return BitConverter.ToInt32(buffer, 0); } /// /// Read a uint from the stream /// public static uint ReadUInt32(this Stream stream) { byte[] buffer = new byte[4]; stream.Read(buffer, 0, 4); return BitConverter.ToUInt32(buffer, 0); } /// /// Read a long from the stream /// public static long ReadInt64(this Stream stream) { byte[] buffer = new byte[8]; stream.Read(buffer, 0, 8); return BitConverter.ToInt64(buffer, 0); } /// /// Read a ulong from the stream /// public static ulong ReadUInt64(this Stream stream) { byte[] buffer = new byte[8]; stream.Read(buffer, 0, 8); return BitConverter.ToUInt64(buffer, 0); } /// /// Read a null-terminated string from the stream /// public static string ReadString(this Stream stream) => stream.ReadString(Encoding.Default); /// /// Read a null-terminated string from the stream /// public static string ReadString(this Stream stream, Encoding encoding) { byte[] nullTerminator = encoding.GetBytes(new char[] { '\0' }); int charWidth = nullTerminator.Length; List tempBuffer = new List(); byte[] buffer = new byte[charWidth]; while (stream.Read(buffer, 0, charWidth) != 0 && buffer.SequenceEqual(nullTerminator)) { tempBuffer.AddRange(buffer); } return encoding.GetString(tempBuffer.ToArray()); } #endregion #region New Executable /// /// Determine if a resource type information entry is an integer or offset /// /// Resource type information entry to check /// True if the entry is an integer type, false if an offset, null on error public static bool? IsIntegerType(this Models.NewExecutable.ResourceTypeInformationEntry entry) { // We can't do anything with an invalid entry if (entry == null) return null; // If the highest order bit is set, it's an integer type return (entry.TypeID & 0x8000) != 0; } /// /// Determine if a resource type resource entry is an integer or offset /// /// Resource type resource entry to check /// True if the entry is an integer type, false if an offset, null on error public static bool? IsIntegerType(this Models.NewExecutable.ResourceTypeResourceEntry entry) { // We can't do anything with an invalid entry if (entry == null) return null; // If the highest order bit is set, it's an integer type return (entry.ResourceID & 0x8000) != 0; } #endregion } }