From 0d4b1c1cb93cc49d7b9cf8d750efadcfd20dea45 Mon Sep 17 00:00:00 2001 From: Frank Tang Date: Mon, 20 Jul 2020 22:35:31 +0000 Subject: [PATCH] ICU-21160 Fix the length return by preflight See #1178 --- icu4c/source/common/locdispnames.cpp | 24 +++++++++++++++--------- icu4c/source/test/cintltst/cloctst.c | 21 +++++++++++++++++++++ icu4c/source/test/cintltst/cloctst.h | 2 ++ 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/icu4c/source/common/locdispnames.cpp b/icu4c/source/common/locdispnames.cpp index 3f056c35e58..0255d30da8a 100644 --- a/icu4c/source/common/locdispnames.cpp +++ b/icu4c/source/common/locdispnames.cpp @@ -406,17 +406,23 @@ uloc_getDisplayScript(const char* locale, UChar *dest, int32_t destCapacity, UErrorCode *pErrorCode) { - UErrorCode err = U_ZERO_ERROR; - int32_t res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, + UErrorCode err = U_ZERO_ERROR; + int32_t res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, uloc_getScript, _kScriptsStandAlone, &err); - - if ( err == U_USING_DEFAULT_WARNING ) { + + if (destCapacity == 0 && err == U_BUFFER_OVERFLOW_ERROR) { + // For preflight, return the max of the value and the fallback. + int32_t fallback_res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, + uloc_getScript, _kScripts, pErrorCode); + return (fallback_res > res) ? fallback_res : res; + } + if ( err == U_USING_DEFAULT_WARNING ) { return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, - uloc_getScript, _kScripts, pErrorCode); - } else { - *pErrorCode = err; - return res; - } + uloc_getScript, _kScripts, pErrorCode); + } else { + *pErrorCode = err; + return res; + } } static int32_t diff --git a/icu4c/source/test/cintltst/cloctst.c b/icu4c/source/test/cintltst/cloctst.c index 71d62c19fa2..2dc4a08cd38 100644 --- a/icu4c/source/test/cintltst/cloctst.c +++ b/icu4c/source/test/cintltst/cloctst.c @@ -217,6 +217,7 @@ void addLocaleTest(TestNode** root) TESTCASE(TestPrefixes); TESTCASE(TestSimpleResourceInfo); TESTCASE(TestDisplayNames); + TESTCASE(TestGetDisplayScriptPreFlighting21160); TESTCASE(TestGetAvailableLocales); TESTCASE(TestGetAvailableLocalesByType); TESTCASE(TestDataDirectory); @@ -808,6 +809,26 @@ static void TestDisplayNames() } } +/** + * ICU-21160 test the pre-flighting call to uloc_getDisplayScript returns the actual length needed + * for the result buffer. + */ +static void TestGetDisplayScriptPreFlighting21160() +{ + const char* locale = "und-Latn"; + const char* inlocale = "de"; + + UErrorCode ec = U_ZERO_ERROR; + UChar* result = NULL; + int32_t length = uloc_getDisplayScript(locale, inlocale, NULL, 0, &ec) + 1; + ec = U_ZERO_ERROR; + result=(UChar*)malloc(sizeof(UChar) * length); + length = uloc_getDisplayScript(locale, inlocale, result, length, &ec); + if (U_FAILURE(ec)) { + log_err("uloc_getDisplayScript length %d returned error %s", length, u_errorName(ec)); + } + free(result); +} /* test for uloc_getAvialable() and uloc_countAvilable()*/ static void TestGetAvailableLocales() diff --git a/icu4c/source/test/cintltst/cloctst.h b/icu4c/source/test/cintltst/cloctst.h index be61de10ba8..3aaba109178 100644 --- a/icu4c/source/test/cintltst/cloctst.h +++ b/icu4c/source/test/cintltst/cloctst.h @@ -33,6 +33,8 @@ static void TestSimpleResourceInfo(void); * Use Locale to access Resource file display names and compare against expected values **/ static void TestDisplayNames(void); +static void TestGetDisplayScriptPreFlighting21160(void); + /** * Test getAvailableLocales **/