ICU-21160 Fix the length return by preflight
See #1178
diff --git a/icu4c/source/common/locdispnames.cpp b/icu4c/source/common/locdispnames.cpp
index 3f056c3..0255d30 100644
--- a/icu4c/source/common/locdispnames.cpp
+++ b/icu4c/source/common/locdispnames.cpp
@@ -406,17 +406,23 @@
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 71d62c1..2dc4a08 100644
--- a/icu4c/source/test/cintltst/cloctst.c
+++ b/icu4c/source/test/cintltst/cloctst.c
@@ -217,6 +217,7 @@
TESTCASE(TestPrefixes);
TESTCASE(TestSimpleResourceInfo);
TESTCASE(TestDisplayNames);
+ TESTCASE(TestGetDisplayScriptPreFlighting21160);
TESTCASE(TestGetAvailableLocales);
TESTCASE(TestGetAvailableLocalesByType);
TESTCASE(TestDataDirectory);
@@ -808,6 +809,26 @@
}
}
+/**
+ * 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 be61de1..3aaba10 100644
--- a/icu4c/source/test/cintltst/cloctst.h
+++ b/icu4c/source/test/cintltst/cloctst.h
@@ -33,6 +33,8 @@
* Use Locale to access Resource file display names and compare against expected values
**/
static void TestDisplayNames(void);
+static void TestGetDisplayScriptPreFlighting21160(void);
+
/**
* Test getAvailableLocales
**/