Skip to content

Let a typed space match a no-break-space separator in Parse [patch] - #176

Open
matt-edmondson wants to merge 1 commit into
mainfrom
fix/174-typed-space-group-separator
Open

matt-edmondson wants to merge 1 commit into
mainfrom
fix/174-typed-space-group-separator

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #174

What changed

fr-FR groups digits with U+202F, and ru-RU, pl-PL, sv-SE and other cultures group with U+00A0. A keyboard types U+0020. Parse compared separators ordinally, so PreciseNumber.Parse("1 234,5", fr) threw where decimal, double and int all return 1234.5. Generic INumberBase<T>.Parse code therefore failed only for PreciseNumber.

A new StartsWithSeparator helper replaces the two ordinal StartsWith checks, for the decimal separator and the group separator. It matches character by character, the way the runtime's MatchChars does. A U+0020 in the input may stand in for a U+00A0 or U+202F in the culture's separator. Every other character stays ordinal, so de-CH's U+2019 still requires U+2019, and a culture whose separator is not a no-break space does not start accepting spaces. #152 (currency separators) hasn't landed yet, so there is nothing to extend there. When it does land, its separators should go through the same helper.

Tests

New cases in PreciseNumberParseCultureTests, using hand-built NumberFormatInfos so they don't depend on ICU:

  • "1 234,5", "-1 234 567" and "1 234 567,25" parse under the provider-only overload, NumberStyles.Number and NumberStyles.Any, for both U+202F and U+00A0 grouping. Each result is checked against decimal.Parse.
  • A typed space parses as a U+00A0 decimal separator, with decimal parity.
  • A real U+202F or U+00A0 still parses.
  • A space is still rejected for an apostrophe (U+2019), . or invariant separator. A U+00A0 does not match a U+202F separator.
  • "1 234" still fails under NumberStyles.Float (no AllowThousands).

Before the source change, the 4 positive tests fail. With it, all 523 tests pass, and dotnet build PreciseNumber.sln succeeds for net7.0–net10.0 with no warnings. Benchmarks were not run. The change only touches the two separator comparisons in Parse, adds no allocation, and leaves the hot arithmetic paths alone.


Generated by Claude Code

fr-FR groups digits with U+202F, and ru-RU, pl-PL and sv-SE with U+00A0,
but a keyboard types U+0020. Parse compared separators ordinally, so
Parse("1 234,5", fr-FR) threw where decimal, double and int all return
1234.5, and generic INumberBase<T>.Parse code failed only for PreciseNumber.
The group and decimal separators are now matched the way the runtime's
MatchChars does: a U+0020 in the input stands in for a U+00A0 or U+202F in
the separator, and every other character stays ordinal.

Fixes #174

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW5r5WL5w6Xw9zvRF9a
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parse("1 234,5", fr-FR) throws where decimal returns 1234.5: a typed space doesn't match a no-break-space group separator

2 participants