/// <summary>
        /// Initializes a new instance of a <see cref="NormalizedSnapshotSpanCollection"/> from a list of <see cref="Span"/>s and a <see cref="ITextSnapshot"/>.
        /// </summary>
        /// <param name="snapshot">The <see cref="ITextSnapshot"/> to apply to <paramref name="spans"/>.</param>
        /// <param name="spans">An arbitrary set of <see cref="Span"/> objects.</param>
        /// <exception cref="ArgumentNullException"><paramref name="snapshot"/> or <paramref name="spans"/> is null.</exception>
        /// <exception cref="ArgumentException">The spans in <paramref name="spans"/> extend beyond the end of <paramref name="snapshot"/>.</exception>
        public NormalizedSnapshotSpanCollection(ITextSnapshot snapshot, IEnumerable <Span> spans)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException(nameof(snapshot));
            }
            if (spans == null)
            {
                throw new ArgumentNullException(nameof(spans));
            }

            using (IEnumerator <Span> spanEnumerator = spans.GetEnumerator())
            {
                if (!spanEnumerator.MoveNext())
                {
                    // empty collection
                }
                else
                {
                    this.snapshot = snapshot;
                    Span span = spanEnumerator.Current;
                    if (!spanEnumerator.MoveNext())
                    {
                        // length one
                        this.span = span;
                        if (span.End > snapshot.Length)
                        {
                            throw new ArgumentException(Strings.SpansBeyondEnd);
                        }
                    }
                    else
                    {
                        // length at least two
                        this.spans = new NormalizedSpanCollection(spans);
                        if (this.spans[this.spans.Count - 1].End > snapshot.Length)
                        {
                            throw new ArgumentException(Strings.SpansBeyondEnd);
                        }
                    }
                }
            }
        }
 /// <summary>
 /// Determines whether this collection intersects with another normalized snapshot span collection.
 /// </summary>
 /// <param name="set">The colllection.</param>
 /// <returns><c>true</c> if the collections intersect, otherwise <c>false</c>.</returns>
 /// <exception cref="ArgumentNullException"><paramref name="set"/> is null.</exception>
 /// <exception cref="ArgumentException">The input collections refer to different snapshots.</exception>
 public bool IntersectsWith(NormalizedSnapshotSpanCollection set)
 {
     if (set == null)
     {
         throw new ArgumentNullException(nameof(set));
     }
     else if (set.Count == 0 || this.Count == 0)
     {
         return(false);
     }
     else if (set.snapshot != this.snapshot)
     {
         throw new ArgumentException(Strings.MismatchedSnapshots);
     }
     else
     {
         NormalizedSpanCollection thisSpans = this.spans ?? new NormalizedSpanCollection(this.span);
         return(thisSpans.IntersectsWith(set));
     }
 }
        /// <summary>
        /// Initializes a new instance of a <see cref="NormalizedSnapshotSpanCollection"/> from a list of <see cref="Span"/>s and a <see cref="ITextSnapshot"/>.
        /// </summary>
        /// <param name="snapshot">The <see cref="ITextSnapshot"/> to apply to <paramref name="spans"/>.</param>
        /// <param name="spans">An arbitrary set of <see cref="Span"/> objects.</param>
        /// <exception cref="ArgumentNullException"><paramref name="snapshot"/> or <paramref name="spans"/> is null.</exception>
        /// <exception cref="ArgumentException">The spans in <paramref name="spans"/> extend beyond the end of <paramref name="snapshot"/>.</exception>
        public NormalizedSnapshotSpanCollection(ITextSnapshot snapshot, IList <Span> spans)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException(nameof(snapshot));
            }
            if (spans == null)
            {
                throw new ArgumentNullException(nameof(spans));
            }

            if (spans.Count == 0)
            {
                // empty collection
            }
            else
            {
                this.snapshot = snapshot;
                if (spans.Count == 1)
                {
                    // length one
                    this.span = spans[0];
                    if (this.span.End > snapshot.Length)
                    {
                        throw new ArgumentException(Strings.SpansBeyondEnd);
                    }
                }
                else
                {
                    // length at least two
                    this.spans = new NormalizedSpanCollection(spans);
                    if (this.spans[this.spans.Count - 1].End > snapshot.Length)
                    {
                        throw new ArgumentException(Strings.SpansBeyondEnd);
                    }
                }
            }
        }
