From 57b4e1efe4b681ed15313d661aabf15d51aa7614 Mon Sep 17 00:00:00 2001 From: Marko Lahma Date: Thu, 31 Jul 2025 09:27:11 +0300 Subject: [PATCH] Minor perf tweaks * use compiled regex in CSharpDocs, check if replacement needed * proper constant stack allocation size in ConversionUtilities * better replace behavior in JsonReferenceVisitorBase --- src/NJsonSchema/ConversionUtilities.cs | 22 +++++++++++++------ .../Visitors/JsonReferenceVisitorBase.cs | 18 ++++++++++----- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/NJsonSchema/ConversionUtilities.cs b/src/NJsonSchema/ConversionUtilities.cs index 95e2dcc4c..5d4cbd2ae 100644 --- a/src/NJsonSchema/ConversionUtilities.cs +++ b/src/NJsonSchema/ConversionUtilities.cs @@ -7,7 +7,6 @@ //----------------------------------------------------------------------- using System.Globalization; -using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Xml.Linq; @@ -93,7 +92,7 @@ private static string ConvertToCamelCase(string input, bool firstCharacterMustBe private static string DoFullCamelCaseConversion(string input, bool firstCharacterMustBeAlpha, CamelCaseMode mode) { var capacity = input.Length + (firstCharacterMustBeAlpha ? 1 : 0); - var buffer = capacity < 2 ? stackalloc char[capacity] : new char[capacity]; + var buffer = capacity <= 256 ? stackalloc char[256] : new char[capacity]; var sb = new ValueStringBuilder(buffer); @@ -363,20 +362,29 @@ private static void AddPrefixToBeginningOfNonEmptyLines(string input, string tab } } + private static readonly char [] _cSharpDocLineBreakChars = ['\r', '\n']; + private static readonly Lazy _cSharpDocLineBreakRegex = new(static () => new Regex("^( *)/// ", RegexOptions.Multiline | RegexOptions.Compiled)); + /// Converts all line breaks in a string into '\n' and removes white spaces. /// The input. /// The tab count. /// The output. public static string ConvertCSharpDocs(string input, int tabCount) { - input = input? - .Replace("\r", string.Empty) - .Replace("\n", "\n" + string.Join("", Enumerable.Repeat(" ", tabCount)) + "/// ") - ?? string.Empty; + input ??= ""; + + var needsCleanup = input.IndexOfAny(_cSharpDocLineBreakChars) != -1; + + if (needsCleanup) + { + input = input + .Replace("\r", string.Empty) + .Replace("\n", "\n" + CreateTabString(tabCount) + "/// "); + } // TODO: Support more markdown features here var xml = new XText(input).ToString(); - return Regex.Replace(xml, @"^( *)/// ", m => m.Groups[1] + "///
", RegexOptions.Multiline); + return _cSharpDocLineBreakRegex.Value.Replace(xml, static m => m.Groups[1] + "///
"); } private static string CreateTabString(int tabCount) diff --git a/src/NJsonSchema/Visitors/JsonReferenceVisitorBase.cs b/src/NJsonSchema/Visitors/JsonReferenceVisitorBase.cs index 2d5d84d28..e2dd982df 100644 --- a/src/NJsonSchema/Visitors/JsonReferenceVisitorBase.cs +++ b/src/NJsonSchema/Visitors/JsonReferenceVisitorBase.cs @@ -243,19 +243,25 @@ protected virtual void Visit(object obj, string path, string? typeNameHint, ISet private static void ReplaceOrDelete(ObservableCollection collection, int index, T obj) { - collection.RemoveAt(index); - if (obj != null) + if (obj is not null) { - collection.Insert(index, obj); + collection[index] = obj; + } + else + { + collection.RemoveAt(index); } } private static void ReplaceOrDelete(IList collection, int index, object obj) { - collection.RemoveAt(index); - if (obj != null) + if (obj is not null) + { + collection[index] = obj; + } + else { - collection.Insert(index, obj); + collection.RemoveAt(index); } } }