PageRenderTime 134ms CodeModel.GetById 111ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/IronPython_Main/Runtime/Microsoft.Dynamic/Utils/ArrayUtils.cs

#
C# | 378 lines | 284 code | 69 blank | 25 comment | 50 complexity | 21a65c8c265e0b44f4e909a960b0417c MD5 | raw file
  1/* ****************************************************************************
  2 *
  3 * Copyright (c) Microsoft Corporation. 
  4 *
  5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
  6 * copy of the license can be found in the License.html file at the root of this distribution. If 
  7 * you cannot locate the  Apache License, Version 2.0, please send an email to 
  8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
  9 * by the terms of the Apache License, Version 2.0.
 10 *
 11 * You must not remove this notice, or any other, from this software.
 12 *
 13 *
 14 * ***************************************************************************/
 15
 16using System;
 17using System.Collections.Generic;
 18using System.Diagnostics;
 19using System.Text;
 20
 21namespace Microsoft.Scripting.Utils {
 22    public static class ArrayUtils {
 23        internal sealed class FunctorComparer<T> : IComparer<T> {
 24            private readonly Comparison<T> _comparison;
 25
 26            public FunctorComparer(Comparison<T> comparison) {
 27                Assert.NotNull(comparison);
 28                _comparison = comparison;
 29            }
 30
 31            public int Compare(T x, T y) {
 32                return _comparison(x, y);
 33            }
 34        }
 35
 36        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
 37        public static readonly string[] EmptyStrings = new string[0];
 38
 39        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
 40        public static readonly object[] EmptyObjects = new object[0];
 41
 42        public static IComparer<T> ToComparer<T>(Comparison<T> comparison) {
 43            return new FunctorComparer<T>(comparison);
 44        }
 45
 46        public static TOutput[] ConvertAll<TInput, TOutput>(TInput[] input, Converter<TInput, TOutput> conv) {
 47#if SILVERLIGHT
 48            ContractUtils.RequiresNotNull(input, "input");
 49            ContractUtils.RequiresNotNull(conv, "conv");
 50
 51            TOutput[] res = new TOutput[input.Length];
 52            for (int i = 0; i < input.Length; i++) {
 53                res[i] = conv(input[i]);
 54            }
 55            return res;
 56#else
 57            return System.Array.ConvertAll<TInput, TOutput>(input, conv);
 58#endif
 59        }
 60
 61        public static T[] FindAll<T>(T[] array, Predicate<T> match) {
 62#if SILVERLIGHT
 63            if (array == null) {
 64                throw new ArgumentNullException("array");
 65            }
 66
 67            if (match == null) {
 68                throw new ArgumentNullException("match");
 69            }
 70
 71            List<T> list = new List<T>();
 72            for (int i = 0; i < array.Length; i++) {
 73                if (match(array[i])) {
 74                    list.Add(array[i]);
 75                }
 76            }
 77            return list.ToArray();
 78#else
 79            return System.Array.FindAll(array, match);
 80#endif
 81        }
 82
 83        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1814:PreferJaggedArraysOverMultidimensional", MessageId = "1#")] // TODO: fix
 84        public static void PrintTable(StringBuilder output, string[,] table) {
 85            ContractUtils.RequiresNotNull(output, "output");
 86            ContractUtils.RequiresNotNull(table, "table");
 87
 88            int max_width = 0;
 89            for (int i = 0; i < table.GetLength(0); i++) {
 90                if (table[i, 0].Length > max_width) {
 91                    max_width = table[i, 0].Length;
 92                }
 93            }
 94
 95            for (int i = 0; i < table.GetLength(0); i++) {
 96                output.Append(" ");
 97                output.Append(table[i, 0]);
 98
 99                for (int j = table[i, 0].Length; j < max_width + 1; j++) {
100                    output.Append(' ');
101                }
102
103                output.AppendLine(table[i, 1]);
104            }
105        }
106
107        public static T[] Copy<T>(T[] array) {
108            return (array.Length > 0) ? (T[])array.Clone() : array;
109        }
110
111        /// <summary>
112        /// Converts a generic ICollection of T into an array of T.  
113        /// 
114        /// If the collection is already an  array of T the original collection is returned.
115        /// </summary>
116        public static T[] ToArray<T>(ICollection<T> list) {
117            return (list as T[]) ?? MakeArray(list);
118        }
119
120        /// <summary>
121        /// Converts a generic ICollection of T into an array of R using a given conversion.  
122        /// 
123        /// If the collection is already an array of R the original collection is returned.
124        /// </summary>
125        public static TResult[] ToArray<TElement, TResult>(ICollection<TElement> list, Func<TElement, TResult> convertor) {
126            TResult[] res = list as TResult[];
127            if (res == null) {
128                res = new TResult[list.Count];
129                int i = 0;
130                foreach (TElement obj in list) {
131                    res[i++] = convertor(obj);
132                }
133            }
134            return res;
135        }
136
137        public static T[] MakeArray<T>(ICollection<T> list) {
138            if (list.Count == 0) {
139                return new T[0];
140            }
141
142            T[] res = new T[list.Count];
143            list.CopyTo(res, 0);
144            return res;
145        }
146
147        public static T[] MakeArray<T>(ICollection<T> elements, int reservedSlotsBefore, int reservedSlotsAfter) {
148            if (reservedSlotsAfter < 0) throw new ArgumentOutOfRangeException("reservedSlotsAfter");
149            if (reservedSlotsBefore < 0) throw new ArgumentOutOfRangeException("reservedSlotsBefore");
150
151            if (elements == null) {
152                return new T[reservedSlotsBefore + reservedSlotsAfter];
153            }
154
155            T[] result = new T[reservedSlotsBefore + elements.Count + reservedSlotsAfter];
156            elements.CopyTo(result, reservedSlotsBefore);
157            return result;
158        }
159
160        public static T[] RotateRight<T>(T[] array, int count) {
161            ContractUtils.RequiresNotNull(array, "array");
162            if ((count < 0) || (count > array.Length)) throw new ArgumentOutOfRangeException("count");
163
164            T[] result = new T[array.Length];
165            // The head of the array is shifted, and the tail will be rotated to the head of the resulting array
166            int sizeOfShiftedArray = array.Length - count;
167            Array.Copy(array, 0, result, count, sizeOfShiftedArray);
168            Array.Copy(array, sizeOfShiftedArray, result, 0, count);
169            return result;
170        }
171
172        public static T[] ShiftRight<T>(T[] array, int count) {
173            ContractUtils.RequiresNotNull(array, "array");
174            if (count < 0) throw new ArgumentOutOfRangeException("count");
175
176            T[] result = new T[array.Length + count];
177            System.Array.Copy(array, 0, result, count, array.Length);
178            return result;
179        }
180
181        public static T[] ShiftLeft<T>(T[] array, int count) {
182            ContractUtils.RequiresNotNull(array, "array");
183            if (count < 0) throw new ArgumentOutOfRangeException("count");
184
185            T[] result = new T[array.Length - count];
186            System.Array.Copy(array, count, result, 0, result.Length);
187            return result;
188        }
189
190        public static T[] Insert<T>(T item, IList<T> list) {
191            T[] res = new T[list.Count + 1];
192            res[0] = item;
193            list.CopyTo(res, 1);
194            return res;
195        }
196
197        public static T[] Insert<T>(T item1, T item2, IList<T> list) {
198            T[] res = new T[list.Count + 2];
199            res[0] = item1;
200            res[1] = item2;
201            list.CopyTo(res, 2);
202            return res;
203        }
204
205        public static T[] Insert<T>(T item, T[] array) {
206            T[] result = ShiftRight(array, 1);
207            result[0] = item;
208            return result;
209        }
210
211        public static T[] Insert<T>(T item1, T item2, T[] array) {
212            T[] result = ShiftRight(array, 2);
213            result[0] = item1;
214            result[1] = item2;
215            return result;
216        }
217
218        public static T[] Append<T>(T[] array, T item) {
219            System.Array.Resize<T>(ref array, (array == null) ? 1 : array.Length + 1);
220            array[array.Length - 1] = item;
221            return array;
222        }
223
224        public static T[] AppendRange<T>(T[] array, IList<T> items) {
225            return AppendRange<T>(array, items, 0);
226        }
227
228        public static T[] AppendRange<T>(T[] array, IList<T> items, int additionalItemCount) {
229            if (additionalItemCount < 0) {
230                throw new ArgumentOutOfRangeException("additionalItemCount");
231            }
232
233            int j = (array == null) ? 0 : array.Length;
234            System.Array.Resize<T>(ref array, j + items.Count + additionalItemCount);
235
236            for (int i = 0; i < items.Count; i++, j++) {
237                array[j] = items[i];
238            }
239
240            return array;
241        }
242
243        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1814:PreferJaggedArraysOverMultidimensional")] // TODO: fix
244        public static T[,] Concatenate<T>(T[,] array1, T[,] array2) {
245            int columnsCount = array1.GetLength(1);
246            Debug.Assert(array2.GetLength(1) == columnsCount);
247
248            int row1Count = array1.GetLength(0);
249            int row2Count = array2.GetLength(0);
250            int totalRowsCount = row1Count + row2Count;
251            T[,] result = new T[totalRowsCount, columnsCount];
252
253            for (int i = 0; i < row1Count; i++) {
254                for (int j = 0; j < columnsCount; j++) {
255                    result[i, j] = array1[i, j];
256                }
257            }
258
259            for (int i = 0; i < row2Count; i++) {
260                for (int j = 0; j < columnsCount; j++) {
261                    result[(i + row1Count), j] = array2[i, j];
262                }
263            }
264
265            return result;
266        }
267
268        public static void SwapLastTwo<T>(T[] array) {
269            Debug.Assert(array != null && array.Length >= 2);
270
271            T temp = array[array.Length - 1];
272            array[array.Length - 1] = array[array.Length - 2];
273            array[array.Length - 2] = temp;
274        }
275
276        public static T[] RemoveFirst<T>(IList<T> list) {
277            return ShiftLeft(MakeArray(list), 1);
278        }
279
280        public static T[] RemoveFirst<T>(T[] array) {
281            return ShiftLeft(array, 1);
282        }
283
284        public static T[] RemoveLast<T>(T[] array) {
285            ContractUtils.RequiresNotNull(array, "array");
286
287            System.Array.Resize(ref array, array.Length - 1);
288            return array;
289        }
290
291        public static T[] RemoveAt<T>(IList<T> list, int indexToRemove) {
292            return RemoveAt(MakeArray(list), indexToRemove);
293        }
294
295        public static T[] RemoveAt<T>(T[] array, int indexToRemove) {
296            ContractUtils.RequiresNotNull(array, "array");
297            ContractUtils.Requires(indexToRemove >= 0 && indexToRemove < array.Length, "index");
298
299            T[] result = new T[array.Length - 1];
300            if (indexToRemove > 0) {
301                Array.Copy(array, 0, result, 0, indexToRemove);
302            }
303            int remaining = array.Length - indexToRemove - 1;
304            if (remaining > 0) {
305                Array.Copy(array, array.Length - remaining, result, result.Length - remaining, remaining);
306            }
307            return result;
308        }
309
310        public static T[] InsertAt<T>(IList<T> list, int index, params T[] items) {
311            return InsertAt(MakeArray(list), index, items);
312        }
313
314        public static T[] InsertAt<T>(T[] array, int index, params T[] items) {
315            ContractUtils.RequiresNotNull(array, "array");
316            ContractUtils.RequiresNotNull(items, "items");
317            ContractUtils.Requires(index >= 0 && index <= array.Length, "index");
318
319            if (items.Length == 0) {
320                return Copy(array);
321            }
322
323            T[] result = new T[array.Length + items.Length];
324            if (index > 0) {
325                Array.Copy(array, 0, result, 0, index);
326            }
327            Array.Copy(items, 0, result, index, items.Length);
328
329            int remaining = array.Length - index;
330            if (remaining > 0) {
331                Array.Copy(array, array.Length - remaining, result, result.Length - remaining, remaining);
332            }
333            return result;
334        }
335
336        public static bool ValueEquals<T>(this T[] array, T[] other) {
337            if (other.Length != array.Length) {
338                return false;
339            }
340
341            for (int i = 0; i < array.Length; i++) {
342                if (!Object.Equals(array[i], other[i])) {
343                    return false;
344                }
345            }
346
347            return true;
348        }
349
350        public static int GetValueHashCode<T>(this T[] array) {
351            return GetValueHashCode<T>(array, 0, array.Length);
352        }
353
354        public static int GetValueHashCode<T>(this T[] array, int start, int count) {
355            ContractUtils.RequiresNotNull(array, "array");
356            ContractUtils.RequiresArrayRange(array.Length, start, count, "start", "count");
357            
358            if (count == 0) {
359                return 0;
360            }
361
362            int result = array[start].GetHashCode();
363            for (int i = 1; i < count; i++) {
364                result = ((result << 5) | (result >> 27)) ^ array[start + i].GetHashCode();
365            }
366
367            return result;
368        }
369
370        public static T[] Reverse<T>(this T[] array) {
371            T[] res = new T[array.Length];
372            for (int i = 0; i < array.Length; i++) {
373                res[array.Length - i - 1] = array[i];
374            }
375            return res;
376        }
377    }
378}