Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Expose StringBuilder.GetChunks() #29877

Merged
merged 6 commits into from
May 25, 2018
Merged
Show file tree
Hide file tree
Changes from 5 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
7 changes: 7 additions & 0 deletions src/System.Runtime/ref/System.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7584,6 +7584,12 @@ public StringBuilder(string value, int startIndex, int length, int capacity) { }
public System.Text.StringBuilder AppendJoin<T>(string separator, System.Collections.Generic.IEnumerable<T> values) { throw null; }
public System.Text.StringBuilder AppendLine() { throw null; }
public System.Text.StringBuilder AppendLine(string value) { throw null; }
public struct ChunkEnumerator
{
public ChunkEnumerator GetEnumerator() { throw null; }
public bool MoveNext() { throw null; }
public ReadOnlyMemory<char> Current { get { throw null; } }
}
public System.Text.StringBuilder Clear() { throw null; }
public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) { }
public void CopyTo(int sourceIndex, System.Span<char> destination, int count) { }
Expand Down Expand Up @@ -7613,6 +7619,7 @@ public void CopyTo(int sourceIndex, System.Span<char> destination, int count) {
public System.Text.StringBuilder Insert(int index, uint value) { throw null; }
[System.CLSCompliantAttribute(false)]
public System.Text.StringBuilder Insert(int index, ulong value) { throw null; }
public ChunkEnumerator GetChunks() { throw null; }
public System.Text.StringBuilder Remove(int startIndex, int length) { throw null; }
public System.Text.StringBuilder Replace(char oldChar, char newChar) { throw null; }
public System.Text.StringBuilder Replace(char oldChar, char newChar, int startIndex, int count) { throw null; }
Expand Down
1 change: 1 addition & 0 deletions src/System.Runtime/src/ApiCompatBaseline.uapaot.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
Expand Up @@ -388,5 +388,34 @@ public static void Equals(StringBuilder sb1, string value, bool expected)
{
Assert.Equal(expected, sb1.Equals(value.AsSpan()));
}

[Fact]
public static void ForEach()
{
// Test on a variety of lengths, at least up to the point of 9 8K chunks = 72K because this is where
// we start using a different technique for creating the ChunkEnumerator. 200 * 500 = 100K which hits this.
for (int i = 0; i < 200; i++)
{
StringBuilder inBuilder = new StringBuilder();
for (int j = 0; j < i; j++)
{
// Make some unique strings that are at least 500 bytes long.
inBuilder.Append(j);
inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz01_");
inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz0123_");
inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz012345_");
inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz012345678_");
inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz01234567890_");
}

// Copy the string out (not using StringBuilder).
string outStr = "";
foreach (ReadOnlyMemory<char> chunk in inBuilder.GetChunks())
outStr += new string(chunk.Span);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want any validation for the behavior when the StringBuilder is modified while its chunks are being enumerated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behavior is undefined when a StringBuilder is modified when enumeration is in progress. I will put a warning about this in EnumerateChunks().

I had considered actively throwing if this is detected, but this DOES slow the main Append() path down (not pay for play), and the value here is very low because this foreach API is a pretty rare use case for use by sophisticated users.


// The strings formed by concatenating the chunks should be the same as the value in the StringBuilder.
Assert.Equal(outStr, inBuilder.ToString());
}
}
}
}