/// <summary> /// Ensures the given indexes falls into the lengths and capacities of the underlying array. If not, the /// capacities and lengths are updated accordingly. A new underlyting array may be allocated in order to adapt /// capacities. /// </summary> /// <param name="indexes"> The indexes that must fall within the array. </param> private void UpdateCountsAndCapacities(int[] indexes) { int[] newCounts = IndexesHelper.Zero(this.Rank); int[] newCapacities = IndexesHelper.Zero(this.Rank); bool newArrayNeeded = false; bool newCountsNeeded = false; for (int dimension = 0; dimension < this.Rank; ++dimension) { int requestedIndex = indexes[dimension]; int currentCapacity = this.GetCapacity(dimension); int currentCount = this.GetCount(dimension); newCounts[dimension] = currentCount; newCapacities[dimension] = currentCapacity; if (requestedIndex < currentCount) { continue; } newCountsNeeded = true; newCounts[dimension] = requestedIndex + 1; if (newCounts[dimension] <= currentCapacity) { continue; } newCapacities[dimension] = Math.Max(2 * currentCapacity, newCounts[dimension]); newArrayNeeded = true; } if (!newCountsNeeded) { return; } if (newArrayNeeded) { Array newData = Array.CreateInstance(typeof(T), newCapacities); IndexesEnumerator ienum = new IndexesEnumerator(IndexesHelper.UpperBound(this.buffer)); foreach (int[] idx in ienum) { newData.SetValue(this.buffer.GetValue(idx), idx); } this.buffer = newData; } // NOTE New lengths are set after allocation to avoid lengths corruption on failure. Array.Copy(newCounts, this.counts, this.counts.Length); }
public static IndexesEnumerator Enumerate(Array arr, bool reverse) { return(new IndexesEnumerator(IndexesHelper.UpperBound(arr), IndexesHelper.Zero(arr.Rank), reverse)); }