Skip to content

Commit a926285

Browse files
committed
perf: Optimize regular numbers parse logics
1 parent 7923dd8 commit a926285

File tree

2 files changed

+62
-7
lines changed

2 files changed

+62
-7
lines changed

YamlDotNet.Test/Serialization/DeserializerTest.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,44 @@ public void NewLinesInKeys()
220220
Assert.Equal($"value\na\nb", dictionary.First().Value);
221221
}
222222

223+
[Theory]
224+
[InlineData(System.Byte.MinValue)]
225+
[InlineData(System.Byte.MaxValue)]
226+
[InlineData(System.Int16.MinValue)]
227+
[InlineData(System.Int16.MaxValue)]
228+
[InlineData(System.Int32.MinValue)]
229+
[InlineData(System.Int32.MaxValue)]
230+
[InlineData(System.Int64.MinValue)]
231+
[InlineData(System.Int64.MaxValue)]
232+
[InlineData(System.UInt64.MaxValue)]
233+
[InlineData(System.Single.MinValue)]
234+
[InlineData(System.Single.MaxValue)]
235+
[InlineData(System.Double.MinValue)]
236+
[InlineData(System.Double.MaxValue)]
237+
public void UnquotedStringTypeDeserialization_RegularNumbers(object expected)
238+
{
239+
var deserializer = new DeserializerBuilder()
240+
.WithAttemptingUnquotedStringTypeDeserialization().Build();
241+
242+
var yaml = $"Value: {expected}";
243+
244+
#if NETFRAMEWORK
245+
// It needs explicitly specifying maximum precision for value roundtrip.
246+
if (expected is float floatValue)
247+
{
248+
yaml = $"Value: {floatValue:G9}";
249+
}
250+
if (expected is double doubleValue)
251+
{
252+
yaml = $"Value: {doubleValue:G17}";
253+
}
254+
#endif
255+
256+
var resultDict = deserializer.Deserialize<IDictionary<string, object>>(yaml);
257+
Assert.True(resultDict.ContainsKey("Value"));
258+
Assert.Equal(expected, resultDict["Value"]);
259+
}
260+
223261
[Theory]
224262
[InlineData(".nan", System.Single.NaN)]
225263
[InlineData(".NaN", System.Single.NaN)]

YamlDotNet/Serialization/NodeDeserializers/ScalarNodeDeserializer.cs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -382,13 +382,30 @@ private static object CastInteger(ulong number, TypeCode typeCode)
382382
}
383383
else if (Regex.IsMatch(v, @"[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?")) //regular number
384384
{
385-
if (TryAndSwallow(() => byte.Parse(v, formatter.NumberFormat), out result)) { }
386-
else if (TryAndSwallow(() => short.Parse(v, formatter.NumberFormat), out result)) { }
387-
else if (TryAndSwallow(() => int.Parse(v, formatter.NumberFormat), out result)) { }
388-
else if (TryAndSwallow(() => long.Parse(v, formatter.NumberFormat), out result)) { }
389-
else if (TryAndSwallow(() => ulong.Parse(v, formatter.NumberFormat), out result)) { }
390-
else if (TryAndSwallow(() => float.Parse(v, formatter.NumberFormat), out result)) { }
391-
else if (TryAndSwallow(() => double.Parse(v, formatter.NumberFormat), out result)) { }
385+
#pragma warning disable format
386+
if ( byte.TryParse(v, NumberStyles.Integer, formatter.NumberFormat, out var byteValue )) { result = byteValue; }
387+
else if (short.TryParse(v, NumberStyles.Integer, formatter.NumberFormat, out var shortValue )) { result = shortValue; }
388+
else if ( int.TryParse(v, NumberStyles.Integer, formatter.NumberFormat, out var intValue )) { result = intValue; }
389+
else if ( long.TryParse(v, NumberStyles.Integer, formatter.NumberFormat, out var longValue )) { result = longValue; }
390+
else if (ulong.TryParse(v, NumberStyles.Integer, formatter.NumberFormat, out var ulongValue )) { result = ulongValue; }
391+
#if NETFRAMEWORK
392+
else if ( float.TryParse(v, NumberStyles.Float | NumberStyles.AllowThousands, formatter.NumberFormat, out var floatValue)) { result = floatValue; }
393+
else if (double.TryParse(v, NumberStyles.Float | NumberStyles.AllowThousands, formatter.NumberFormat, out var doubleValue)) { result = doubleValue; }
394+
#else
395+
else if (double.TryParse(v, NumberStyles.Float | NumberStyles.AllowThousands, formatter.NumberFormat, out var doubleValue))
396+
{
397+
var floatValue = (float)doubleValue;
398+
if (!float.IsNaN(floatValue) && !float.IsInfinity(floatValue)) // .NET 6 or later support float.IsNormal
399+
{
400+
result = floatValue;
401+
}
402+
else
403+
{
404+
result = doubleValue;
405+
}
406+
}
407+
#endif
408+
#pragma warning restore format
392409
else
393410
{
394411
//we couldn't parse it, default to string, It's probably too big

0 commit comments

Comments
 (0)