summaryrefslogtreecommitdiffstats
path: root/luni
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2014-03-13 12:15:23 +0000
committerNarayan Kamath <narayan@google.com>2014-03-13 17:11:37 +0000
commit11c1f6f38955e0ec20d86ca70891f30bf5f5e4bb (patch)
treeb5cf983a9001c31fdbcf7e0296e24b8769d6a858 /luni
parente6e7947cef6e6299d617b8efbe108d1c89a8f91d (diff)
downloadlibcore-11c1f6f38955e0ec20d86ca70891f30bf5f5e4bb.zip
libcore-11c1f6f38955e0ec20d86ca70891f30bf5f5e4bb.tar.gz
libcore-11c1f6f38955e0ec20d86ca70891f30bf5f5e4bb.tar.bz2
Fix ICU glue for uloc_toLanguageTag.
There were several issues : - ICU does not set the output param UErrorCode* to U_ZERO_ERROR when an API call is successful, so we need to clear it before every API call. - ICU sets the error code to U_BUFFER_OVERFLOW_ERROR (and sets the output length to the required size) if the input buffer is too small. - ICU sets the error code to U_STRING_NOT_TERMINATED_WARNING when the input buffer is one character too short. bug: 13414549 bug: 13412659 Change-Id: I3e23ea507a540f37ab1c14a60afe801bca286554
Diffstat (limited to 'luni')
-rw-r--r--luni/src/main/native/libcore_icu_ICU.cpp34
-rw-r--r--luni/src/test/java/libcore/java/util/LocaleTest.java10
2 files changed, 28 insertions, 16 deletions
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index c869542..dc57b10 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -168,26 +168,28 @@ static jstring ICU_localeForLanguageTag(JNIEnv* env, jclass, jstring languageTag
static jstring ICU_languageTagForLocale(JNIEnv* env, jclass, jstring javaLocaleId) {
ScopedUtfChars localeID(env, javaLocaleId);
- // The conversion from an ICU locale ID to a BCP 47 tag will shrink
- // the size of the string unless there's an invalid language or a bad
- // parse (which will result in an x-lvariant private use subtag at
- // the end of the input).
- const size_t initialBufferSize = localeID.size();
+ // In most common cases, the BCP 47 tag will be the same size as the ICU
+ // locale ID
+ const size_t initialBufferSize = localeID.size() + 1;
std::vector<char> buffer(initialBufferSize);
UErrorCode status = U_ZERO_ERROR;
- while (true) {
- const size_t outputLength = uloc_toLanguageTag(localeID.c_str(),
- &buffer[0], buffer.size(), false /* strict */, &status);
- if (U_FAILURE(status)) {
- return NULL;
- }
+ const size_t outputLength = uloc_toLanguageTag(localeID.c_str(),
+ &buffer[0], buffer.size(), false /* strict */, &status);
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
+ buffer.resize(outputLength + 1);
+ status = U_ZERO_ERROR;
+ uloc_toLanguageTag(localeID.c_str(), &buffer[0], buffer.size(),
+ false /* strict */, &status);
+ }
- if (outputLength == buffer.size()) {
- buffer.resize(buffer.size() << 1);
- } else {
- break;
- }
+ if (status == U_STRING_NOT_TERMINATED_WARNING) {
+ buffer.resize(buffer.size() + 1);
+ buffer[buffer.size() -1] = '\0';
+ }
+
+ if (maybeThrowIcuException(env, "ICU::languageTagForLocale", status)) {
+ return NULL;
}
return env->NewStringUTF(&buffer[0]);
diff --git a/luni/src/test/java/libcore/java/util/LocaleTest.java b/luni/src/test/java/libcore/java/util/LocaleTest.java
index c6aea9e..89a64c7 100644
--- a/luni/src/test/java/libcore/java/util/LocaleTest.java
+++ b/luni/src/test/java/libcore/java/util/LocaleTest.java
@@ -1134,5 +1134,15 @@ public class LocaleTest extends junit.framework.TestCase {
b.setLanguage("en").setExtension('x', "fooo-baar");
assertEquals("en__#x-fooo-baar", b.build().toString());
}
+
+ // Tests cases where our "guess" for the output size is incorrect.
+ //
+ // https://b.corp.google.com/issue?id=13414549
+ public void test_toLanguageTag_largerTag() {
+ Locale posix = new Locale.Builder()
+ .setLanguage("en").setRegion("US").setVariant("POSIX")
+ .build();
+ assertEquals("en-US-u-va-posix", posix.toLanguageTag());
+ }
}