/******************************************************************************
* 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
}
}