PageRenderTime 66ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/corlib/System/Array.cs

http://github.com/mono/mono
C# | 778 lines | 547 code | 141 blank | 90 comment | 117 complexity | fcc41ddc941944c5ac68bca22bc06ba9 MD5 | raw file
Possible License(s): GPL-2.0, CC-BY-SA-3.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, LGPL-2.1, Unlicense, Apache-2.0
  1. //
  2. // System.Array.cs
  3. //
  4. // Authors:
  5. // Joe Shaw (joe@ximian.com)
  6. // Martin Baulig (martin@gnome.org)
  7. // Dietmar Maurer (dietmar@ximian.com)
  8. // Gonzalo Paniagua Javier (gonzalo@ximian.com)
  9. // Jeffrey Stedfast (fejj@novell.com)
  10. // Marek Safar (marek.safar@gmail.com)
  11. //
  12. // (C) 2001-2003 Ximian, Inc. http://www.ximian.com
  13. // Copyright (C) 2004-2011 Novell, Inc (http://www.novell.com)
  14. // Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
  15. //
  16. // Permission is hereby granted, free of charge, to any person obtaining
  17. // a copy of this software and associated documentation files (the
  18. // "Software"), to deal in the Software without restriction, including
  19. // without limitation the rights to use, copy, modify, merge, publish,
  20. // distribute, sublicense, and/or sell copies of the Software, and to
  21. // permit persons to whom the Software is furnished to do so, subject to
  22. // the following conditions:
  23. //
  24. // The above copyright notice and this permission notice shall be
  25. // included in all copies or substantial portions of the Software.
  26. //
  27. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  28. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  29. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  30. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  31. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  32. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  33. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  34. //
  35. using System.Collections;
  36. using System.Runtime.CompilerServices;
  37. using System.Runtime.InteropServices;
  38. using System.Collections.Generic;
  39. using System.Collections.ObjectModel;
  40. using System.Runtime.ConstrainedExecution;
  41. namespace System
  42. {
  43. public abstract partial class Array
  44. {
  45. // Constructor
  46. private Array ()
  47. {
  48. }
  49. /*
  50. * These methods are used to implement the implicit generic interfaces
  51. * implemented by arrays in NET 2.0.
  52. * Only make those methods generic which really need it, to avoid
  53. * creating useless instantiations.
  54. */
  55. internal int InternalArray__ICollection_get_Count ()
  56. {
  57. return Length;
  58. }
  59. internal bool InternalArray__ICollection_get_IsReadOnly ()
  60. {
  61. return true;
  62. }
  63. // adapted to the Mono array layout
  64. [StructLayout(LayoutKind.Sequential)]
  65. private class RawData
  66. {
  67. public IntPtr Bounds;
  68. public IntPtr Count;
  69. public byte Data;
  70. }
  71. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  72. internal ref byte GetRawSzArrayData()
  73. {
  74. return ref Unsafe.As<RawData>(this).Data;
  75. }
  76. internal IEnumerator<T> InternalArray__IEnumerable_GetEnumerator<T> ()
  77. {
  78. if (Length == 0)
  79. return EmptyInternalEnumerator<T>.Value;
  80. else
  81. return new InternalEnumerator<T> (this);
  82. }
  83. internal void InternalArray__ICollection_Clear ()
  84. {
  85. throw new NotSupportedException ("Collection is read-only");
  86. }
  87. internal void InternalArray__ICollection_Add<T> (T item)
  88. {
  89. throw new NotSupportedException ("Collection is of a fixed size");
  90. }
  91. internal bool InternalArray__ICollection_Remove<T> (T item)
  92. {
  93. throw new NotSupportedException ("Collection is of a fixed size");
  94. }
  95. internal bool InternalArray__ICollection_Contains<T> (T item)
  96. {
  97. if (this.Rank > 1)
  98. throw new RankException ("Only single dimension arrays are supported.");
  99. int length = this.Length;
  100. for (int i = 0; i < length; i++) {
  101. T value;
  102. // Do not change this to call GetGenericValue_icall directly, due to special casing in the runtime.
  103. GetGenericValueImpl (i, out value);
  104. if (item == null){
  105. if (value == null) {
  106. return true;
  107. }
  108. continue;
  109. }
  110. if (item.Equals (value)) {
  111. return true;
  112. }
  113. }
  114. return false;
  115. }
  116. internal void InternalArray__ICollection_CopyTo<T> (T[] array, int arrayIndex)
  117. {
  118. Copy (this, GetLowerBound (0), array, arrayIndex, Length);
  119. }
  120. internal T InternalArray__IReadOnlyList_get_Item<T> (int index)
  121. {
  122. if (unchecked ((uint) index) >= unchecked ((uint) Length))
  123. throw new ArgumentOutOfRangeException ("index");
  124. T value;
  125. // Do not change this to call GetGenericValue_icall directly, due to special casing in the runtime.
  126. GetGenericValueImpl (index, out value);
  127. return value;
  128. }
  129. internal int InternalArray__IReadOnlyCollection_get_Count ()
  130. {
  131. return Length;
  132. }
  133. internal void InternalArray__Insert<T> (int index, T item)
  134. {
  135. throw new NotSupportedException ("Collection is of a fixed size");
  136. }
  137. internal void InternalArray__RemoveAt (int index)
  138. {
  139. throw new NotSupportedException ("Collection is of a fixed size");
  140. }
  141. internal int InternalArray__IndexOf<T> (T item)
  142. {
  143. if (this.Rank > 1)
  144. throw new RankException ("Only single dimension arrays are supported.");
  145. int length = this.Length;
  146. for (int i = 0; i < length; i++) {
  147. T value;
  148. // Do not change this to call GetGenericValue_icall directly, due to special casing in the runtime.
  149. GetGenericValueImpl (i, out value);
  150. if (item == null){
  151. if (value == null)
  152. return i + this.GetLowerBound (0);
  153. continue;
  154. }
  155. if (value.Equals (item))
  156. // array index may not be zero-based.
  157. // use lower bound
  158. return i + this.GetLowerBound (0);
  159. }
  160. unchecked {
  161. // lower bound may be MinValue
  162. return this.GetLowerBound (0) - 1;
  163. }
  164. }
  165. internal T InternalArray__get_Item<T> (int index)
  166. {
  167. if (unchecked ((uint) index) >= unchecked ((uint) Length))
  168. throw new ArgumentOutOfRangeException ("index");
  169. T value;
  170. // Do not change this to call GetGenericValue_icall directly, due to special casing in the runtime.
  171. GetGenericValueImpl (index, out value);
  172. return value;
  173. }
  174. internal void InternalArray__set_Item<T> (int index, T item)
  175. {
  176. if (unchecked ((uint) index) >= unchecked ((uint) Length))
  177. throw new ArgumentOutOfRangeException ("index");
  178. object[] oarray = this as object [];
  179. if (oarray != null) {
  180. oarray [index] = (object)item;
  181. return;
  182. }
  183. // Do not change this to call SetGenericValue_icall directly, due to special casing in the runtime.
  184. SetGenericValueImpl (index, ref item);
  185. }
  186. // CAUTION! No bounds checking!
  187. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  188. extern static void GetGenericValue_icall<T> (ref Array self, int pos, out T value);
  189. // CAUTION! No bounds checking!
  190. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  191. extern static void SetGenericValue_icall<T> (ref Array self, int pos, ref T value);
  192. // This is a special case in the runtime.
  193. internal void GetGenericValueImpl<T> (int pos, out T value)
  194. {
  195. var self = this;
  196. GetGenericValue_icall (ref self, pos, out value);
  197. }
  198. // This is a special case in the runtime.
  199. internal void SetGenericValueImpl<T> (int pos, ref T value)
  200. {
  201. var self = this;
  202. SetGenericValue_icall (ref self, pos, ref value);
  203. }
  204. internal struct InternalEnumerator<T> : IEnumerator<T>
  205. {
  206. const int NOT_STARTED = -2;
  207. // this MUST be -1, because we depend on it in move next.
  208. // we just decr the size, so, 0 - 1 == FINISHED
  209. const int FINISHED = -1;
  210. readonly Array array;
  211. int idx;
  212. internal InternalEnumerator (Array array)
  213. {
  214. this.array = array;
  215. idx = NOT_STARTED;
  216. }
  217. public void Dispose ()
  218. {
  219. }
  220. public bool MoveNext ()
  221. {
  222. if (idx == NOT_STARTED)
  223. idx = array.Length;
  224. return idx != FINISHED && -- idx != FINISHED;
  225. }
  226. public T Current {
  227. get {
  228. if (idx == NOT_STARTED)
  229. throw new InvalidOperationException ("Enumeration has not started. Call MoveNext");
  230. if (idx == FINISHED)
  231. throw new InvalidOperationException ("Enumeration already finished");
  232. return array.InternalArray__get_Item<T> (array.Length - 1 - idx);
  233. }
  234. }
  235. void IEnumerator.Reset ()
  236. {
  237. idx = NOT_STARTED;
  238. }
  239. object IEnumerator.Current {
  240. get {
  241. return Current;
  242. }
  243. }
  244. }
  245. // Properties
  246. public int Length {
  247. [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
  248. get {
  249. int length = this.GetLength (0);
  250. for (int i = 1; i < this.Rank; i++) {
  251. length *= this.GetLength (i);
  252. }
  253. return length;
  254. }
  255. }
  256. public int Rank {
  257. [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
  258. get {
  259. return this.GetRank ();
  260. }
  261. }
  262. internal class EmptyInternalEnumerator<T> : IEnumerator<T>
  263. {
  264. public static readonly EmptyInternalEnumerator<T> Value = new EmptyInternalEnumerator<T> ();
  265. public void Dispose ()
  266. {
  267. return;
  268. }
  269. public bool MoveNext ()
  270. {
  271. return false;
  272. }
  273. public T Current {
  274. get {
  275. throw new InvalidOperationException ("Enumeration has not started. Call MoveNext");
  276. }
  277. }
  278. object IEnumerator.Current {
  279. get {
  280. return Current;
  281. }
  282. }
  283. void IEnumerator.Reset ()
  284. {
  285. return;
  286. }
  287. }
  288. // InternalCall Methods
  289. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  290. extern int GetRank ();
  291. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  292. public extern int GetLength (int dimension);
  293. [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
  294. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  295. public extern int GetLowerBound (int dimension);
  296. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  297. public extern object GetValue (params int[] indices);
  298. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  299. public extern void SetValue (object value, params int[] indices);
  300. // CAUTION! No bounds checking!
  301. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  302. internal extern object GetValueImpl (int pos);
  303. // CAUTION! No bounds checking!
  304. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  305. internal extern void SetValueImpl (object value, int pos);
  306. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  307. internal extern static bool FastCopy (Array source, int source_idx, Array dest, int dest_idx, int length);
  308. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  309. internal extern static Array CreateInstanceImpl (Type elementType, int[] lengths, int[] bounds);
  310. [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
  311. public int GetUpperBound (int dimension)
  312. {
  313. return GetLowerBound (dimension) + GetLength (dimension) - 1;
  314. }
  315. public object GetValue (int index)
  316. {
  317. if (Rank != 1)
  318. throw new ArgumentException (SR.Arg_RankMultiDimNotSupported);
  319. var lb = GetLowerBound (0);
  320. if (index < lb || index > GetUpperBound (0))
  321. throw new IndexOutOfRangeException ("Index has to be between upper and lower bound of the array.");
  322. if (GetType ().GetElementType ().IsPointer)
  323. throw new NotSupportedException ("Type is not supported.");
  324. return GetValueImpl (index - lb);
  325. }
  326. public object GetValue (int index1, int index2)
  327. {
  328. int[] ind = {index1, index2};
  329. return GetValue (ind);
  330. }
  331. public object GetValue (int index1, int index2, int index3)
  332. {
  333. int[] ind = {index1, index2, index3};
  334. return GetValue (ind);
  335. }
  336. public void SetValue (object value, int index)
  337. {
  338. if (Rank != 1)
  339. throw new ArgumentException (SR.Arg_RankMultiDimNotSupported);
  340. var lb = GetLowerBound (0);
  341. if (index < lb || index > GetUpperBound (0))
  342. throw new IndexOutOfRangeException ("Index has to be >= lower bound and <= upper bound of the array.");
  343. if (GetType ().GetElementType ().IsPointer)
  344. throw new NotSupportedException ("Type is not supported.");
  345. SetValueImpl (value, index - lb);
  346. }
  347. public void SetValue (object value, int index1, int index2)
  348. {
  349. int[] ind = {index1, index2};
  350. SetValue (value, ind);
  351. }
  352. public void SetValue (object value, int index1, int index2, int index3)
  353. {
  354. int[] ind = {index1, index2, index3};
  355. SetValue (value, ind);
  356. }
  357. internal static Array UnsafeCreateInstance(Type elementType, int[] lengths, int[] lowerBounds)
  358. {
  359. return CreateInstance(elementType, lengths, lowerBounds);
  360. }
  361. internal static Array UnsafeCreateInstance (Type elementType, int length1, int length2)
  362. {
  363. return CreateInstance (elementType, length1, length2);
  364. }
  365. internal static Array UnsafeCreateInstance (Type elementType, params int[] lengths)
  366. {
  367. return CreateInstance(elementType, lengths);
  368. }
  369. public static Array CreateInstance (Type elementType, int length)
  370. {
  371. int[] lengths = {length};
  372. return CreateInstance (elementType, lengths);
  373. }
  374. public static Array CreateInstance (Type elementType, int length1, int length2)
  375. {
  376. int[] lengths = {length1, length2};
  377. return CreateInstance (elementType, lengths);
  378. }
  379. public static Array CreateInstance (Type elementType, int length1, int length2, int length3)
  380. {
  381. int[] lengths = {length1, length2, length3};
  382. return CreateInstance (elementType, lengths);
  383. }
  384. public static Array CreateInstance (Type elementType, params int[] lengths)
  385. {
  386. if (elementType == null)
  387. throw new ArgumentNullException ("elementType");
  388. if (lengths == null)
  389. throw new ArgumentNullException ("lengths");
  390. if (lengths.Length > 255)
  391. throw new TypeLoadException ();
  392. int[] bounds = null;
  393. elementType = elementType.UnderlyingSystemType as RuntimeType;
  394. if (elementType == null)
  395. throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
  396. if (elementType.Equals (typeof (void)))
  397. throw new NotSupportedException ("Array type can not be void");
  398. if (elementType.ContainsGenericParameters)
  399. throw new NotSupportedException ("Array type can not be an open generic type");
  400. return CreateInstanceImpl (elementType, lengths, bounds);
  401. }
  402. public static Array CreateInstance (Type elementType, int[] lengths, int [] lowerBounds)
  403. {
  404. if (elementType == null)
  405. throw new ArgumentNullException ("elementType");
  406. if (lengths == null)
  407. throw new ArgumentNullException ("lengths");
  408. if (lowerBounds == null)
  409. throw new ArgumentNullException ("lowerBounds");
  410. elementType = elementType.UnderlyingSystemType as RuntimeType;
  411. if (elementType == null)
  412. throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
  413. if (elementType.Equals (typeof (void)))
  414. throw new NotSupportedException ("Array type can not be void");
  415. if (elementType.ContainsGenericParameters)
  416. throw new NotSupportedException ("Array type can not be an open generic type");
  417. if (lengths.Length < 1)
  418. throw new ArgumentException ("Arrays must contain >= 1 elements.");
  419. if (lengths.Length != lowerBounds.Length)
  420. throw new ArgumentException ("Arrays must be of same size.");
  421. for (int j = 0; j < lowerBounds.Length; j ++) {
  422. if (lengths [j] < 0)
  423. throw new ArgumentOutOfRangeException ("lengths", "Each value has to be >= 0.");
  424. if ((long)lowerBounds [j] + (long)lengths [j] > (long)Int32.MaxValue)
  425. throw new ArgumentOutOfRangeException ("lengths", "Length + bound must not exceed Int32.MaxValue.");
  426. }
  427. if (lengths.Length > 255)
  428. throw new TypeLoadException ();
  429. return CreateInstanceImpl (elementType, lengths, lowerBounds);
  430. }
  431. [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
  432. public static void Clear (Array array, int index, int length)
  433. {
  434. if (array == null)
  435. throw new ArgumentNullException ("array");
  436. if (length < 0)
  437. throw new IndexOutOfRangeException ("length < 0");
  438. int low = array.GetLowerBound (0);
  439. if (index < low)
  440. throw new IndexOutOfRangeException ("index < lower bound");
  441. index = index - low;
  442. // re-ordered to avoid possible integer overflow
  443. if (index > array.Length - length)
  444. throw new IndexOutOfRangeException ("index + length > size");
  445. ClearInternal (array, index, length);
  446. }
  447. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  448. static extern void ClearInternal (Array a, int index, int count);
  449. [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
  450. public static void Copy (Array sourceArray, Array destinationArray, int length)
  451. {
  452. // need these checks here because we are going to use
  453. // GetLowerBound() on source and dest.
  454. if (sourceArray == null)
  455. throw new ArgumentNullException ("sourceArray");
  456. if (destinationArray == null)
  457. throw new ArgumentNullException ("destinationArray");
  458. Copy (sourceArray, sourceArray.GetLowerBound (0), destinationArray,
  459. destinationArray.GetLowerBound (0), length);
  460. }
  461. [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
  462. public static void Copy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
  463. {
  464. if (sourceArray == null)
  465. throw new ArgumentNullException ("sourceArray");
  466. if (destinationArray == null)
  467. throw new ArgumentNullException ("destinationArray");
  468. if (length < 0)
  469. throw new ArgumentOutOfRangeException ("length", "Value has to be >= 0.");
  470. if (sourceArray.Rank != destinationArray.Rank)
  471. throw new RankException(SR.Rank_MultiDimNotSupported);
  472. if (sourceIndex < 0)
  473. throw new ArgumentOutOfRangeException ("sourceIndex", "Value has to be >= 0.");
  474. if (destinationIndex < 0)
  475. throw new ArgumentOutOfRangeException ("destinationIndex", "Value has to be >= 0.");
  476. if (FastCopy (sourceArray, sourceIndex, destinationArray, destinationIndex, length))
  477. return;
  478. int source_pos = sourceIndex - sourceArray.GetLowerBound (0);
  479. int dest_pos = destinationIndex - destinationArray.GetLowerBound (0);
  480. if (dest_pos < 0)
  481. throw new ArgumentOutOfRangeException ("destinationIndex", "Index was less than the array's lower bound in the first dimension.");
  482. // re-ordered to avoid possible integer overflow
  483. if (source_pos > sourceArray.Length - length)
  484. throw new ArgumentException ("length");
  485. if (dest_pos > destinationArray.Length - length) {
  486. throw new ArgumentException ("Destination array was not long enough. Check destIndex and length, and the array's lower bounds", nameof (destinationArray));
  487. }
  488. Type src_type = sourceArray.GetType ().GetElementType ();
  489. Type dst_type = destinationArray.GetType ().GetElementType ();
  490. var dst_type_vt = dst_type.IsValueType;
  491. if (!Object.ReferenceEquals (sourceArray, destinationArray) || source_pos > dest_pos) {
  492. for (int i = 0; i < length; i++) {
  493. Object srcval = sourceArray.GetValueImpl (source_pos + i);
  494. if (srcval == null && dst_type_vt)
  495. throw new InvalidCastException ();
  496. try {
  497. destinationArray.SetValueImpl (srcval, dest_pos + i);
  498. } catch (ArgumentException) {
  499. throw CreateArrayTypeMismatchException ();
  500. } catch (InvalidCastException) {
  501. if (CanAssignArrayElement (src_type, dst_type))
  502. throw;
  503. throw CreateArrayTypeMismatchException ();
  504. }
  505. }
  506. }
  507. else {
  508. for (int i = length - 1; i >= 0; i--) {
  509. Object srcval = sourceArray.GetValueImpl (source_pos + i);
  510. try {
  511. destinationArray.SetValueImpl (srcval, dest_pos + i);
  512. } catch (ArgumentException) {
  513. throw CreateArrayTypeMismatchException ();
  514. } catch {
  515. if (CanAssignArrayElement (src_type, dst_type))
  516. throw;
  517. throw CreateArrayTypeMismatchException ();
  518. }
  519. }
  520. }
  521. }
  522. static ArrayTypeMismatchException CreateArrayTypeMismatchException ()
  523. {
  524. return new ArrayTypeMismatchException ();
  525. }
  526. static bool CanAssignArrayElement (Type source, Type target)
  527. {
  528. if (source.IsValueType)
  529. return source.IsAssignableFrom (target);
  530. if (source.IsInterface)
  531. return !target.IsValueType;
  532. if (target.IsInterface)
  533. return !source.IsValueType;
  534. return source.IsAssignableFrom (target) || target.IsAssignableFrom (source);
  535. }
  536. [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
  537. //
  538. // The constrained copy should guarantee that if there is an exception thrown
  539. // during the copy, the destination array remains unchanged.
  540. // This is related to System.Runtime.Reliability.CER
  541. public static void ConstrainedCopy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
  542. {
  543. Copy (sourceArray, sourceIndex, destinationArray, destinationIndex, length);
  544. }
  545. public static T[] Empty<T>()
  546. {
  547. return EmptyArray<T>.Value;
  548. }
  549. public void Initialize()
  550. {
  551. return;
  552. }
  553. static int IndexOfImpl<T>(T[] array, T value, int startIndex, int count)
  554. {
  555. #if NETCORE
  556. throw new NotImplementedException ();
  557. #else
  558. return EqualityComparer<T>.Default.IndexOf (array, value, startIndex, count);
  559. #endif
  560. }
  561. static int LastIndexOfImpl<T>(T[] array, T value, int startIndex, int count)
  562. {
  563. #if NETCORE
  564. throw new NotImplementedException ();
  565. #else
  566. return EqualityComparer<T>.Default.LastIndexOf (array, value, startIndex, count);
  567. #endif
  568. }
  569. static void SortImpl (Array keys, Array items, int index, int length, IComparer comparer)
  570. {
  571. Object[] objKeys = keys as Object[];
  572. Object[] objItems = null;
  573. if (objKeys != null)
  574. objItems = items as Object[];
  575. if (objKeys != null && (items == null || objItems != null)) {
  576. SorterObjectArray sorter = new SorterObjectArray(objKeys, objItems, comparer);
  577. sorter.Sort(index, length);
  578. } else {
  579. SorterGenericArray sorter = new SorterGenericArray(keys, items, comparer);
  580. sorter.Sort(index, length);
  581. }
  582. }
  583. #region Unsafe array operations
  584. //
  585. // Loads array index with no safety checks (JIT intristics)
  586. //
  587. internal static T UnsafeLoad<T> (T[] array, int index) {
  588. return array [index];
  589. }
  590. //
  591. // Stores values at specified array index with no safety checks (JIT intristics)
  592. //
  593. internal static void UnsafeStore<T> (T[] array, int index, T value) {
  594. array [index] = value;
  595. }
  596. //
  597. // Moved value from instance into target of different type with no checks (JIT intristics)
  598. //
  599. // Restrictions:
  600. //
  601. // S and R must either:
  602. // both be blitable valuetypes
  603. // both be reference types (IOW, an unsafe cast)
  604. // S and R cannot be float or double
  605. // S and R must either:
  606. // both be a struct
  607. // both be a scalar
  608. // S and R must either:
  609. // be of same size
  610. // both be a scalar of size <= 4
  611. //
  612. internal static R UnsafeMov<S,R> (S instance) {
  613. return (R)(object) instance;
  614. }
  615. #endregion
  616. internal sealed class FunctorComparer<T> : IComparer<T> {
  617. Comparison<T> comparison;
  618. public FunctorComparer(Comparison<T> comparison) {
  619. this.comparison = comparison;
  620. }
  621. public int Compare(T x, T y) {
  622. return comparison(x, y);
  623. }
  624. }
  625. partial class ArrayEnumerator
  626. {
  627. public Object Current {
  628. get {
  629. if (_index < 0) throw new InvalidOperationException (SR.InvalidOperation_EnumNotStarted);
  630. if (_index >= _endIndex) throw new InvalidOperationException (SR.InvalidOperation_EnumEnded);
  631. if (_index == 0 && _array.GetType ().GetElementType ().IsPointer) throw new NotSupportedException ("Type is not supported.");
  632. return _array.GetValueImpl(_index);
  633. }
  634. }
  635. }
  636. }
  637. }