Skip to content

Commit

Permalink
Use IndexOfAnyValues in CoreLib (#78678)
Browse files Browse the repository at this point in the history
* Use IndexOfAnyValues in CoreLib

* Avoid the init overhead of IndexOfAnyValues in string
  • Loading branch information
MihaZupan authored Nov 22, 2022
1 parent e0aff76 commit 47158cc
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 12 deletions.
15 changes: 11 additions & 4 deletions src/coreclr/System.Private.CoreLib/src/System/TypeNameParser.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Buffers;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
Expand Down Expand Up @@ -88,7 +89,8 @@ internal sealed partial class TypeNameParser : IDisposable

#region Private Data Members
private readonly SafeTypeNameParserHandle m_NativeParser;
private static readonly char[] SPECIAL_CHARS = { ',', '[', ']', '&', '*', '+', '\\' }; /* see typeparse.h */
private const string SpecialChars = ",[]&*+\\"; // see typeparse.h
private static readonly IndexOfAnyValues<char> s_specialChars = IndexOfAnyValues.Create(SpecialChars);
#endregion

#region Constructor and Disposer
Expand Down Expand Up @@ -276,13 +278,18 @@ public void Dispose()

private static string EscapeTypeName(string name)
{
if (name.IndexOfAny(SPECIAL_CHARS) < 0)
int specialCharIndex = name.AsSpan().IndexOfAny(s_specialChars);
if (specialCharIndex < 0)
{
return name;
}

var sb = new ValueStringBuilder(stackalloc char[64]);
foreach (char c in name)
sb.Append(name.AsSpan(0, specialCharIndex));

foreach (char c in name.AsSpan(specialCharIndex))
{
if (Array.IndexOf<char>(SPECIAL_CHARS, c) >= 0)
if (SpecialChars.Contains(c))
sb.Append('\\');

sb.Append(c);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ namespace System
{
public partial class String
{
// Avoid paying the init cost of all the IndexOfAnyValues unless they are actually used.
private static class IndexOfAnyValuesStorage
{
// The Unicode Standard, Sec. 5.8, Recommendation R4 and Table 5-2 state that the CR, LF,
// CRLF, NEL, LS, FF, and PS sequences are considered newline functions. That section
// also specifically excludes VT from the list of newline functions, so we do not include
// it in the needle list.
public static readonly IndexOfAnyValues<char> NewLineChars =
IndexOfAnyValues.Create("\r\n\f\u0085\u2028\u2029");
}

private const int StackallocIntBufferSizeLimit = 128;

private static void FillStringChecked(string dest, int destPos, string src)
Expand Down Expand Up @@ -1233,16 +1244,9 @@ internal static int IndexOfNewlineChar(ReadOnlySpan<char> text, out int stride)
// the haystack; or O(n) if no needle is found. This ensures that in the common case
// of this method being called within a loop, the worst-case runtime is O(n) rather than
// O(n^2), where n is the length of the input text.
//
// The Unicode Standard, Sec. 5.8, Recommendation R4 and Table 5-2 state that the CR, LF,
// CRLF, NEL, LS, FF, and PS sequences are considered newline functions. That section
// also specifically excludes VT from the list of newline functions, so we do not include
// it in the needle list.

const string needles = "\r\n\f\u0085\u2028\u2029";

stride = default;
int idx = text.IndexOfAny(needles);
int idx = text.IndexOfAny(IndexOfAnyValuesStorage.NewLineChars);
if ((uint)idx < (uint)text.Length)
{
stride = 1; // needle found
Expand Down

0 comments on commit 47158cc

Please sign in to comment.