/****************************************************************************** * Copyright (C) Ultraleap, Inc. 2011-2021. * * * * Use subject to the terms of the Apache License 2.0 available at * * http://www.apache.org/licenses/LICENSE-2.0, or another agreement * * between Ultraleap and you, your company or other organization. * ******************************************************************************/ using Leap.Unity.Query; using System; using System.Collections.Generic; namespace Leap.Unity { public static class SliceExtensions { /// /// Creates a slice into the List with an inclusive beginIdx and an _exclusive_ /// endIdx. A slice with identical begin and end indices would be an empty slice. /// /// A slice whose endIdx is smaller than its beginIdx will index backwards along the /// underlying List. /// /// Not providing either index argument will simply refer to the beginning of the /// list (for beginIdx) or to the end of the list (for endIdx). /// /// Slices do not allocate, and they provide an enumerator definition so they can be /// used in a foreach statement. /// public static Slice Slice(this IList list, int beginIdx = -1, int endIdx = -1) { if (beginIdx == -1 && endIdx == -1) { return new Slice(list, 0, list.Count); } else if (beginIdx == -1 && endIdx != -1) { return new Slice(list, 0, endIdx); } else if (endIdx == -1 && beginIdx != -1) { return new Slice(list, beginIdx, list.Count); } else { return new Slice(list, beginIdx, endIdx); } } public static Slice FromIndex(this IList list, int fromIdx) { return Slice(list, fromIdx); } /// Creates a new array and returns it, with the contents of this /// slice. public static T[] ToArray(this Slice slice) { var array = new T[slice.Count]; for (int i = 0; i < slice.Count; i++) { array[i] = slice[i]; } return array; } } public struct Slice : IIndexableStruct> { private IList _list; private int _beginIdx; private int _endIdx; private int _direction; /// /// Creates a slice into the List with an inclusive beginIdx and an _exclusive_ /// endIdx. A slice with identical begin and end indices would be an empty slice. /// /// A slice whose endIdx is smaller than its beginIdx will index backwards along the /// underlying List. /// public Slice(IList list, int beginIdx = 0, int endIdx = -1) { _list = list; _beginIdx = beginIdx; if (endIdx == -1) endIdx = _list.Count; _endIdx = endIdx; _direction = beginIdx <= endIdx ? 1 : -1; } public T this[int index] { get { if (index < 0 || index > Count - 1) { throw new IndexOutOfRangeException(); } return _list[_beginIdx + index * _direction]; } set { if (index < 0 || index > Count - 1) { throw new IndexOutOfRangeException(); } _list[_beginIdx + index * _direction] = value; } } public int Count { get { return (_endIdx - _beginIdx) * _direction; } } #region foreach and Query() public IndexableStructEnumerator> GetEnumerator() { return new IndexableStructEnumerator>(this); } public Query Query() { T[] array = ArrayPool.Spawn(Count); for (int i = 0; i < Count; i++) { array[i] = this[i]; } return new Query(array, Count); } #endregion } }