This is an automated email from the ASF dual-hosted git repository.

nightowl888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucenenet.git


The following commit(s) were added to refs/heads/master by this push:
     new 86052e5c4 SWEEP: Prefer 'AsSpan' over 'Substring' when span-based 
overloads are available. Fixes #675.
86052e5c4 is described below

commit 86052e5c4701b70cb15f9dbbbd48dad8f7f0b512
Author: Shad Storhaug <[email protected]>
AuthorDate: Mon Oct 17 02:01:38 2022 +0700

    SWEEP: Prefer 'AsSpan' over 'Substring' when span-based overloads are 
available. Fixes #675.
---
 Directory.Build.targets                                  |  7 +++++--
 .../Analysis/Hunspell/Dictionary.cs                      |  4 ++++
 .../Analysis/Pattern/PatternReplaceCharFilter.cs         | 16 ++++++++++++----
 .../Language/DoubleMetaphone.cs                          |  8 ++++++++
 .../ByTask/Feeds/EnwikiContentSource.cs                  | 15 +++++++++++++--
 .../ByTask/Tasks/SearchTravRetHighlightTask.cs           |  4 ++++
 .../Flexible/Standard/Parser/EscapeQuerySyntaxImpl.cs    | 11 +++++++++++
 .../Flexible/Standard/Parser/StandardSyntaxParser.cs     | 12 ++++++++++--
 src/Lucene.Net.Replicator/Http/HttpClientBase.cs         |  2 +-
 .../Suggest/Analyzing/AnalyzingInfixSuggester.cs         |  8 ++++++++
 src/Lucene.Net/Util/AttributeSource.cs                   | 13 +++++++++++++
 11 files changed, 89 insertions(+), 11 deletions(-)

diff --git a/Directory.Build.targets b/Directory.Build.targets
index 575b43be5..aa039fc02 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -34,6 +34,7 @@
 
     <DefineConstants>$(DefineConstants);FEATURE_ARGITERATOR</DefineConstants>
     
<DefineConstants>$(DefineConstants);FEATURE_DICTIONARY_REMOVE_CONTINUEENUMERATION</DefineConstants>
+    
<DefineConstants>$(DefineConstants);FEATURE_STRING_CONCAT_READONLYSPAN</DefineConstants>
 
   </PropertyGroup>
   
@@ -53,8 +54,10 @@
 
     
<DefineConstants>$(DefineConstants);FEATURE_CONDITIONALWEAKTABLE_ENUMERATOR</DefineConstants>
     
<DefineConstants>$(DefineConstants);FEATURE_CONDITIONALWEAKTABLE_ADDORUPDATE</DefineConstants>
-    <DefineConstants>$(DefineConstants);FEATURE_SPAN</DefineConstants>
-    
+    
<DefineConstants>$(DefineConstants);FEATURE_NUMBER_PARSE_READONLYSPAN</DefineConstants>
+    
<DefineConstants>$(DefineConstants);FEATURE_STREAM_READ_SPAN</DefineConstants>
+    
<DefineConstants>$(DefineConstants);FEATURE_STRINGBUILDER_APPEND_READONLYSPAN</DefineConstants>
+
   </PropertyGroup>
 
   <!-- Features in .NET Standard 2.x, .NET Core 2.x, .NET Core 3.x, .NET 5.x, 
and .NET 6.x -->
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Hunspell/Dictionary.cs 
b/src/Lucene.Net.Analysis.Common/Analysis/Hunspell/Dictionary.cs
index 57027293c..5008384c0 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Hunspell/Dictionary.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Hunspell/Dictionary.cs
@@ -967,7 +967,11 @@ namespace Lucene.Net.Analysis.Hunspell
                                     sb.Length = 0;
                                     sb.Append(cleansed);
                                 }
+#if FEATURE_STRINGBUILDER_APPEND_READONLYSPAN
+                                sb.Append(line.AsSpan(flagSep));
+#else
                                 sb.Append(line.Substring(flagSep));
+#endif
                                 
writer.Write(sb.ToString().GetBytes(Encoding.UTF8));
                             }
                         }
diff --git 
a/src/Lucene.Net.Analysis.Common/Analysis/Pattern/PatternReplaceCharFilter.cs 
b/src/Lucene.Net.Analysis.Common/Analysis/Pattern/PatternReplaceCharFilter.cs
index 75c6c3b8d..d42d9f3ea 100644
--- 
a/src/Lucene.Net.Analysis.Common/Analysis/Pattern/PatternReplaceCharFilter.cs
+++ 
b/src/Lucene.Net.Analysis.Common/Analysis/Pattern/PatternReplaceCharFilter.cs
@@ -87,7 +87,7 @@ namespace Lucene.Net.Analysis.Pattern
             {
                 buffered.Append(temp, 0, cnt);
             }
