From 247365714878d8b880889447065b94bdf1613645 Mon Sep 17 00:00:00 2001 From: lindexi Date: Mon, 30 Apr 2018 21:41:24 +0800 Subject: [PATCH 1/3] Fix 1533 Avoid throwing exception in TryReadDouble --- src/Avalonia.Base/Utilities/StringTokenizer.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Base/Utilities/StringTokenizer.cs b/src/Avalonia.Base/Utilities/StringTokenizer.cs index 2559e52932..f4e9eee960 100644 --- a/src/Avalonia.Base/Utilities/StringTokenizer.cs +++ b/src/Avalonia.Base/Utilities/StringTokenizer.cs @@ -70,8 +70,15 @@ namespace Avalonia.Utilities public bool TryReadDouble(out double result, char? separator = null) { var success = TryReadString(out var stringResult, separator); - result = success ? double.Parse(stringResult, _formatProvider) : 0; - return success; + + if (success) + { + success = double.TryParse(stringResult, NumberStyles.Float, _formatProvider, out result); + return success; + } + + result = default(double); + return false; } public double ReadDouble(char? separator = null) From a3f1c0d6210bfeff93573e4051fd7f873f68e19d Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 15 May 2018 06:59:04 +0200 Subject: [PATCH 2/3] Make TryReadInt32 not throw too. And simplify the code. --- .../Utilities/StringTokenizer.cs | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/Avalonia.Base/Utilities/StringTokenizer.cs b/src/Avalonia.Base/Utilities/StringTokenizer.cs index f4e9eee960..a159bfb72e 100644 --- a/src/Avalonia.Base/Utilities/StringTokenizer.cs +++ b/src/Avalonia.Base/Utilities/StringTokenizer.cs @@ -52,9 +52,16 @@ namespace Avalonia.Utilities public bool TryReadInt32(out Int32 result, char? separator = null) { - var success = TryReadString(out var stringResult, separator); - result = success ? int.Parse(stringResult, _formatProvider) : 0; - return success; + if (TryReadString(out var stringResult, separator) && + int.TryParse(stringResult, NumberStyles.Integer, _formatProvider, out result)) + { + return true; + } + else + { + result = default(Int32); + return false; + } } public int ReadInt32(char? separator = null) @@ -69,16 +76,16 @@ namespace Avalonia.Utilities public bool TryReadDouble(out double result, char? separator = null) { - var success = TryReadString(out var stringResult, separator); - - if (success) + if (TryReadString(out var stringResult, separator) && + double.TryParse(stringResult, NumberStyles.Float, _formatProvider, out result)) { - success = double.TryParse(stringResult, NumberStyles.Float, _formatProvider, out result); - return success; + return true; + } + else + { + result = default(double); + return false; } - - result = default(double); - return false; } public double ReadDouble(char? separator = null) From b615be746ab662a866b3babc92e17471d040a770 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 15 May 2018 07:23:53 +0200 Subject: [PATCH 3/3] Added a few StringTokenizer tests. --- .../Utilities/StringTokenizerTests.cs | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 tests/Avalonia.Base.UnitTests/Utilities/StringTokenizerTests.cs diff --git a/tests/Avalonia.Base.UnitTests/Utilities/StringTokenizerTests.cs b/tests/Avalonia.Base.UnitTests/Utilities/StringTokenizerTests.cs new file mode 100644 index 0000000000..4f94b1ca80 --- /dev/null +++ b/tests/Avalonia.Base.UnitTests/Utilities/StringTokenizerTests.cs @@ -0,0 +1,69 @@ +using System; +using Avalonia.Utilities; +using Xunit; + +namespace Avalonia.Base.UnitTests.Utilities +{ + public class StringTokenizerTests + { + [Fact] + public void ReadInt32_Reads_Values() + { + var target = new StringTokenizer("123,456"); + + Assert.Equal(123, target.ReadInt32()); + Assert.Equal(456, target.ReadInt32()); + Assert.Throws(() => target.ReadInt32()); + } + + [Fact] + public void ReadDouble_Reads_Values() + { + var target = new StringTokenizer("12.3,45.6"); + + Assert.Equal(12.3, target.ReadDouble()); + Assert.Equal(45.6, target.ReadDouble()); + Assert.Throws(() => target.ReadDouble()); + } + + [Fact] + public void TryReadInt32_Reads_Values() + { + var target = new StringTokenizer("123,456"); + + Assert.True(target.TryReadInt32(out var value)); + Assert.Equal(123, value); + Assert.True(target.TryReadInt32(out value)); + Assert.Equal(456, value); + Assert.False(target.TryReadInt32(out value)); + } + + [Fact] + public void TryReadInt32_Doesnt_Throw() + { + var target = new StringTokenizer("abc"); + + Assert.False(target.TryReadInt32(out var value)); + } + + [Fact] + public void TryReadDouble_Reads_Values() + { + var target = new StringTokenizer("12.3,45.6"); + + Assert.True(target.TryReadDouble(out var value)); + Assert.Equal(12.3, value); + Assert.True(target.TryReadDouble(out value)); + Assert.Equal(45.6, value); + Assert.False(target.TryReadDouble(out value)); + } + + [Fact] + public void TryReadDouble_Doesnt_Throw() + { + var target = new StringTokenizer("abc"); + + Assert.False(target.TryReadDouble(out var value)); + } + } +}