private int RemoveHelper(int removeAt, int count, SortedRangeValueList <T> moveRanges) { if (removeAt >= Count) { return(rangeValues.Count); } int n = Split(removeAt); Split(removeAt + count); int total = 0; int deleteCount = 0; while (total < count && n + deleteCount < rangeValues.Count) { RangeValuePair <T> rv = rangeValues[n + deleteCount]; total += rv.Count; deleteCount++; if (moveRanges != null && !rv.Value.Equals(defaultValue)) { moveRanges.rangeValues.Add(new RangeValuePair <T>(rv.Start - removeAt, rv.Count, rv.Value)); } } rangeValues.RemoveRange(n, deleteCount); return(n); }
/// <summary> /// Compares the current range with the range of the other object. The value is /// ignored. /// </summary> /// <param name="obj">An object to compare with this instance.</param> /// <returns> /// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less than zero This instance is less than <paramref name="obj"/>. Zero This instance is equal to <paramref name="obj"/>. Greater than zero This instance is greater than <paramref name="obj"/>. /// </returns> public int CompareTo(object obj) { RangeValuePair <T> x = this; var y = (RangeValuePair <T>)obj; if (x.start >= y.start && x.start < y.start + y.count || y.start >= x.start && y.start < x.start + x.count) { return(0); } return(start.CompareTo(y.start)); }
/// <summary> /// Gets a range that contains the specified index and also /// returns a count indicating the delta between the index and the /// end of the range. /// </summary> /// <param name="index">The index.</param> /// <param name="count">The count.</param> /// <returns></returns> public T GetRange(int index, out int count) { if (index >= Count) { count = int.MaxValue; return(defaultValue); } RangeValuePair <T> rv = GetRangeValue(index); count = rv.End - index + 1; return(rv.Value); }
/// <summary> /// Inserts a range intialized with a given value at /// the specified index. When necessary it splits a range and creates /// a new range value pair. /// </summary> /// <param name="insertAt">The insertion point.</param> /// <param name="count">The count.</param> /// <param name="value">The value.</param> /// <param name="moveRanges">Allocate this object before a preceeding Remove call when moving ranges. /// Otherwise specify null.</param> public void Insert(int insertAt, int count, T value, SortedRangeValueList <T> moveRanges) { if (insertAt >= Count) { if (value.Equals(defaultValue) && (moveRanges == null || moveRanges.Count == 0)) { return; } EnsureCount(insertAt); rangeValues.Add(new RangeValuePair <T>(insertAt, count, value)); if (rangeValues.Count >= 2) { Merge(rangeValues.Count - 2); } } else { int n = rangeValues.BinarySearch(new RangeValuePair <T>(insertAt)); RangeValuePair <T> rv = rangeValues[n]; if (value.Equals(rv.Value)) { rv.Count += count; AdjustStart(n + 1, count); } else { n = Split(insertAt, n); Split(insertAt + 1); var rv2 = new RangeValuePair <T>(insertAt, count, value); rangeValues.Insert(n, rv2); AdjustStart(n + 1, count); Merge(n); if (n > 0) { Merge(n - 1); } } } if (moveRanges != null) { foreach (RangeValuePair <T> rv in moveRanges) { SetRange(rv.Start + insertAt, rv.Count, rv.Value); } } }
/// <summary> /// Sets the value for a range at the specified index. When necessary ranges /// are split or merged to make sure integrity of the list is maintained. /// (SortedRangeValueList ensures that ranges /// of the elements inside the list do not overlap and it also ensures /// that there are no empty gaps meaning that the subsequent range will /// always have the Start position be set to the End position of the previous /// range plus one.) /// </summary> /// <param name="index">The index for the range to be changed.</param> /// <param name="count">The count.</param> /// <param name="value">The value.</param> public void SetRange(int index, int count, T value) { if (index >= Count && value.Equals(defaultValue)) { return; } EnsureCount(index); int n = RemoveHelper(index, count, null); var rv = new RangeValuePair <T>(index, count, value); rangeValues.Insert(n, rv); Merge(n); if (n > 0) { Merge(n - 1); } }
int Split(int index, int n) { RangeValuePair <T> rv = rangeValues[n]; if (rangeValues[n].Start == index) { return(n); } int count1 = index - rangeValues[n].Start; int count2 = rangeValues[n].Count - count1; rv.Count = count1; var rv2 = new RangeValuePair <T>(index, count2, rv.Value); rangeValues.Insert(n + 1, rv2); return(n + 1); }
void Merge(int n) { if (n >= rangeValues.Count) { return; } RangeValuePair <T> rv1 = rangeValues[n]; if (n == rangeValues.Count - 1) { if (rv1.Value.Equals(defaultValue)) { rangeValues.RemoveAt(n); } return; } RangeValuePair <T> rv2 = rangeValues[n + 1]; if (rv1.Value.Equals(rv2.Value)) { rv1.Count += rv2.Count; rangeValues.RemoveAt(n + 1); } }