-            transformedInput = new 
StringReader(ProcessPattern(buffered).ToString());
+            transformedInput = new StringReader(ProcessPattern(buffered)); // 
LUCENENET specific: ProcessPattern already returns string, no need to call 
ToString() on it
         }
 
         public override int Read()
@@ -110,7 +110,7 @@ namespace Lucene.Net.Analysis.Pattern
         /// </summary>
         private string ProcessPattern(StringBuilder input)
         {
-            // LUCENENET TODO: Replacing characters in a StringBuilder is not 
natively
+            // LUCENENET TODO: Replacing characters in a StringBuilder via 
regex is not natively
             // supported in .NET, so this is the approach we are left with.
             // At some point it might make sense to try to port the
             // MONO implementation over that DOES support Regex on a 
StringBuilder.
@@ -131,7 +131,11 @@ namespace Lucene.Net.Analysis.Pattern
                     int lengthBeforeReplacement = cumulativeOutput.Length + 
skippedSize;
 
                     // Add the part that didn't match the regex
+#if FEATURE_STRINGBUILDER_APPEND_READONLYSPAN
+                    cumulativeOutput.Append(inputStr.AsSpan(lastMatchEnd, 
m.Index - lastMatchEnd));
+#else
                     cumulativeOutput.Append(inputStr.Substring(lastMatchEnd, 
m.Index - lastMatchEnd));
+#endif
 
                     int groupSize = m.Length;
                     lastMatchEnd = m.Index + m.Length;
@@ -171,12 +175,16 @@ namespace Lucene.Net.Analysis.Pattern
                 } while ((m = m.NextMatch()).Success);
 
                 // Append the remaining output, no further changes to indices.
-                cumulativeOutput.Append(input.ToString(lastMatchEnd, 
input.Length - lastMatchEnd));
+#if FEATURE_STRINGBUILDER_APPEND_READONLYSPAN
+                cumulativeOutput.Append(inputStr.AsSpan(lastMatchEnd, 
input.Length - lastMatchEnd));
+#else
+                cumulativeOutput.Append(inputStr.Substring(lastMatchEnd, 
input.Length - lastMatchEnd));
+#endif
                 return cumulativeOutput.ToString();
             }
 
             // No match - just return the original string.
-            return input.ToString();
+            return inputStr; // LUCENENET: Since we have already dumped the 
string from input, just return it directly.
         }
     }
 }
\ No newline at end of file
diff --git a/src/Lucene.Net.Analysis.Phonetic/Language/DoubleMetaphone.cs 
b/src/Lucene.Net.Analysis.Phonetic/Language/DoubleMetaphone.cs
index 0c2aba590..192ae286e 100644
--- a/src/Lucene.Net.Analysis.Phonetic/Language/DoubleMetaphone.cs
+++ b/src/Lucene.Net.Analysis.Phonetic/Language/DoubleMetaphone.cs
@@ -1240,7 +1240,11 @@ namespace Lucene.Net.Analysis.Phonetic.Language
                 }
                 else
                 {
+#if FEATURE_STRINGBUILDER_APPEND_READONLYSPAN
+                    this.primary.Append(value.AsSpan(0, addChars - 0));
+#else
                     this.primary.Append(value.Substring(0, addChars - 0));
+#endif
                 }
             }
 
@@ -1253,7 +1257,11 @@ namespace Lucene.Net.Analysis.Phonetic.Language
                 }
                 else
                 {
+#if FEATURE_STRINGBUILDER_APPEND_READONLYSPAN
+                    this.alternate.Append(value.AsSpan(0, addChars - 0));
+#else
                     this.alternate.Append(value.Substring(0, addChars - 0));
+#endif
                 }
             }
 
