public SpanSet <T> Add(Span span, T data) { if (this.DeleteZeroLengthSpans && (span.Length == 0)) { return(this); } var newTrees = SpanTree <T> .Add(_trees, 0, span, data); return(new SpanSet <T>(this, newTrees)); }
internal static IEnumerable <SpanAndData <T> > GetSpansIntersecting(IReadOnlyList <SpanTree <T> > trees, Span span, int offset) { var first = SpanTree <T> .FirstEndIndexOnOrAfterPosition(trees, span.Start - offset); var last = SpanTree <T> .LastStartIndexBeforeOrOnPosition(trees, span.End - offset); for (int i = first; (i <= last); ++i) { var child = trees[i]; if (child.Children.Count == 0) { // Handle childless nodes as a special case (avoid the overhead of the foreach below) yield return(new SpanAndData <T>(new Span(child.Span.Start + offset, child.Span.Length), child.Data)); } else { foreach (var c in child.GetSpansIntersecting(span, offset)) { yield return(c); } } } }
internal static IReadOnlyList <SpanTree <T> > Add(IReadOnlyList <SpanTree <T> > trees, int offset, Span span, T data) { Assert(span.Start >= offset); span = new Span(span.Start - offset, span.Length); SpanTree <T>[] newTrees = null; var first = FirstStartIndexOnOrAfterPosition(trees, span.Start); Assert((first == trees.Count) || (span.Start <= trees[first].Span.Start)); var last = LastEndIndexBeforeOrOnPosition(trees, first, trees.Count - 1, span.End); if (last < first) { Assert(last + 1 == first); // span doesn't contain any existing trees but might be contained by first or last if ((first < trees.Count) && (span.Start == trees[first].Span.Start)) { var tree = trees[first]; newTrees = trees.Copy(); newTrees[first] = new SpanTree <T>(tree, Add(tree.Children, tree.Span.Start, span, data)); } else if ((last >= 0) && (span.Start >= trees[last].Span.Start) && (span.End <= trees[last].Span.End)) { var tree = trees[last]; newTrees = trees.Copy(); newTrees[last] = new SpanTree <T>(tree, Add(tree.Children, tree.Span.Start, span, data)); } else { newTrees = trees.InsertAt(first, new SpanTree <T>(span, data)); } } else { Assert(span.End >= trees[last].Span.End); // trees [first ... last] are contained by the new span. // copy those nodes to a sublist which will become the children of the new span. var newChildren = new SpanTree <T> [1 + last - first]; for (int i = first; (i <= last); ++i) { var newChild = trees[i]; newChildren[i - first] = (span.Start == 0) ? newChild : new SpanTree <T>(new Span(newChild.Span.Start - span.Start, newChild.Span.Length), newChild.Data, newChild.Children); } var newTree = new SpanTree <T>(span, data, newChildren); newTrees = new SpanTree <T> [trees.Count - (last - first)]; trees.CopyTo(0, newTrees, 0, first); newTrees[first] = newTree; trees.CopyTo(last + 1, newTrees, first + 1, trees.Count - (last + 1)); } return(newTrees); }
protected SpanTree(SpanTree <T> spanTree, IReadOnlyList <SpanTree <T> > children) : this(spanTree.Span, spanTree.Data, children) { }
internal bool IsValid(int length) { return(SpanTree <T> .IsValid(_trees, length)); }
public IEnumerable <SpanAndData <T> > GetSpansIntersecting(Span span) { return(SpanTree <T> .GetSpansIntersecting(_trees, span, 0)); }
public IEnumerable <SpanAndData <T> > GetAllSpans() { return(SpanTree <T> .GetAllSpans(_trees, 0)); }