Merge pull request #4155 from BrzVlad/fix-tls-lmf-addr
[mono-project.git] / mcs / class / dlr / Runtime / Microsoft.Dynamic / Utils / ArrayUtils.cs
blob4262c15b0def9879c541effeb4e2a293a7902d95
1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
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.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
16 using System;
17 using System.Collections.Generic;
18 using System.Diagnostics;
19 using System.Text;
21 namespace Microsoft.Scripting.Utils {
22 public static class ArrayUtils {
23 internal sealed class FunctorComparer<T> : IComparer<T> {
24 private readonly Comparison<T> _comparison;
26 public FunctorComparer(Comparison<T> comparison) {
27 Assert.NotNull(comparison);
28 _comparison = comparison;
31 public int Compare(T x, T y) {
32 return _comparison(x, y);
36 // Emitted:
37 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
38 public static readonly string[] EmptyStrings = new string[0];
40 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
41 public static readonly object[] EmptyObjects = new object[0];
43 public static IComparer<T> ToComparer<T>(Comparison<T> comparison) {
44 return new FunctorComparer<T>(comparison);
47 public static TOutput[] ConvertAll<TInput, TOutput>(TInput[] input, Func<TInput, TOutput> conv) {
48 ContractUtils.RequiresNotNull(input, "input");
49 ContractUtils.RequiresNotNull(conv, "conv");
51 TOutput[] res = new TOutput[input.Length];
52 for (int i = 0; i < input.Length; i++) {
53 res[i] = conv(input[i]);
56 return res;
59 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1814:PreferJaggedArraysOverMultidimensional", MessageId = "1#")] // TODO: fix
60 public static void PrintTable(StringBuilder output, string[,] table) {
61 ContractUtils.RequiresNotNull(output, "output");
62 ContractUtils.RequiresNotNull(table, "table");
64 int max_width = 0;
65 for (int i = 0; i < table.GetLength(0); i++) {
66 if (table[i, 0].Length > max_width) {
67 max_width = table[i, 0].Length;
71 for (int i = 0; i < table.GetLength(0); i++) {
72 output.Append(" ");
73 output.Append(table[i, 0]);
75 for (int j = table[i, 0].Length; j < max_width + 1; j++) {
76 output.Append(' ');
79 output.AppendLine(table[i, 1]);
83 public static T[] Copy<T>(T[] array) {
84 return (array.Length > 0) ? (T[])array.Clone() : array;
87 /// <summary>
88 /// Converts a generic ICollection of T into an array of T.
89 ///
90 /// If the collection is already an array of T the original collection is returned.
91 /// </summary>
92 public static T[] ToArray<T>(ICollection<T> list) {
93 return (list as T[]) ?? MakeArray(list);
96 /// <summary>
97 /// Converts a generic ICollection of T into an array of R using a given conversion.
98 ///
99 /// If the collection is already an array of R the original collection is returned.
100 /// </summary>
101 public static TResult[] ToArray<TElement, TResult>(ICollection<TElement> list, Func<TElement, TResult> convertor) {
102 TResult[] res = list as TResult[];
103 if (res == null) {
104 res = new TResult[list.Count];
105 int i = 0;
106 foreach (TElement obj in list) {
107 res[i++] = convertor(obj);
110 return res;
113 public static T[] MakeArray<T>(ICollection<T> list) {
114 if (list.Count == 0) {
115 return new T[0];
118 T[] res = new T[list.Count];
119 list.CopyTo(res, 0);
120 return res;
123 public static T[] MakeArray<T>(ICollection<T> elements, int reservedSlotsBefore, int reservedSlotsAfter) {
124 if (reservedSlotsAfter < 0) throw new ArgumentOutOfRangeException("reservedSlotsAfter");
125 if (reservedSlotsBefore < 0) throw new ArgumentOutOfRangeException("reservedSlotsBefore");
127 if (elements == null) {
128 return new T[reservedSlotsBefore + reservedSlotsAfter];
131 T[] result = new T[reservedSlotsBefore + elements.Count + reservedSlotsAfter];
132 elements.CopyTo(result, reservedSlotsBefore);
133 return result;
136 public static T[] RotateRight<T>(T[] array, int count) {
137 ContractUtils.RequiresNotNull(array, "array");
138 if ((count < 0) || (count > array.Length)) throw new ArgumentOutOfRangeException("count");
140 T[] result = new T[array.Length];
141 // The head of the array is shifted, and the tail will be rotated to the head of the resulting array
142 int sizeOfShiftedArray = array.Length - count;
143 Array.Copy(array, 0, result, count, sizeOfShiftedArray);
144 Array.Copy(array, sizeOfShiftedArray, result, 0, count);
145 return result;
148 public static T[] ShiftRight<T>(T[] array, int count) {
149 ContractUtils.RequiresNotNull(array, "array");
150 if (count < 0) throw new ArgumentOutOfRangeException("count");
152 T[] result = new T[array.Length + count];
153 System.Array.Copy(array, 0, result, count, array.Length);
154 return result;
157 public static T[] ShiftLeft<T>(T[] array, int count) {
158 ContractUtils.RequiresNotNull(array, "array");
159 if (count < 0) throw new ArgumentOutOfRangeException("count");
161 T[] result = new T[array.Length - count];
162 System.Array.Copy(array, count, result, 0, result.Length);
163 return result;
166 public static T[] Insert<T>(T item, IList<T> list) {
167 T[] res = new T[list.Count + 1];
168 res[0] = item;
169 list.CopyTo(res, 1);
170 return res;
173 public static T[] Insert<T>(T item1, T item2, IList<T> list) {
174 T[] res = new T[list.Count + 2];
175 res[0] = item1;
176 res[1] = item2;
177 list.CopyTo(res, 2);
178 return res;
181 public static T[] Insert<T>(T item, T[] array) {
182 T[] result = ShiftRight(array, 1);
183 result[0] = item;
184 return result;
187 public static T[] Insert<T>(T item1, T item2, T[] array) {
188 T[] result = ShiftRight(array, 2);
189 result[0] = item1;
190 result[1] = item2;
191 return result;
194 public static T[] Append<T>(T[] array, T item) {
195 System.Array.Resize<T>(ref array, (array == null) ? 1 : array.Length + 1);
196 array[array.Length - 1] = item;
197 return array;
200 public static T[] AppendRange<T>(T[] array, IList<T> items) {
201 return AppendRange<T>(array, items, 0);
204 public static T[] AppendRange<T>(T[] array, IList<T> items, int additionalItemCount) {
205 if (additionalItemCount < 0) {
206 throw new ArgumentOutOfRangeException("additionalItemCount");
209 int j = (array == null) ? 0 : array.Length;
210 System.Array.Resize<T>(ref array, j + items.Count + additionalItemCount);
212 for (int i = 0; i < items.Count; i++, j++) {
213 array[j] = items[i];
216 return array;
219 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1814:PreferJaggedArraysOverMultidimensional")] // TODO: fix
220 public static T[,] Concatenate<T>(T[,] array1, T[,] array2) {
221 int columnsCount = array1.GetLength(1);
222 Debug.Assert(array2.GetLength(1) == columnsCount);
224 int row1Count = array1.GetLength(0);
225 int row2Count = array2.GetLength(0);
226 int totalRowsCount = row1Count + row2Count;
227 T[,] result = new T[totalRowsCount, columnsCount];
229 for (int i = 0; i < row1Count; i++) {
230 for (int j = 0; j < columnsCount; j++) {
231 result[i, j] = array1[i, j];
235 for (int i = 0; i < row2Count; i++) {
236 for (int j = 0; j < columnsCount; j++) {
237 result[(i + row1Count), j] = array2[i, j];
241 return result;
244 public static void SwapLastTwo<T>(T[] array) {
245 Debug.Assert(array != null && array.Length >= 2);
247 T temp = array[array.Length - 1];
248 array[array.Length - 1] = array[array.Length - 2];
249 array[array.Length - 2] = temp;
252 public static T[] RemoveFirst<T>(IList<T> list) {
253 return ShiftLeft(MakeArray(list), 1);
256 public static T[] RemoveFirst<T>(T[] array) {
257 return ShiftLeft(array, 1);
260 public static T[] RemoveLast<T>(T[] array) {
261 ContractUtils.RequiresNotNull(array, "array");
263 System.Array.Resize(ref array, array.Length - 1);
264 return array;
267 public static T[] RemoveAt<T>(IList<T> list, int indexToRemove) {
268 return RemoveAt(MakeArray(list), indexToRemove);
271 public static T[] RemoveAt<T>(T[] array, int indexToRemove) {
272 ContractUtils.RequiresNotNull(array, "array");
273 ContractUtils.Requires(indexToRemove >= 0 && indexToRemove < array.Length, "index");
275 T[] result = new T[array.Length - 1];
276 if (indexToRemove > 0) {
277 Array.Copy(array, 0, result, 0, indexToRemove);
279 int remaining = array.Length - indexToRemove - 1;
280 if (remaining > 0) {
281 Array.Copy(array, array.Length - remaining, result, result.Length - remaining, remaining);
283 return result;
286 public static T[] InsertAt<T>(IList<T> list, int index, params T[] items) {
287 return InsertAt(MakeArray(list), index, items);
290 public static T[] InsertAt<T>(T[] array, int index, params T[] items) {
291 ContractUtils.RequiresNotNull(array, "array");
292 ContractUtils.RequiresNotNull(items, "items");
293 ContractUtils.Requires(index >= 0 && index <= array.Length, "index");
295 if (items.Length == 0) {
296 return Copy(array);
299 T[] result = new T[array.Length + items.Length];
300 if (index > 0) {
301 Array.Copy(array, 0, result, 0, index);
303 Array.Copy(items, 0, result, index, items.Length);
305 int remaining = array.Length - index;
306 if (remaining > 0) {
307 Array.Copy(array, array.Length - remaining, result, result.Length - remaining, remaining);
309 return result;
312 public static bool ValueEquals<T>(this T[] array, T[] other) {
313 if (other.Length != array.Length) {
314 return false;
317 for (int i = 0; i < array.Length; i++) {
318 if (!Object.Equals(array[i], other[i])) {
319 return false;
323 return true;
326 public static int GetValueHashCode<T>(this T[] array) {
327 return GetValueHashCode<T>(array, 0, array.Length);
330 public static int GetValueHashCode<T>(this T[] array, int start, int count) {
331 ContractUtils.RequiresNotNull(array, "array");
332 ContractUtils.RequiresArrayRange(array.Length, start, count, "start", "count");
334 if (count == 0) {
335 return 0;
338 int result = array[start].GetHashCode();
339 for (int i = 1; i < count; i++) {
340 result = ((result << 5) | (result >> 27)) ^ array[start + i].GetHashCode();
343 return result;
346 public static T[] Reverse<T>(this T[] array) {
347 T[] res = new T[array.Length];
348 for (int i = 0; i < array.Length; i++) {
349 res[array.Length - i - 1] = array[i];
351 return res;