diff --git a/src/Lucene.Net.Benchmark/ByTask/Feeds/EnwikiContentSource.cs 
b/src/Lucene.Net.Benchmark/ByTask/Feeds/EnwikiContentSource.cs
index 15c5b11f3..8d81b7c07 100644
--- a/src/Lucene.Net.Benchmark/ByTask/Feeds/EnwikiContentSource.cs
+++ b/src/Lucene.Net.Benchmark/ByTask/Feeds/EnwikiContentSource.cs
@@ -116,16 +116,27 @@ namespace Lucene.Net.Benchmarks.ByTask.Feeds
 
             internal string Time(string original)
             {
-                StringBuilder buffer = new StringBuilder();
+                StringBuilder buffer = new StringBuilder(24); // LUCENENET: We 
always have 24 chars, so allocate it up front
 
+#if FEATURE_STRINGBUILDER_APPEND_READONLYSPAN
+                buffer.Append(original.AsSpan(8, 10 - 8));
+                buffer.Append('-');
+                buffer.Append(months[int.Parse(original.AsSpan(5, 7 - 5), 
NumberStyles.Integer, CultureInfo.InvariantCulture) - 1]);
+                buffer.Append('-');
+                buffer.Append(original.AsSpan(0, 4 - 0));
+                buffer.Append(' ');
+                buffer.Append(original.AsSpan(11, 19 - 11));
+                buffer.Append(".000");
+#else
                 buffer.Append(original.Substring(8, 10 - 8));
                 buffer.Append('-');
-                buffer.Append(months[Convert.ToInt32(original.Substring(5, 7 - 
5), CultureInfo.InvariantCulture) - 1]);
+                buffer.Append(months[int.Parse(original.Substring(5, 7 - 5), 
NumberStyles.Integer, CultureInfo.InvariantCulture) - 1]);
                 buffer.Append('-');
                 buffer.Append(original.Substring(0, 4 - 0));
                 buffer.Append(' ');
                 buffer.Append(original.Substring(11, 19 - 11));
                 buffer.Append(".000");
+#endif
 
                 return buffer.ToString();
             }
diff --git 
a/src/Lucene.Net.Benchmark/ByTask/Tasks/SearchTravRetHighlightTask.cs 
b/src/Lucene.Net.Benchmark/ByTask/Tasks/SearchTravRetHighlightTask.cs
index 1f54d9bcd..b207b930c 100644
--- a/src/Lucene.Net.Benchmark/ByTask/Tasks/SearchTravRetHighlightTask.cs
+++ b/src/Lucene.Net.Benchmark/ByTask/Tasks/SearchTravRetHighlightTask.cs
@@ -157,7 +157,11 @@ namespace Lucene.Net.Benchmarks.ByTask.Tasks
                 else if (splits[i].StartsWith("mergeContiguous[", 
StringComparison.Ordinal) == true)
                 {
                     int len = "mergeContiguous[".Length;
+#if FEATURE_NUMBER_PARSE_READONLYSPAN
+                    m_mergeContiguous = bool.Parse(splits[i].AsSpan(len, 
(splits[i].Length - 1) - len));
+#else
                     m_mergeContiguous = bool.Parse(splits[i].Substring(len, 
(splits[i].Length - 1) - len));
+#endif
                 }
                 else if (splits[i].StartsWith("fields[", 
StringComparison.Ordinal) == true)
                 {
diff --git 
a/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/EscapeQuerySyntaxImpl.cs 
b/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/EscapeQuerySyntaxImpl.cs
index 595f50876..182a82caa 100644
--- 
a/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/EscapeQuerySyntaxImpl.cs
+++ 
b/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/EscapeQuerySyntaxImpl.cs
@@ -170,10 +170,17 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
                 }
                 if (found)
                 {
+#if FEATURE_STRINGBUILDER_APPEND_READONLYSPAN
+                    result.Append(@string.ToString().AsSpan(copyStart, 
firstIndex - copyStart));
+                    result.Append(escapeChar);
+                    result.Append(@string.ToString().AsSpan(firstIndex,
+                        (firstIndex + sequence1Length) - firstIndex));
+#else
                     result.Append(@string.ToString().Substring(copyStart, 
firstIndex - copyStart));
                     result.Append(escapeChar);
                     result.Append(@string.ToString().Substring(firstIndex,
                         (firstIndex + sequence1Length) - firstIndex));
+#endif
                     copyStart = start = firstIndex + sequence1Length;
                 }
                 else
@@ -184,7 +191,11 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
             
             if (result.Length == 0 && copyStart == 0)
                 return @string;
+#if FEATURE_STRINGBUILDER_APPEND_READONLYSPAN
+            result.Append(@string.ToString().AsSpan(copyStart));
+#else
             result.Append(@string.ToString().Substring(copyStart));
+#endif
             return result.ToString().AsCharSequence();
         }
 
