Fix XMM scanning on Mac x86.
[mono.git] / mcs / class / System.IO.Compression / SharpCompress / Utility.cs
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.Linq;
5 using SharpCompress.Archive;
6 using SharpCompress.Common;
7 using SharpCompress.IO;
8
9 namespace SharpCompress
10 {
11     internal static class Utility
12     {
13         public static ReadOnlyCollection<T> ToReadOnly<T>(this IEnumerable<T> items)
14         {
15             return new ReadOnlyCollection<T>(items.ToList());
16         }
17
18         /// <summary>
19         /// Performs an unsigned bitwise right shift with the specified number
20         /// </summary>
21         /// <param name="number">Number to operate on</param>
22         /// <param name="bits">Ammount of bits to shift</param>
23         /// <returns>The resulting number from the shift operation</returns>
24         public static int URShift(int number, int bits)
25         {
26             if (number >= 0)
27                 return number >> bits;
28             else
29                 return (number >> bits) + (2 << ~bits);
30         }
31
32         /// <summary>
33         /// Performs an unsigned bitwise right shift with the specified number
34         /// </summary>
35         /// <param name="number">Number to operate on</param>
36         /// <param name="bits">Ammount of bits to shift</param>
37         /// <returns>The resulting number from the shift operation</returns>
38         public static int URShift(int number, long bits)
39         {
40             return URShift(number, (int)bits);
41         }
42
43         /// <summary>
44         /// Performs an unsigned bitwise right shift with the specified number
45         /// </summary>
46         /// <param name="number">Number to operate on</param>
47         /// <param name="bits">Ammount of bits to shift</param>
48         /// <returns>The resulting number from the shift operation</returns>
49         public static long URShift(long number, int bits)
50         {
51             if (number >= 0)
52                 return number >> bits;
53             else
54                 return (number >> bits) + (2L << ~bits);
55         }
56
57         /// <summary>
58         /// Performs an unsigned bitwise right shift with the specified number
59         /// </summary>
60         /// <param name="number">Number to operate on</param>
61         /// <param name="bits">Ammount of bits to shift</param>
62         /// <returns>The resulting number from the shift operation</returns>
63         public static long URShift(long number, long bits)
64         {
65             return URShift(number, (int)bits);
66         }
67
68         /// <summary>
69         /// Fills the array with an specific value from an specific index to an specific index.
70         /// </summary>
71         /// <param name="array">The array to be filled.</param>
72         /// <param name="fromindex">The first index to be filled.</param>
73         /// <param name="toindex">The last index to be filled.</param>
74         /// <param name="val">The value to fill the array with.</param>
75         public static void Fill<T>(T[] array, int fromindex, int toindex, T val) where T : struct
76         {
77             if (array.Length == 0)
78             {
79                 throw new NullReferenceException();
80             }
81             if (fromindex > toindex)
82             {
83                 throw new ArgumentException();
84             }
85             if ((fromindex < 0) || ((System.Array)array).Length < toindex)
86             {
87                 throw new IndexOutOfRangeException();
88             }
89             for (int index = (fromindex > 0) ? fromindex-- : fromindex; index < toindex; index++)
90             {
91                 array[index] = val;
92             }
93         }
94
95         /// <summary>
96         /// Fills the array with an specific value.
97         /// </summary>
98         /// <param name="array">The array to be filled.</param>
99         /// <param name="val">The value to fill the array with.</param>
100         public static void Fill<T>(T[] array, T val) where T : struct
101         {
102             Fill(array, 0, array.Length, val);
103         }
104
105         public static void SetSize(this List<byte> list, int count)
106         {
107             if (count > list.Count)
108             {
109                 for (int i = list.Count; i < count; i++)
110                 {
111                     list.Add(0x0);
112                 }
113             }
114             else
115             {
116                 byte[] temp = new byte[count];
117                 list.CopyTo(temp, 0);
118                 list.Clear();
119                 list.AddRange(temp);
120             }
121         }
122
123         /// <summary> Read a int value from the byte array at the given position (Big Endian)
124         /// 
125         /// </summary>
126         /// <param name="array">the array to read from
127         /// </param>
128         /// <param name="pos">the offset
129         /// </param>
130         /// <returns> the value
131         /// </returns>
132         public static int readIntBigEndian(byte[] array, int pos)
133         {
134             int temp = 0;
135             temp |= array[pos] & 0xff;
136             temp <<= 8;
137             temp |= array[pos + 1] & 0xff;
138             temp <<= 8;
139             temp |= array[pos + 2] & 0xff;
140             temp <<= 8;
141             temp |= array[pos + 3] & 0xff;
142             return temp;
143         }
144
145         /// <summary> Read a short value from the byte array at the given position (little
146         /// Endian)
147         /// 
148         /// </summary>
149         /// <param name="array">the array to read from
150         /// </param>
151         /// <param name="pos">the offset
152         /// </param>
153         /// <returns> the value
154         /// </returns>
155         public static short readShortLittleEndian(byte[] array, int pos)
156         {
157             return BitConverter.ToInt16(array, pos);
158         }
159
160         /// <summary> Read an int value from the byte array at the given position (little
161         /// Endian)
162         /// 
163         /// </summary>
164         /// <param name="array">the array to read from
165         /// </param>
166         /// <param name="pos">the offset
167         /// </param>
168         /// <returns> the value
169         /// </returns>
170         public static int readIntLittleEndian(byte[] array, int pos)
171         {
172             return BitConverter.ToInt32(array, pos);
173         }
174
175         /// <summary> Write an int value into the byte array at the given position (Big endian)
176         /// 
177         /// </summary>
178         /// <param name="array">the array
179         /// </param>
180         /// <param name="pos">the offset
181         /// </param>
182         /// <param name="value">the value to write
183         /// </param>
184         public static void writeIntBigEndian(byte[] array, int pos, int value)
185         {
186             array[pos] = (byte)((Utility.URShift(value, 24)) & 0xff);
187             array[pos + 1] = (byte)((Utility.URShift(value, 16)) & 0xff);
188             array[pos + 2] = (byte)((Utility.URShift(value, 8)) & 0xff);
189             array[pos + 3] = (byte)((value) & 0xff);
190         }
191
192         /// <summary> Write a short value into the byte array at the given position (little
193         /// endian)
194         /// 
195         /// </summary>
196         /// <param name="array">the array
197         /// </param>
198         /// <param name="pos">the offset
199         /// </param>
200         /// <param name="value">the value to write
201         /// </param>
202 #if PORTABLE || NETFX_CORE
203         public static void WriteLittleEndian(byte[] array, int pos, short value)
204         {
205             byte[] newBytes = BitConverter.GetBytes(value);
206             Array.Copy(newBytes, 0, array, pos, newBytes.Length);
207         }
208 #else
209         public static unsafe void WriteLittleEndian(byte[] array, int pos, short value)
210         {
211             fixed (byte* numRef = &(array[pos]))
212             {
213                 *((short*)numRef) = value;
214             }
215         }
216 #endif
217
218         /// <summary> Increment a short value at the specified position by the specified amount
219         /// (little endian).
220         /// </summary>
221         public static void incShortLittleEndian(byte[] array, int pos, short incrementValue)
222         {
223             short existingValue = BitConverter.ToInt16(array, pos);
224             existingValue += incrementValue;
225             WriteLittleEndian(array, pos, existingValue);
226             //int c = Utility.URShift(((array[pos] & 0xff) + (dv & 0xff)), 8);
227             //array[pos] = (byte)(array[pos] + (dv & 0xff));
228             //if ((c > 0) || ((dv & 0xff00) != 0))
229             //{
230             //    array[pos + 1] = (byte)(array[pos + 1] + ((Utility.URShift(dv, 8)) & 0xff) + c);
231             //}
232         }
233
234         /// <summary> Write an int value into the byte array at the given position (little
235         /// endian)
236         /// 
237         /// </summary>
238         /// <param name="array">the array
239         /// </param>
240         /// <param name="pos">the offset
241         /// </param>
242         /// <param name="value">the value to write
243         /// </param>
244 #if PORTABLE || NETFX_CORE
245         public static void WriteLittleEndian(byte[] array, int pos, int value)
246         {
247             byte[] newBytes = BitConverter.GetBytes(value);
248             Array.Copy(newBytes, 0, array, pos, newBytes.Length);
249         }
250 #else
251         public static unsafe void WriteLittleEndian(byte[] array, int pos, int value)
252         {
253             fixed (byte* numRef = &(array[pos]))
254             {
255                 *((int*)numRef) = value;
256             }
257         }
258 #endif
259
260         public static void Initialize<T>(this T[] array, Func<T> func)
261         {
262             for (int i = 0; i < array.Length; i++)
263             {
264                 array[i] = func();
265             }
266         }
267
268         public static void AddRange<T>(this ICollection<T> destination, IEnumerable<T> source)
269         {
270             foreach (T item in source)
271             {
272                 destination.Add(item);
273             }
274         }
275
276         public static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
277         {
278             foreach (T item in items)
279             {
280                 action(item);
281             }
282         }
283
284         public static IEnumerable<T> AsEnumerable<T>(this T item)
285         {
286             yield return item;
287         }
288
289         public static void CheckNotNull(this object obj, string name)
290         {
291             if (obj == null)
292             {
293                 throw new ArgumentNullException(name);
294             }
295         }
296
297         public static void CheckNotNullOrEmpty(this string obj, string name)
298         {
299             obj.CheckNotNull(name);
300             if (obj.Length == 0)
301             {
302                 throw new ArgumentException("String is empty.");
303             }
304         }
305
306         public static void Skip(this Stream source, long advanceAmount)
307         {
308             byte[] buffer = new byte[32 * 1024];
309             int read = 0;
310             int readCount = 0;
311             do
312             {
313                 readCount = buffer.Length;
314                 if (readCount > advanceAmount)
315                 {
316                     readCount = (int)advanceAmount;
317                 }
318                 read = source.Read(buffer, 0, readCount);
319                 if (read < 0)
320                 {
321                     break;
322                 }
323                 advanceAmount -= read;
324                 if (advanceAmount == 0)
325                 {
326                     break;
327                 }
328             } while (true);
329         }
330
331         public static void SkipAll(this Stream source)
332         {
333             byte[] buffer = new byte[32 * 1024];
334             do
335             {
336             } while (source.Read(buffer, 0, buffer.Length) == buffer.Length);
337         }
338
339
340         public static byte[] UInt32ToBigEndianBytes(uint x)
341         {
342             return new byte[]
343                        {
344                            (byte) ((x >> 24) & 0xff),
345                            (byte) ((x >> 16) & 0xff),
346                            (byte) ((x >> 8) & 0xff),
347                            (byte) (x & 0xff)
348                        };
349         }
350
351         public static DateTime DosDateToDateTime(UInt16 iDate, UInt16 iTime)
352         {
353             int year = iDate / 512 + 1980;
354             int month = iDate % 512 / 32;
355             int day = iDate % 512 % 32;
356             int hour = iTime / 2048;
357             int minute = iTime % 2048 / 32;
358             int second = iTime % 2048 % 32 * 2;
359
360             if (iDate == UInt16.MaxValue || month == 0 || day == 0)
361             {
362                 year = 1980;
363                 month = 1;
364                 day = 1;
365             }
366
367             if (iTime == UInt16.MaxValue)
368             {
369                 hour = minute = second = 0;
370             }
371
372             DateTime dt;
373             try
374             {
375                 dt = new DateTime(year, month, day, hour, minute, second);
376             }
377             catch
378             {
379                 dt = new DateTime();
380             }
381             return dt;
382         }
383
384         public static uint DateTimeToDosTime(this DateTime? dateTime)
385         {
386             if (dateTime == null)
387             {
388                 return 0;
389             }
390             return (uint)(
391                               (dateTime.Value.Second / 2) | (dateTime.Value.Minute << 5) | (dateTime.Value.Hour << 11) |
392                               (dateTime.Value.Day << 16) | (dateTime.Value.Month << 21) |
393                               ((dateTime.Value.Year - 1980) << 25));
394         }
395
396
397         public static DateTime DosDateToDateTime(UInt32 iTime)
398         {
399             return DosDateToDateTime((UInt16)(iTime / 65536),
400                                      (UInt16)(iTime % 65536));
401         }
402
403         public static DateTime DosDateToDateTime(Int32 iTime)
404         {
405             return DosDateToDateTime((UInt32)iTime);
406         }
407
408         public static long TransferTo(this Stream source, Stream destination)
409         {
410             byte[] array = new byte[81920];
411             int count;
412             long total = 0;
413             while ((count = source.Read(array, 0, array.Length)) != 0)
414             {
415                 total += count;
416                 destination.Write(array, 0, count);
417             }
418             return total;
419         }
420
421         public static bool ReadFully(this Stream stream, byte[] buffer)
422         {
423             int total = 0;
424             int read;
425             while ((read = stream.Read(buffer, total, buffer.Length - total)) > 0)
426             {
427                 total += read;
428                 if (total >= buffer.Length)
429                 {
430                     return true;
431                 }
432             }
433             return (total >= buffer.Length);
434         }
435
436         public static string TrimNulls(this string source)
437         {
438             return source.Replace('\0', ' ').Trim();
439         }
440
441         public static bool BinaryEquals(this byte[] source, byte[] target)
442         {
443             if (source.Length != target.Length)
444             {
445                 return false;
446             }
447             for (int i = 0; i < source.Length; ++i)
448             {
449                 if (source[i] != target[i])
450                 {
451                     return false;
452                 }
453             }
454             return true;
455         }
456
457 #if PORTABLE || NETFX_CORE
458         public static void CopyTo(this byte[] array, byte[] destination, int index)
459         {
460             Array.Copy(array, 0, destination, index, array.Length);
461         }
462
463         public static long HostToNetworkOrder(long host)
464         {
465             return (int)((long)HostToNetworkOrder((int)host)
466                 & unchecked((long)(unchecked((ulong)-1))) << 32
467                 | ((long)HostToNetworkOrder((int)((int)host >> 32)) & unchecked((long)(unchecked((ulong)-1)))));
468         }
469         public static int HostToNetworkOrder(int host)
470         {
471             return (int)((int)(HostToNetworkOrder((short)host) & -1) << 16 | (HostToNetworkOrder((short)(host >> 16)) & -1));
472         }
473         public static short HostToNetworkOrder(short host)
474         {
475             return (short)((int)(host & 255) << 8 | ((int)host >> 8 & 255));
476         }
477         public static long NetworkToHostOrder(long network)
478         {
479             return HostToNetworkOrder(network);
480         }
481         public static int NetworkToHostOrder(int network)
482         {
483             return HostToNetworkOrder(network);
484         }
485         public static short NetworkToHostOrder(short network)
486         {
487             return HostToNetworkOrder(network);
488         }
489 #endif
490     }
491 }