From 467f78b58d3ee2554a79df40693e260cd736d3ca Mon Sep 17 00:00:00 2001 From: robloo Date: Fri, 15 Apr 2022 19:16:17 -0400 Subject: [PATCH] Improve color format length checking for performance --- src/Avalonia.Base/Media/Color.cs | 22 ++++++++++++++-------- src/Avalonia.Base/Media/HslColor.cs | 11 +++++++++-- src/Avalonia.Base/Media/HsvColor.cs | 11 +++++++++-- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/Avalonia.Base/Media/Color.cs b/src/Avalonia.Base/Media/Color.cs index 2f0def58a4..dc22f87d49 100644 --- a/src/Avalonia.Base/Media/Color.cs +++ b/src/Avalonia.Base/Media/Color.cs @@ -166,7 +166,10 @@ namespace Avalonia.Media return true; } - if (s.Length > 5 && + // Note: The length checks are also an important optimization. + // The shortest possible CSS format is "rbg(0,0,0)", Length = 10. + + if (s.Length >= 10 && (s[0] == 'r' || s[0] == 'R') && (s[1] == 'g' || s[1] == 'G') && (s[2] == 'b' || s[2] == 'B') && @@ -175,7 +178,7 @@ namespace Avalonia.Media return true; } - if (s.Length > 5 && + if (s.Length >= 10 && (s[0] == 'h' || s[0] == 'H') && (s[1] == 's' || s[1] == 'S') && (s[2] == 'l' || s[2] == 'L') && @@ -185,7 +188,7 @@ namespace Avalonia.Media return true; } - if (s.Length > 5 && + if (s.Length >= 10 && (s[0] == 'h' || s[0] == 'H') && (s[1] == 's' || s[1] == 'S') && (s[2] == 'v' || s[2] == 'V') && @@ -229,7 +232,10 @@ namespace Avalonia.Media // At this point all parsing uses strings var str = s.ToString(); - if (s.Length > 5 && + // Note: The length checks are also an important optimization. + // The shortest possible CSS format is "rbg(0,0,0)", Length = 10. + + if (s.Length >= 10 && (s[0] == 'r' || s[0] == 'R') && (s[1] == 'g' || s[1] == 'G') && (s[2] == 'b' || s[2] == 'B') && @@ -238,7 +244,7 @@ namespace Avalonia.Media return true; } - if (s.Length > 5 && + if (s.Length >= 10 && (s[0] == 'h' || s[0] == 'H') && (s[1] == 's' || s[1] == 'S') && (s[2] == 'l' || s[2] == 'L') && @@ -248,7 +254,7 @@ namespace Avalonia.Media return true; } - if (s.Length > 5 && + if (s.Length >= 10 && (s[0] == 'h' || s[0] == 'H') && (s[1] == 's' || s[1] == 'S') && (s[2] == 'v' || s[2] == 'V') && @@ -342,14 +348,14 @@ namespace Avalonia.Media return false; } - if (workingString.Length > 6 && + if (workingString.Length >= 11 && workingString.StartsWith("rgba(", StringComparison.OrdinalIgnoreCase) && workingString.EndsWith(")", StringComparison.Ordinal)) { workingString = workingString.Substring(5, workingString.Length - 6); } - if (workingString.Length > 5 && + if (workingString.Length >= 10 && workingString.StartsWith("rgb(", StringComparison.OrdinalIgnoreCase) && workingString.EndsWith(")", StringComparison.Ordinal)) { diff --git a/src/Avalonia.Base/Media/HslColor.cs b/src/Avalonia.Base/Media/HslColor.cs index e27a4f3106..622d3ac2b7 100644 --- a/src/Avalonia.Base/Media/HslColor.cs +++ b/src/Avalonia.Base/Media/HslColor.cs @@ -241,19 +241,26 @@ namespace Avalonia.Media return false; } - if (workingString.Length > 6 && + // Note: The length checks are also an important optimization. + // The shortest possible format is "hsl(0,0,0)", Length = 10. + + if (workingString.Length >= 11 && workingString.StartsWith("hsla(", StringComparison.OrdinalIgnoreCase) && workingString.EndsWith(")", StringComparison.Ordinal)) { workingString = workingString.Substring(5, workingString.Length - 6); } - if (workingString.Length > 5 && + if (workingString.Length >= 10 && workingString.StartsWith("hsl(", StringComparison.OrdinalIgnoreCase) && workingString.EndsWith(")", StringComparison.Ordinal)) { workingString = workingString.Substring(4, workingString.Length - 5); } + else + { + return false; + } string[] components = workingString.Split(','); diff --git a/src/Avalonia.Base/Media/HsvColor.cs b/src/Avalonia.Base/Media/HsvColor.cs index 164aeb1df1..1e718b5739 100644 --- a/src/Avalonia.Base/Media/HsvColor.cs +++ b/src/Avalonia.Base/Media/HsvColor.cs @@ -241,19 +241,26 @@ namespace Avalonia.Media return false; } - if (workingString.Length > 6 && + // Note: The length checks are also an important optimization. + // The shortest possible format is "hsv(0,0,0)", Length = 10. + + if (workingString.Length >= 11 && workingString.StartsWith("hsva(", StringComparison.OrdinalIgnoreCase) && workingString.EndsWith(")", StringComparison.Ordinal)) { workingString = workingString.Substring(5, workingString.Length - 6); } - if (workingString.Length > 5 && + if (workingString.Length >= 10 && workingString.StartsWith("hsv(", StringComparison.OrdinalIgnoreCase) && workingString.EndsWith(")", StringComparison.Ordinal)) { workingString = workingString.Substring(4, workingString.Length - 5); } + else + { + return false; + } string[] components = workingString.Split(',');