diff --git 
a/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/StandardSyntaxParser.cs 
b/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/StandardSyntaxParser.cs
index 7bb9afd6d..4421b52e3 100644
--- 
a/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/StandardSyntaxParser.cs
+++ 
b/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/StandardSyntaxParser.cs
@@ -633,7 +633,11 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
                     if (fuzzy)
                     {
                         // LUCENENET specific: parse without throwing 
exceptions
-                        float fms = 
float.TryParse(fuzzySlop.Image.Substring(1), NumberStyles.Float, 
CultureInfo.InvariantCulture, out float temp) ? temp : defaultMinSimilarity;
+#if FEATURE_NUMBER_PARSE_READONLYSPAN
+                        float fms = float.TryParse(fuzzySlop.Image.AsSpan(1), 
NumberStyles.Float, CultureInfo.InvariantCulture, out float temp) ? temp : 
defaultMinSimilarity;
+#else
+                        float fms = 
float.TryParse(fuzzySlop.Image.Substring(1), NumberStyles.Float, 
CultureInfo.InvariantCulture, out float temp) ? temp: defaultMinSimilarity;
+#endif
                         if (fms < 0.0f)
                         {
                             { if (true) throw new 
ParseException(QueryParserMessages.INVALID_SYNTAX_FUZZY_LIMITS); }
@@ -766,8 +770,12 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
 
                     if (fuzzySlop != null)
                     {
-                        // LUCENENET: don't let parsing throw exceptions
+                        // LUCENENET specific: parse without throwing 
exceptions
+#if FEATURE_NUMBER_PARSE_READONLYSPAN
+                        if (float.TryParse(fuzzySlop.Image.AsSpan(1), 
NumberStyles.Float, CultureInfo.InvariantCulture, out float temp))
+#else
                         if (float.TryParse(fuzzySlop.Image.Substring(1), 
NumberStyles.Float, CultureInfo.InvariantCulture, out float temp))
+#endif
                         {
                             try
                             {
diff --git a/src/Lucene.Net.Replicator/Http/HttpClientBase.cs 
b/src/Lucene.Net.Replicator/Http/HttpClientBase.cs
index 880310841..2ea4aa574 100644
--- a/src/Lucene.Net.Replicator/Http/HttpClientBase.cs
+++ b/src/Lucene.Net.Replicator/Http/HttpClientBase.cs
@@ -440,7 +440,7 @@ namespace Lucene.Net.Replicator.Http
                 return res;
             }
 
-#if FEATURE_SPAN
+#if FEATURE_STREAM_READ_SPAN
             public override int Read(Span<byte> buffer)
             {
                 int res = input.Read(buffer);
diff --git 
a/src/Lucene.Net.Suggest/Suggest/Analyzing/AnalyzingInfixSuggester.cs 
b/src/Lucene.Net.Suggest/Suggest/Analyzing/AnalyzingInfixSuggester.cs
index 789a84254..8c1c86c5e 100644
--- a/src/Lucene.Net.Suggest/Suggest/Analyzing/AnalyzingInfixSuggester.cs
+++ b/src/Lucene.Net.Suggest/Suggest/Analyzing/AnalyzingInfixSuggester.cs
@@ -783,11 +783,19 @@ namespace Lucene.Net.Search.Suggest.Analyzing
             // TODO: apps can try to invert their analysis logic
             // here, e.g. downcase the two before checking prefix:
             sb.Append("<b>");
+#if FEATURE_STRINGBUILDER_APPEND_READONLYSPAN
+            sb.Append(surface.AsSpan(0, prefixToken.Length - 0));
+#else
             sb.Append(surface.Substring(0, prefixToken.Length - 0));
+#endif
             sb.Append("</b>");
             if (prefixToken.Length < surface.Length)
             {
+#if FEATURE_STRINGBUILDER_APPEND_READONLYSPAN
+                sb.Append(surface.AsSpan(prefixToken.Length));
+#else
                 sb.Append(surface.Substring(prefixToken.Length));
+#endif
             }
         }
 
diff --git a/src/Lucene.Net/Util/AttributeSource.cs 
b/src/Lucene.Net/Util/AttributeSource.cs
index 2e4f5c0b4..fd5300ece 100644
--- a/src/Lucene.Net/Util/AttributeSource.cs
+++ b/src/Lucene.Net/Util/AttributeSource.cs
@@ -152,16 +152,29 @@ namespace Lucene.Net.Util
                     int lastPlus = 
attributeInterfaceType.FullName.LastIndexOf('+');
                     if (lastPlus == -1)
                     {
+#if FEATURE_STRING_CONCAT_READONLYSPAN
+                        return string.Concat(
+                            attributeInterfaceType.Namespace,
+                            ".",
+                            attributeInterfaceType.Name.AsSpan(1));
+#else
                         return string.Concat(
                             attributeInterfaceType.Namespace,
                             ".",
                             attributeInterfaceType.Name.Substring(1));
+#endif
                     }
                     else
                     {
+#if FEATURE_STRING_CONCAT_READONLYSPAN
+                        return string.Concat(
+                            attributeInterfaceType.FullName.AsSpan(0, lastPlus 
+ 1),
+                            attributeInterfaceType.Name.AsSpan(1));
+#else
                         return string.Concat(
                             attributeInterfaceType.FullName.Substring(0, 
lastPlus + 1),
                             attributeInterfaceType.Name.Substring(1));
+#endif
                     }
                 }
             }

Reply via email to