Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/core/MonoDevelop.Core/MonoDevelop.Core.Text/ISegment.cs')
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.Text/ISegment.cs406
1 files changed, 406 insertions, 0 deletions
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Text/ISegment.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Text/ISegment.cs
new file mode 100644
index 0000000000..02c0acfda2
--- /dev/null
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Text/ISegment.cs
@@ -0,0 +1,406 @@
+//
+// ISegment.cs
+//
+// Author:
+// Mike Krüger <mkrueger@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+
+namespace MonoDevelop.Core.Text
+{
+ /// <summary>
+ /// An (Offset,Length)-pair.
+ /// </summary>
+ public interface ISegment
+ {
+ /// <summary>
+ /// Gets the start offset of the segment.
+ /// </summary>
+ int Offset { get; }
+
+ /// <summary>
+ /// Gets the length of the segment.
+ /// </summary>
+ /// <remarks>For line segments (IDocumentLine), the length does not include the line delimeter.</remarks>
+ int Length { get; }
+
+ /// <summary>
+ /// Gets the end offset of the segment.
+ /// </summary>
+ /// <remarks>EndOffset = Offset + Length;</remarks>
+ int EndOffset { get; }
+ }
+
+ /// <summary>
+ /// An (Offset, Length) pair representing a text span.
+ /// </summary>
+ public struct TextSegment : IEquatable<TextSegment>, ISegment
+ {
+ public static readonly TextSegment Invalid = new TextSegment (-1, 0);
+
+ readonly int offset;
+
+ /// <summary>
+ /// Gets the start offset of the segment.
+ /// </summary>
+ /// <value>
+ /// The offset.
+ /// </value>
+ public int Offset {
+ get {
+ return offset;
+ }
+ }
+
+ readonly int length;
+
+ /// <summary>
+ /// Gets the length of the segment.
+ /// </summary>
+ /// <value>
+ /// The length.
+ /// </value>
+ public int Length {
+ get {
+ return length;
+ }
+ }
+
+ /// <summary>
+ /// Gets the end offset of the segment.
+ /// </summary>
+ /// <remarks>
+ /// EndOffset = Offset + Length;
+ /// </remarks>
+ /// <value>
+ /// The end offset.
+ /// </value>
+ public int EndOffset {
+ get {
+ return Offset + Length;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this instance is empty.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if this instance is empty; otherwise, <c>false</c>.
+ /// </value>
+ public bool IsEmpty {
+ get {
+ return Length == 0;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this instance is invalid.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if this instance is invalid; otherwise, <c>false</c>.
+ /// </value>
+ public bool IsInvalid {
+ get {
+ return Offset < 0;
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TextSegment"/> struct.
+ /// </summary>
+ /// <param name='offset'>
+ /// The offset of the segment.
+ /// </param>
+ /// <param name='length'>
+ /// The length of the segment.
+ /// </param>
+ public TextSegment (int offset, int length)
+ {
+ this.offset = offset;
+ this.length = length;
+ }
+
+ public static bool operator == (TextSegment left, TextSegment right)
+ {
+ return Equals (left, right);
+ }
+
+ public static bool operator != (TextSegment left, TextSegment right)
+ {
+ return !Equals (left, right);
+ }
+
+ public static bool Equals (TextSegment left, TextSegment right)
+ {
+ return left.Offset == right.Offset && left.Length == right.Length;
+ }
+
+ /// <summary>
+ /// Determines whether this instance is inside the specified offset.
+ /// </summary>
+ /// <returns>
+ /// <c>true</c> if this instance is inside the specified offset (upper bound inclusive); otherwise, <c>false</c>.
+ /// </returns>
+ /// <param name='offset'>
+ /// The offset offset.
+ /// </param>
+ public bool IsInside (int offset)
+ {
+ return Offset <= offset && offset <= EndOffset;
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="TextSegment"/> is equal to the current <see cref="TextSegment"/>.
+ /// </summary>
+ /// <param name='other'>
+ /// The <see cref="TextSegment"/> to compare with the current <see cref="TextSegment"/>.
+ /// </param>
+ /// <returns>
+ /// <c>true</c> if the specified <see cref="TextSegment"/> is equal to the current
+ /// <see cref="TextSegment"/>; otherwise, <c>false</c>.
+ /// </returns>
+ public bool Equals (TextSegment other)
+ {
+ return Equals (this, other);
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="System.Object"/> is equal to the current <see cref="TextSegment"/>.
+ /// </summary>
+ /// <param name='obj'>
+ /// The <see cref="System.Object"/> to compare with the current <see cref="TextSegment"/>.
+ /// </param>
+ /// <returns>
+ /// <c>true</c> if the specified <see cref="System.Object"/> is equal to the current
+ /// <see cref="TextSegment"/>; otherwise, <c>false</c>.
+ /// </returns>
+ public override bool Equals (object obj)
+ {
+ return obj is ISegment && Equals (this, (ISegment)obj);
+ }
+
+ /// <summary>
+ /// Serves as a hash function for a <see cref="TextSegment"/> object.
+ /// </summary>
+ /// <returns>
+ /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
+ /// </returns>
+ public override int GetHashCode ()
+ {
+ return Offset ^ Length;
+ }
+
+ public static TextSegment FromBounds (int startOffset, int endOffset)
+ {
+ if (startOffset > endOffset)
+ throw new ArgumentOutOfRangeException ("endOffset", "endOffset < startOffset");
+ return new TextSegment (startOffset, endOffset - startOffset);
+ }
+
+ /// <summary>
+ /// Returns a <see cref="System.String"/> that represents the current <see cref="TextSegment"/>.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="System.String"/> that represents the current <see cref="TextSegment"/>.
+ /// </returns>
+ public override string ToString ()
+ {
+ return string.Format ("[TextSegment: Offset={0}, Length={1}]", Offset, Length);
+ }
+ }
+
+ /// <summary>
+ /// An abstract implementation of the ISegment (Offset, Length) pair representing a text span.
+ /// </summary>
+ public abstract class AbstractSegment : ISegment
+ {
+ readonly int offset;
+
+ /// <summary>
+ /// Gets the start offset of the segment.
+ /// </summary>
+ /// <value>
+ /// The offset.
+ /// </value>
+ public int Offset {
+ get {
+ return offset;
+ }
+ }
+
+ readonly int length;
+
+ /// <summary>
+ /// Gets the length of the segment.
+ /// </summary>
+ /// <value>
+ /// The length.
+ /// </value>
+ public int Length {
+ get {
+ return length;
+ }
+ }
+
+ /// <summary>
+ /// Gets the end offset of the segment.
+ /// </summary>
+ /// <remarks>
+ /// EndOffset = Offset + Length;
+ /// </remarks>
+ /// <value>
+ /// The end offset.
+ /// </value>
+ public int EndOffset {
+ get {
+ return Offset + Length;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this instance is empty.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if this instance is empty; otherwise, <c>false</c>.
+ /// </value>
+ public bool IsEmpty {
+ get {
+ return Length == 0;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this instance is invalid.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if this instance is invalid; otherwise, <c>false</c>.
+ /// </value>
+ public bool IsInvalid {
+ get {
+ return Offset < 0;
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TextSegment"/> struct.
+ /// </summary>
+ /// <param name='offset'>
+ /// The offset of the segment.
+ /// </param>
+ /// <param name='length'>
+ /// The length of the segment.
+ /// </param>
+ protected AbstractSegment (int offset, int length)
+ {
+ this.offset = offset;
+ this.length = length;
+ }
+
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TextSegment"/> struct.
+ /// </summary>
+ protected AbstractSegment (ISegment segment)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ this.offset = segment.Offset;
+ this.length = segment.Length;
+ }
+ }
+
+
+ /// <summary>
+ /// Extension methods for <see cref="ISegment"/>.
+ /// </summary>
+ public static class ISegmentExtensions
+ {
+ /// <summary>
+ /// Gets whether <paramref name="segment"/> fully contains the specified segment.
+ /// </summary>
+ /// <remarks>
+ /// Use <c>segment.Contains(offset, 0)</c> to detect whether a segment (end inclusive) contains offset;
+ /// use <c>segment.Contains(offset, 1)</c> to detect whether a segment (end exclusive) contains offset.
+ /// </remarks>
+ public static bool Contains (this ISegment segment, int offset, int length)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ return segment.Offset <= offset && offset + length <= segment.EndOffset;
+ }
+
+ /// <summary>
+ /// Gets whether <paramref name="segment"/> fully contains the specified segment.
+ /// </summary>
+ public static bool Contains (this ISegment segment, ISegment span)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ if (span == null)
+ throw new ArgumentNullException ("span");
+ return segment.Offset <= span.Offset && span.EndOffset <= segment.EndOffset;
+ }
+
+ /// <summary>
+ /// Gets whether the offset is within the <paramref name="segment"/>.
+ /// </summary>
+ public static bool Contains (this ISegment segment, int offset)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ return unchecked((uint)(offset - segment.Offset) < (uint)segment.Length);
+ }
+
+ /// <summary>
+ /// Determines whether <paramref name="other"/> overlaps this span. Two spans are considered to overlap
+ /// if they have positions in common and neither is empty. Empty spans do not overlap with any
+ /// other span.
+ /// </summary>
+ public static bool OverlapsWith (this ISegment segment, ISegment other)
+ {
+ int overlapStart = Math.Max (segment.Offset, other.Offset);
+ int overlapEnd = Math.Min (segment.EndOffset, other.EndOffset);
+ return overlapStart < overlapEnd;
+ }
+
+ public static ISegment AdjustSegment (this ISegment segment, TextChangeEventArgs args)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ if (args.Offset < segment.Offset)
+ return new TextSegment (segment.Offset + args.InsertionLength - args.RemovalLength, segment.Length);
+ if (args.Offset <= segment.EndOffset)
+ return new TextSegment (segment.Offset, segment.Length);
+ return segment;
+ }
+
+ public static IEnumerable<ISegment> AdjustSegments (this IEnumerable<ISegment> segments, TextChangeEventArgs args)
+ {
+ if (segments == null)
+ throw new ArgumentNullException ("segments");
+ foreach (var segment in segments) {
+ yield return segment.AdjustSegment (args);
+ }
+ }
+ }
+} \ No newline at end of file