File: Text\SubText.cs
Web Access
Project: ..\..\..\src\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj (Microsoft.CodeAnalysis)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Text;
 
namespace Microsoft.CodeAnalysis.Text
{
    /// <summary>
    /// A <see cref="SourceText"/> that represents a subrange of another <see cref="SourceText"/>.
    /// </summary>
    internal sealed class SubText : SourceText
    {
        public SubText(SourceText text, TextSpan span)
            : base(checksumAlgorithm: text.ChecksumAlgorithm)
        {
            if (text == null)
            {
                throw new ArgumentNullException(nameof(text));
            }
 
            if (span.Start < 0
                || span.Start >= text.Length
                || span.End < 0
                || span.End > text.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(span));
            }
 
            UnderlyingText = text;
            UnderlyingSpan = span;
        }
 
        public override Encoding? Encoding => UnderlyingText.Encoding;
 
        public SourceText UnderlyingText { get; }
 
        public TextSpan UnderlyingSpan { get; }
 
        public override int Length => UnderlyingSpan.Length;
 
        internal override int StorageSize
        {
            get { return this.UnderlyingText.StorageSize; }
        }
 
        internal override SourceText StorageKey
        {
            get { return this.UnderlyingText.StorageKey; }
        }
 
        public override char this[int position]
        {
            get
            {
                if (position < 0 || position > this.Length)
                {
                    throw new ArgumentOutOfRangeException(nameof(position));
                }
 
                return UnderlyingText[UnderlyingSpan.Start + position];
            }
        }
 
        public override string ToString(TextSpan span)
        {
            CheckSubSpan(span);
 
            return UnderlyingText.ToString(GetCompositeSpan(span.Start, span.Length));
        }
 
        public override SourceText GetSubText(TextSpan span)
        {
            CheckSubSpan(span);
 
            return new SubText(UnderlyingText, GetCompositeSpan(span.Start, span.Length));
        }
 
        public override void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)
        {
            var span = GetCompositeSpan(sourceIndex, count);
            UnderlyingText.CopyTo(span.Start, destination, destinationIndex, span.Length);
        }
 
        private TextSpan GetCompositeSpan(int start, int length)
        {
            int compositeStart = Math.Min(UnderlyingText.Length, UnderlyingSpan.Start + start);
            int compositeEnd = Math.Min(UnderlyingText.Length, compositeStart + length);
            return new TextSpan(compositeStart, compositeEnd - compositeStart);
        }
    }
}