Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1217,6 +1217,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Text\SpanRuneEnumerator.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\StringBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\StringBuilder.Debug.cs" Condition="'$(Configuration)' == 'Debug'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\StringBuilderRuneEnumerator.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\StringRuneEnumerator.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\TranscodingStream.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\TrimType.cs" />
Expand Down
13 changes: 13 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Char.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,19 @@ public bool Equals(char obj)
return m_value == obj;
}

internal bool Equals(char right, StringComparison comparisonType)
{
switch (comparisonType)
{
case StringComparison.Ordinal:
return Equals(right);
default:
ReadOnlySpan<char> leftCharsSlice = [this];
ReadOnlySpan<char> rightCharsSlice = [right];
return leftCharsSlice.Equals(rightCharsSlice, comparisonType);
}
}

// Compares this object to another object, returning an integer that
// indicates the relationship.
// Returns a value less than zero if this object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,16 @@ public override void Write(char value)
_writer.Write(value);
}

/// <summary>
/// Writes out the specified <see cref="Rune"/>, inserting tabs at the start of every line.
/// </summary>
/// <param name="value">The <see cref="Rune"/> to write.</param>
public override void Write(Rune value)
{
OutputTabs();
_writer.Write(value);
}

public override void Write(char[]? buffer)
{
OutputTabs();
Expand Down Expand Up @@ -197,6 +207,18 @@ public override async Task WriteAsync(char value)
await _writer.WriteAsync(value).ConfigureAwait(false);
}

/// <summary>
/// Asynchronously writes the specified <see cref="Rune"/> to the underlying <see cref="TextWriter"/>, inserting
/// tabs at the start of every line.
/// </summary>
/// <param name="value">The <see cref="Rune"/> to write.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public override async Task WriteAsync(Rune value)
{
await OutputTabsAsync().ConfigureAwait(false);
await _writer.WriteAsync(value).ConfigureAwait(false);
}

/// <summary>
/// Asynchronously writes the specified number of <see cref="char"/>s from the specified buffer
/// to the underlying <see cref="TextWriter"/>, starting at the specified index, and outputting tabs at the
Expand Down Expand Up @@ -293,6 +315,17 @@ public override void WriteLine(char value)
_tabsPending = true;
}

/// <summary>
/// Writes out the specified <see cref="Rune"/>, followed by a line terminator, inserting tabs at the start of every line.
/// </summary>
/// <param name="value">The <see cref="Rune"/> to write.</param>
public override void WriteLine(Rune value)
{
OutputTabs();
_writer.WriteLine(value);
_tabsPending = true;
}

public override void WriteLine(char[]? buffer)
{
OutputTabs();
Expand Down Expand Up @@ -404,6 +437,19 @@ public override async Task WriteLineAsync(char value)
_tabsPending = true;
}

/// <summary>
/// Asynchronously writes the specified <see cref="Rune"/> to the underlying <see cref="TextWriter"/> followed by a line terminator, inserting tabs
/// at the start of every line.
/// </summary>
/// <param name="value">The character to write.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public override async Task WriteLineAsync(Rune value)
{
await OutputTabsAsync().ConfigureAwait(false);
await _writer.WriteLineAsync(value).ConfigureAwait(false);
_tabsPending = true;
}

/// <summary>
/// Asynchronously writes the specified number of characters from the specified buffer followed by a line terminator,
/// to the underlying <see cref="TextWriter"/>, starting at the specified index within the buffer, inserting tabs at the start of every line.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,17 @@ public string ToLower(string str)
return ChangeCaseCommon<ToLowerConversion>(str);
}

internal void ToLower(ReadOnlySpan<char> source, Span<char> destination)
{
if (GlobalizationMode.Invariant)
{
InvariantModeCasing.ToLower(source, destination);
return;
}

ChangeCaseCommon<ToLowerConversion>(source, destination);
}

private unsafe char ChangeCase(char c, bool toUpper)
{
Debug.Assert(!GlobalizationMode.Invariant);
Expand Down Expand Up @@ -451,6 +462,17 @@ public string ToUpper(string str)
return ChangeCaseCommon<ToUpperConversion>(str);
}

internal void ToUpper(ReadOnlySpan<char> source, Span<char> destination)
{
if (GlobalizationMode.Invariant)
{
InvariantModeCasing.ToUpper(source, destination);
return;
}

ChangeCaseCommon<ToUpperConversion>(source, destination);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static char ToUpperAsciiInvariant(char c)
{
Expand All @@ -461,6 +483,50 @@ internal static char ToUpperAsciiInvariant(char c)
return c;
}

/// <summary>
/// Converts the specified rune to lowercase.
/// </summary>
/// <param name="value">The rune to convert to lowercase.</param>
/// <returns>The specified rune converted to lowercase.</returns>
public Rune ToLower(Rune value)
{
// Convert rune to span
ReadOnlySpan<char> valueChars = value.AsSpan(stackalloc char[Rune.MaxUtf16CharsPerRune]);

// Change span to lower and convert to rune
if (valueChars.Length == 2)
{
Span<char> lowerChars = stackalloc char[2];
ToLower(valueChars, lowerChars);
return new Rune(lowerChars[0], lowerChars[1]);
}

char lowerChar = ToLower(valueChars[0]);
return new Rune(lowerChar);
}

/// <summary>
/// Converts the specified rune to uppercase.
/// </summary>
/// <param name="value">The rune to convert to uppercase.</param>
/// <returns>The specified rune converted to uppercase.</returns>
public Rune ToUpper(Rune value)
{
// Convert rune to span
ReadOnlySpan<char> valueChars = value.AsSpan(stackalloc char[Rune.MaxUtf16CharsPerRune]);

// Change span to upper and convert to rune
if (valueChars.Length == 2)
{
Span<char> upperChars = stackalloc char[2];
ToUpper(valueChars, upperChars);
return new Rune(upperChars[0], upperChars[1]);
}

char upperChar = ToUpper(valueChars[0]);
return new Rune(upperChar);
}

private bool IsAsciiCasingSameAsInvariant
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@ public override void Write(char value)
}
}

public override void Write(Rune value)
{
foreach (TextWriter writer in _writers)
{
writer.Write(value);
}
}

public override void Write(char[] buffer, int index, int count)
{
foreach (TextWriter writer in _writers)
Expand Down Expand Up @@ -292,6 +300,14 @@ public override void WriteLine(char value)
}
}

public override void WriteLine(Rune value)
{
foreach (TextWriter writer in _writers)
{
writer.WriteLine(value);
}
}

public override void WriteLine(char[]? buffer)
{
foreach (TextWriter writer in _writers)
Expand Down Expand Up @@ -452,6 +468,14 @@ public override async Task WriteAsync(char value)
}
}

public override async Task WriteAsync(Rune value)
{
foreach (TextWriter writer in _writers)
{
await writer.WriteAsync(value).ConfigureAwait(false);
}
}

public override async Task WriteAsync(string? value)
{
foreach (TextWriter writer in _writers)
Expand Down Expand Up @@ -492,6 +516,14 @@ public override async Task WriteLineAsync(char value)
}
}

public override async Task WriteLineAsync(Rune value)
{
foreach (TextWriter writer in _writers)
{
await writer.WriteLineAsync(value).ConfigureAwait(false);
}
}

public override async Task WriteLineAsync(string? value)
{
foreach (TextWriter writer in _writers)
Expand Down
Loading