ICU-13339 Do not parse decimal point for integers

This commit is contained in:
Ramon 2020-05-12 14:13:50 +02:00 committed by Shane F. Carr
parent e734111ee5
commit 2de2585f1b
2 changed files with 52 additions and 3 deletions

View file

@ -695,9 +695,10 @@ u_scanf_integer_handler(UFILE *input,
int32_t len;
void *num = (void*) (args[0].ptrValue);
UNumberFormat *format;
UNumberFormat *format, *localFormat;
int32_t parsePos = 0;
int32_t skipped;
int32_t parseIntOnly = 0;
UErrorCode status = U_ZERO_ERROR;
int64_t result;
@ -722,11 +723,20 @@ u_scanf_integer_handler(UFILE *input,
if(format == 0)
return 0;
/* for integer types, do not attempt to parse fractions */
localFormat = unum_clone(format, &status);
if(U_FAILURE(status))
return 0;
if(info->fSpec == 'd' || info->fSpec == 'i' || info->fSpec == 'u')
parseIntOnly = 1;
unum_setAttribute(localFormat, UNUM_PARSE_INT_ONLY, parseIntOnly);
/* Skip the positive prefix. ICU normally can't handle this due to strict parsing. */
skipped += u_scanf_skip_leading_positive_sign(input, format, &status);
skipped += u_scanf_skip_leading_positive_sign(input, localFormat, &status);
/* parse the number */
result = unum_parseInt64(format, input->str.fPos, len, &parsePos, &status);
result = unum_parseInt64(localFormat, input->str.fPos, len, &parsePos, &status);
/* mask off any necessary bits */
if (!info->fSkipArg) {
@ -741,6 +751,9 @@ u_scanf_integer_handler(UFILE *input,
/* update the input's position to reflect consumed data */
input->str.fPos += parsePos;
/* cleanup cloned formatter */
unum_close(localFormat);
/* we converted 1 arg */
*argConverted = !info->fSkipArg;
return parsePos + skipped;

View file

@ -359,6 +359,41 @@ static void U_CALLCONV DataDrivenPrintf(void)
}
U_CDECL_END
U_CDECL_BEGIN
static void U_CALLCONV ScanfMultipleIntegers(void)
{
UnicodeString input = UNICODE_STRING("[1.2.3]", 7);
UnicodeString fmt = UNICODE_STRING("[%d.%d.%d]", 10);
DataDrivenLogger logger;
const int32_t expectedFirst = 1;
const int32_t expectedSecond = 2;
const int32_t expectedThird = 3;
const int32_t expectedResult = 3;
int32_t first = 0;
int32_t second = 0;
int32_t third = 0;
int32_t result = u_sscanf_u(input.getBuffer(), fmt.getBuffer(), &first, &second, &third);
if(first != expectedFirst){
log_err("error in scanfmultipleintegers test 'first' Got: %d Exp: %d\n",
first, expectedFirst);
}
if(second != expectedSecond){
log_err("error in scanfmultipleintegers test 'second' Got: %d Exp: %d\n",
second, expectedSecond);
}
if(third != expectedThird){
log_err("error in scanfmultipleintegers test 'third' Got: %d Exp: %d\n",
third, expectedThird);
}
if(result != expectedResult){
log_err("error in scanfmultipleintegers test 'result' Got: %d Exp: %d\n",
result, expectedResult);
}
}
U_CDECL_END
U_CDECL_BEGIN
static void U_CALLCONV DataDrivenScanf(void)
{
@ -698,6 +733,7 @@ static void addAllTests(TestNode** root) {
addTest(root, &DataDrivenPrintfPrecision, "datadriv/DataDrivenPrintfPrecision");
addTest(root, &DataDrivenScanf, "datadriv/DataDrivenScanf");
#endif
addTest(root, &ScanfMultipleIntegers, "ScanfMultipleIntegers");
addStreamTests(root);
}