Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions PreciseNumber.Test/PreciseNumberParseCultureTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace ktsu.PreciseNumber.Test;

using System.Globalization;
using System.Numerics;

[TestClass]
public class PreciseNumberParseCultureTests
Expand Down Expand Up @@ -135,6 +136,27 @@ public void Parse_ThrowsForWhatTheStyleDoesNotAllow()
Assert.ThrowsExactly<FormatException>(() => PreciseNumber.Parse("1e 5", NumberStyles.Float, CultureInfo.InvariantCulture));
}

[TestMethod]
[DataRow("10", NumberStyles.HexNumber)]
[DataRow("A", NumberStyles.HexNumber)]
[DataRow("10", NumberStyles.AllowHexSpecifier)]
[DataRow("1010", NumberStyles.BinaryNumber)]
[DataRow("1010", NumberStyles.AllowBinarySpecifier)]
public void ParseAndTryParse_RejectHexAndBinaryStylesAsDecimalDoes(string text, NumberStyles style)
{
Assert.ThrowsExactly<ArgumentException>(() => decimal.Parse(text, style, CultureInfo.InvariantCulture));

Assert.ThrowsExactly<ArgumentException>(() => PreciseNumber.Parse(text, style, CultureInfo.InvariantCulture));
Assert.ThrowsExactly<ArgumentException>(() => PreciseNumber.Parse(text.AsSpan(), style, CultureInfo.InvariantCulture));
Assert.ThrowsExactly<ArgumentException>(() => PreciseNumber.TryParse(text, style, CultureInfo.InvariantCulture, out _));
Assert.ThrowsExactly<ArgumentException>(() => PreciseNumber.TryParse(text.AsSpan(), style, CultureInfo.InvariantCulture, out _));
Assert.ThrowsExactly<ArgumentException>(() => ParseGeneric<PreciseNumber>(text, style));
}

private static T ParseGeneric<T>(string text, NumberStyles style)
where T : INumberBase<T> =>
T.Parse(text, style, CultureInfo.InvariantCulture);

[TestMethod]
public void Parse_WithoutAStyleStillReadsFractionsExponentsAndSigns()
{
Expand Down
15 changes: 15 additions & 0 deletions PreciseNumber/PreciseNumber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@
/// The message carried by the <see cref="FormatException"/> that parsing throws.
/// </summary>
private const string InvalidFormatMessage = "Input string was not in a correct format.";
private const string UnsupportedParseStylesMessage = "The number styles AllowHexSpecifier and AllowBinarySpecifier are not supported by PreciseNumber.";

#if NET8_0_OR_GREATER
private const NumberStyles UnsupportedParseStyles = NumberStyles.AllowHexSpecifier | NumberStyles.AllowBinarySpecifier;
#else
// NumberStyles.AllowBinarySpecifier arrived in .NET 8, but a caller on net7.0 can still pass its value.
private const NumberStyles UnsupportedParseStyles = NumberStyles.AllowHexSpecifier | (NumberStyles)0x400;
#endif

/// <summary>
/// The fewest significant digits <see cref="Divide(PreciseNumber, PreciseNumber)"/> produces
Expand Down Expand Up @@ -736,7 +744,7 @@
/// A fixed precision such as <c>E15</c> rounds values that need 17 digits, which turns
/// <see cref="double.MaxValue"/> into a number that converts back to infinity.
/// </remarks>
internal static string GetStringFormatForFloatType<TFloat>()

Check warning on line 747 in PreciseNumber/PreciseNumber.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

Remove this method and declare a constant for this value.

Check warning on line 747 in PreciseNumber/PreciseNumber.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

Remove this method and declare a constant for this value.
where TFloat : INumber<TFloat>
=> "R";

Expand Down Expand Up @@ -1197,12 +1205,19 @@
public static PreciseNumber MinMagnitudeNumber(PreciseNumber x, PreciseNumber y) => MinMagnitude(x, y);

/// <inheritdoc/>
public static PreciseNumber Parse(ReadOnlySpan<char> s, NumberStyles style, IFormatProvider? provider)

Check warning on line 1208 in PreciseNumber/PreciseNumber.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

Refactor this method to reduce its Cognitive Complexity from 29 to the 15 allowed.

Check warning on line 1208 in PreciseNumber/PreciseNumber.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

All 'Parse' method overloads should be adjacent.

Check warning on line 1208 in PreciseNumber/PreciseNumber.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

Refactor this method to reduce its Cognitive Complexity from 29 to the 15 allowed.

Check warning on line 1208 in PreciseNumber/PreciseNumber.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

All 'Parse' method overloads should be adjacent.
{
// Read the separator and signs from the same culture TryFormat writes them with, so that
// Parse(x.ToString(p), p) round-trips for every provider.
NumberFormatInfo numberFormat = NumberFormatInfo.GetInstance(provider ?? InvariantCulture);

// Hex and binary input would be read as decimal digits and come back as the wrong number,
// so refuse those styles outright, as decimal and double do.
if ((style & UnsupportedParseStyles) != 0)
{
throw new ArgumentException(UnsupportedParseStylesMessage, nameof(style));
}

s = TrimAllowedWhite(s, style);

if (s.IsEmpty)
Expand Down Expand Up @@ -1247,14 +1262,14 @@
}

hasDecimal = true;
i += decimalSeparator.Length - 1;

Check warning on line 1265 in PreciseNumber/PreciseNumber.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

Do not update the stop condition variable 'i' in the body of the for loop.

Check warning on line 1265 in PreciseNumber/PreciseNumber.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

Do not update the stop condition variable 'i' in the body of the for loop.
continue;
}

// Group separators may only sit between integral digits.
if (allowThousands && !hasDecimal && digitCount > 0 && s[i..].StartsWith(groupSeparator, StringComparison.Ordinal))
{
i += groupSeparator.Length - 1;

Check warning on line 1272 in PreciseNumber/PreciseNumber.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

Do not update the stop condition variable 'i' in the body of the for loop.

Check warning on line 1272 in PreciseNumber/PreciseNumber.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

Do not update the stop condition variable 'i' in the body of the for loop.
continue;
}

Expand Down
Loading