using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace BinaryObjectScanner.Utilities { public static class Extensions { #region ConcurrentQueue /// /// Add a range of values from one queue to another /// /// Queue to add data to /// Array to get data from public static void AddRange(this ConcurrentQueue original, string[] values) { if (values == null || values.Length == 0) return; for (int i = 0; i < values.Length; i++) { original.Enqueue(values[i]); } } /// /// Add a range of values from one queue to another /// /// Queue to add data to /// Queue to get data from public static void AddRange(this ConcurrentQueue original, ConcurrentQueue values) { while (!values.IsEmpty) { if (!values.TryDequeue(out string value)) return; original.Enqueue(value); } } #endregion #region BitArray /// /// Convert a bit array into a byte /// public static byte AsByte(this BitArray array) { byte value = 0; int maxValue = Math.Min(8, array.Length); for (int i = maxValue - 1; i >= 0; i--) { value <<= 1; value |= (byte)(array[i] ? 1 : 0); } return value; } /// /// Convert a bit array into an sbyte /// public static sbyte AsSByte(this BitArray array) { sbyte value = 0; int maxValue = Math.Min(val1: 8, array.Length); for (int i = maxValue - 1; i >= 0; i--) { value <<= 1; value |= (sbyte)(array[i] ? 1 : 0); } return value; } /// /// Convert a bit array into a short /// public static short AsInt16(this BitArray array) { short value = 0; int maxValue = Math.Min(16, array.Length); for (int i = maxValue - 1; i >= 0; i--) { value <<= 1; value |= (short)(array[i] ? 1 : 0); } return value; } /// /// Convert a bit array into a ushort /// public static ushort AsUInt16(this BitArray array) { ushort value = 0; int maxValue = Math.Min(16, array.Length); for (int i = maxValue - 1; i >= 0; i--) { value <<= 1; value |= (ushort)(array[i] ? 1 : 0); } return value; } /// /// Convert a bit array into an int /// public static int AsInt32(this BitArray array) { int value = 0; int maxValue = Math.Min(32, array.Length); for (int i = maxValue - 1; i >= 0; i--) { value <<= 1; value |= (int)(array[i] ? 1 : 0); } return value; } /// /// Convert a bit array into a uint /// public static uint AsUInt32(this BitArray array) { uint value = 0; int maxValue = Math.Min(32, array.Length); for (int i = maxValue - 1; i >= 0; i--) { value <<= 1; value |= (uint)(array[i] ? 1 : 0); } return value; } /// /// Convert a bit array into a long /// public static long AsInt64(this BitArray array) { long value = 0; int maxValue = Math.Min(64, array.Length); for (int i = maxValue - 1; i >= 0; i--) { value <<= 1; value |= (long)(array[i] ? 1 : 0); } return value; } /// /// Convert a bit array into a ulong /// public static ulong AsUInt64(this BitArray array) { ulong value = 0; int maxValue = Math.Min(64, array.Length); for (int i = maxValue - 1; i >= 0; i--) { value <<= 1; value |= (ulong)(array[i] ? 1 : 0); } return value; } #endregion #region Byte Array Reading /// /// 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) { // 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 /// 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) { 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'); } #endregion #region Stream Reading /// /// 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) { // If there's an invalid byte count, don't do anything if (count <= 0) return null; byte[] buffer = new byte[count]; stream.Read(buffer, 0, count); return buffer; } /// /// Read an sbyte from the stream /// public static sbyte ReadSByte(this Stream stream) { byte[] buffer = new byte[1]; stream.Read(buffer, 0, 1); return (sbyte)buffer[0]; } /// /// 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 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 short from the stream in big-endian format /// public static short ReadInt16BE(this Stream stream) { byte[] buffer = new byte[2]; stream.Read(buffer, 0, 2); Array.Reverse(buffer); 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 a ushort from the stream in big-endian format /// public static ushort ReadUInt16BE(this Stream stream) { byte[] buffer = new byte[2]; stream.Read(buffer, 0, 2); Array.Reverse(buffer); 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 an int from the stream in big-endian format /// public static int ReadInt32BE(this Stream stream) { byte[] buffer = new byte[4]; stream.Read(buffer, 0, 4); Array.Reverse(buffer); 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 uint from the stream in big-endian format /// public static uint ReadUInt32BE(this Stream stream) { byte[] buffer = new byte[4]; stream.Read(buffer, 0, 4); Array.Reverse(buffer); 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 long from the stream in big-endian format /// public static long ReadInt64BE(this Stream stream) { byte[] buffer = new byte[8]; stream.Read(buffer, 0, 8); Array.Reverse(buffer); 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 ulong from the stream in big-endian format /// public static ulong ReadUInt64BE(this Stream stream) { byte[] buffer = new byte[8]; stream.Read(buffer, 0, 8); Array.Reverse(buffer); return BitConverter.ToUInt64(buffer, 0); } /// /// Read a Guid from the stream /// public static Guid ReadGuid(this Stream stream) { byte[] buffer = new byte[16]; stream.Read(buffer, 0, 16); return new Guid(buffer); } /// /// Read a Guid from the stream in big-endian format /// public static Guid ReadGuidBE(this Stream stream) { byte[] buffer = new byte[16]; stream.Read(buffer, 0, 16); Array.Reverse(buffer); return new Guid(buffer); } /// /// 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) { if (stream.Position >= stream.Length) return null; byte[] nullTerminator = encoding.GetBytes(new char[] { '\0' }); int charWidth = nullTerminator.Length; List tempBuffer = new List(); byte[] buffer = new byte[charWidth]; while (stream.Position < stream.Length && stream.Read(buffer, 0, charWidth) != 0 && !buffer.SequenceEqual(nullTerminator)) { tempBuffer.AddRange(buffer); } return encoding.GetString(tempBuffer.ToArray()); } #endregion } }