using System; using System.Collections.Generic; using System.IO; using System.Linq; using SharpCompress.Archive; using SharpCompress.Common; using SharpCompress.IO; namespace SharpCompress { internal static class Utility { public static ReadOnlyCollection ToReadOnly(this IEnumerable items) { return new ReadOnlyCollection(items.ToList()); } /// /// Performs an unsigned bitwise right shift with the specified number /// /// Number to operate on /// Ammount of bits to shift /// The resulting number from the shift operation public static int URShift(int number, int bits) { if (number >= 0) return number >> bits; else return (number >> bits) + (2 << ~bits); } /// /// Performs an unsigned bitwise right shift with the specified number /// /// Number to operate on /// Ammount of bits to shift /// The resulting number from the shift operation public static int URShift(int number, long bits) { return URShift(number, (int)bits); } /// /// Performs an unsigned bitwise right shift with the specified number /// /// Number to operate on /// Ammount of bits to shift /// The resulting number from the shift operation public static long URShift(long number, int bits) { if (number >= 0) return number >> bits; else return (number >> bits) + (2L << ~bits); } /// /// Performs an unsigned bitwise right shift with the specified number /// /// Number to operate on /// Ammount of bits to shift /// The resulting number from the shift operation public static long URShift(long number, long bits) { return URShift(number, (int)bits); } /// /// Fills the array with an specific value from an specific index to an specific index. /// /// The array to be filled. /// The first index to be filled. /// The last index to be filled. /// The value to fill the array with. public static void Fill(T[] array, int fromindex, int toindex, T val) where T : struct { if (array.Length == 0) { throw new NullReferenceException(); } if (fromindex > toindex) { throw new ArgumentException(); } if ((fromindex < 0) || ((System.Array)array).Length < toindex) { throw new IndexOutOfRangeException(); } for (int index = (fromindex > 0) ? fromindex-- : fromindex; index < toindex; index++) { array[index] = val; } } /// /// Fills the array with an specific value. /// /// The array to be filled. /// The value to fill the array with. public static void Fill(T[] array, T val) where T : struct { Fill(array, 0, array.Length, val); } public static void SetSize(this List list, int count) { if (count > list.Count) { for (int i = list.Count; i < count; i++) { list.Add(0x0); } } else { byte[] temp = new byte[count]; list.CopyTo(temp, 0); list.Clear(); list.AddRange(temp); } } /// Read a int value from the byte array at the given position (Big Endian) /// /// /// the array to read from /// /// the offset /// /// the value /// public static int readIntBigEndian(byte[] array, int pos) { int temp = 0; temp |= array[pos] & 0xff; temp <<= 8; temp |= array[pos + 1] & 0xff; temp <<= 8; temp |= array[pos + 2] & 0xff; temp <<= 8; temp |= array[pos + 3] & 0xff; return temp; } /// Read a short value from the byte array at the given position (little /// Endian) /// /// /// the array to read from /// /// the offset /// /// the value /// public static short readShortLittleEndian(byte[] array, int pos) { return BitConverter.ToInt16(array, pos); } /// Read an int value from the byte array at the given position (little /// Endian) /// /// /// the array to read from /// /// the offset /// /// the value /// public static int readIntLittleEndian(byte[] array, int pos) { return BitConverter.ToInt32(array, pos); } /// Write an int value into the byte array at the given position (Big endian) /// /// /// the array /// /// the offset /// /// the value to write /// public static void writeIntBigEndian(byte[] array, int pos, int value) { array[pos] = (byte)((Utility.URShift(value, 24)) & 0xff); array[pos + 1] = (byte)((Utility.URShift(value, 16)) & 0xff); array[pos + 2] = (byte)((Utility.URShift(value, 8)) & 0xff); array[pos + 3] = (byte)((value) & 0xff); } /// Write a short value into the byte array at the given position (little /// endian) /// /// /// the array /// /// the offset /// /// the value to write /// #if PORTABLE || NETFX_CORE public static void WriteLittleEndian(byte[] array, int pos, short value) { byte[] newBytes = BitConverter.GetBytes(value); Array.Copy(newBytes, 0, array, pos, newBytes.Length); } #else public static unsafe void WriteLittleEndian(byte[] array, int pos, short value) { fixed (byte* numRef = &(array[pos])) { *((short*)numRef) = value; } } #endif /// Increment a short value at the specified position by the specified amount /// (little endian). /// public static void incShortLittleEndian(byte[] array, int pos, short incrementValue) { short existingValue = BitConverter.ToInt16(array, pos); existingValue += incrementValue; WriteLittleEndian(array, pos, existingValue); //int c = Utility.URShift(((array[pos] & 0xff) + (dv & 0xff)), 8); //array[pos] = (byte)(array[pos] + (dv & 0xff)); //if ((c > 0) || ((dv & 0xff00) != 0)) //{ // array[pos + 1] = (byte)(array[pos + 1] + ((Utility.URShift(dv, 8)) & 0xff) + c); //} } /// Write an int value into the byte array at the given position (little /// endian) /// /// /// the array /// /// the offset /// /// the value to write /// #if PORTABLE || NETFX_CORE public static void WriteLittleEndian(byte[] array, int pos, int value) { byte[] newBytes = BitConverter.GetBytes(value); Array.Copy(newBytes, 0, array, pos, newBytes.Length); } #else public static unsafe void WriteLittleEndian(byte[] array, int pos, int value) { fixed (byte* numRef = &(array[pos])) { *((int*)numRef) = value; } } #endif public static void Initialize(this T[] array, Func func) { for (int i = 0; i < array.Length; i++) { array[i] = func(); } } public static void AddRange(this ICollection destination, IEnumerable source) { foreach (T item in source) { destination.Add(item); } } public static void ForEach(this IEnumerable items, Action action) { foreach (T item in items) { action(item); } } public static IEnumerable AsEnumerable(this T item) { yield return item; } public static void CheckNotNull(this object obj, string name) { if (obj == null) { throw new ArgumentNullException(name); } } public static void CheckNotNullOrEmpty(this string obj, string name) { obj.CheckNotNull(name); if (obj.Length == 0) { throw new ArgumentException("String is empty."); } } public static void Skip(this Stream source, long advanceAmount) { byte[] buffer = new byte[32 * 1024]; int read = 0; int readCount = 0; do { readCount = buffer.Length; if (readCount > advanceAmount) { readCount = (int)advanceAmount; } read = source.Read(buffer, 0, readCount); if (read < 0) { break; } advanceAmount -= read; if (advanceAmount == 0) { break; } } while (true); } public static void SkipAll(this Stream source) { byte[] buffer = new byte[32 * 1024]; do { } while (source.Read(buffer, 0, buffer.Length) == buffer.Length); } public static byte[] UInt32ToBigEndianBytes(uint x) { return new byte[] { (byte) ((x >> 24) & 0xff), (byte) ((x >> 16) & 0xff), (byte) ((x >> 8) & 0xff), (byte) (x & 0xff) }; } public static DateTime DosDateToDateTime(UInt16 iDate, UInt16 iTime) { int year = iDate / 512 + 1980; int month = iDate % 512 / 32; int day = iDate % 512 % 32; int hour = iTime / 2048; int minute = iTime % 2048 / 32; int second = iTime % 2048 % 32 * 2; if (iDate == UInt16.MaxValue || month == 0 || day == 0) { year = 1980; month = 1; day = 1; } if (iTime == UInt16.MaxValue) { hour = minute = second = 0; } DateTime dt; try { dt = new DateTime(year, month, day, hour, minute, second); } catch { dt = new DateTime(); } return dt; } public static uint DateTimeToDosTime(this DateTime? dateTime) { if (dateTime == null) { return 0; } return (uint)( (dateTime.Value.Second / 2) | (dateTime.Value.Minute << 5) | (dateTime.Value.Hour << 11) | (dateTime.Value.Day << 16) | (dateTime.Value.Month << 21) | ((dateTime.Value.Year - 1980) << 25)); } public static DateTime DosDateToDateTime(UInt32 iTime) { return DosDateToDateTime((UInt16)(iTime / 65536), (UInt16)(iTime % 65536)); } public static DateTime DosDateToDateTime(Int32 iTime) { return DosDateToDateTime((UInt32)iTime); } public static long TransferTo(this Stream source, Stream destination) { byte[] array = new byte[81920]; int count; long total = 0; while ((count = source.Read(array, 0, array.Length)) != 0) { total += count; destination.Write(array, 0, count); } return total; } public static bool ReadFully(this Stream stream, byte[] buffer) { int total = 0; int read; while ((read = stream.Read(buffer, total, buffer.Length - total)) > 0) { total += read; if (total >= buffer.Length) { return true; } } return (total >= buffer.Length); } public static string TrimNulls(this string source) { return source.Replace('\0', ' ').Trim(); } public static bool BinaryEquals(this byte[] source, byte[] target) { if (source.Length != target.Length) { return false; } for (int i = 0; i < source.Length; ++i) { if (source[i] != target[i]) { return false; } } return true; } #if PORTABLE || NETFX_CORE public static void CopyTo(this byte[] array, byte[] destination, int index) { Array.Copy(array, 0, destination, index, array.Length); } public static long HostToNetworkOrder(long host) { return (int)((long)HostToNetworkOrder((int)host) & unchecked((long)(unchecked((ulong)-1))) << 32 | ((long)HostToNetworkOrder((int)((int)host >> 32)) & unchecked((long)(unchecked((ulong)-1))))); } public static int HostToNetworkOrder(int host) { return (int)((int)(HostToNetworkOrder((short)host) & -1) << 16 | (HostToNetworkOrder((short)(host >> 16)) & -1)); } public static short HostToNetworkOrder(short host) { return (short)((int)(host & 255) << 8 | ((int)host >> 8 & 255)); } public static long NetworkToHostOrder(long network) { return HostToNetworkOrder(network); } public static int NetworkToHostOrder(int network) { return HostToNetworkOrder(network); } public static short NetworkToHostOrder(short network) { return HostToNetworkOrder(network); } #endif } }