/****************************************************************************** * 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; using System.Collections.Generic; using UnityEngine; namespace Leap.Unity { public static class ReadonlySliceExtensions { /// /// Creates a readonlySlice into the ReadonlyList with an inclusive beginIdx and an _exclusive_ /// endIdx. A readonlySlice with identical begin and end indices would be an empty readonlySlice. /// /// A readonlySlice whose endIdx is smaller than its beginIdx will index backwards along the /// underlying ReadonlyList. /// /// 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). /// /// ReadonlySlices do not allocate, and they provide an enumerator definition so they can be /// used in a foreach statement. /// public static ReadonlySlice ReadonlySlice(this ReadonlyList list, int beginIdx = -1, int endIdx = -1) { if (beginIdx == -1 && endIdx == -1) { return new ReadonlySlice(list, 0, list.Count); } else if (beginIdx == -1 && endIdx != -1) { return new ReadonlySlice(list, 0, endIdx); } else if (endIdx == -1 && beginIdx != -1) { return new ReadonlySlice(list, beginIdx, list.Count); } else { return new ReadonlySlice(list, beginIdx, endIdx); } } public static ReadonlySlice FromIndex(this ReadonlyList list, int fromIdx) { return ReadonlySlice(list, fromIdx); } } public struct ReadonlySlice : IIndexableStruct> { private ReadonlyList _list; private int _beginIdx; private int _endIdx; private int _direction; /// /// Creates a readonlySlice into the ReadonlyList with an inclusive beginIdx and an _exclusive_ /// endIdx. A readonlySlice with identical begin and end indices would be an empty readonlySlice. /// /// A readonlySlice whose endIdx is smaller than its beginIdx will index backwards along the /// underlying ReadonlyList. /// public ReadonlySlice(ReadonlyList list, int beginIdx, int endIdx) { _list = list; _beginIdx = beginIdx; _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]; } } 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 } }