| File: SetterSpecificityList.cs | Web Access |
| Project: src\src\Controls\src\Core\Controls.Core.csproj (Microsoft.Maui.Controls) |
#nullable disable using System; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace Microsoft.Maui.Controls { /// <summary> /// Stores values for a property with different specificities. /// </summary> internal class SetterSpecificityList<T> where T : class { const int CapacityDelta = 3; SetterSpecificity[] _keys; T[] _values; int _count; public int Count => _count; public T this[SetterSpecificity key] { set => SetValue(key, value); get => GetValue(key); } public SetterSpecificityList() { _keys = Array.Empty<SetterSpecificity>(); _values = Array.Empty<T>(); } public SetterSpecificityList(int initialCapacity) { if (initialCapacity == 0) { _keys = Array.Empty<SetterSpecificity>(); _values = Array.Empty<T>(); } else { _keys = new SetterSpecificity[initialCapacity]; _values = new T[initialCapacity]; } } /// <summary> /// Gets the highest specificity /// </summary> /// <returns></returns> public SetterSpecificity GetSpecificity() { var index = _count - 1; return index < 0 ? default : _keys[index]; } /// <summary> /// Gets the value for the highest specificity /// </summary> /// <returns></returns> public T GetValue() { var index = _count - 1; return index < 0 ? default : _values[index]; } /// <summary> /// Returns what the value would be if the current value was removed /// </summary> public T GetClearedValue() { var index = _count - 2; return index < 0 ? default : _values[index]; } /// <summary> /// Returns what the value would be if the specificity value was removed /// </summary> public T GetClearedValue(SetterSpecificity specificity) { var index = _count - 1; if (index >= 0 && _keys[index] == specificity) { --index; } return index < 0 ? default : _values[index]; } /// <summary> /// Returns what the SetterSpecificity would be if the current value was removed /// </summary> public SetterSpecificity GetClearedSpecificity() { var index = _count - 2; return index < 0 ? default : _keys[index]; } /// <summary> /// Gets the highest specificity and value /// </summary> /// <returns></returns> public KeyValuePair<SetterSpecificity, T> GetSpecificityAndValue() { var index = _count - 1; return index < 0 ? default : new KeyValuePair<SetterSpecificity, T>(_keys[index], _values[index]); } [MethodImpl(MethodImplOptions.AggressiveInlining)] void SetValue(SetterSpecificity key, T value) { var count = _count; var lo = 0; var hi = count - 1; while (lo <= hi) { var index = lo + ((hi - lo) >> 1); var indexSpecificity = _keys[index]; if (indexSpecificity == key) { _values[index] = value; return; } if (indexSpecificity < key) { lo = index + 1; } else { hi = index - 1; } } if (_keys.Length == count) { SetCapacity(count, count + CapacityDelta); } if (count > lo) { Array.Copy(_keys, lo, _keys, lo + 1, count - lo); Array.Copy(_values, lo, _values, lo + 1, count - lo); } _keys[lo] = key; _values[lo] = value; ++_count; } [MethodImpl(MethodImplOptions.AggressiveInlining)] T GetValue(SetterSpecificity key) { var count = _count; var lo = 0; var hi = count - 1; while (lo <= hi) { var index = lo + ((hi - lo) >> 1); var indexSpecificity = _keys[index]; if (indexSpecificity == key) { return _values[index]; } if (indexSpecificity < key) { lo = index + 1; } else { hi = index - 1; } } return default; } public void Remove(SetterSpecificity key) { var count = _count; var lo = 0; var hi = count - 1; while (lo <= hi) { var index = lo + ((hi - lo) >> 1); var indexSpecificity = _keys[index]; if (indexSpecificity == key) { var nextIndex = index + 1; if (nextIndex < count) { Array.Copy(_keys, nextIndex, _keys, index, count - nextIndex); Array.Copy(_values, nextIndex, _values, index, count - nextIndex); _values[count - 1] = null; } else { _values[index] = null; } --_count; return; } if (indexSpecificity < key) { lo = index + 1; } else { hi = index - 1; } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] void SetCapacity(int currentCapacity, int capacity) { var newKeys = new SetterSpecificity[capacity]; var newValues = new T[capacity]; if (currentCapacity > 0) { Array.Copy(_keys, newKeys, currentCapacity); Array.Copy(_values, newValues, currentCapacity); } _keys = newKeys; _values = newValues; } } }