Loading files
d2871d28eThis file is pinned to the selected release. Download the original to open it in your design tool.
/******************************************************************************
* Copyright (C) Leap Motion, Inc. 2011-2018. *
* Leap Motion proprietary and confidential. *
* *
* Use subject to the terms of the Leap Motion SDK Agreement available at *
* https://developer.leapmotion.com/sdk_agreement, or another agreement *
* between Leap Motion and you, your company or other organization. *
******************************************************************************/
using System;
using System.Collections.Generic;
namespace Leap.Unity.Query {
public static class QueryCollapseExtensions {
/// <summary>
/// Returns true if all elements in the Query satisfy the predicate.
/// </summary>
public static bool All<T>(this Query<T> query, Func<T, bool> predicate) {
using (var slice = query.Deconstruct()) {
for (int i = 0; i < slice.Count; i++) {
if (!predicate(slice[i])) {
return false;
}
}
return true;
}
}
/// <summary>
/// Returns true if all elements in the Query are equal to the same value.
/// Will always return true for Queries with one or zero elements.
/// </summary>
public static bool AllEqual<T>(this Query<T> query) {
using (var slice = query.Deconstruct()) {
if (slice.Count <= 1) {
return true;
}
var comparer = EqualityComparer<T>.Default;
var first = slice[0];
for (int i = 1; i < slice.Count; i++) {
if (!comparer.Equals(first, slice[i])) {
return false;
}
}
return true;
}
}
/// <summary>
/// Returns true if the Query has any elements in it.
/// </summary>
public static bool Any<T>(this Query<T> query) {
return query.Count() > 0;
}
/// <summary>
/// Returns true if any elements in the Query satisfy the predicate.
/// </summary>
public static bool Any<T>(this Query<T> query, Func<T, bool> predicate) {
using (var slice = query.Deconstruct()) {
for (int i = 0; i < slice.Count; i++) {
if (predicate(slice[i])) {
return true;
}
}
return false;
}
}
/// <summary>
/// Returns the average of a Query of floats.
/// </summary>
public static float Average(this Query<float> query) {
using (var slice = query.Deconstruct()) {
float sum = 0;
for (int i = 0; i < slice.Count; i++) {
sum += slice[i];
}
return sum / slice.Count;
}
}
/// <summary>
/// Returns the average of a Query of doubles.
/// </summary>
public static double Average(this Query<double> query) {
using (var slice = query.Deconstruct()) {
double sum = 0;
for (int i = 0; i < slice.Count; i++) {
sum += slice[i];
}
return sum / slice.Count;
}
}
/// <summary>
/// Returns true if any element in the Query is equal to a specific value.
/// </summary>
public static bool Contains<T>(this Query<T> query, T item) {
T[] array;
int count;
query.Deconstruct(out array, out count);
var comparer = EqualityComparer<T>.Default;
for (int i = 0; i < count; i++) {
if (comparer.Equals(item, array[i])) {
ArrayPool<T>.Recycle(array);
return true;
}
}
ArrayPool<T>.Recycle(array);
return false;
}
/// <summary>
/// Returns the number of elements in the Query.
/// </summary>
public static int Count<T>(this Query<T> query) {
using (var slice = query.Deconstruct()) {
return slice.Count;
}
}
/// <summary>
/// Returns the number of elements in the Query that satisfy a predicate.
/// </summary>
public static int Count<T>(this Query<T> query, Func<T, bool> predicate) {
return query.Where(predicate).Count();
}
/// <summary>
/// Counts the number of distinct elements in the Query.
/// </summary>
public static int CountUnique<T>(this Query<T> query) {
var slice = query.Deconstruct();
var set = Pool<HashSet<T>>.Spawn();
try {
for (int i = 0; i < slice.Count; i++) {
set.Add(slice[i]);
}
return set.Count;
} finally {
slice.Dispose();
set.Clear();
Pool<HashSet<T>>.Recycle(set);
}
}
/// <summary>
/// Returns the number of distinct elements in the Query once it has been mapped
/// using a selector function.
/// </summary>
public static int CountUnique<T, K>(this Query<T> query, Func<T, K> selector) {
return query.Select(selector).CountUnique();
}
/// <summary>
/// Returns the element at a specific index in the Query. Will throw an error
/// if the Query has no element at that index.
/// </summary>
public static T ElementAt<T>(this Query<T> query, int index) {
using (var slice = query.Deconstruct()) {
if (index < 0 || index >= slice.Count) {
throw new IndexOutOfRangeException("The index " + index + " was out of range. Query only has length of " + slice.Count);
}
return slice[index];
}
}
/// <summary>
/// Returns the element at a specific index in the Query. Will return
/// the default value if the Query has no element at that index.
/// </summary>
public static T ElementAtOrDefault<T>(this Query<T> query, int index) {
using (var slice = query.Deconstruct()) {
if (index < 0 || index >= slice.Count) {
return default(T);
}
return slice[index];
}
}
/// <summary>
/// Returns the first element in the Query. Will throw an error if there are
/// no elements in the Query.
/// </summary>
public static T First<T>(this Query<T> query) {
using (var slice = query.Deconstruct()) {
if (slice.Count == 0) {
throw new InvalidOperationException("The source Query was empty.");
}
return slice[0];
}
}
/// <summary>
/// Returns the first element in the Query that satisfies a predicate. Will
/// throw an error if there is no such element.
/// </summary>
public static T First<T>(this Query<T> query, Func<T, bool> predicate) {
return query.Where(predicate).First();
}
/// <summary>
/// Returns the first element in the Query. Will return the default value
/// if the Query is empty.
/// </summary>
public static T FirstOrDefault<T>(this Query<T> query) {
using (var slice = query.Deconstruct()) {
if (slice.Count == 0) {
return default(T);
}
return slice[0];
}
}
/// <summary>
/// Returns the first element in the Query that satisfies a predicate. Will return
/// the default value if there is no such element.
/// </summary>
public static T FirstOrDefault<T>(this Query<T> query, Func<T, bool> predicate) {
return query.Where(predicate).FirstOrDefault();
}
/// <summary>
/// Returns Some value that represents the first value in the Query, or None
/// if there is no such value.
/// </summary>
public static Maybe<T> FirstOrNone<T>(this Query<T> query) {
using (var slice = query.Deconstruct()) {
if (slice.Count == 0) {
return Maybe.None;
}
return Maybe.Some(slice[0]);
}
}
/// <summary>
/// Returns the Some value representing the first value that satisfies the predicate,
/// or None if there is no such value.
/// </summary>
public static Maybe<T> FirstOrNone<T>(this Query<T> query, Func<T, bool> predicate) {
return query.Where(predicate).FirstOrNone();
}
/// <summary>
/// Folds all of the elements in the Query into a single element, using a fold function.
/// Will throw an error if there are no elements in the Query.
///
/// The fold function takes in the current folded value, and the next item to fold in.
/// It returns the result of folding the item into the current folded value. For example,
/// you can use the Fold operation to implement a sum:
///
/// var sum = numbers.Query().Fold((a,b) => a + b);
/// </summary>
public static T Fold<T>(this Query<T> query, Func<T, T, T> foldFunc) {
using (var slice = query.Deconstruct()) {
if (slice.Count == 0) {
throw new InvalidOperationException("The source Query was empty.");
}
var result = slice[0];
for (int i = 1; i < slice.Count; i++) {
result = foldFunc(result, slice[i]);
}
return result;
}
}
/// <summary>
/// Returns the index of the first element that is equal to a specific value. Will return
/// a negative index if there is no such element.
/// </summary>
public static int IndexOf<T>(this Query<T> query, T t) {
using (var slice = query.Deconstruct()) {
var comparer = EqualityComparer<T>.Default;
for (int i = 0; i < slice.Count; i++) {
if (comparer.Equals(t, slice[i])) {
return i;
}
}
return -1;
}
}
/// <summary>
/// Returns the index of the first element to satisfy a predicate. Will return a negative
/// index if there is no such element.
/// </summary>
public static int IndexOf<T>(this Query<T> query, Func<T, bool> predicate) {
using (var slice = query.Deconstruct()) {
for (int i = 0; i < slice.Count; i++) {
if (predicate(slice[i])) {
return i;
}
}
return -1;
}
}
/// <summary>
/// Returns the last element in the Query. Will throw an error if the Query is empty.
/// </summary>
public static T Last<T>(this Query<T> query) {
using (var slice = query.Deconstruct()) {
if (slice.Count == 0) {
throw new InvalidOperationException("The source Query was empty.");
} else {
return slice[slice.Count - 1];
}
}
}
/// <summary>
/// Returns the last element in the Query that satisfies a predicate. Will throw an error
/// if there is no such element.
/// </summary>
public static T Last<T>(this Query<T> query, Func<T, bool> predicate) {
return query.Where(predicate).Last();
}
/// <summary>
/// Returns the last element in the Query. Will return the default value if the Query is empty.
/// </summary>
public static T LastOrDefault<T>(this Query<T> query) {
using (var slice = query.Deconstruct()) {
if (slice.Count == 0) {
return default(T);
} else {
return slice[slice.Count - 1];
}
}
}
/// <summary>
/// Returns the last element in the Query that satisfies a predicate. Will return
/// the default value if there is no such element.
/// </summary>
public static T LastOrDefault<T>(this Query<T> query, Func<T, bool> predicate) {
return query.Where(predicate).LastOrDefault();
}
/// <summary>
/// Returns Some value that represents the last value in the Query, or None
/// if there is no such value.
/// </summary>
public static Maybe<T> LastOrNone<T>(this Query<T> query) {
using (var slice = query.Deconstruct()) {
if (slice.Count == 0) {
return Maybe.None;
} else {
return Maybe.Some(slice[slice.Count - 1]);
}
}
}
/// <summary>
/// Returns the Some value representing the last value that satisfies the predicate,
/// or None if there is no such value.
/// </summary>
public static Maybe<T> LastOrNone<T>(this Query<T> query, Func<T, bool> predicate) {
return query.Where(predicate).LastOrNone();
}
/// <summary>
/// Returns the largest element in the Query.
/// </summary>
public static T Max<T>(this Query<T> query) where T : IComparable<T> {
return query.Fold(FoldDelegate<T>.max);
}
/// <summary>
/// Returns the largest element in the Query after it has been mapped using a selector function.
/// </summary>
public static K Max<T, K>(this Query<T> query, Func<T, K> selector) where K : IComparable<K> {
return query.Select(selector).Max();
}
/// <summary>
/// Returns the smallest element in the Query.
/// </summary>
public static T Min<T>(this Query<T> query) where T : IComparable<T> {
return query.Fold(FoldDelegate<T>.min);
}
/// <summary>
/// Returns the smallest element in the Query after it has been mapped using a selector function.
/// </summary>
public static K Min<T, K>(this Query<T> query, Func<T, K> selector) where K : IComparable<K> {
return query.Select(selector).Min();
}
/// <summary>
/// Returns the first and only element in the Query. Will throw an error if the length of the
/// Query is anything other than 1.
/// </summary>
public static T Single<T>(this Query<T> query) {
using (var slice = query.Deconstruct()) {
if (slice.Count != 1) {
throw new InvalidOperationException("The Query had a count of " + slice.Count + " instead of a count of 1.");
} else {
return slice[0];
}
}
}
/// <summary>
/// Returns the first and only element in the Query that satisfies the predicate. Will throw
/// an error if the number of such elements is anything other than 1.
/// </summary>
public static T Single<T>(this Query<T> query, Func<T, bool> predicate) {
return query.Where(predicate).Single();
}
/// <summary>
/// Returns the first and only element in the Query. Will return the default value if the number
/// of elements is anything other than 1.
/// </summary>
public static T SingleOrDefault<T>(this Query<T> query) {
using (var slice = query.Deconstruct()) {
if (slice.Count != 1) {
return default(T);
} else {
return slice[0];
}
}
}
/// <summary>
/// Returns the first and only element in the Query that satisfies the predicate. Will return
/// the default value if the number of such elements is anything other than 1.
/// </summary>
public static T SingleOrDefault<T>(this Query<T> query, Func<T, bool> predicate) {
return query.Where(predicate).SingleOrDefault();
}
/// <summary>
/// Returns the first and only element in the Query. Will return None if the number
/// of elements is anything other than 1.
/// </summary>
public static Maybe<T> SingleOrNone<T>(this Query<T> query) {
using (var slice = query.Deconstruct()) {
if (slice.Count != 1) {
return Maybe.None;
} else {
return Maybe.Some(slice[0]);
}
}
}
/// <summary>
/// Returns the first and only element in the Query that satisfies the predicate. Will return
/// None if the number of such elements is anything other than 1.
/// </summary>
public static Maybe<T> SingleOrNone<T>(this Query<T> query, Func<T, bool> predicate) {
return query.Where(predicate).SingleOrNone();
}
/// <summary>
/// Returns the sum of a Query of ints.
/// </summary>
public static int Sum(this Query<int> query) {
return query.Fold((a, b) => a + b);
}
/// <summary>
/// Returns the sum of a Query of floats.
/// </summary>
public static float Sum(this Query<float> query) {
return query.Fold((a, b) => a + b);
}
/// <summary>
/// Returns the sum of a Query of doubles.
/// </summary>
public static double Sum(this Query<double> query) {
return query.Fold((a, b) => a + b);
}
/// <summary>
/// Returns the single value that is present in the entire Query. If there is more
/// than one value in the Query or there are no values at all, this method will return
/// the default value.
/// </summary>
public static T UniformOrDefault<T>(this Query<T> query) {
return query.UniformOrNone().valueOrDefault;
}
/// <summary>
/// Returns Some single value that is present in the entire Query. If there is more
/// than one value in the Query or there are no values at all, this method will return
/// None.
/// </summary>
public static Maybe<T> UniformOrNone<T>(this Query<T> query) {
using (var slice = query.Deconstruct()) {
if (slice.Count == 0) {
return Maybe.None;
}
var array = slice;
T reference = array[0];
var comparer = EqualityComparer<T>.Default;
for (int i = 1; i < slice.Count; i++) {
if (!comparer.Equals(reference, slice[i])) {
return Maybe.None;
}
}
return Maybe.Some(reference);
}
}
/// <summary>
/// Converts the Query into an array.
/// </summary>
public static T[] ToArray<T>(this Query<T> query) {
using (var slice = query.Deconstruct()) {
T[] result = new T[slice.Count];
Array.Copy(slice.BackingArray, result, slice.Count);
return result;
}
}
/// <summary>
/// Copies the elements of the Query into an array. Can optionally specify the offset into the array
/// where to copy.
/// </summary>
public static void FillArray<T>(this Query<T> query, T[] array, int offset = 0) {
using (var slice = query.Deconstruct()) {
Array.Copy(slice.BackingArray, 0, array, offset, slice.Count);
}
}
/// <summary>
/// Converts the Query into a list.
/// </summary>
public static List<T> ToList<T>(this Query<T> query) {
using (var slice = query.Deconstruct()) {
List<T> result = new List<T>(slice.Count);
for (int i = 0; i < slice.Count; i++) {
result.Add(slice[i]);
}
return result;
}
}
/// <summary>
/// Fills a given list with the elements in this Query. The list is cleared before the fill happens.
/// </summary>
public static void FillList<T>(this Query<T> query, List<T> list) {
list.Clear();
query.AppendList(list);
}
/// <summary>
/// Appends the elements in this Query to the end of a given list.
/// </summary>
public static void AppendList<T>(this Query<T> query, List<T> list) {
using (var slice = query.Deconstruct()) {
for (int i = 0; i < slice.Count; i++) {
list.Add(slice[i]);
}
}
}
/// <summary>
/// Converts the Query into a HashSet.
/// </summary>
public static HashSet<T> ToHashSet<T>(this Query<T> query) {
HashSet<T> set = new HashSet<T>();
query.AppendHashSet(set);
return set;
}
/// <summary>
/// Fills a given HashSet with the elements in the Query. The set is cleared before the fill happens.
/// </summary>
public static void FillHashSet<T>(this Query<T> query, HashSet<T> set) {
set.Clear();
query.AppendHashSet(set);
}
/// <summary>
/// Appends the elements in this Query into the given HashSet.
/// </summary>
public static void AppendHashSet<T>(this Query<T> query, HashSet<T> set) {
using (var slice = query.Deconstruct()) {
for (int i = 0; i < slice.Count; i++) {
set.Add(slice[i]);
}
}
}
/// <summary>
/// Converts the Query into a Dictionary using a specific key selector and value selector.
/// </summary>
public static Dictionary<K, V> ToDictionary<T, K, V>(this Query<T> query, Func<T, K> keySelector, Func<T, V> valueSelector) {
using (var slice = query.Deconstruct()) {
Dictionary<K, V> dictionary = new Dictionary<K, V>();
for (int i = 0; i < slice.Count; i++) {
dictionary[keySelector(slice[i])] = valueSelector(slice[i]);
}
return dictionary;
}
}
/// <summary>
/// Converts the Query into a Dictionary using the query elements as keys, and using a value selector
/// to select the value tied to the key.
/// </summary>
public static Dictionary<T, V> ToDictionary<T, V>(this Query<T> query, Func<T, V> valueSelector) {
return query.ToDictionary(t => t, valueSelector);
}
private static class FoldDelegate<T> where T : IComparable<T> {
public readonly static Func<T, T, T> max = (a, b) => a.CompareTo(b) > 0 ? a : b;
public readonly static Func<T, T, T> min = (a, b) => a.CompareTo(b) < 0 ? a : b;
}
}
}