File: SpanBasedStringBuilder.Simple.cs
Web Access
Project: ..\..\..\src\StringTools\StringTools.csproj (Microsoft.NET.StringTools.net35)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Text;
 
namespace Microsoft.NET.StringTools
{
    /// <summary>
    /// A simple version of SpanBasedStringBuilder to be used on .NET Framework 3.5. Wraps a <see cref="StringBuilder"/>.
    /// </summary>
    public class SpanBasedStringBuilder : IDisposable
    {
        /// <summary>
        /// Enumerator for the top-level struct. Enumerates characters of the string.
        /// </summary>
        public struct Enumerator
        {
            /// <summary>
            /// The StringBuilder being enumerated.
            /// </summary>
            private StringBuilder _builder;
 
            /// <summary>
            /// Index of the current character, -1 if MoveNext has not been called yet.
            /// </summary>
            private int _charIndex;
 
            public Enumerator(StringBuilder builder)
            {
                _builder = builder;
                _charIndex = -1;
            }
 
            /// <summary>
            /// Returns the current character.
            /// </summary>
            public readonly char Current => _builder[_charIndex];
 
            /// <summary>
            /// Moves to the next character.
            /// </summary>
            /// <returns>True if there is another character, false if the enumerator reached the end.</returns>
            public bool MoveNext()
            {
                int newIndex = _charIndex + 1;
                if (newIndex < _builder.Length)
                {
                    _charIndex = newIndex;
                    return true;
                }
                return false;
            }
        }
 
        /// <summary>
        /// The backing StringBuilder.
        /// </summary>
        private StringBuilder _builder;
 
        internal StringBuilder Builder => _builder;
 
        /// <summary>
        /// Constructs a new SpanBasedStringBuilder containing the given string.
        /// </summary>
        /// <param name="str">The string to wrap, must be non-null.</param>
        public SpanBasedStringBuilder(string str)
            : this()
        {
            if (str == null)
            {
                throw new ArgumentNullException(nameof(str));
            }
            Append(str);
        }
 
        /// <summary>
        /// Constructs a new empty SpanBasedStringBuilder with the given expected number of spans.
        /// </summary>
        public SpanBasedStringBuilder(int capacity = 4)
        {
            // Since we're using StringBuilder as the backing store in this implementation, our capacity is expressed
            // in number of characters rather than number of spans. We use 128 as a reasonable expected multiplier to
            // go from one to the other, i.e. by default we'll preallocate a 512-character StringBuilder.
            _builder = new StringBuilder(capacity * 128);
        }
 
        /// <summary>
        /// Gets the length of the string.
        /// </summary>
        public int Length => _builder.Length;
 
        /// <summary>
        /// Creates a new enumerator for enumerating characters in this string. Does not allocate.
        /// </summary>
        /// <returns>The enumerator.</returns>
        public Enumerator GetEnumerator()
        {
            return new Enumerator(_builder);
        }
 
        /// <summary>
        /// Converts this instance to a System.String while first searching for a match in the intern table.
        /// </summary>
        /// <remarks>
        /// May allocate depending on whether the string has already been interned.
        /// </remarks>
        public override string ToString()
        {
            return new InternableString(this).ToString();
        }
 
        /// <summary>
        /// Releases this instance.
        /// </summary>
        public void Dispose()
        {
            Strings.ReturnSpanBasedStringBuilder(this);
        }
 
        #region Public mutating methods
 
        /// <summary>
        /// Appends a string.
        /// </summary>
        /// <param name="value">The string to append.</param>
        internal void Append(string value)
        {
            _builder.Append(value);
        }
 
        /// <summary>
        /// Appends a substring.
        /// </summary>
        /// <param name="value">The string to append.</param>
        /// <param name="startIndex">The start index of the substring within <paramref name="value"/> to append.</param>
        /// <param name="count">The length of the substring to append.</param>
        internal void Append(string value, int startIndex, int count)
        {
            _builder.Append(value, startIndex, count);
        }
 
        /// <summary>
        /// Clears this instance making it represent an empty string.
        /// </summary>
        public void Clear()
        {
            _builder.Length = 0;
        }
 
        #endregion
    }
}