ICU-13339 Do not parse decimal point for integers
diff --git a/icu4c/source/io/uscanf_p.cpp b/icu4c/source/io/uscanf_p.cpp
index 6dc1c09..5bf3e5b 100644
--- a/icu4c/source/io/uscanf_p.cpp
+++ b/icu4c/source/io/uscanf_p.cpp
@@ -695,9 +695,10 @@
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 @@
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 @@
/* 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;
diff --git a/icu4c/source/test/iotest/iotest.cpp b/icu4c/source/test/iotest/iotest.cpp
index 186d10e..2d6d336 100644
--- a/icu4c/source/test/iotest/iotest.cpp
+++ b/icu4c/source/test/iotest/iotest.cpp
@@ -360,6 +360,41 @@
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)
{
#if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO
@@ -698,6 +733,7 @@
addTest(root, &DataDrivenPrintfPrecision, "datadriv/DataDrivenPrintfPrecision");
addTest(root, &DataDrivenScanf, "datadriv/DataDrivenScanf");
#endif
+ addTest(root, &ScanfMultipleIntegers, "ScanfMultipleIntegers");
addStreamTests(root);
}