summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/ScopedJavaUnicodeString.h58
-rw-r--r--luni/src/main/java/libcore/icu/Transliterator.java31
-rw-r--r--luni/src/main/native/IcuUtilities.cpp73
-rw-r--r--luni/src/main/native/IcuUtilities.h28
-rw-r--r--luni/src/main/native/JniException.cpp23
-rw-r--r--luni/src/main/native/JniException.h3
-rw-r--r--luni/src/main/native/Register.cpp1
-rw-r--r--luni/src/main/native/ZipUtilities.h (renamed from luni/src/main/native/zip.h)6
-rw-r--r--luni/src/main/native/java_text_Bidi.cpp1
-rw-r--r--luni/src/main/native/java_util_regex_Matcher.cpp1
-rw-r--r--luni/src/main/native/java_util_regex_Pattern.cpp3
-rw-r--r--luni/src/main/native/java_util_zip_Deflater.cpp2
-rw-r--r--luni/src/main/native/java_util_zip_Inflater.cpp2
-rw-r--r--luni/src/main/native/libcore_icu_ICU.cpp51
-rw-r--r--luni/src/main/native/libcore_icu_NativeBreakIterator.cpp1
-rw-r--r--luni/src/main/native/libcore_icu_NativeCollation.cpp1
-rw-r--r--luni/src/main/native/libcore_icu_NativeConverter.cpp1
-rw-r--r--luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp18
-rw-r--r--luni/src/main/native/libcore_icu_NativeNormalizer.cpp39
-rw-r--r--luni/src/main/native/libcore_icu_NativePluralRules.cpp1
-rw-r--r--luni/src/main/native/libcore_icu_TimeZones.cpp28
-rw-r--r--luni/src/main/native/libcore_icu_Transliterator.cpp62
-rw-r--r--luni/src/main/native/sub.mk2
-rw-r--r--luni/src/test/java/libcore/icu/TransliteratorTest.java77
24 files changed, 393 insertions, 120 deletions
diff --git a/include/ScopedJavaUnicodeString.h b/include/ScopedJavaUnicodeString.h
index b108a6b..f6ed7ad 100644
--- a/include/ScopedJavaUnicodeString.h
+++ b/include/ScopedJavaUnicodeString.h
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -24,34 +24,44 @@
// jstring. We give ICU a direct pointer to the characters on the Java heap.
// It's clever enough to copy-on-write if necessary.
class ScopedJavaUnicodeString {
-public:
- ScopedJavaUnicodeString(JNIEnv* env, jstring s) : mEnv(env), mString(s) {
- mChars = env->GetStringChars(mString, NULL);
- const int32_t charCount = env->GetStringLength(mString);
- mUnicodeString.setTo(false, mChars, charCount);
+ public:
+ ScopedJavaUnicodeString(JNIEnv* env, jstring s) : mEnv(env), mString(s) {
+ if (s == NULL) {
+ jniThrowNullPointerException(mEnv, NULL);
+ } else {
+ mChars = env->GetStringChars(mString, NULL);
+ const int32_t charCount = env->GetStringLength(mString);
+ mUnicodeString.setTo(false, mChars, charCount);
}
+ }
- ~ScopedJavaUnicodeString() {
- mEnv->ReleaseStringChars(mString, mChars);
+ ~ScopedJavaUnicodeString() {
+ if (mString != NULL) {
+ mEnv->ReleaseStringChars(mString, mChars);
}
+ }
- const UnicodeString& unicodeString() const {
- return mUnicodeString;
- }
+ bool valid() const {
+ return (mString != NULL);
+ }
- UnicodeString& unicodeString() {
- return mUnicodeString;
- }
+ const UnicodeString& unicodeString() const {
+ return mUnicodeString;
+ }
+
+ UnicodeString& unicodeString() {
+ return mUnicodeString;
+ }
-private:
- JNIEnv* mEnv;
- jstring mString;
- const UChar* mChars;
- UnicodeString mUnicodeString;
+ private:
+ JNIEnv* mEnv;
+ jstring mString;
+ const UChar* mChars;
+ UnicodeString mUnicodeString;
- // Disallow copy and assignment.
- ScopedJavaUnicodeString(const ScopedJavaUnicodeString&);
- void operator=(const ScopedJavaUnicodeString&);
+ // Disallow copy and assignment.
+ ScopedJavaUnicodeString(const ScopedJavaUnicodeString&);
+ void operator=(const ScopedJavaUnicodeString&);
};
#endif // SCOPED_JAVA_UNICODE_STRING_H_included
diff --git a/luni/src/main/java/libcore/icu/Transliterator.java b/luni/src/main/java/libcore/icu/Transliterator.java
new file mode 100644
index 0000000..bef5d37
--- /dev/null
+++ b/luni/src/main/java/libcore/icu/Transliterator.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.icu;
+
+public final class Transliterator {
+ /**
+ * Returns the ids of all known transliterators.
+ */
+ public static native String[] getAvailableIDs();
+
+ /**
+ * Transliterates 's' using the transliterator identified by 'id'.
+ */
+ public static native String transliterate(String id, String s);
+
+ private Transliterator() {}
+}
diff --git a/luni/src/main/native/IcuUtilities.cpp b/luni/src/main/native/IcuUtilities.cpp
new file mode 100644
index 0000000..ef9909b
--- /dev/null
+++ b/luni/src/main/native/IcuUtilities.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "IcuUtilities"
+
+#include "IcuUtilities.h"
+
+#include "JniConstants.h"
+#include "JniException.h"
+#include "ScopedLocalRef.h"
+#include "ScopedUtfChars.h"
+#include "UniquePtr.h"
+#include "cutils/log.h"
+#include "unicode/strenum.h"
+#include "unicode/uloc.h"
+#include "unicode/ustring.h"
+
+Locale getLocale(JNIEnv* env, jstring localeName) {
+ return Locale::createFromName(ScopedUtfChars(env, localeName).c_str());
+}
+
+jobjectArray fromStringEnumeration(JNIEnv* env, StringEnumeration* se) {
+ UniquePtr<StringEnumeration> deleter(se);
+ if (se == NULL) {
+ return NULL;
+ }
+
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t count = se->count(status);
+ if (maybeThrowIcuException(env, "StringEnumeration::count", status)) {
+ return NULL;
+ }
+
+ jobjectArray result = env->NewObjectArray(count, JniConstants::stringClass, NULL);
+ for (int32_t i = 0; i < count; ++i) {
+ const UnicodeString* string = se->snext(status);
+ if (maybeThrowIcuException(env, "StringEnumeration::snext", status)) {
+ return NULL;
+ }
+ ScopedLocalRef<jstring> javaString(env, env->NewString(string->getBuffer(), string->length()));
+ env->SetObjectArrayElement(result, i, javaString.get());
+ }
+ return result;
+}
+
+bool maybeThrowIcuException(JNIEnv* env, const char* function, UErrorCode error) {
+ if (U_SUCCESS(error)) {
+ return false;
+ }
+ const char* exceptionClass = "java/lang/RuntimeException";
+ if (error == U_ILLEGAL_ARGUMENT_ERROR) {
+ exceptionClass = "java/lang/IllegalArgumentException";
+ } else if (error == U_INDEX_OUTOFBOUNDS_ERROR || error == U_BUFFER_OVERFLOW_ERROR) {
+ exceptionClass = "java/lang/ArrayIndexOutOfBoundsException";
+ } else if (error == U_UNSUPPORTED_ERROR) {
+ exceptionClass = "java/lang/UnsupportedOperationException";
+ }
+ jniThrowExceptionFmt(env, exceptionClass, "%s failed: %s", function, u_errorName(error));
+ return true;
+}
diff --git a/luni/src/main/native/IcuUtilities.h b/luni/src/main/native/IcuUtilities.h
new file mode 100644
index 0000000..219d663
--- /dev/null
+++ b/luni/src/main/native/IcuUtilities.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ICU_UTILITIES_H_included
+#define ICU_UTILITIES_H_included
+
+#include "jni.h"
+#include "unicode/utypes.h" // For UErrorCode.
+#include "unicode/locid.h" // For Locale.
+
+extern Locale getLocale(JNIEnv* env, jstring localeName);
+extern jobjectArray fromStringEnumeration(JNIEnv* env, StringEnumeration*);
+bool maybeThrowIcuException(JNIEnv* env, const char* function, UErrorCode error);
+
+#endif // ICU_UTILITIES_H_included
diff --git a/luni/src/main/native/JniException.cpp b/luni/src/main/native/JniException.cpp
index c733db4..8f97891 100644
--- a/luni/src/main/native/JniException.cpp
+++ b/luni/src/main/native/JniException.cpp
@@ -17,29 +17,6 @@
#include "JniException.h"
#include "JNIHelp.h"
-bool maybeThrowIcuException(JNIEnv* env, const char* function, UErrorCode error) {
- if (U_SUCCESS(error)) {
- return false;
- }
- const char* exceptionClass;
- switch (error) {
- case U_ILLEGAL_ARGUMENT_ERROR:
- exceptionClass = "java/lang/IllegalArgumentException";
- break;
- case U_INDEX_OUTOFBOUNDS_ERROR:
- case U_BUFFER_OVERFLOW_ERROR:
- exceptionClass = "java/lang/ArrayIndexOutOfBoundsException";
- break;
- case U_UNSUPPORTED_ERROR:
- exceptionClass = "java/lang/UnsupportedOperationException";
- break;
- default:
- exceptionClass = "java/lang/RuntimeException";
- break;
- }
- return jniThrowExceptionFmt(env, exceptionClass, "%s failed: %s", function, u_errorName(error));
-}
-
void jniThrowExceptionWithErrno(JNIEnv* env, const char* exceptionClassName, int error) {
char buf[BUFSIZ];
jniThrowException(env, exceptionClassName, jniStrError(error, buf, sizeof(buf)));
diff --git a/luni/src/main/native/JniException.h b/luni/src/main/native/JniException.h
index cece2aa..2d4a097 100644
--- a/luni/src/main/native/JniException.h
+++ b/luni/src/main/native/JniException.h
@@ -18,13 +18,10 @@
#define JNI_EXCEPTION_H_included
#include "jni.h"
-#include "unicode/utypes.h" // For UErrorCode.
void jniThrowExceptionWithErrno(JNIEnv* env, const char* exceptionClassName, int error);
void jniThrowOutOfMemoryError(JNIEnv* env, const char* message);
void jniThrowSocketException(JNIEnv* env, int error);
-bool maybeThrowIcuException(JNIEnv* env, const char* function, UErrorCode error);
-
#endif // JNI_EXCEPTION_H_included
diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp
index 36abd7b..7ef36ad 100644
--- a/luni/src/main/native/Register.cpp
+++ b/luni/src/main/native/Register.cpp
@@ -63,6 +63,7 @@ int JNI_OnLoad(JavaVM* vm, void*) {
REGISTER(register_libcore_icu_NativeNormalizer);
REGISTER(register_libcore_icu_NativePluralRules);
REGISTER(register_libcore_icu_TimeZones);
+ REGISTER(register_libcore_icu_Transliterator);
REGISTER(register_libcore_io_AsynchronousCloseMonitor);
REGISTER(register_libcore_io_Memory);
REGISTER(register_libcore_io_OsConstants);
diff --git a/luni/src/main/native/zip.h b/luni/src/main/native/ZipUtilities.h
index 303c940..4c86f32 100644
--- a/luni/src/main/native/zip.h
+++ b/luni/src/main/native/ZipUtilities.h
@@ -15,8 +15,8 @@
* limitations under the License.
*/
-#if !defined(zip_h)
-#define zip_h
+#ifndef ZIP_UTILITIES_H_included
+#define ZIP_UTILITIES_H_included
#include "JNIHelp.h"
#include "JniException.h"
@@ -97,4 +97,4 @@ static NativeZipStream* toNativeZipStream(jlong address) {
return reinterpret_cast<NativeZipStream*>(static_cast<uintptr_t>(address));
}
-#endif /* zip_h */
+#endif // ZIP_UTILITIES_H_included
diff --git a/luni/src/main/native/java_text_Bidi.cpp b/luni/src/main/native/java_text_Bidi.cpp
index cb492b4..d9ef35d 100644
--- a/luni/src/main/native/java_text_Bidi.cpp
+++ b/luni/src/main/native/java_text_Bidi.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "Bidi"
+#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
diff --git a/luni/src/main/native/java_util_regex_Matcher.cpp b/luni/src/main/native/java_util_regex_Matcher.cpp
index a8ee1a0..9b58301 100644
--- a/luni/src/main/native/java_util_regex_Matcher.cpp
+++ b/luni/src/main/native/java_util_regex_Matcher.cpp
@@ -18,6 +18,7 @@
#include <stdlib.h>
+#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
diff --git a/luni/src/main/native/java_util_regex_Pattern.cpp b/luni/src/main/native/java_util_regex_Pattern.cpp
index cad154f..bd1f326 100644
--- a/luni/src/main/native/java_util_regex_Pattern.cpp
+++ b/luni/src/main/native/java_util_regex_Pattern.cpp
@@ -83,6 +83,9 @@ static jint Pattern_compileImpl(JNIEnv* env, jclass, jstring javaRegex, jint fla
error.offset = -1;
ScopedJavaUnicodeString regex(env, javaRegex);
+ if (!regex.valid()) {
+ return 0;
+ }
UnicodeString& regexString(regex.unicodeString());
RegexPattern* result = RegexPattern::compile(regexString, flags, error, status);
if (!U_SUCCESS(status)) {
diff --git a/luni/src/main/native/java_util_zip_Deflater.cpp b/luni/src/main/native/java_util_zip_Deflater.cpp
index e129134..ed7d754 100644
--- a/luni/src/main/native/java_util_zip_Deflater.cpp
+++ b/luni/src/main/native/java_util_zip_Deflater.cpp
@@ -19,7 +19,7 @@
#include "JniConstants.h"
#include "ScopedPrimitiveArray.h"
-#include "zip.h"
+#include "ZipUtilities.h"
static void Deflater_setDictionaryImpl(JNIEnv* env, jobject, jbyteArray dict, int off, int len, jlong handle) {
toNativeZipStream(handle)->setDictionary(env, dict, off, len, false);
diff --git a/luni/src/main/native/java_util_zip_Inflater.cpp b/luni/src/main/native/java_util_zip_Inflater.cpp
index 890c6dc..6aa3e24 100644
--- a/luni/src/main/native/java_util_zip_Inflater.cpp
+++ b/luni/src/main/native/java_util_zip_Inflater.cpp
@@ -19,7 +19,7 @@
#include "JniConstants.h"
#include "ScopedPrimitiveArray.h"
-#include "zip.h"
+#include "ZipUtilities.h"
#include <errno.h>
static jlong Inflater_createStream(JNIEnv* env, jobject, jboolean noHeader) {
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index eafb336..7385757 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "ICU"
+#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
@@ -92,10 +93,6 @@ class ScopedResourceBundle {
DISALLOW_COPY_AND_ASSIGN(ScopedResourceBundle);
};
-Locale getLocale(JNIEnv* env, jstring localeName) {
- return Locale::createFromName(ScopedUtfChars(env, localeName).c_str());
-}
-
static jstring ICU_addLikelySubtags(JNIEnv* env, jclass, jstring javaLocale) {
UErrorCode status = U_ZERO_ERROR;
ScopedUtfChars localeID(env, javaLocale);
@@ -119,10 +116,13 @@ static jstring ICU_getScript(JNIEnv* env, jclass, jstring javaLocale) {
}
static jint ICU_getCurrencyFractionDigits(JNIEnv* env, jclass, jstring javaCurrencyCode) {
- ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode);
- UnicodeString icuCurrencyCode(currencyCode.unicodeString());
- UErrorCode status = U_ZERO_ERROR;
- return ucurr_getDefaultFractionDigits(icuCurrencyCode.getTerminatedBuffer(), &status);
+ ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode);
+ if (!currencyCode.valid()) {
+ return 0;
+ }
+ UnicodeString icuCurrencyCode(currencyCode.unicodeString());
+ UErrorCode status = U_ZERO_ERROR;
+ return ucurr_getDefaultFractionDigits(icuCurrencyCode.getTerminatedBuffer(), &status);
}
// TODO: rewrite this with int32_t ucurr_forLocale(const char* locale, UChar* buff, int32_t buffCapacity, UErrorCode* ec)...
@@ -170,7 +170,13 @@ static jstring ICU_getCurrencyCode(JNIEnv* env, jclass, jstring javaCountryCode)
static jstring getCurrencyName(JNIEnv* env, jstring javaLocaleName, jstring javaCurrencyCode, UCurrNameStyle nameStyle) {
ScopedUtfChars localeName(env, javaLocaleName);
+ if (localeName.c_str() == NULL) {
+ return NULL;
+ }
ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode);
+ if (!currencyCode.valid()) {
+ return NULL;
+ }
UnicodeString icuCurrencyCode(currencyCode.unicodeString());
UErrorCode status = U_ZERO_ERROR;
UBool isChoiceFormat = false;
@@ -621,19 +627,25 @@ static jboolean ICU_initLocaleDataImpl(JNIEnv* env, jclass, jstring javaLocaleNa
}
static jstring ICU_toLowerCase(JNIEnv* env, jclass, jstring javaString, jstring localeName) {
- ScopedJavaUnicodeString scopedString(env, javaString);
- UnicodeString& s(scopedString.unicodeString());
- UnicodeString original(s);
- s.toLower(Locale::createFromName(ScopedUtfChars(env, localeName).c_str()));
- return s == original ? javaString : env->NewString(s.getBuffer(), s.length());
+ ScopedJavaUnicodeString scopedString(env, javaString);
+ if (!scopedString.valid()) {
+ return NULL;
+ }
+ UnicodeString& s(scopedString.unicodeString());
+ UnicodeString original(s);
+ s.toLower(Locale::createFromName(ScopedUtfChars(env, localeName).c_str()));
+ return s == original ? javaString : env->NewString(s.getBuffer(), s.length());
}
static jstring ICU_toUpperCase(JNIEnv* env, jclass, jstring javaString, jstring localeName) {
- ScopedJavaUnicodeString scopedString(env, javaString);
- UnicodeString& s(scopedString.unicodeString());
- UnicodeString original(s);
- s.toUpper(Locale::createFromName(ScopedUtfChars(env, localeName).c_str()));
- return s == original ? javaString : env->NewString(s.getBuffer(), s.length());
+ ScopedJavaUnicodeString scopedString(env, javaString);
+ if (!scopedString.valid()) {
+ return NULL;
+ }
+ UnicodeString& s(scopedString.unicodeString());
+ UnicodeString original(s);
+ s.toUpper(Locale::createFromName(ScopedUtfChars(env, localeName).c_str()));
+ return s == original ? javaString : env->NewString(s.getBuffer(), s.length());
}
static jstring versionString(JNIEnv* env, const UVersionInfo& version) {
@@ -689,6 +701,9 @@ static jstring ICU_getBestDateTimePattern(JNIEnv* env, jclass, jstring javaPatte
}
ScopedJavaUnicodeString patternHolder(env, javaPattern);
+ if (!patternHolder.valid()) {
+ return NULL;
+ }
UnicodeString result(generator->getBestPattern(patternHolder.unicodeString(), status));
if (maybeThrowIcuException(env, "DateTimePatternGenerator::getBestPattern", status)) {
return NULL;
diff --git a/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp b/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
index 92c41ab..c025a60 100644
--- a/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
+++ b/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "NativeBreakIterator"
+#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
diff --git a/luni/src/main/native/libcore_icu_NativeCollation.cpp b/luni/src/main/native/libcore_icu_NativeCollation.cpp
index 32b1cc4..98a78ea 100644
--- a/luni/src/main/native/libcore_icu_NativeCollation.cpp
+++ b/luni/src/main/native/libcore_icu_NativeCollation.cpp
@@ -9,6 +9,7 @@
#define LOG_TAG "NativeCollation"
+#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
diff --git a/luni/src/main/native/libcore_icu_NativeConverter.cpp b/luni/src/main/native/libcore_icu_NativeConverter.cpp
index d7eee14..24dfa6f 100644
--- a/luni/src/main/native/libcore_icu_NativeConverter.cpp
+++ b/luni/src/main/native/libcore_icu_NativeConverter.cpp
@@ -15,6 +15,7 @@
#define LOG_TAG "NativeConverter"
+#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
diff --git a/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp b/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp
index 0406094..cdc3bad 100644
--- a/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp
+++ b/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "NativeDecimalFormat"
+#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
@@ -106,13 +107,12 @@ static jint NativeDecimalFormat_open(JNIEnv* env, jclass, jstring pattern0,
jstring internationalCurrencySymbol, jchar minusSign,
jchar monetaryDecimalSeparator, jstring nan, jchar patternSeparator,
jchar percent, jchar perMill, jchar zeroDigit) {
- if (pattern0 == NULL) {
- jniThrowNullPointerException(env, NULL);
- return 0;
- }
UErrorCode status = U_ZERO_ERROR;
UParseError parseError;
ScopedJavaUnicodeString pattern(env, pattern0);
+ if (!pattern.valid()) {
+ return 0;
+ }
DecimalFormatSymbols* symbols = makeDecimalFormatSymbols(env,
currencySymbol, decimalSeparator, digit, exponentSeparator, groupingSeparator,
infinity, internationalCurrencySymbol, minusSign,
@@ -188,11 +188,10 @@ static jstring NativeDecimalFormat_getTextAttribute(JNIEnv* env, jclass, jint ad
}
static void NativeDecimalFormat_applyPatternImpl(JNIEnv* env, jclass, jint addr, jboolean localized, jstring pattern0) {
- if (pattern0 == NULL) {
- jniThrowNullPointerException(env, NULL);
- return;
- }
ScopedJavaUnicodeString pattern(env, pattern0);
+ if (!pattern.valid()) {
+ return;
+ }
DecimalFormat* fmt = toDecimalFormat(addr);
UErrorCode status = U_ZERO_ERROR;
const char* function;
@@ -299,6 +298,9 @@ static jobject NativeDecimalFormat_parse(JNIEnv* env, jclass, jint addr, jstring
Formattable res;
ParsePosition pp(parsePos);
ScopedJavaUnicodeString src(env, text);
+ if (!src.valid()) {
+ return NULL;
+ }
DecimalFormat* fmt = toDecimalFormat(addr);
fmt->parse(src.unicodeString(), res, pp);
diff --git a/luni/src/main/native/libcore_icu_NativeNormalizer.cpp b/luni/src/main/native/libcore_icu_NativeNormalizer.cpp
index 693e944..8ae42d9 100644
--- a/luni/src/main/native/libcore_icu_NativeNormalizer.cpp
+++ b/luni/src/main/native/libcore_icu_NativeNormalizer.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "NativeNormalizer"
+#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
@@ -23,28 +24,34 @@
#include "unicode/normlzr.h"
static jstring NativeNormalizer_normalizeImpl(JNIEnv* env, jclass, jstring s, jint intMode) {
- ScopedJavaUnicodeString src(env, s);
- UNormalizationMode mode = static_cast<UNormalizationMode>(intMode);
- UErrorCode status = U_ZERO_ERROR;
- UnicodeString dst;
- Normalizer::normalize(src.unicodeString(), mode, 0, dst, status);
- maybeThrowIcuException(env, "Normalizer::normalize", status);
- return dst.isBogus() ? NULL : env->NewString(dst.getBuffer(), dst.length());
+ ScopedJavaUnicodeString src(env, s);
+ if (!src.valid()) {
+ return NULL;
+ }
+ UNormalizationMode mode = static_cast<UNormalizationMode>(intMode);
+ UErrorCode status = U_ZERO_ERROR;
+ UnicodeString dst;
+ Normalizer::normalize(src.unicodeString(), mode, 0, dst, status);
+ maybeThrowIcuException(env, "Normalizer::normalize", status);
+ return dst.isBogus() ? NULL : env->NewString(dst.getBuffer(), dst.length());
}
static jboolean NativeNormalizer_isNormalizedImpl(JNIEnv* env, jclass, jstring s, jint intMode) {
- ScopedJavaUnicodeString src(env, s);
- UNormalizationMode mode = static_cast<UNormalizationMode>(intMode);
- UErrorCode status = U_ZERO_ERROR;
- UBool result = Normalizer::isNormalized(src.unicodeString(), mode, status);
- maybeThrowIcuException(env, "Normalizer::isNormalized", status);
- return result;
+ ScopedJavaUnicodeString src(env, s);
+ if (!src.valid()) {
+ return JNI_FALSE;
+ }
+ UNormalizationMode mode = static_cast<UNormalizationMode>(intMode);
+ UErrorCode status = U_ZERO_ERROR;
+ UBool result = Normalizer::isNormalized(src.unicodeString(), mode, status);
+ maybeThrowIcuException(env, "Normalizer::isNormalized", status);
+ return result;
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(NativeNormalizer, normalizeImpl, "(Ljava/lang/String;I)Ljava/lang/String;"),
- NATIVE_METHOD(NativeNormalizer, isNormalizedImpl, "(Ljava/lang/String;I)Z"),
+ NATIVE_METHOD(NativeNormalizer, normalizeImpl, "(Ljava/lang/String;I)Ljava/lang/String;"),
+ NATIVE_METHOD(NativeNormalizer, isNormalizedImpl, "(Ljava/lang/String;I)Z"),
};
void register_libcore_icu_NativeNormalizer(JNIEnv* env) {
- jniRegisterNativeMethods(env, "libcore/icu/NativeNormalizer", gMethods, NELEM(gMethods));
+ jniRegisterNativeMethods(env, "libcore/icu/NativeNormalizer", gMethods, NELEM(gMethods));
}
diff --git a/luni/src/main/native/libcore_icu_NativePluralRules.cpp b/luni/src/main/native/libcore_icu_NativePluralRules.cpp
index df228ff..3253eb8 100644
--- a/luni/src/main/native/libcore_icu_NativePluralRules.cpp
+++ b/luni/src/main/native/libcore_icu_NativePluralRules.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "NativePluralRules"
+#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
diff --git a/luni/src/main/native/libcore_icu_TimeZones.cpp b/luni/src/main/native/libcore_icu_TimeZones.cpp
index 11e53a5..80cb096 100644
--- a/luni/src/main/native/libcore_icu_TimeZones.cpp
+++ b/luni/src/main/native/libcore_icu_TimeZones.cpp
@@ -19,6 +19,7 @@
#include <map>
#include <vector>
+#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
@@ -29,34 +30,12 @@
#include "unicode/smpdtfmt.h"
#include "unicode/timezone.h"
-extern Locale getLocale(JNIEnv* env, jstring localeName);
-
static jobjectArray TimeZones_forCountryCode(JNIEnv* env, jclass, jstring countryCode) {
ScopedUtfChars countryChars(env, countryCode);
if (countryChars.c_str() == NULL) {
return NULL;
}
-
- UniquePtr<StringEnumeration> ids(TimeZone::createEnumeration(countryChars.c_str()));
- if (ids.get() == NULL) {
- return NULL;
- }
- UErrorCode status = U_ZERO_ERROR;
- int32_t idCount = ids->count(status);
- if (maybeThrowIcuException(env, "StringEnumeration::count", status)) {
- return NULL;
- }
-
- jobjectArray result = env->NewObjectArray(idCount, JniConstants::stringClass, NULL);
- for (int32_t i = 0; i < idCount; ++i) {
- const UnicodeString* id = ids->snext(status);
- if (maybeThrowIcuException(env, "StringEnumeration::snext", status)) {
- return NULL;
- }
- ScopedLocalRef<jstring> idString(env, env->NewString(id->getBuffer(), id->length()));
- env->SetObjectArrayElement(result, i, idString.get());
- }
- return result;
+ return fromStringEnumeration(env, TimeZone::createEnumeration(countryChars.c_str()));
}
struct TimeZoneNames {
@@ -146,6 +125,9 @@ static jobjectArray TimeZones_getZoneStringsImpl(JNIEnv* env, jclass, jstring lo
ScopedLocalRef<jstring> javaZoneId(env,
reinterpret_cast<jstring>(env->GetObjectArrayElement(timeZoneIds, i)));
ScopedJavaUnicodeString zoneId(env, javaZoneId.get());
+ if (!zoneId.valid()) {
+ return NULL;
+ }
UnicodeString id(zoneId.unicodeString());
TimeZoneNames row;
diff --git a/luni/src/main/native/libcore_icu_Transliterator.cpp b/luni/src/main/native/libcore_icu_Transliterator.cpp
new file mode 100644
index 0000000..7f38192
--- /dev/null
+++ b/luni/src/main/native/libcore_icu_Transliterator.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Transliterator"
+
+#include "IcuUtilities.h"
+#include "JNIHelp.h"
+#include "JniConstants.h"
+#include "JniException.h"
+#include "ScopedJavaUnicodeString.h"
+#include "ScopedStringChars.h"
+#include "unicode/translit.h"
+
+extern jobjectArray fromStringEnumeration(JNIEnv* env, StringEnumeration*);
+
+static jobjectArray Transliterator_getAvailableIDs(JNIEnv* env, jclass) {
+ UErrorCode status = U_ZERO_ERROR;
+ return fromStringEnumeration(env, Transliterator::getAvailableIDs(status));
+}
+
+static jstring Transliterator_transliterate(JNIEnv* env, jclass, jstring javaId, jstring javaString) {
+ ScopedJavaUnicodeString id(env, javaId);
+ if (!id.valid()) {
+ return NULL;
+ }
+ ScopedJavaUnicodeString string(env, javaString);
+ if (!string.valid()) {
+ return NULL;
+ }
+
+ UErrorCode status = U_ZERO_ERROR;
+ Transliterator* t = Transliterator::createInstance(id.unicodeString(), UTRANS_FORWARD, status);
+ if (maybeThrowIcuException(env, "Transliterator::createInstance", status)) {
+ return NULL;
+ }
+
+ UnicodeString& s(string.unicodeString());
+ t->transliterate(s);
+
+ return env->NewString(s.getBuffer(), s.length());
+}
+
+static JNINativeMethod gMethods[] = {
+ NATIVE_METHOD(Transliterator, getAvailableIDs, "()[Ljava/lang/String;"),
+ NATIVE_METHOD(Transliterator, transliterate, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
+};
+void register_libcore_icu_Transliterator(JNIEnv* env) {
+ jniRegisterNativeMethods(env, "libcore/icu/Transliterator", gMethods, NELEM(gMethods));
+}
diff --git a/luni/src/main/native/sub.mk b/luni/src/main/native/sub.mk
index d5705a6..e562972 100644
--- a/luni/src/main/native/sub.mk
+++ b/luni/src/main/native/sub.mk
@@ -5,6 +5,7 @@
LOCAL_SRC_FILES := \
AsynchronousSocketCloseMonitor.cpp \
+ IcuUtilities.cpp \
JniConstants.cpp \
JniException.cpp \
NetworkUtilities.cpp \
@@ -39,6 +40,7 @@ LOCAL_SRC_FILES := \
libcore_icu_NativeNormalizer.cpp \
libcore_icu_NativePluralRules.cpp \
libcore_icu_TimeZones.cpp \
+ libcore_icu_Transliterator.cpp \
libcore_io_AsynchronousCloseMonitor.cpp \
libcore_io_Memory.cpp \
libcore_io_OsConstants.cpp \
diff --git a/luni/src/test/java/libcore/icu/TransliteratorTest.java b/luni/src/test/java/libcore/icu/TransliteratorTest.java
new file mode 100644
index 0000000..7187cbc
--- /dev/null
+++ b/luni/src/test/java/libcore/icu/TransliteratorTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.icu;
+
+public class TransliteratorTest extends junit.framework.TestCase {
+ public void testAll() throws Exception {
+ for (String id : Transliterator.getAvailableIDs()) {
+ System.err.println(id);
+ Transliterator.transliterate(id, "hello");
+ }
+ }
+
+ public void test_Unknown() throws Exception {
+ try {
+ Transliterator.transliterate("Unknown", "hello");
+ fail();
+ } catch (RuntimeException expected) {
+ }
+ }
+
+ public void test_null_id() throws Exception {
+ try {
+ Transliterator.transliterate(null, "hello");
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void test_null_string() throws Exception {
+ try {
+ Transliterator.transliterate("Any-Upper", null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void test_Any_Upper() throws Exception {
+ assertEquals("HELLO WORLD!", Transliterator.transliterate("Any-Upper", "HeLlO WoRlD!"));
+ assertEquals("STRASSE", Transliterator.transliterate("Any-Upper", "Straße"));
+ }
+
+ public void test_Any_Lower() throws Exception {
+ assertEquals("hello world!", Transliterator.transliterate("Any-Lower", "HeLlO WoRlD!"));
+ }
+
+ public void test_Greek_Latin() throws Exception {
+ String greek = "Καλημέρα κόσμε!";
+
+ // Transliterate Greek to Latin, then to plain ASCII.
+ String latin = Transliterator.transliterate("Greek-Latin", greek);
+ String ascii = Transliterator.transliterate("Latin-Ascii", latin);
+ assertEquals("Kalēméra kósme!", latin);
+ assertEquals("Kalemera kosme!", ascii);
+
+ // Use alternative transliteration variants.
+ assertEquals("Kaliméra kósme!", Transliterator.transliterate("Greek-Latin/BGN", greek));
+ assertEquals("Kali̱méra kósme!", Transliterator.transliterate("Greek-Latin/UNGEGN", greek));
+ }
+
+ public void test_Han_Latin() throws Exception {
+ assertEquals("hàn zì/hàn zì", Transliterator.transliterate("Han-Latin", "汉字/漢字"));
+ }
+}