Example #4
0
        /// <summary>
        /// Finds the union of two span sets.
        /// </summary>
        /// <param name="left">
        /// The first span set.
        /// </param>
        /// <param name="right">
        /// The second span set.
        /// </param>
        /// <returns>
        /// The new span set that corresponds to the union of <paramref name="left"/> and <paramref name="right"/>.
        /// </returns>
        /// <remarks>This operator runs in O(N+M) time where N = left.Count, M = right.Count.</remarks>
        /// <exception cref="ArgumentNullException">Either <paramref name="left"/> or <paramref name="right"/> is null.</exception>
        public static NormalizedSpanCollection Union(NormalizedSpanCollection left, NormalizedSpanCollection right)
        {
            if (left == null)
            {
                throw new ArgumentNullException("left");
            }
            if (right == null)
            {
                throw new ArgumentNullException("right");
            }

            if (left.Count == 0)
            {
                return(right);
            }
            if (right.Count == 0)
            {
                return(left);
            }

            List <Span> spans = new List <Span>();

            int index1 = 0;
            int index2 = 0;

            int start = -1;
            int end   = int.MaxValue;

            while ((index1 < left.Count) && (index2 < right.Count))
            {
                Span span1 = left[index1];
                Span span2 = right[index2];

                if (span1.Start < span2.Start)
                {
                    NormalizedSpanCollection.UpdateSpanUnion(span1, spans, ref start, ref end);
                    ++index1;
                }
                else
                {
                    NormalizedSpanCollection.UpdateSpanUnion(span2, spans, ref start, ref end);
                    ++index2;
                }
            }
            while (index1 < left.Count)
            {
                NormalizedSpanCollection.UpdateSpanUnion(left[index1], spans, ref start, ref end);
                ++index1;
            }
            while (index2 < right.Count)
            {
                NormalizedSpanCollection.UpdateSpanUnion(right[index2], spans, ref start, ref end);
                ++index2;
            }

            if (end != int.MaxValue)
            {
                spans.Add(Span.FromBounds(start, end));
            }

            return(CreateFromNormalizedSpans(spans));
        }
Example #5
0
        /// <summary>
        /// Determines whether this span set is the same as another object.
        /// </summary>
        /// <param name="obj">The object to test.</param>
        /// <returns><c>true</c> if the two objects are equal, otherwise <c>false</c>.</returns>
        public override bool Equals(object obj)
        {
            NormalizedSpanCollection set = obj as NormalizedSpanCollection;

            return(this == set);
        }
Example #6
0
 /// <summary>
 /// Initializes a new instance of <see cref="NormalizedSpanCollection"/> that contains the specified list of spans.
 /// </summary>
 /// <param name="spans">The spans to be added.</param>
 /// <remarks>
 /// <para>The list of spans will be sorted and normalized (overlapping and adjoining spans will be combined).</para>
 /// <para>This constructor runs in O(N log N) time, where N = spans.Count.</para></remarks>
 /// <exception cref="ArgumentNullException"><paramref name="spans"/> is null.</exception>
 public NormalizedSpanCollection(IEnumerable <Span> spans)
     : base(NormalizedSpanCollection.NormalizeSpans(spans))
 {
     //NormalizeSpans will throw if spans == null.
 }
