Browse Source

Merge pull request #1534 from dotnet-campus/t/lindexi1/fix-1533

Fix 1533 Avoid throwing exception in TryReadDouble
Steven Kirk 7 years ago
parent
commit
d00dc76f11

+ 20 - 6
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,9 +76,16 @@ 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 (TryReadString(out var stringResult, separator) &&
+                double.TryParse(stringResult, NumberStyles.Float, _formatProvider, out result))
+            {
+                return true;
+            }
+            else
+            {
+                result = default(double);
+                return false;
+            }
         }
 
         public double ReadDouble(char? separator = null)

+ 69 - 0
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<FormatException>(() => 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<FormatException>(() => 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));
+        }
+    }
+}