ImageSharp/SixLabors.Fonts/Unicode/MemoryExtensions.cs
2026-08-03 22:31:27 +02:00

255 lines
12 KiB
C#

// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
namespace SixLabors.Fonts.Unicode {
/// <summary>
/// Contains extension methods for memory types.
/// </summary>
public static class MemoryExtensions
{
/// <summary>
/// Returns an enumeration of <see cref="CodePoint"/> from the provided span.
/// </summary>
/// <param name="span">The read-only span of char elements representing the text to enumerate.</param>
/// <remarks>
/// Invalid UTF-16 sequences will be represented in the enumeration by <see cref="CodePoint.ReplacementChar"/>.
/// </remarks>
/// <returns>The <see cref="SpanCodePointEnumerator"/>.</returns>
public static SpanCodePointEnumerator EnumerateCodePoints(this ReadOnlySpan<char> span)
=> new(span);
/// <summary>
/// Returns an enumeration of <see cref="CodePoint"/> from the provided span.
/// </summary>
/// <param name="span">The span of char elements representing the text to enumerate.</param>
/// <remarks>
/// Invalid UTF-16 sequences will be represented in the enumeration by <see cref="CodePoint.ReplacementChar"/>.
/// </remarks>
/// <returns>The <see cref="SpanCodePointEnumerator"/>.</returns>
public static SpanCodePointEnumerator EnumerateCodePoints(this Span<char> span)
=> new(span);
/// <summary>
/// Returns the number of code points in the provided text.
/// </summary>
/// <param name="text">The text to enumerate.</param>
/// <returns>The number of code points.</returns>
public static int GetCodePointCount(this string text) => text.AsSpan().GetCodePointCount();
/// <summary>
/// Returns the number of code points in the provided span.
/// </summary>
/// <param name="span">The read-only span of char elements representing the text to enumerate.</param>
/// <returns>The number of code points.</returns>
public static int GetCodePointCount(this ReadOnlySpan<char> span) => CodePoint.GetCodePointCount(span);
/// <summary>
/// Returns the number of code points in the provided span.
/// </summary>
/// <param name="span">The span of char elements representing the text to enumerate.</param>
/// <returns>The number of code points.</returns>
public static int GetCodePointCount(this Span<char> span) => CodePoint.GetCodePointCount(span);
/// <summary>
/// Returns an enumeration of grapheme clusters from the provided span.
/// </summary>
/// <param name="span">The read-only span of char elements representing the text to enumerate.</param>
/// <remarks>
/// Invalid UTF-16 sequences are treated as <see cref="CodePoint.ReplacementChar"/> while determining grapheme boundaries.
/// </remarks>
/// <returns>The <see cref="SpanGraphemeEnumerator"/>.</returns>
public static SpanGraphemeEnumerator EnumerateGraphemes(this ReadOnlySpan<char> span)
=> new(span);
/// <summary>
/// Returns an enumeration of grapheme clusters from the provided span with terminal-width metadata.
/// </summary>
/// <param name="span">The read-only span of char elements representing the text to enumerate.</param>
/// <param name="terminalWidthOptions">
/// The terminal width options used to resolve <see cref="GraphemeCluster.TerminalCellWidth"/>.
/// </param>
/// <remarks>
/// Invalid UTF-16 sequences are treated as <see cref="CodePoint.ReplacementChar"/> while determining grapheme boundaries.
/// Terminal width options affect only the width metadata on each returned cluster; they do not affect grapheme segmentation.
/// </remarks>
/// <returns>The <see cref="SpanGraphemeEnumerator"/>.</returns>
public static SpanGraphemeEnumerator EnumerateGraphemes(this ReadOnlySpan<char> span, TerminalWidthOptions terminalWidthOptions)
=> new(span, terminalWidthOptions);
/// <summary>
/// Returns an enumeration of grapheme clusters from the provided span.
/// </summary>
/// <param name="span">The span of char elements representing the text to enumerate.</param>
/// <remarks>
/// Invalid UTF-16 sequences are treated as <see cref="CodePoint.ReplacementChar"/> while determining grapheme boundaries.
/// </remarks>
/// <returns>The <see cref="SpanGraphemeEnumerator"/>.</returns>
public static SpanGraphemeEnumerator EnumerateGraphemes(this Span<char> span)
=> new(span);
/// <summary>
/// Returns an enumeration of grapheme clusters from the provided span with terminal-width metadata.
/// </summary>
/// <param name="span">The span of char elements representing the text to enumerate.</param>
/// <param name="terminalWidthOptions">
/// The terminal width options used to resolve <see cref="GraphemeCluster.TerminalCellWidth"/>.
/// </param>
/// <remarks>
/// Invalid UTF-16 sequences are treated as <see cref="CodePoint.ReplacementChar"/> while determining grapheme boundaries.
/// Terminal width options affect only the width metadata on each returned cluster; they do not affect grapheme segmentation.
/// </remarks>
/// <returns>The <see cref="SpanGraphemeEnumerator"/>.</returns>
public static SpanGraphemeEnumerator EnumerateGraphemes(this Span<char> span, TerminalWidthOptions terminalWidthOptions)
=> new(span, terminalWidthOptions);
/// <summary>
/// Returns an enumeration of Unicode word-boundary segments from the provided span.
/// </summary>
/// <param name="span">The read-only span of char elements representing the text to enumerate.</param>
/// <remarks>
/// Invalid UTF-16 sequences are treated as <see cref="CodePoint.ReplacementChar"/> while determining word boundaries.
/// </remarks>
/// <returns>The <see cref="SpanWordEnumerator"/>.</returns>
public static SpanWordEnumerator EnumerateWordSegments(this ReadOnlySpan<char> span)
=> new(span);
/// <summary>
/// Returns an enumeration of Unicode word-boundary segments from the provided span.
/// </summary>
/// <param name="span">The span of char elements representing the text to enumerate.</param>
/// <remarks>
/// Invalid UTF-16 sequences are treated as <see cref="CodePoint.ReplacementChar"/> while determining word boundaries.
/// </remarks>
/// <returns>The <see cref="SpanWordEnumerator"/>.</returns>
public static SpanWordEnumerator EnumerateWordSegments(this Span<char> span)
=> new(span);
/// <summary>
/// Returns the terminal cell width of the provided text.
/// </summary>
/// <param name="text">The text to measure.</param>
/// <returns>
/// The terminal cell width, or <c>-1</c> when the configured control-character policy treats
/// any grapheme cluster in the text as non-printable.
/// </returns>
public static int GetTerminalCellWidth(this string text) => text.AsSpan().GetTerminalCellWidth();
/// <summary>
/// Returns the terminal cell width of the provided text.
/// </summary>
/// <param name="text">The text to measure.</param>
/// <param name="terminalWidthOptions">The terminal width options to apply while measuring.</param>
/// <returns>
/// The terminal cell width, or <c>-1</c> when the configured control-character policy treats
/// any grapheme cluster in the text as non-printable.
/// </returns>
public static int GetTerminalCellWidth(this string text, TerminalWidthOptions terminalWidthOptions)
=> text.AsSpan().GetTerminalCellWidth(terminalWidthOptions);
/// <summary>
/// Returns the terminal cell width of the provided span.
/// </summary>
/// <param name="span">The read-only span of char elements representing the text to measure.</param>
/// <returns>
/// The terminal cell width, or <c>-1</c> when the configured control-character policy treats
/// any grapheme cluster in the text as non-printable.
/// </returns>
public static int GetTerminalCellWidth(this ReadOnlySpan<char> span)
=> span.GetTerminalCellWidth(default);
/// <summary>
/// Returns the terminal cell width of the provided span.
/// </summary>
/// <param name="span">The read-only span of char elements representing the text to measure.</param>
/// <param name="terminalWidthOptions">The terminal width options to apply while measuring.</param>
/// <returns>
/// The terminal cell width, or <c>-1</c> when the configured control-character policy treats
/// any grapheme cluster in the text as non-printable.
/// </returns>
public static int GetTerminalCellWidth(this ReadOnlySpan<char> span, TerminalWidthOptions terminalWidthOptions)
{
int width = 0;
SpanGraphemeEnumerator enumerator = new(span, terminalWidthOptions);
while (enumerator.MoveNext())
{
int terminalCellWidth = enumerator.Current.TerminalCellWidth;
if (terminalCellWidth < 0)
{
return -1;
}
width += terminalCellWidth;
}
return width;
}
/// <summary>
/// Returns the terminal cell width of the provided span.
/// </summary>
/// <param name="span">The span of char elements representing the text to measure.</param>
/// <returns>
/// The terminal cell width, or <c>-1</c> when the configured control-character policy treats
/// any grapheme cluster in the text as non-printable.
/// </returns>
public static int GetTerminalCellWidth(this Span<char> span)
=> ((ReadOnlySpan<char>)span).GetTerminalCellWidth();
/// <summary>
/// Returns the terminal cell width of the provided span.
/// </summary>
/// <param name="span">The span of char elements representing the text to measure.</param>
/// <param name="terminalWidthOptions">The terminal width options to apply while measuring.</param>
/// <returns>
/// The terminal cell width, or <c>-1</c> when the configured control-character policy treats
/// any grapheme cluster in the text as non-printable.
/// </returns>
public static int GetTerminalCellWidth(this Span<char> span, TerminalWidthOptions terminalWidthOptions)
=> ((ReadOnlySpan<char>)span).GetTerminalCellWidth(terminalWidthOptions);
/// <summary>
/// Returns the number of grapheme clusters in the provided text.
/// </summary>
/// <param name="text">The text to enumerate.</param>
/// <returns>The number of grapheme clusters.</returns>
public static int GetGraphemeCount(this string text) => text.AsSpan().GetGraphemeCount();
/// <summary>
/// Returns the number of grapheme clusters in the provided span.
/// </summary>
/// <param name="span">The read-only span of char elements representing the text to enumerate.</param>
/// <returns>The number of grapheme clusters.</returns>
public static int GetGraphemeCount(this ReadOnlySpan<char> span)
{
int count = 0;
SpanGraphemeEnumerator enumerator = new(span);
while (enumerator.MoveNext())
{
count++;
}
return count;
}
/// <summary>
/// Returns the number of grapheme clusters in the provided span.
/// </summary>
/// <param name="span">The span of char elements representing the text to enumerate.</param>
/// <returns>The number of grapheme clusters.</returns>
public static int GetGraphemeCount(this Span<char> span)
{
int count = 0;
SpanGraphemeEnumerator enumerator = new(span);
while (enumerator.MoveNext())
{
count++;
}
return count;
}
}
}