Skip to content

Commit 62fa208

Browse files
committed
Add Culture property (default InvariantCulture) extend Number regex to support commas
1 parent 6fa02d3 commit 62fa208

File tree

4 files changed

+52
-10
lines changed

4 files changed

+52
-10
lines changed

src/CommunityToolkit.Maui.UnitTests/Converters/MathExpressionConverterTests.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,4 +284,33 @@ public void MathExpressionConverter_WithAlternateCulture_ReturnsCorrectNumericRe
284284
Assert.True(result is not null);
285285
Assert.Equal(expectedResult, result);
286286
}
287+
288+
[Theory]
289+
[InlineData("", "-12.34 + 56.78", 44.44)]
290+
[InlineData("en-US", "-12.34 + 56.78", 44.44)]
291+
[InlineData("fr-FR", "-12,34 + 56,78", 44.44)]
292+
public void MathExpressionConverter_CultureInfoProperty_HandlesDoubleParsing(string cultureName, string expression, double expectedResult)
293+
{
294+
CultureInfo culture = !string.IsNullOrEmpty(cultureName) ? new CultureInfo(cultureName) : CultureInfo.InvariantCulture;
295+
var mathExpressionConverter = new MultiMathExpressionConverter
296+
{
297+
Culture = culture
298+
};
299+
var result = mathExpressionConverter.Convert(new object?[] { }, mathExpressionTargetType, expression);
300+
Assert.True(result is not null);
301+
Assert.Equal(expectedResult, result);
302+
}
303+
304+
[Theory]
305+
[InlineData("ar-SA", "-12.34 + 56.78")]
306+
[InlineData("ar-SA", "-12,34 + 56.78")]
307+
public void MathExpressionConverter_ArabicCulture_ThrowsException(string cultureName, string expression)
308+
{
309+
CultureInfo culture = !string.IsNullOrEmpty(cultureName) ? new CultureInfo(cultureName) : CultureInfo.InvariantCulture;
310+
var mathExpressionConverter = new MultiMathExpressionConverter
311+
{
312+
Culture = culture
313+
};
314+
Assert.Throws<FormatException>(() => mathExpressionConverter.Convert(new object?[] { }, mathExpressionTargetType, expression));
315+
}
287316
}

src/CommunityToolkit.Maui/Converters/MathExpressionConverter/MathExpression.shared.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ sealed record MathToken(MathTokenType Type, string Text, object? Value);
1515

