diff --git a/BeefLibs/corlib/src/Float.bf b/BeefLibs/corlib/src/Float.bf index 4676cb25..3ecfae64 100644 --- a/BeefLibs/corlib/src/Float.bf +++ b/BeefLibs/corlib/src/Float.bf @@ -182,6 +182,7 @@ namespace System bool isNeg = val[0] == '-'; bool isPos = val[0] == '+'; + bool digitsFound = false; double result = 0; double decimalMultiplier = 0; @@ -205,7 +206,7 @@ namespace System if ((c == 'e') || (c == 'E')) { //Error if there are no numbers after the prefix - if(i == val.Length - 1) + if(i == val.Length - 1 || !digitsFound) return .Err; var exponent = Try!(int32.Parse(val.Substring(i + 1))); result *= Math.Pow(10, (double)exponent); @@ -237,10 +238,15 @@ namespace System { result *= 10; result += (int32)(c - '0'); + digitsFound = true; } else return .Err; } + + if (!digitsFound) + return .Err; + return isNeg ? (float)(-result) : (float)result; } } diff --git a/BeefLibs/corlib/src/Int16.bf b/BeefLibs/corlib/src/Int16.bf index c78178ca..a092c211 100644 --- a/BeefLibs/corlib/src/Int16.bf +++ b/BeefLibs/corlib/src/Int16.bf @@ -83,6 +83,7 @@ namespace System return .Err(.NoValue); bool isNeg = false; + bool digitsFound = false; int16 result = 0; int16 radix = style.HasFlag(.Hex) ? 0x10 : 10; @@ -101,6 +102,7 @@ namespace System { result &*= radix; result &+= (int16)(c - '0'); + digitsFound = true; } else if ((c >= 'a') && (c <= 'f')) { @@ -108,6 +110,7 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= c - 'a' + 10; + digitsFound = true; } else if ((c >= 'A') && (c <= 'F')) { @@ -115,12 +118,14 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= c - 'A' + 10; + digitsFound = true; } else if ((c == 'X') || (c == 'x')) { if ((!style.HasFlag(.AllowHexSpecifier)) || (i == 0) || (result != 0)) return .Err(.InvalidChar(result)); radix = 0x10; + digitsFound = false; } else if (c == '\'') { @@ -137,6 +142,9 @@ namespace System return .Err(.Overflow); } + if (!digitsFound) + return .Err(.NoValue); + return isNeg ? -result : result; } diff --git a/BeefLibs/corlib/src/Int32.bf b/BeefLibs/corlib/src/Int32.bf index 4dda63d5..3dc6b6c2 100644 --- a/BeefLibs/corlib/src/Int32.bf +++ b/BeefLibs/corlib/src/Int32.bf @@ -132,6 +132,7 @@ namespace System return .Err(.NoValue); bool isNeg = false; + bool digitsFound = false; int32 result = 0; int32 radix = style.HasFlag(.Hex) ? 0x10 : 10; @@ -150,6 +151,7 @@ namespace System { result &*= radix; result &+= (int32)(c - '0'); + digitsFound = true; } else if ((c >= 'a') && (c <= 'f')) { @@ -157,6 +159,7 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= c - 'a' + 10; + digitsFound = true; } else if ((c >= 'A') && (c <= 'F')) { @@ -164,12 +167,14 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= c - 'A' + 10; + digitsFound = true; } else if ((c == 'X') || (c == 'x')) { if ((!style.HasFlag(.AllowHexSpecifier)) || (i == 0) || (result != 0)) return .Err(.InvalidChar(result)); radix = 0x10; + digitsFound = false; } else if (c == '\'') { @@ -186,6 +191,9 @@ namespace System return .Err(.Overflow); } + if (!digitsFound) + return .Err(.NoValue); + return isNeg ? -result : result; } diff --git a/BeefLibs/corlib/src/Int64.bf b/BeefLibs/corlib/src/Int64.bf index d160e43d..ac427ab7 100644 --- a/BeefLibs/corlib/src/Int64.bf +++ b/BeefLibs/corlib/src/Int64.bf @@ -113,6 +113,7 @@ namespace System return .Err(.NoValue); bool isNeg = false; + bool digitsFound = false; int64 result = 0; int64 radix = style.HasFlag(.Hex) ? 0x10 : 10; @@ -131,6 +132,7 @@ namespace System { result &*= radix; result &+= (int64)(c - '0'); + digitsFound = true; } else if ((c >= 'a') && (c <= 'f')) { @@ -138,6 +140,7 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= c - 'a' + 10; + digitsFound = true; } else if ((c >= 'A') && (c <= 'F')) { @@ -145,12 +148,14 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= c - 'A' + 10; + digitsFound = true; } else if ((c == 'X') || (c == 'x')) { if ((!style.HasFlag(.AllowHexSpecifier)) || (i == 0) || (result != 0)) return .Err(.InvalidChar(result)); radix = 0x10; + digitsFound = false; } else if (c == '\'') { @@ -167,6 +172,9 @@ namespace System return .Err(.Overflow); } + if (!digitsFound) + return .Err(.NoValue); + return isNeg ? -result : result; } diff --git a/BeefLibs/corlib/src/Int8.bf b/BeefLibs/corlib/src/Int8.bf index f0a2702f..cca29c69 100644 --- a/BeefLibs/corlib/src/Int8.bf +++ b/BeefLibs/corlib/src/Int8.bf @@ -83,6 +83,7 @@ namespace System return .Err(.NoValue); bool isNeg = false; + bool digitsFound = false; int8 result = 0; int8 radix = style.HasFlag(.Hex) ? 0x10 : 10; @@ -101,6 +102,7 @@ namespace System { result &*= radix; result &+= (int8)(c - '0'); + digitsFound = true; } else if ((c >= 'a') && (c <= 'f')) { @@ -108,6 +110,7 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= (int8)(c - 'a' + 10); + digitsFound = true; } else if ((c >= 'A') && (c <= 'F')) { @@ -115,12 +118,14 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= (int8)(c - 'A' + 10); + digitsFound = true; } else if ((c == 'X') || (c == 'x')) { if ((!style.HasFlag(.AllowHexSpecifier)) || (i == 0) || (result != 0)) return .Err(.InvalidChar(result)); radix = 0x10; + digitsFound = false; } else if (c == '\'') { @@ -137,6 +142,9 @@ namespace System return .Err(.Overflow); } + if (!digitsFound) + return .Err(.NoValue); + return isNeg ? -result : result; } diff --git a/BeefLibs/corlib/src/UInt16.bf b/BeefLibs/corlib/src/UInt16.bf index 40c4469f..15370e58 100644 --- a/BeefLibs/corlib/src/UInt16.bf +++ b/BeefLibs/corlib/src/UInt16.bf @@ -82,6 +82,7 @@ namespace System if (val.IsEmpty) return .Err(.NoValue); + bool digitsFound = false; uint16 result = 0; uint16 prevResult = 0; @@ -95,6 +96,7 @@ namespace System { result &*= radix; result &+= (uint16)(c - '0'); + digitsFound = true; } else if ((c >= 'a') && (c <= 'f')) { @@ -102,6 +104,7 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= (uint16)(c - 'a' + 10); + digitsFound = true; } else if ((c >= 'A') && (c <= 'F')) { @@ -109,12 +112,14 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= (uint16)(c - 'A' + 10); + digitsFound = true; } else if ((c == 'X') || (c == 'x')) { if ((!style.HasFlag(.AllowHexSpecifier)) || (i == 0) || (result != 0)) return .Err(.InvalidChar(result)); radix = 0x10; + digitsFound = false; } else if (c == '\'') { @@ -132,6 +137,9 @@ namespace System prevResult = result; } + if (!digitsFound) + return .Err(.NoValue); + return result; } diff --git a/BeefLibs/corlib/src/UInt32.bf b/BeefLibs/corlib/src/UInt32.bf index f53ba571..e5ffe9e2 100644 --- a/BeefLibs/corlib/src/UInt32.bf +++ b/BeefLibs/corlib/src/UInt32.bf @@ -110,6 +110,7 @@ namespace System if (val.IsEmpty) return .Err(.NoValue); + bool digitsFound = false; uint32 result = 0; uint32 prevResult = 0; @@ -123,6 +124,7 @@ namespace System { result &*= radix; result &+= (uint32)(c - '0'); + digitsFound = true; } else if ((c >= 'a') && (c <= 'f')) { @@ -130,6 +132,7 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= (uint32)(c - 'a' + 10); + digitsFound = true; } else if ((c >= 'A') && (c <= 'F')) { @@ -137,12 +140,14 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= (uint32)(c - 'A' + 10); + digitsFound = true; } else if ((c == 'X') || (c == 'x')) { if ((!style.HasFlag(.AllowHexSpecifier)) || (i == 0) || (result != 0)) return .Err(.InvalidChar(result)); radix = 0x10; + digitsFound = false; } else if (c == '\'') { @@ -160,6 +165,9 @@ namespace System prevResult = result; } + if (!digitsFound) + return .Err(.NoValue); + return result; } diff --git a/BeefLibs/corlib/src/UInt64.bf b/BeefLibs/corlib/src/UInt64.bf index 8ae6e3af..89d7e990 100644 --- a/BeefLibs/corlib/src/UInt64.bf +++ b/BeefLibs/corlib/src/UInt64.bf @@ -94,6 +94,7 @@ namespace System if (val.IsEmpty) return .Err(.NoValue); + bool digitsFound = false; uint64 result = 0; uint64 prevResult = 0; @@ -107,6 +108,7 @@ namespace System { result &*= radix; result &+= (uint64)(c - '0'); + digitsFound = true; } else if ((c >= 'a') && (c <= 'f')) { @@ -114,6 +116,7 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= (uint64)(c - 'a' + 10); + digitsFound = true; } else if ((c >= 'A') && (c <= 'F')) { @@ -121,12 +124,14 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= (uint64)(c - 'A' + 10); + digitsFound = true; } else if ((c == 'X') || (c == 'x')) { if ((!style.HasFlag(.AllowHexSpecifier)) || (i == 0) || (result != 0)) return .Err(.InvalidChar(result)); radix = 0x10; + digitsFound = false; } else if (c == '\'') { @@ -144,6 +149,9 @@ namespace System prevResult = result; } + if (!digitsFound) + return .Err(.NoValue); + return result; } diff --git a/BeefLibs/corlib/src/UInt8.bf b/BeefLibs/corlib/src/UInt8.bf index ca5aae11..b780fd50 100644 --- a/BeefLibs/corlib/src/UInt8.bf +++ b/BeefLibs/corlib/src/UInt8.bf @@ -82,6 +82,7 @@ namespace System if (val.IsEmpty) return .Err(.NoValue); + bool digitsFound = false; uint8 result = 0; uint8 prevResult = 0; @@ -95,6 +96,7 @@ namespace System { result &*= radix; result &+= (uint8)(c - '0'); + digitsFound = true; } else if ((c >= 'a') && (c <= 'f')) { @@ -102,6 +104,7 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= (uint8)(c - 'a' + 10); + digitsFound = true; } else if ((c >= 'A') && (c <= 'F')) { @@ -109,12 +112,14 @@ namespace System return .Err(.InvalidChar(result)); result &*= radix; result &+= (uint8)(c - 'A' + 10); + digitsFound = true; } else if ((c == 'X') || (c == 'x')) { if ((!style.HasFlag(.AllowHexSpecifier)) || (i == 0) || (result != 0)) return .Err(.InvalidChar(result)); radix = 0x10; + digitsFound = false; } else if (c == '\'') { @@ -132,6 +137,9 @@ namespace System prevResult = result; } + if (!digitsFound) + return .Err(.NoValue); + return result; } diff --git a/IDEHelper/Tests/src/Floats.bf b/IDEHelper/Tests/src/Floats.bf index 9bbb2e2a..d9853198 100644 --- a/IDEHelper/Tests/src/Floats.bf +++ b/IDEHelper/Tests/src/Floats.bf @@ -22,5 +22,33 @@ namespace Tests FloatParseTest("3.3e-11", 3.3e-11f); FloatParseTest("0.002e5", 0.002e5f); } + + public static void FloatParseErrTest(StringView string) + { + Test.Assert(float.Parse(string) case .Err); + } + + [Test] + public static void TestErrors() + { + FloatParseErrTest(""); + FloatParseErrTest("-"); + FloatParseErrTest("+"); + FloatParseErrTest("."); + FloatParseErrTest("+."); + FloatParseErrTest("-."); + FloatParseErrTest("E"); + FloatParseErrTest("e"); + FloatParseErrTest(".E"); + FloatParseErrTest(".e"); + FloatParseErrTest("-.E"); + FloatParseErrTest("-.e"); + FloatParseErrTest("+.E"); + FloatParseErrTest("+.e"); + FloatParseErrTest("5E-"); + FloatParseErrTest("5e-"); + FloatParseErrTest("6E+"); + FloatParseErrTest("6e+"); + } } } diff --git a/IDEHelper/Tests/src/Ints.bf b/IDEHelper/Tests/src/Ints.bf index 07836e3a..f1ea9d3c 100644 --- a/IDEHelper/Tests/src/Ints.bf +++ b/IDEHelper/Tests/src/Ints.bf @@ -1,6 +1,7 @@ #pragma warning disable 168 using System; +using System.Globalization; namespace Tests { @@ -43,5 +44,74 @@ namespace Tests int i1 = i0 % 1; Test.Assert(i1 == 0); } + + public static void Int64ParseTest(StringView string, int64 expectedResult, NumberStyles style = .Number) + { + int64 result = int64.Parse(string, style); + Test.Assert(expectedResult == result); + } + + [Test] + public static void TestInt64Parse() + { + Int64ParseTest("1234567890", 1234567890L); + Int64ParseTest("+1234567890", 1234567890L); + Int64ParseTest("-9876543210", -9876543210L); + Int64ParseTest("0x123456789abcdef", 81985529216486895L, .HexNumber); + Int64ParseTest("0X123456789ABCDEF", 81985529216486895L, .HexNumber); + Int64ParseTest("+0x123456789abcdef", 81985529216486895L, .HexNumber); + Int64ParseTest("-0x76543210fedcba", -33306621262093498L, .HexNumber); + } + + public static void Int64ParseErrorTest(StringView string, NumberStyles style = .Number) + { + Test.Assert(int64.Parse(string, style) case .Err); + } + + [Test] + public static void TestInt64ParseError() + { + Int64ParseErrorTest(""); + Int64ParseErrorTest("-"); + Int64ParseErrorTest("+"); + Int64ParseErrorTest("0x", .HexNumber); + Int64ParseErrorTest("0X", .HexNumber); + Int64ParseErrorTest("+0x", .HexNumber); + Int64ParseErrorTest("+0X", .HexNumber); + Int64ParseErrorTest("-0x", .HexNumber); + Int64ParseErrorTest("-0X", .HexNumber); + } + + public static void Uint64ParseTest(StringView string, uint64 expectedResult, NumberStyles style = .Number) + { + uint64 result = uint64.Parse(string, style); + Test.Assert(expectedResult == result); + } + + [Test] + public static void TestUint64Parse() + { + Uint64ParseTest("1234567890", 1234567890UL); + Uint64ParseTest("+9876543210", 9876543210UL); + Uint64ParseTest("0x123456789abcdef", 81985529216486895UL, .HexNumber); + Uint64ParseTest("0X123456789ABCDEF", 81985529216486895UL, .HexNumber); + Uint64ParseTest("+0xfedcba9876543210", 18364758544493064720UL, .HexNumber); + } + + public static void Uint64ParseErrorTest(StringView string, NumberStyles style = .Number) + { + Test.Assert(uint64.Parse(string, style) case .Err); + } + + [Test] + public static void TestUint64ParseError() + { + Uint64ParseErrorTest(""); + Uint64ParseErrorTest("+"); + Uint64ParseErrorTest("0x", .HexNumber); + Uint64ParseErrorTest("0X", .HexNumber); + Uint64ParseErrorTest("+0x", .HexNumber); + Uint64ParseErrorTest("+0X", .HexNumber); + } } }