PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms 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
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  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. using System;
  16. using System.Collections.Generic;
  17. using System.Diagnostics;
  18. using System.Text;
  19. namespace Microsoft.Scripting.Utils {
  20. public static class ArrayUtils {
  21. internal sealed class FunctorComparer<T> : IComparer<T> {
  22. private readonly Comparison<T> _comparison;
  23. public FunctorComparer(Comparison<T> comparison) {
  24. Assert.NotNull(comparison);
  25. _comparison = comparison;
  26. }
  27. public int Compare(T x, T y) {
  28. return _comparison(x, y);
  29. }
  30. }
  31. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
  32. public static readonly string[] EmptyStrings = new string[0];
  33. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
  34. public static readonly object[] EmptyObjects = new object[0];
  35. public static IComparer<T> ToComparer<T>(Comparison<T> comparison) {
  36. return new FunctorComparer<T>(comparison);
  37. }
  38. public static TOutput[] ConvertAll<TInput, TOutput>(TInput[] input, Converter<TInput, TOutput> conv) {
  39. #if SILVERLIGHT
  40. ContractUtils.RequiresNotNull(input, "input");
  41. ContractUtils.RequiresNotNull(conv, "conv");
  42. TOutput[] res = new TOutput[input.Length];
  43. for (int i = 0; i < input.Length; i++) {
  44. res[i] = conv(input[i]);
  45. }
  46. return res;
  47. #else
  48. return System.Array.ConvertAll<TInput, TOutput>(input, conv);
  49. #endif
  50. }
  51. public static T[] FindAll<T>(T[] array, Predicate<T> match) {
  52. #if SILVERLIGHT
  53. if (array == null) {
  54. throw new ArgumentNullException("array");
  55. }
  56. if (match == null) {
  57. throw new ArgumentNullException("match");
  58. }
  59. List<T> list = new List<T>();
  60. for (int i = 0; i < array.Length; i++) {
  61. if (match(array[i])) {
  62. list.Add(array[i]);
  63. }
  64. }
  65. return list.ToArray();
  66. #else
  67. return System.Array.FindAll(array, match);
  68. #endif
  69. }
  70. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1814:PreferJaggedArraysOverMultidimensional", MessageId = "1#")] // TODO: fix
  71. public static void PrintTable(StringBuilder output, string[,] table) {
  72. ContractUtils.RequiresNotNull(output, "output");
  73. ContractUtils.RequiresNotNull(table, "table");
  74. int max_width = 0;
  75. for (int i = 0; i < table.GetLength(0); i++) {
  76. if (table[i, 0].Length > max_width) {
  77. max_width = table[i, 0].Length;
  78. }
  79. }
  80. for (int i = 0; i < table.GetLength(0); i++) {
  81. output.Append(" ");
  82. output.Append(table[i, 0]);
  83. for (int j = table[i, 0].Length; j < max_width + 1; j++) {
  84. output.Append(' ');
  85. }
  86. output.AppendLine(table[i, 1]);
  87. }
  88. }
  89. public static T[] Copy<T>(T[] array) {
  90. return (array.Length > 0) ? (T[])array.Clone() : array;
  91. }
  92. /// <summary>
  93. /// Converts a generic ICollection of T into an array of T.
  94. ///
  95. /// If the collection is already an array of T the original collection is returned.
  96. /// </summary>
  97. public static T[] ToArray<T>(ICollection<T> list) {
  98. return (list as T[]) ?? MakeArray(list);
  99. }
  100. /// <summary>
  101. /// Converts a generic ICollection of T into an array of R using a given conversion.
  102. ///
  103. /// If the collection is already an array of R the original collection is returned.
  104. /// </summary>
  105. public static TResult[] ToArray<TElement, TResult>(ICollection<TElement> list, Func<TElement, TResult> convertor) {
  106. TResult[] res = list as TResult[];
  107. if (res == null) {
  108. res = new TResult[list.Count];
  109. int i = 0;
  110. foreach (TElement obj in list) {
  111. res[i++] = convertor(obj);
  112. }
  113. }
  114. return res;
  115. }
  116. public static T[] MakeArray<T>(ICollection<T> list) {
  117. if (list.Count == 0) {
  118. return new T[0];
  119. }
  120. T[] res = new T[list.Count];
  121. list.CopyTo(res, 0);
  122. return res;
  123. }
  124. public static T[] MakeArray<T>(ICollection<T> elements, int reservedSlotsBefore, int reservedSlotsAfter) {
  125. if (reservedSlotsAfter < 0) throw new ArgumentOutOfRangeException("reservedSlotsAfter");
  126. if (reservedSlotsBefore < 0) throw new ArgumentOutOfRangeException("reservedSlotsBefore");
  127. if (elements == null) {
  128. return new T[reservedSlotsBefore + reservedSlotsAfter];
  129. }
  130. T[] result = new T[reservedSlotsBefore + elements.Count + reservedSlotsAfter];
  131. elements.CopyTo(result, reservedSlotsBefore);
  132. return result;
  133. }
  134. public static T[] RotateRight<T>(T[] array, int count) {
  135. ContractUtils.RequiresNotNull(array, "array");
  136. if ((count < 0) || (count > array.Length)) throw new ArgumentOutOfRangeException("count");
  137. T[] result = new T[array.Length];
  138. // The head of the array is shifted, and the tail will be rotated to the head of the resulting array
  139. int sizeOfShiftedArray = array.Length - count;
  140. Array.Copy(array, 0, result, count, sizeOfShiftedArray);
  141. Array.Copy(array, sizeOfShiftedArray, result, 0, count);
  142. return result;
  143. }
  144. public static T[] ShiftRight<T>(T[] array, int count) {
  145. ContractUtils.RequiresNotNull(array, "array");
  146. if (count < 0) throw new ArgumentOutOfRangeException("count");
  147. T[] result = new T[array.Length + count];
  148. System.Array.Copy(array, 0, result, count, array.Length);
  149. return result;
  150. }
  151. public static T[] ShiftLeft<T>(T[] array, int count) {
  152. ContractUtils.RequiresNotNull(array, "array");
  153. if (count < 0) throw new ArgumentOutOfRangeException("count");
  154. T[] result = new T[array.Length - count];
  155. System.Array.Copy(array, count, result, 0, result.Length);
  156. return result;
  157. }
  158. public static T[] Insert<T>(T item, IList<T> list) {
  159. T[] res = new T[list.Count + 1];
  160. res[0] = item;
  161. list.CopyTo(res, 1);
  162. return res;
  163. }
  164. public static T[] Insert<T>(T item1, T item2, IList<T> list) {
  165. T[] res = new T[list.Count + 2];
  166. res[0] = item1;
  167. res[1] = item2;
  168. list.CopyTo(res, 2);
  169. return res;
  170. }
  171. public static T[] Insert<T>(T item, T[] array) {
  172. T[] result = ShiftRight(array, 1);
  173. result[0] = item;
  174. return result;
  175. }
  176. public static T[] Insert<T>(T item1, T item2, T[] array) {
  177. T[] result = ShiftRight(array, 2);
  178. result[0] = item1;
  179. result[1] = item2;
  180. return result;
  181. }
  182. public static T[] Append<T>(T[] array, T item) {
  183. System.Array.Resize<T>(ref array, (array == null) ? 1 : array.Length + 1);
  184. array[array.Length - 1] = item;
  185. return array;
  186. }
  187. public static T[] AppendRange<T>(T[] array, IList<T> items) {
  188. return AppendRange<T>(array, items, 0);
  189. }
  190. public static T[] AppendRange<T>(T[] array, IList<T> items, int additionalItemCount) {
  191. if (additionalItemCount < 0) {
  192. throw new ArgumentOutOfRangeException("additionalItemCount");
  193. }
  194. int j = (array == null) ? 0 : array.Length;
  195. System.Array.Resize<T>(ref array, j + items.Count + additionalItemCount);
  196. for (int i = 0; i < items.Count; i++, j++) {
  197. array[j] = items[i];
  198. }
  199. return array;
  200. }
  201. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1814:PreferJaggedArraysOverMultidimensional")] // TODO: fix
  202. public static T[,] Concatenate<T>(T[,] array1, T[,] array2) {
  203. int columnsCount = array1.GetLength(1);
  204. Debug.Assert(array2.GetLength(1) == columnsCount);
  205. int row1Count = array1.GetLength(0);
  206. int row2Count = array2.GetLength(0);
  207. int totalRowsCount = row1Count + row2Count;
  208. T[,] result = new T[totalRowsCount, columnsCount];
  209. for (int i = 0; i < row1Count; i++) {
  210. for (int j = 0; j < columnsCount; j++) {
  211. result[i, j] = array1[i, j];
  212. }
  213. }
  214. for (int i = 0; i < row2Count; i++) {
  215. for (int j = 0; j < columnsCount; j++) {
  216. result[(i + row1Count), j] = array2[i, j];
  217. }
  218. }
  219. return result;
  220. }
  221. public static void SwapLastTwo<T>(T[] array) {
  222. Debug.Assert(array != null && array.Length >= 2);
  223. T temp = array[array.Length - 1];
  224. array[array.Length - 1] = array[array.Length - 2];
  225. array[array.Length - 2] = temp;
  226. }
  227. public static T[] RemoveFirst<T>(IList<T> list) {
  228. return ShiftLeft(MakeArray(list), 1);
  229. }
  230. public static T[] RemoveFirst<T>(T[] array) {
  231. return ShiftLeft(array, 1);
  232. }
  233. public static T[] RemoveLast<T>(T[] array) {
  234. ContractUtils.RequiresNotNull(array, "array");
  235. System.Array.Resize(ref array, array.Length - 1);
  236. return array;
  237. }
  238. public static T[] RemoveAt<T>(IList<T> list, int indexToRemove) {
  239. return RemoveAt(MakeArray(list), indexToRemove);
  240. }
  241. public static T[] RemoveAt<T>(T[] array, int indexToRemove) {
  242. ContractUtils.RequiresNotNull(array, "array");
  243. ContractUtils.Requires(indexToRemove >= 0 && indexToRemove < array.Length, "index");
  244. T[] result = new T[array.Length - 1];
  245. if (indexToRemove > 0) {
  246. Array.Copy(array, 0, result, 0, indexToRemove);
  247. }
  248. int remaining = array.Length - indexToRemove - 1;
  249. if (remaining > 0) {
  250. Array.Copy(array, array.Length - remaining, result, result.Length - remaining, remaining);
  251. }
  252. return result;
  253. }
  254. public static T[] InsertAt<T>(IList<T> list, int index, params T[] items) {
  255. return InsertAt(MakeArray(list), index, items);
  256. }
  257. public static T[] InsertAt<T>(T[] array, int index, params T[] items) {
  258. ContractUtils.RequiresNotNull(array, "array");
  259. ContractUtils.RequiresNotNull(items, "items");
  260. ContractUtils.Requires(index >= 0 && index <= array.Length, "index");
  261. if (items.Length == 0) {
  262. return Copy(array);
  263. }
  264. T[] result = new T[array.Length + items.Length];
  265. if (index > 0) {
  266. Array.Copy(array, 0, result, 0, index);
  267. }
  268. Array.Copy(items, 0, result, index, items.Length);
  269. int remaining = array.Length - index;
  270. if (remaining > 0) {
  271. Array.Copy(array, array.Length - remaining, result, result.Length - remaining, remaining);
  272. }
  273. return result;
  274. }
  275. public static bool ValueEquals<T>(this T[] array, T[] other) {
  276. if (other.Length != array.Length) {
  277. return false;
  278. }
  279. for (int i = 0; i < array.Length; i++) {
  280. if (!Object.Equals(array[i], other[i])) {
  281. return false;
  282. }
  283. }
  284. return true;
  285. }
  286. public static int GetValueHashCode<T>(this T[] array) {
  287. return GetValueHashCode<T>(array, 0, array.Length);
  288. }
  289. public static int GetValueHashCode<T>(this T[] array, int start, int count) {
  290. ContractUtils.RequiresNotNull(array, "array");
  291. ContractUtils.RequiresArrayRange(array.Length, start, count, "start", "count");
  292. if (count == 0) {
  293. return 0;
  294. }
  295. int result = array[start].GetHashCode();
  296. for (int i = 1; i < count; i++) {
  297. result = ((result << 5) | (result >> 27)) ^ array[start + i].GetHashCode();
  298. }
  299. return result;
  300. }
  301. public static T[] Reverse<T>(this T[] array) {
  302. T[] res = new T[array.Length];
  303. for (int i = 0; i < array.Length; i++) {
  304. res[array.Length - i - 1] = array[i];
  305. }
  306. return res;
  307. }
  308. }
  309. }