8000 Optimize parsing/conversion of TextDecorations from string, reduce allocations by h3xds1nz · Pull Request #9778 · dotnet/wpf · GitHub
[go: up one dir, main page]

Skip to content

Optimize parsing/conversion of TextDecorations from string, reduce allocations #9778

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
May 16, 2025
Prev Previous commit
Next Next commit
Add documentation, remove whitespaces, final cleanup
  • Loading branch information
h3xds1nz committed Mar 24, 2025
commit bff9377997eb3979f6ab3ee1a30e28da0b7a5799
10000
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,19 @@
namespace System.Windows
{
/// <summary>
/// TypeConverter for TextDecorationCollection
/// </summary>
/// Provides a type converter to convert from <see langword="string"/> to <see cref="TextDecorationCollection"/> only.
/// </summary>
public sealed class TextDecorationCollectionConverter : TypeConverter
{
/// <summary>
/// CanConvertTo method
/// Returns whether this converter can convert the object to the specified
/// <paramref name="destinationType"/>, using the specified <paramref name="context"/>.
/// </summary>
/// <param name="context"> ITypeDescriptorContext </param>
/// <param name="destinationType"> Type to convert to </param>
/// <returns> false will always be returned because TextDecorations cannot be converted to any other type. </returns>
/// <param name="context">Context information used for conversion.</param>
/// <param name="destinationType">Type being evaluated for conversion.</param>
/// <returns>
/// <see langword="false"/> will always be returned because <see cref="TextDecorations"/> cannot be converted to any other type.
/// </returns>
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
// Return false for any other target type. Don't call base.CanConvertTo() because it would be confusing
Expand All @@ -28,44 +31,46 @@ public override bool CanConvertTo(ITypeDescriptorContext context, Type destinati
}

/// <summary>
/// CanConvertFrom
/// Returns whether this class can convert specific <see cref="Type"/> into <see cref="TextDecorationCollection"/>.
/// </summary>
/// <param name="context"> ITypeDescriptorContext </param>
/// <param name="sourceType">Type to convert to </param>
/// <returns> true if it can convert from sourceType to TextDecorations, false otherwise </returns>
/// <param name="sourceType">Type being evaluated for conversion.</param>
/// <returns>
/// <see langword="true"/> if <paramref name="sourceType"/> is <see langword="string"/>, otherwise <see langword="false"/>.
/// </returns>
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}

/// <summary>
/// ConvertFrom
/// Converts <paramref name="input"/> of <see langword="string"/> type to its <see cref="TextDecorationCollection"/> represensation.
/// </summary>
/// <param name="context"> ITypeDescriptorContext </param>
/// <param name="culture"> CultureInfo </param>
/// <param name="input"> The input object to be converted to TextDecorations </param>
/// <returns> the converted value of the input object </returns>
/// <param name="context">Context information used for conversion, ignored currently.</param>
/// <param name="culture">The culture specifier to use, ignored currently.</param>
/// <param name="input">The string to convert from.</param>
/// <returns>A <see cref="TextDecorationCollection"/> representing the <see langword="string"/> specified by <paramref name="input"/>.</returns>
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object input)
{
if (input is null)
throw GetConvertFromException(input);

if (input is not string value)
throw new ArgumentException(SR.Format(SR.General_BadType, "ConvertFrom"), nameof(input));
return ConvertFromString(value);
throw new ArgumentException(SR.Format(SR.General_BadType, "ConvertFrom"), nameof(input));

return ConvertFromString(value);
}

/// <summary>
/// ConvertFromString
/// Converts <paramref name="text"/> to its <see cref="TextDecorationCollection"/> represensation.
/// </summary>
/// <param name="text"> The string to be converted into TextDecorationCollection object </param>
/// <returns> the converted value of the string flag </returns>
/// <param name="text">The string to be converted into TextDecorationCollection object.</param>
/// <returns>A <see cref="TextDecorationCollection"/> representing the <see langword="string"/> specified by <paramref name="text"/>.</returns>
/// <remarks>
/// The text parameter can be either string "None" or a combination of the predefined
/// TextDecoration names delimited by commas (,). One or more blanks spaces can precede
/// or follow each text decoration name or comma. There can't be duplicate TextDecoration names in the
/// string. The operation is case-insensitive.
/// The text parameter can be either be <see langword="null"/>; <see cref="string.Empty"/>; the string "None"
/// or a combination of the predefined <see cref="TextDecorations"/> names delimited by commas (,).
/// One or more blanks spaces can precede or follow each text decoration name or comma.
/// There can't be duplicate TextDecoration names in the string. The operation is case-insensitive.
/// </remarks>
public static new TextDecorationCollection ConvertFromString(string text)
{
Expand All @@ -88,7 +93,7 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c
if (decorationsSpan.IsEmpty || decorationsSpan.Equals("None", StringComparison.OrdinalIgnoreCase))
return new TextDecorationCollection();

// Create new collection, save allocations
// Create new collection, save re-allocations
TextDecorationCollection textDecorations = new(1 + decorationsSpan.Count(','));

// Go through each item in the input and match accordingly
Expand Down Expand Up @@ -123,16 +128,16 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c
}

return textDecorations;
}
}

/// <summary>
/// ConvertTo
/// Converts a <paramref name="value"/> of <see cref="TextDecorationCollection"/> to the specified <paramref name="destinationType"/>.
/// </summary>
/// <param name="context"> ITypeDescriptorContext </param>
/// <param name="culture"> CultureInfo </param>
/// <param name="value"> the object to be converted to another type </param>
/// <param name="destinationType"> The destination type of the conversion </param>
/// <returns> null will always be returned because TextDecorations cannot be converted to any other type. </returns>
/// <param name="context">Context information used for conversion.</param>
/// <param name="culture">The culture specifier to use.</param>
/// <param name="value">Duration value to convert from.</param>
/// <param name="destinationType">Type being evaluated for conversion.</param>
/// <returns><see langword="null"/> will always be returned because <see cref="TextDecorations"/> cannot be converted to any other type.</returns>
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor) && value is IEnumerable<TextDecoration>)
Expand All @@ -144,6 +149,6 @@ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cul

// Pass unhandled cases to base class (which will throw exceptions for null value or destinationType.)
return base.ConvertTo(context, culture, value, destinationType);
}
}
}
}
}
0