123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using System.Reflection.Emit;
- using System.Runtime.InteropServices;
- #if NETCORE
- using SharpCompress.Buffers;
- #endif
- using SharpCompress.Readers;
- namespace SharpCompress
- {
- internal static class Utility
- {
- public static ReadOnlyCollection<T> ToReadOnly<T>(this IEnumerable<T> items)
- {
- return new ReadOnlyCollection<T>(items.ToList());
- }
- /// <summary>
- /// Performs an unsigned bitwise right shift with the specified number
- /// </summary>
- /// <param name="number">Number to operate on</param>
- /// <param name="bits">Ammount of bits to shift</param>
- /// <returns>The resulting number from the shift operation</returns>
- public static int URShift(int number, int bits)
- {
- if (number >= 0)
- {
- return number >> bits;
- }
- return (number >> bits) + (2 << ~bits);
- }
- /// <summary>
- /// Performs an unsigned bitwise right shift with the specified number
- /// </summary>
- /// <param name="number">Number to operate on</param>
- /// <param name="bits">Ammount of bits to shift</param>
- /// <returns>The resulting number from the shift operation</returns>
- public static long URShift(long number, int bits)
- {
- if (number >= 0)
- {
- return number >> bits;
- }
- return (number >> bits) + (2L << ~bits);
- }
- /// <summary>
- /// Fills the array with an specific value from an specific index to an specific index.
- /// </summary>
- /// <param name="array">The array to be filled.</param>
- /// <param name="fromindex">The first index to be filled.</param>
- /// <param name="toindex">The last index to be filled.</param>
- /// <param name="val">The value to fill the array with.</param>
- public static void Fill<T>(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) || array.Length < toindex)
- {
- throw new IndexOutOfRangeException();
- }
- for (int index = (fromindex > 0) ? fromindex-- : fromindex; index < toindex; index++)
- {
- array[index] = val;
- }
- }
- #if NET45
- // super fast memset, up to 40x faster than for loop on large arrays
- // see https://stackoverflow.com/questions/1897555/what-is-the-equivalent-of-memset-in-c
- private static readonly Action<IntPtr, byte, uint> MemsetDelegate = CreateMemsetDelegate();
- private static Action<IntPtr, byte, uint> CreateMemsetDelegate() {
- var dynamicMethod = new DynamicMethod(
- "Memset",
- MethodAttributes.Public | MethodAttributes.Static,
- CallingConventions.Standard,
- null,
- new[] { typeof(IntPtr), typeof(byte), typeof(uint) },
- typeof(Utility),
- true);
- var generator = dynamicMethod.GetILGenerator();
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Ldarg_1);
- generator.Emit(OpCodes.Ldarg_2);
- generator.Emit(OpCodes.Initblk);
- generator.Emit(OpCodes.Ret);
- return (Action<IntPtr, byte, uint>)dynamicMethod.CreateDelegate(typeof(Action<IntPtr, byte, uint>));
- }
- public static void Memset(byte[] array, byte what, int length)
- {
- var gcHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
- MemsetDelegate(gcHandle.AddrOfPinnedObject(), what, (uint)length);
- gcHandle.Free();
- }
- #else
- public static void Memset(byte[] array, byte what, int length)
- {
- for(var i = 0; i < length; i++)
- {
- array[i] = what;
- }
- }
- #endif
- public static void Memset<T>(T[] array, T what, int length)
- {
- for(var i = 0; i < length; i++)
- {
- array[i] = what;
- }
- }
- public static void FillFast<T>(T[] array, T val) where T : struct
- {
- for (int i = 0; i < array.Length; i++)
- {
- array[i] = val;
- }
- }
- public static void FillFast<T>(T[] array, int start, int length, T val) where T : struct
- {
- int toIndex = start + length;
- for (int i = start; i < toIndex; i++)
- {
- array[i] = val;
- }
- }
- /// <summary>
- /// Fills the array with an specific value.
- /// </summary>
- /// <param name="array">The array to be filled.</param>
- /// <param name="val">The value to fill the array with.</param>
- public static void Fill<T>(T[] array, T val) where T : struct
- {
- Fill(array, 0, array.Length, val);
- }
- public static void SetSize(this List<byte> 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);
- }
- }
- public static void AddRange<T>(this ICollection<T> destination, IEnumerable<T> source)
- {
- foreach (T item in source)
- {
- destination.Add(item);
- }
- }
- public static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
- {
- foreach (T item in items)
- {
- action(item);
- }
- }
-
- public static void Copy(Array sourceArray, long sourceIndex, Array destinationArray, long destinationIndex, long length)
- {
- if (sourceIndex > Int32.MaxValue || sourceIndex < Int32.MinValue)
- throw new ArgumentOutOfRangeException();
- if (destinationIndex > Int32.MaxValue || destinationIndex < Int32.MinValue)
- throw new ArgumentOutOfRangeException();
- if (length > Int32.MaxValue || length < Int32.MinValue)
- throw new ArgumentOutOfRangeException();
- Array.Copy(sourceArray, (int)sourceIndex, destinationArray, (int)destinationIndex, (int)length);
- }
- public static IEnumerable<T> AsEnumerable<T>(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)
- {
- if (source.CanSeek)
- {
- source.Position += advanceAmount;
- return;
- }
- byte[] buffer = GetTransferByteArray();
- try
- {
- 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);
- }
- finally
- {
- #if NETCORE
- ArrayPool<byte>.Shared.Return(buffer);
- #endif
- }
- }
- public static void Skip(this Stream source)
- {
- byte[] buffer = GetTransferByteArray();
- try
- {
- do
- {
- }
- while (source.Read(buffer, 0, buffer.Length) == buffer.Length);
- }
- finally
- {
- #if NETCORE
- ArrayPool<byte>.Shared.Return(buffer);
- #endif
- }
- }
- 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, DateTimeKind.Local);
- }
- catch
- {
- dt = new DateTime();
- }
- return dt;
- }
- public static uint DateTimeToDosTime(this DateTime? dateTime)
- {
- if (dateTime == null)
- {
- return 0;
- }
- var localDateTime = dateTime.Value.ToLocalTime();
- return (uint)(
- (localDateTime.Second / 2) | (localDateTime.Minute << 5) | (localDateTime.Hour << 11) |
- (localDateTime.Day << 16) | (localDateTime.Month << 21) |
- ((localDateTime.Year - 1980) << 25));
- }
- public static DateTime DosDateToDateTime(UInt32 iTime)
- {
- return DosDateToDateTime((UInt16)(iTime / 65536),
- (UInt16)(iTime % 65536));
- }
- /// <summary>
- /// Convert Unix time value to a DateTime object.
- /// </summary>
- /// <param name="unixtime">The Unix time stamp you want to convert to DateTime.</param>
- /// <returns>Returns a DateTime object that represents value of the Unix time.</returns>
- public static DateTime UnixTimeToDateTime(long unixtime)
- {
- DateTime sTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
- return sTime.AddSeconds(unixtime);
- }
- public static long TransferTo(this Stream source, Stream destination)
- {
- byte[] array = GetTransferByteArray();
- try
- {
- int count;
- long total = 0;
- while (ReadTransferBlock(source, array, out count))
- {
- total += count;
- destination.Write(array, 0, count);
- }
- return total;
- }
- finally
- {
- #if NETCORE
- ArrayPool<byte>.Shared.Return(array);
- #endif
- }
- }
- public static long TransferTo(this Stream source, Stream destination, Common.Entry entry, IReaderExtractionListener readerExtractionListener)
- {
- byte[] array = GetTransferByteArray();
- try
- {
- int count;
- var iterations = 0;
- long total = 0;
- while (ReadTransferBlock(source, array, out count))
- {
- total += count;
- destination.Write(array, 0, count);
- iterations++;
- readerExtractionListener.FireEntryExtractionProgress(entry, total, iterations);
- }
- return total;
- }
- finally
- {
- #if NETCORE
- ArrayPool<byte>.Shared.Return(array);
- #endif
- }
- }
- private static bool ReadTransferBlock(Stream source, byte[] array, out int count)
- {
- return (count = source.Read(array, 0, array.Length)) != 0;
- }
- private static byte[] GetTransferByteArray()
- {
- #if NETCORE
- return ArrayPool<byte>.Shared.Rent(81920);
- #else
- return new byte[81920];
- #endif
- }
- 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;
- }
- }
- }
|