Example #7
0
        /// <summary>
        /// Finds the difference between two sets. The difference is defined as everything in the first span set that is not in the second span set.
        /// </summary>
        /// <param name="left">The first span set.</param>
        /// <param name="right">The second span set.</param>
        /// <returns>The new span set that corresponds to the difference between <paramref name="left"/> and <paramref name="right"/>.</returns>
        /// <remarks>
        /// Empty spans in the second set do not affect the first set at all. This method returns empty spans in the first set that are not contained by any set in
        /// the second set.
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="left"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="right"/> is null.</exception>
        public static NormalizedSpanCollection Difference(NormalizedSpanCollection left, NormalizedSpanCollection right)
        {
            if (left == null)
            {
                throw new ArgumentNullException("left");
            }
            if (right == null)
            {
                throw new ArgumentNullException("right");
            }

            if (left.Count == 0)
            {
                return(left);
            }
            if (right.Count == 0)
            {
                return(left);
            }

            List <Span> spans = new List <Span>();

            int index1  = 0;
            int index2  = 0;
            int lastEnd = -1;

            do
            {
                Span span1 = left[index1];
                Span span2 = right[index2];

                if ((span2.Length == 0) || (span1.Start >= span2.End))
                {
                    ++index2;
                }
                else if (span1.End <= span2.Start)
                {
                    //lastEnd is set to the end of the previously encountered intersecting span from right when
                    //it ended before the end of span1 (so it must still be less than the end of span1).
                    Debug.Assert(lastEnd < span1.End);
                    spans.Add(Span.FromBounds(Math.Max(lastEnd, span1.Start), span1.End));
                    ++index1;
                }
                else
                {
                    // The spans intersect, so add anything from span1 that extends to the left of span2.
                    if (span1.Start < span2.Start)
                    {
                        //lastEnd is set to the end of the previously encountered intersecting span on span2, so it must
                        //be less than the start of the current span on span2.
                        Debug.Assert(lastEnd < span2.Start);
                        spans.Add(Span.FromBounds(Math.Max(lastEnd, span1.Start), span2.Start));
                    }

                    if (span1.End < span2.End)
                    {
                        ++index1;
                    }
                    else if (span1.End == span2.End)
                    {
                        //Both spans ended at the same place so we're done with both.
                        ++index1; ++index2;
                    }
                    else
                    {
                        //span2 ends before span1, so keep track of where it ended so that we don't try to add
                        //the excluded portion the next time we add a span.
                        lastEnd = span2.End;
                        ++index2;
                    }
                }
            }while ((index1 < left.Count) && (index2 < right.Count));

            while (index1 < left.Count)
            {
                Span span1 = left[index1++];
                spans.Add(Span.FromBounds(Math.Max(lastEnd, span1.Start), span1.End));
            }

            return(CreateFromNormalizedSpans(spans));
        }
Example #8
0
        /// <summary>
        /// Finds the intersection of two span sets.
        /// </summary>
        /// <param name="left">The first span set.</param>
        /// <param name="right">The second span set.</param>
        /// <returns>The new span set that corresponds to the intersection of <paramref name="left"/> and <paramref name="right"/>.</returns>
        /// <remarks>This operator runs in O(N+M) time where N = left.Count, M = right.Count.</remarks>
        /// <exception cref="ArgumentNullException"><paramref name="left"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="right"/> is null.</exception>
        public static NormalizedSpanCollection Intersection(NormalizedSpanCollection left, NormalizedSpanCollection right)
        {
            if (left == null)
            {
                throw new ArgumentNullException("left");
            }
            if (right == null)
            {
                throw new ArgumentNullException("right");
            }

            if (left.Count == 0)
            {
                return(left);
            }
            if (right.Count == 0)
            {
                return(right);
            }

            List <Span> spans = new List <Span>();

            for (int index1 = 0, index2 = 0; (index1 < left.Count) && (index2 < right.Count);)
            {
                Span span1 = left[index1];
                Span span2 = right[index2];

                if (span1.IntersectsWith(span2))
                {
                    spans.Add(span1.Intersection(span2).Value);
                }

                if (span1.End < span2.End)
                {
                    ++index1;
                }
                else
                {
                    ++index2;
                }
            }

            return(CreateFromNormalizedSpans(spans));
        }