Skip to content

Commit

Permalink
Remove some string interpolation allocation (#1510)
Browse files Browse the repository at this point in the history
  • Loading branch information
stephentoub authored May 29, 2024
1 parent 001f792 commit 01c46ff
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 59 deletions.
18 changes: 8 additions & 10 deletions src/Humanizer/HeadingExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Humanizer;
namespace Humanizer;

/// <summary>
/// Style for the cardinal direction humanization
Expand All @@ -23,6 +23,7 @@ public enum HeadingStyle
public static class HeadingExtensions
{
internal static readonly string[] Headings = ["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"];
internal static readonly string[] HeadingsShort = ["N_Short", "NNE_Short", "NE_Short", "ENE_Short", "E_Short", "ESE_Short", "SE_Short", "SSE_Short", "S_Short", "SSW_Short", "SW_Short", "WSW_Short", "W_Short", "WNW_Short", "NW_Short", "NNW_Short"];
internal static readonly char[] HeadingArrows = ['↑', '↗', '→', '↘', '↓', '↙', '←', '↖'];

// https://stackoverflow.com/a/7490772/1720761
Expand All @@ -39,14 +40,11 @@ public static string ToHeading(this double heading, HeadingStyle style = Heading
{
var val = (int) (heading / 22.5 + .5);

var result = Headings[val % 16];
var headingsIndex = val % 16;

if (style == HeadingStyle.Abbreviated)
{
return Resources.GetResource($"{result}_Short", culture);
}

return Resources.GetResource(result, culture);
return Resources.GetResource(
style == HeadingStyle.Abbreviated ? HeadingsShort[headingsIndex] : Headings[headingsIndex],
culture);
}

/// <summary>
Expand Down Expand Up @@ -86,9 +84,9 @@ public static double FromAbbreviatedHeading(this string heading, CultureInfo? cu
culture ??= CultureInfo.CurrentCulture;

var upperCaseHeading = culture.TextInfo.ToUpper(heading);
for (var index = 0; index < Headings.Length; ++index)
for (var index = 0; index < HeadingsShort.Length; ++index)
{
var localizedShortHeading = Resources.GetResource($"{Headings[index]}_Short", culture);
var localizedShortHeading = Resources.GetResource(HeadingsShort[index], culture);
if (culture.CompareInfo.Compare(upperCaseHeading, localizedShortHeading) == 0)
{
return index * 22.5;
Expand Down
24 changes: 21 additions & 3 deletions src/Humanizer/Localisation/Formatters/DefaultFormatter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Humanizer;
namespace Humanizer;

/// <summary>
/// Default implementation of IFormatter interface.
Expand Down Expand Up @@ -50,11 +50,29 @@ public virtual string TimeSpanHumanize_Age()
/// <inheritdoc cref="IFormatter.DataUnitHumanize(DataUnit, double, bool)"/>
public virtual string DataUnitHumanize(DataUnit dataUnit, double count, bool toSymbol = true)
{
var resourceKey = toSymbol ? $"DataUnit_{dataUnit}Symbol" : $"DataUnit_{dataUnit}";
var resourceKey = (toSymbol, dataUnit) switch
{
(true, DataUnit.Bit) => "DataUnit_BitSymbol",
(true, DataUnit.Byte) => "DataUnit_ByteSymbol",
(true, DataUnit.Kilobyte) => "DataUnit_KilobyteSymbol",
(true, DataUnit.Megabyte) => "DataUnit_MegabyteSymbol",
(true, DataUnit.Gigabyte) => "DataUnit_GigabyteSymbol",
(true, DataUnit.Terabyte) => "DataUnit_TerabyteSymbol",
(true, _) => $"DataUnit_{dataUnit}Symbol",

(false, DataUnit.Bit) => "DataUnit_Bit",
(false, DataUnit.Byte) => "DataUnit_Byte",
(false, DataUnit.Kilobyte) => "DataUnit_Kilobyte",
(false, DataUnit.Megabyte) => "DataUnit_Megabyte",
(false, DataUnit.Gigabyte) => "DataUnit_Gigabyte",
(false, DataUnit.Terabyte) => "DataUnit_Terabyte",
(false, _) => $"DataUnit_{dataUnit}",
};

var resourceValue = Format(resourceKey);

if (!toSymbol && count > 1)
resourceValue += 's';
resourceValue += "s";

return resourceValue;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,11 @@
namespace Humanizer;
namespace Humanizer;

class EnglishNumberToWordsConverter : GenderlessNumberToWordsConverter
{
static readonly string[] UnitsMap = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"];
static readonly string[] UnitsMapTh = ["zeroth", "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth", "fourteenth", "fifteenth", "sixteenth", "seventeenth", "eighteenth", "nineteenth"];
static readonly string[] TensMap = ["zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"];

static readonly Dictionary<long, string> OrdinalExceptions = new()
{
{
1, "first"
},
{
2, "second"
},
{
3, "third"
},
{
4, "fourth"
},
{
5, "fifth"
},
{
8, "eighth"
},
{
9, "ninth"
},
{
12, "twelfth"
},
};

public override string Convert(long number) =>
Convert(number, false);

Expand Down Expand Up @@ -126,23 +99,8 @@ static void CollectPartsUnderAThousand(List<string> parts, long number, bool isO
}
}

static string GetUnitValue(long number, bool isOrdinal)
{
if (isOrdinal)
{
if (ExceptionNumbersToWords(number, out var exceptionString))
{
return exceptionString;
}

return $"{UnitsMap[number]}th";
}

return UnitsMap[number];
}

static bool ExceptionNumbersToWords(long number, [NotNullWhen(true)] out string? words) =>
OrdinalExceptions.TryGetValue(number, out words);
static string GetUnitValue(long number, bool isOrdinal) =>
isOrdinal ? UnitsMapTh[number] : UnitsMap[number];

public override string ConvertToTuple(int number) =>
number switch
Expand Down

0 comments on commit 01c46ff

Please sign in to comment.