1616
sealed partial class MathExpression
1717
{
18+
CultureInfo culture { get; init; } = CultureInfo.InvariantCulture;
19+
1820
readonly IReadOnlyList<MathOperator> operators;
1921

20-
internal MathExpression(in string expression, in IReadOnlyList<object?> arguments)
22+
internal MathExpression(in string expression, in IReadOnlyList<object?> arguments, CultureInfo culture)
2123
{
2224
ArgumentException.ThrowIfNullOrEmpty(expression, "Expression can't be null or empty.");
2325
ArgumentNullException.ThrowIfNull(arguments, "Arguments cannot be null.");
@@ -96,6 +98,7 @@ internal MathExpression(in string expression, in IReadOnlyList<object?> argument
9698
}
9799

98100
this.operators = operators;
101+
this.culture = culture;
99102
}
100103

101104
static ReadOnlyDictionary<string, string> BinaryMappingDictionary { get; } = new Dictionary<string, string>
@@ -223,7 +226,7 @@ internal MathExpression(in string expression, in IReadOnlyList<object?> argument
223226
[GeneratedRegex("""^(\-|\!)""")]
224227
private static partial Regex EvaluateUnaryOperators();
225228

226-
[GeneratedRegex("""^(\-?\d+\.\d+|\-?\d+)""")]
229+
[GeneratedRegex("""^(\-?\d+[\.,]\d+| \-?\d+)""")]
227230
private static partial Regex EvaluateNumberPattern();
228231

229232
[GeneratedRegex("""^["]([^"]*)["]""")]
@@ -241,20 +244,20 @@ internal MathExpression(in string expression, in IReadOnlyList<object?> argument
241244
[GeneratedRegex("""^\s*""")]
242245
private static partial Regex EvaluateWhitespace();
243246

244-
static bool ConvertToBoolean(object? b) => b switch
247+
bool ConvertToBoolean(object? b) => b switch
245248
{
246249
bool x => x,
247250
null => false,
248251
double doubleValue => doubleValue != 0 && !double.IsNaN(doubleValue),
249252
string stringValue => !string.IsNullOrEmpty(stringValue),
250-
_ => Convert.ToBoolean(b, CultureInfo.InvariantCulture)
253+
_ => Convert.ToBoolean(b, culture)
251254
};
252255

253-
static double ConvertToDouble(object? x) => Convert.ToDouble(x, CultureInfo.InvariantCulture);
256+
double ConvertToDouble(object? x) => Convert.ToDouble(x, culture);
254257

255-
static int ConvertToInt32(object? x) => Convert.ToInt32(x, CultureInfo.InvariantCulture);
258+
int ConvertToInt32(object? x) => Convert.ToInt32(x, culture);
256259

257-
static string? ConvertToString(object? x) => Convert.ToString(x, CultureInfo.InvariantCulture);
260+
string? ConvertToString(object? x) => Convert.ToString(x, culture);
258261

259262
bool ParsePattern(Regex regex)
260263
{
@@ -367,7 +370,7 @@ bool ParsePrimary()
367370
if (ParsePattern(EvaluateNumberPattern()))
368371
{
369372
string _number = PatternMatch.Groups[1].Value;
370-
RPN.Add(new MathToken(MathTokenType.Value, _number, double.Parse(_number, CultureInfo.InvariantCulture)));
373+
RPN.Add(new MathToken(MathTokenType.Value, _number, double.Parse(_number, culture)));
371374
return true;
372375
}
373376

src/CommunityToolkit.Maui/Converters/MathExpressionConverter/MathExpressionConverter.shared.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ public partial class MathExpressionConverter : BaseConverterOneWay<object?, obje
1111
/// <inheritdoc/>
1212
public override object? DefaultConvertReturnValue { get; set; } = 0.0d;
1313

14+
/// <summary>
15+
/// Get or set the culture to use in the converter.
16+
/// </summary>
17+
public CultureInfo Culture { get; set; } = CultureInfo.InvariantCulture;
18+
1419
/// <summary>
1520
/// Calculate the incoming expression string with one variable.
1621
/// </summary>
@@ -22,6 +27,6 @@ public partial class MathExpressionConverter : BaseConverterOneWay<object?, obje
2227
{
2328
ArgumentNullException.ThrowIfNull(parameter);
2429

25-
return new MathExpression(parameter, [inputValue]).CalculateResult();
30+
return new MathExpression(parameter, [inputValue], Culture).CalculateResult();
2631
}
2732
}

src/CommunityToolkit.Maui/Converters/MathExpressionConverter/MultiMathExpressionConverter.shared.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ namespace CommunityToolkit.Maui.Converters;
1010
[AcceptEmptyServiceProvider]
1111
public class MultiMathExpressionConverter : MultiValueConverterExtension, ICommunityToolkitMultiValueConverter
1212
{
13+
/// <summary>
14+
/// Get or set the culture to use in the converter.
15+
/// </summary>
16+
public CultureInfo Culture { get; set; } = CultureInfo.InvariantCulture;
17+
1318
/// <summary>
1419
/// Calculate the incoming expression string with variables.
1520
/// </summary>
@@ -30,7 +35,7 @@ public class MultiMathExpressionConverter : MultiValueConverterExtension, ICommu
3035

3136
return values is null
3237
? null
33-
: new MathExpression(expression, values).CalculateResult();
38+
: new MathExpression(expression, values, this.Culture).CalculateResult();
3439
}
3540

3641
/// <summary>

0 commit comments

Comments
 (0)