The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 1 | /** |
| 2 | ******************************************************************************* |
| 3 | * Copyright (C) 1996-2005, International Business Machines Corporation and * |
| 4 | * others. All Rights Reserved. * |
| 5 | ******************************************************************************* |
| 6 | * |
| 7 | ******************************************************************************* |
| 8 | */ |
| 9 | |
Elliott Hughes | 757a794 | 2010-04-16 14:14:28 -0700 | [diff] [blame] | 10 | #define LOG_TAG "NativeCollation" |
| 11 | |
Elliott Hughes | 3aac4dd | 2013-02-04 15:37:52 -0800 | [diff] [blame] | 12 | #include "IcuUtilities.h" |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 13 | #include "JNIHelp.h" |
Elliott Hughes | e22935d | 2010-08-12 17:27:27 -0700 | [diff] [blame] | 14 | #include "JniConstants.h" |
Elliott Hughes | bef9ec3 | 2011-04-19 10:26:58 -0700 | [diff] [blame] | 15 | #include "JniException.h" |
Elliott Hughes | fe711d6 | 2011-04-22 15:56:03 -0700 | [diff] [blame] | 16 | #include "ScopedStringChars.h" |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 17 | #include "ScopedUtfChars.h" |
| 18 | #include "UniquePtr.h" |
| 19 | #include "ucol_imp.h" |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 20 | #include "unicode/ucol.h" |
| 21 | #include "unicode/ucoleitr.h" |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 22 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 23 | static UCollator* toCollator(jlong address) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 24 | return reinterpret_cast<UCollator*>(static_cast<uintptr_t>(address)); |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 25 | } |
| 26 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 27 | static UCollationElements* toCollationElements(jlong address) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 28 | return reinterpret_cast<UCollationElements*>(static_cast<uintptr_t>(address)); |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 29 | } |
| 30 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 31 | static void NativeCollation_closeCollator(JNIEnv*, jclass, jlong address) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 32 | ucol_close(toCollator(address)); |
| 33 | } |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 34 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 35 | static void NativeCollation_closeElements(JNIEnv*, jclass, jlong address) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 36 | ucol_closeElements(toCollationElements(address)); |
| 37 | } |
| 38 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 39 | static jint NativeCollation_compare(JNIEnv* env, jclass, jlong address, jstring javaLhs, jstring javaRhs) { |
Elliott Hughes | fe711d6 | 2011-04-22 15:56:03 -0700 | [diff] [blame] | 40 | ScopedStringChars lhs(env, javaLhs); |
| 41 | if (lhs.get() == NULL) { |
Doug Kwan | f08498e | 2011-06-25 00:31:42 -0700 | [diff] [blame] | 42 | return 0; |
Elliott Hughes | fe711d6 | 2011-04-22 15:56:03 -0700 | [diff] [blame] | 43 | } |
| 44 | ScopedStringChars rhs(env, javaRhs); |
| 45 | if (rhs.get() == NULL) { |
Doug Kwan | f08498e | 2011-06-25 00:31:42 -0700 | [diff] [blame] | 46 | return 0; |
Elliott Hughes | fe711d6 | 2011-04-22 15:56:03 -0700 | [diff] [blame] | 47 | } |
| 48 | return ucol_strcoll(toCollator(address), lhs.get(), lhs.size(), rhs.get(), rhs.size()); |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 49 | } |
| 50 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 51 | static jint NativeCollation_getAttribute(JNIEnv* env, jclass, jlong address, jint type) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 52 | UErrorCode status = U_ZERO_ERROR; |
| 53 | jint result = ucol_getAttribute(toCollator(address), (UColAttribute) type, &status); |
Elliott Hughes | 5ec69b2 | 2012-07-23 16:32:51 -0700 | [diff] [blame] | 54 | maybeThrowIcuException(env, "ucol_getAttribute", status); |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 55 | return result; |
| 56 | } |
| 57 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 58 | static jlong NativeCollation_getCollationElementIterator(JNIEnv* env, jclass, jlong address, jstring javaSource) { |
Elliott Hughes | fe711d6 | 2011-04-22 15:56:03 -0700 | [diff] [blame] | 59 | ScopedStringChars source(env, javaSource); |
| 60 | if (source.get() == NULL) { |
| 61 | return -1; |
| 62 | } |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 63 | UErrorCode status = U_ZERO_ERROR; |
Elliott Hughes | fe711d6 | 2011-04-22 15:56:03 -0700 | [diff] [blame] | 64 | UCollationElements* result = ucol_openElements(toCollator(address), source.get(), source.size(), &status); |
Elliott Hughes | 5ec69b2 | 2012-07-23 16:32:51 -0700 | [diff] [blame] | 65 | maybeThrowIcuException(env, "ucol_openElements", status); |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 66 | return static_cast<jlong>(reinterpret_cast<uintptr_t>(result)); |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 67 | } |
| 68 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 69 | static jint NativeCollation_getMaxExpansion(JNIEnv*, jclass, jlong address, jint order) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 70 | return ucol_getMaxExpansion(toCollationElements(address), order); |
| 71 | } |
| 72 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 73 | static jint NativeCollation_getOffset(JNIEnv*, jclass, jlong address) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 74 | return ucol_getOffset(toCollationElements(address)); |
| 75 | } |
| 76 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 77 | static jstring NativeCollation_getRules(JNIEnv* env, jclass, jlong address) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 78 | int32_t length = 0; |
| 79 | const UChar* rules = ucol_getRules(toCollator(address), &length); |
| 80 | return env->NewString(rules, length); |
| 81 | } |
| 82 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 83 | static jbyteArray NativeCollation_getSortKey(JNIEnv* env, jclass, jlong address, jstring javaSource) { |
Elliott Hughes | fe711d6 | 2011-04-22 15:56:03 -0700 | [diff] [blame] | 84 | ScopedStringChars source(env, javaSource); |
| 85 | if (source.get() == NULL) { |
| 86 | return NULL; |
| 87 | } |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 88 | const UCollator* collator = toCollator(address); |
| 89 | uint8_t byteArray[UCOL_MAX_BUFFER * 2]; |
| 90 | UniquePtr<uint8_t[]> largerByteArray; |
Elliott Hughes | acce5ff | 2010-08-13 16:14:21 -0700 | [diff] [blame] | 91 | uint8_t* usedByteArray = byteArray; |
Elliott Hughes | fe711d6 | 2011-04-22 15:56:03 -0700 | [diff] [blame] | 92 | size_t byteArraySize = ucol_getSortKey(collator, source.get(), source.size(), usedByteArray, sizeof(byteArray) - 1); |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 93 | if (byteArraySize > sizeof(byteArray) - 1) { |
| 94 | // didn't fit, try again with a larger buffer. |
| 95 | largerByteArray.reset(new uint8_t[byteArraySize + 1]); |
| 96 | usedByteArray = largerByteArray.get(); |
Elliott Hughes | fe711d6 | 2011-04-22 15:56:03 -0700 | [diff] [blame] | 97 | byteArraySize = ucol_getSortKey(collator, source.get(), source.size(), usedByteArray, byteArraySize); |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 98 | } |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 99 | if (byteArraySize == 0) { |
| 100 | return NULL; |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 101 | } |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 102 | jbyteArray result = env->NewByteArray(byteArraySize); |
| 103 | env->SetByteArrayRegion(result, 0, byteArraySize, reinterpret_cast<jbyte*>(usedByteArray)); |
| 104 | return result; |
| 105 | } |
| 106 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 107 | static jint NativeCollation_next(JNIEnv* env, jclass, jlong address) { |
Elliott Hughes | ebe438a | 2010-03-26 14:46:11 -0700 | [diff] [blame] | 108 | UErrorCode status = U_ZERO_ERROR; |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 109 | jint result = ucol_next(toCollationElements(address), &status); |
Elliott Hughes | 5ec69b2 | 2012-07-23 16:32:51 -0700 | [diff] [blame] | 110 | maybeThrowIcuException(env, "ucol_next", status); |
Elliott Hughes | ebe438a | 2010-03-26 14:46:11 -0700 | [diff] [blame] | 111 | return result; |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 112 | } |
| 113 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 114 | static jlong NativeCollation_openCollator(JNIEnv* env, jclass, jstring localeName) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 115 | ScopedUtfChars localeChars(env, localeName); |
Elliott Hughes | 0596087 | 2010-05-26 17:45:07 -0700 | [diff] [blame] | 116 | if (localeChars.c_str() == NULL) { |
| 117 | return 0; |
| 118 | } |
Elliott Hughes | 9a00adf | 2009-10-05 16:01:35 -0700 | [diff] [blame] | 119 | UErrorCode status = U_ZERO_ERROR; |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 120 | UCollator* c = ucol_open(localeChars.c_str(), &status); |
Elliott Hughes | 5ec69b2 | 2012-07-23 16:32:51 -0700 | [diff] [blame] | 121 | maybeThrowIcuException(env, "ucol_open", status); |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 122 | return static_cast<jlong>(reinterpret_cast<uintptr_t>(c)); |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 123 | } |
| 124 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 125 | static jlong NativeCollation_openCollatorFromRules(JNIEnv* env, jclass, jstring javaRules, jint mode, jint strength) { |
Elliott Hughes | fe711d6 | 2011-04-22 15:56:03 -0700 | [diff] [blame] | 126 | ScopedStringChars rules(env, javaRules); |
| 127 | if (rules.get() == NULL) { |
| 128 | return -1; |
| 129 | } |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 130 | UErrorCode status = U_ZERO_ERROR; |
Elliott Hughes | fe711d6 | 2011-04-22 15:56:03 -0700 | [diff] [blame] | 131 | UCollator* c = ucol_openRules(rules.get(), rules.size(), |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 132 | UColAttributeValue(mode), UCollationStrength(strength), NULL, &status); |
Elliott Hughes | 5ec69b2 | 2012-07-23 16:32:51 -0700 | [diff] [blame] | 133 | maybeThrowIcuException(env, "ucol_openRules", status); |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 134 | return static_cast<jlong>(reinterpret_cast<uintptr_t>(c)); |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 135 | } |
| 136 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 137 | static jint NativeCollation_previous(JNIEnv* env, jclass, jlong address) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 138 | UErrorCode status = U_ZERO_ERROR; |
| 139 | jint result = ucol_previous(toCollationElements(address), &status); |
Elliott Hughes | 5ec69b2 | 2012-07-23 16:32:51 -0700 | [diff] [blame] | 140 | maybeThrowIcuException(env, "ucol_previous", status); |
Elliott Hughes | 9a00adf | 2009-10-05 16:01:35 -0700 | [diff] [blame] | 141 | return result; |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 142 | } |
| 143 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 144 | static void NativeCollation_reset(JNIEnv*, jclass, jlong address) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 145 | ucol_reset(toCollationElements(address)); |
| 146 | } |
| 147 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 148 | static jlong NativeCollation_safeClone(JNIEnv* env, jclass, jlong address) { |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 149 | UErrorCode status = U_ZERO_ERROR; |
Elliott Hughes | bf6f2af | 2013-10-07 11:44:07 -0700 | [diff] [blame] | 150 | UCollator* c = ucol_safeClone(toCollator(address), NULL, NULL, &status); |
Elliott Hughes | 5ec69b2 | 2012-07-23 16:32:51 -0700 | [diff] [blame] | 151 | maybeThrowIcuException(env, "ucol_safeClone", status); |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 152 | return static_cast<jlong>(reinterpret_cast<uintptr_t>(c)); |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 153 | } |
| 154 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 155 | static void NativeCollation_setAttribute(JNIEnv* env, jclass, jlong address, jint type, jint value) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 156 | UErrorCode status = U_ZERO_ERROR; |
| 157 | ucol_setAttribute(toCollator(address), (UColAttribute)type, (UColAttributeValue)value, &status); |
Elliott Hughes | 5ec69b2 | 2012-07-23 16:32:51 -0700 | [diff] [blame] | 158 | maybeThrowIcuException(env, "ucol_setAttribute", status); |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 159 | } |
| 160 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 161 | static void NativeCollation_setOffset(JNIEnv* env, jclass, jlong address, jint offset) { |
Elliott Hughes | 9a00adf | 2009-10-05 16:01:35 -0700 | [diff] [blame] | 162 | UErrorCode status = U_ZERO_ERROR; |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 163 | ucol_setOffset(toCollationElements(address), offset, &status); |
Elliott Hughes | 5ec69b2 | 2012-07-23 16:32:51 -0700 | [diff] [blame] | 164 | maybeThrowIcuException(env, "ucol_setOffset", status); |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 165 | } |
| 166 | |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 167 | static void NativeCollation_setText(JNIEnv* env, jclass, jlong address, jstring javaSource) { |
Elliott Hughes | fe711d6 | 2011-04-22 15:56:03 -0700 | [diff] [blame] | 168 | ScopedStringChars source(env, javaSource); |
| 169 | if (source.get() == NULL) { |
| 170 | return; |
| 171 | } |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 172 | UErrorCode status = U_ZERO_ERROR; |
Elliott Hughes | fe711d6 | 2011-04-22 15:56:03 -0700 | [diff] [blame] | 173 | ucol_setText(toCollationElements(address), source.get(), source.size(), &status); |
Elliott Hughes | 5ec69b2 | 2012-07-23 16:32:51 -0700 | [diff] [blame] | 174 | maybeThrowIcuException(env, "ucol_setText", status); |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 175 | } |
| 176 | |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 177 | static JNINativeMethod gMethods[] = { |
Elliott Hughes | 1e5d730 | 2013-04-22 17:01:52 -0700 | [diff] [blame] | 178 | NATIVE_METHOD(NativeCollation, closeCollator, "(J)V"), |
| 179 | NATIVE_METHOD(NativeCollation, closeElements, "(J)V"), |
| 180 | NATIVE_METHOD(NativeCollation, compare, "(JLjava/lang/String;Ljava/lang/String;)I"), |
| 181 | NATIVE_METHOD(NativeCollation, getAttribute, "(JI)I"), |
| 182 | NATIVE_METHOD(NativeCollation, getCollationElementIterator, "(JLjava/lang/String;)I"), |
| 183 | NATIVE_METHOD(NativeCollation, getMaxExpansion, "(JI)I"), |
| 184 | NATIVE_METHOD(NativeCollation, getOffset, "(J)I"), |
| 185 | NATIVE_METHOD(NativeCollation, getRules, "(J)Ljava/lang/String;"), |
| 186 | NATIVE_METHOD(NativeCollation, getSortKey, "(JLjava/lang/String;)[B"), |
| 187 | NATIVE_METHOD(NativeCollation, next, "(J)I"), |
| 188 | NATIVE_METHOD(NativeCollation, openCollator, "(Ljava/lang/String;)J"), |
| 189 | NATIVE_METHOD(NativeCollation, openCollatorFromRules, "(Ljava/lang/String;II)J"), |
| 190 | NATIVE_METHOD(NativeCollation, previous, "(J)I"), |
| 191 | NATIVE_METHOD(NativeCollation, reset, "(J)V"), |
| 192 | NATIVE_METHOD(NativeCollation, safeClone, "(J)J"), |
| 193 | NATIVE_METHOD(NativeCollation, setAttribute, "(JII)V"), |
| 194 | NATIVE_METHOD(NativeCollation, setOffset, "(JI)V"), |
| 195 | NATIVE_METHOD(NativeCollation, setText, "(JLjava/lang/String;)V"), |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 196 | }; |
Elliott Hughes | 7cd6760 | 2012-05-03 17:21:04 -0700 | [diff] [blame] | 197 | void register_libcore_icu_NativeCollation(JNIEnv* env) { |
| 198 | jniRegisterNativeMethods(env, "libcore/icu/NativeCollation", gMethods, NELEM(gMethods)); |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 199 | } |