private static IEnumerable <ITagSpan <TTag> > GetTags(NormalizedSnapshotSpanCollection requestedSpans, ITagSpanIntervalTree <TTag> tags) { // Special case the case where there is only one requested span. In that case, we don't // need to allocate any intermediate collections return(requestedSpans.Count == 1 ? tags.GetIntersectingSpans(requestedSpans[0]) : requestedSpans.Count < MaxNumberOfRequestedSpans ? GetTagsForSmallNumberOfSpans(requestedSpans, tags) : GetTagsForLargeNumberOfSpans(requestedSpans, tags)); }
private static IEnumerable <ITagSpan <TTag> > GetTagsForSmallNumberOfSpans( NormalizedSnapshotSpanCollection requestedSpans, ITagSpanIntervalTree <TTag> tags) { var result = new List <ITagSpan <TTag> >(); foreach (var s in requestedSpans) { result.AddRange(tags.GetIntersectingSpans(s)); } return(result); }
private static IEnumerable <ITagSpan <TTag> > GetTagsForLargeNumberOfSpans( NormalizedSnapshotSpanCollection requestedSpans, ITagSpanIntervalTree <TTag> tags) { // we are asked with bunch of spans. rather than asking same question again and again, ask once with big span // which will return superset of what we want. and then filter them out in O(m+n) cost. // m == number of requested spans, n = number of returned spans var mergedSpan = new SnapshotSpan(requestedSpans[0].Start, requestedSpans[requestedSpans.Count - 1].End); var result = tags.GetIntersectingSpans(mergedSpan); int requestIndex = 0; var enumerator = result.GetEnumerator(); try { if (!enumerator.MoveNext()) { return(SpecializedCollections.EmptyEnumerable <ITagSpan <TTag> >()); } var hashSet = new HashSet <ITagSpan <TTag> >(); while (true) { var currentTag = enumerator.Current; var currentRequestSpan = requestedSpans[requestIndex]; var currentTagSpan = currentTag.Span; if (currentRequestSpan.Start > currentTagSpan.End) { if (!enumerator.MoveNext()) { break; } } else if (currentTagSpan.Start > currentRequestSpan.End) { requestIndex++; if (requestIndex >= requestedSpans.Count) { break; } } else { if (currentTagSpan.Length > 0) { hashSet.Add(currentTag); } if (!enumerator.MoveNext()) { break; } } } return(hashSet); } finally { enumerator.Dispose(); } }