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 | |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 12 | #include "ErrorCode.h" |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 13 | #include "JNIHelp.h" |
| 14 | #include "ScopedJavaUnicodeString.h" |
| 15 | #include "ScopedUtfChars.h" |
| 16 | #include "UniquePtr.h" |
| 17 | #include "ucol_imp.h" |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 18 | #include "unicode/ucol.h" |
| 19 | #include "unicode/ucoleitr.h" |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 20 | |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 21 | static UCollator* toCollator(jint address) { |
| 22 | return reinterpret_cast<UCollator*>(static_cast<uintptr_t>(address)); |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 23 | } |
| 24 | |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 25 | static UCollationElements* toCollationElements(jint address) { |
| 26 | return reinterpret_cast<UCollationElements*>(static_cast<uintptr_t>(address)); |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 27 | } |
| 28 | |
Brian Carlstrom | 44e0e56 | 2010-05-06 23:44:16 -0700 | [diff] [blame] | 29 | static void closeCollator(JNIEnv*, jclass, jint address) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 30 | ucol_close(toCollator(address)); |
| 31 | } |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 32 | |
Brian Carlstrom | 44e0e56 | 2010-05-06 23:44:16 -0700 | [diff] [blame] | 33 | static void closeElements(JNIEnv*, jclass, jint address) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 34 | ucol_closeElements(toCollationElements(address)); |
| 35 | } |
| 36 | |
| 37 | static jint compare(JNIEnv* env, jclass, jint address, jstring lhs0, jstring rhs0) { |
| 38 | ScopedJavaUnicodeString lhs(env, lhs0); |
| 39 | ScopedJavaUnicodeString rhs(env, rhs0); |
| 40 | return ucol_strcoll(toCollator(address), |
| 41 | lhs.unicodeString().getBuffer(), lhs.unicodeString().length(), |
| 42 | rhs.unicodeString().getBuffer(), rhs.unicodeString().length()); |
| 43 | } |
| 44 | |
| 45 | static jint getAttribute(JNIEnv* env, jclass, jint address, jint type) { |
| 46 | UErrorCode status = U_ZERO_ERROR; |
| 47 | jint result = ucol_getAttribute(toCollator(address), (UColAttribute) type, &status); |
| 48 | icu4jni_error(env, status); |
| 49 | return result; |
| 50 | } |
| 51 | |
| 52 | static jint getCollationElementIterator(JNIEnv* env, jclass, jint address, jstring source0) { |
| 53 | ScopedJavaUnicodeString source(env, source0); |
| 54 | UErrorCode status = U_ZERO_ERROR; |
| 55 | UCollationElements* result = ucol_openElements(toCollator(address), |
| 56 | source.unicodeString().getBuffer(), source.unicodeString().length(), &status); |
| 57 | icu4jni_error(env, status); |
| 58 | return static_cast<jint>(reinterpret_cast<uintptr_t>(result)); |
| 59 | } |
| 60 | |
Brian Carlstrom | 44e0e56 | 2010-05-06 23:44:16 -0700 | [diff] [blame] | 61 | static jint getMaxExpansion(JNIEnv*, jclass, jint address, jint order) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 62 | return ucol_getMaxExpansion(toCollationElements(address), order); |
| 63 | } |
| 64 | |
| 65 | static jint getNormalization(JNIEnv* env, jclass, jint address) { |
| 66 | UErrorCode status = U_ZERO_ERROR; |
| 67 | jint result = ucol_getAttribute(toCollator(address), UCOL_NORMALIZATION_MODE, &status); |
| 68 | icu4jni_error(env, status); |
| 69 | return result; |
| 70 | } |
| 71 | |
| 72 | static void setNormalization(JNIEnv* env, jclass, jint address, jint mode) { |
| 73 | UErrorCode status = U_ZERO_ERROR; |
| 74 | ucol_setAttribute(toCollator(address), UCOL_NORMALIZATION_MODE, UColAttributeValue(mode), &status); |
| 75 | icu4jni_error(env, status); |
| 76 | } |
| 77 | |
Brian Carlstrom | 44e0e56 | 2010-05-06 23:44:16 -0700 | [diff] [blame] | 78 | static jint getOffset(JNIEnv*, jclass, jint address) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 79 | return ucol_getOffset(toCollationElements(address)); |
| 80 | } |
| 81 | |
| 82 | static jstring getRules(JNIEnv* env, jclass, jint address) { |
| 83 | int32_t length = 0; |
| 84 | const UChar* rules = ucol_getRules(toCollator(address), &length); |
| 85 | return env->NewString(rules, length); |
| 86 | } |
| 87 | |
| 88 | static jbyteArray getSortKey(JNIEnv* env, jclass, jint address, jstring source0) { |
| 89 | ScopedJavaUnicodeString source(env, source0); |
| 90 | const UCollator* collator = toCollator(address); |
| 91 | uint8_t byteArray[UCOL_MAX_BUFFER * 2]; |
| 92 | UniquePtr<uint8_t[]> largerByteArray; |
| 93 | uint8_t *usedByteArray = byteArray; |
| 94 | const UChar* chars = source.unicodeString().getBuffer(); |
| 95 | size_t charCount = source.unicodeString().length(); |
| 96 | size_t byteArraySize = ucol_getSortKey(collator, chars, charCount, usedByteArray, sizeof(byteArray) - 1); |
| 97 | if (byteArraySize > sizeof(byteArray) - 1) { |
| 98 | // didn't fit, try again with a larger buffer. |
| 99 | largerByteArray.reset(new uint8_t[byteArraySize + 1]); |
| 100 | usedByteArray = largerByteArray.get(); |
| 101 | byteArraySize = ucol_getSortKey(collator, chars, charCount, usedByteArray, byteArraySize); |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 102 | } |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 103 | if (byteArraySize == 0) { |
| 104 | return NULL; |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 105 | } |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 106 | jbyteArray result = env->NewByteArray(byteArraySize); |
| 107 | env->SetByteArrayRegion(result, 0, byteArraySize, reinterpret_cast<jbyte*>(usedByteArray)); |
| 108 | return result; |
| 109 | } |
| 110 | |
| 111 | static jint next(JNIEnv* env, jclass, jint address) { |
Elliott Hughes | ebe438a | 2010-03-26 14:46:11 -0700 | [diff] [blame] | 112 | UErrorCode status = U_ZERO_ERROR; |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 113 | jint result = ucol_next(toCollationElements(address), &status); |
Elliott Hughes | ebe438a | 2010-03-26 14:46:11 -0700 | [diff] [blame] | 114 | icu4jni_error(env, status); |
| 115 | return result; |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 116 | } |
| 117 | |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 118 | static jint openCollator(JNIEnv* env, jclass, jstring localeName) { |
| 119 | ScopedUtfChars localeChars(env, localeName); |
Elliott Hughes | 0596087 | 2010-05-26 17:45:07 -0700 | [diff] [blame^] | 120 | if (localeChars.c_str() == NULL) { |
| 121 | return 0; |
| 122 | } |
Elliott Hughes | 9a00adf | 2009-10-05 16:01:35 -0700 | [diff] [blame] | 123 | UErrorCode status = U_ZERO_ERROR; |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 124 | UCollator* c = ucol_open(localeChars.c_str(), &status); |
| 125 | icu4jni_error(env, status); |
| 126 | return static_cast<jint>(reinterpret_cast<uintptr_t>(c)); |
| 127 | } |
| 128 | |
| 129 | static jint openCollatorFromRules(JNIEnv* env, jclass, jstring rules0, jint mode, jint strength) { |
| 130 | ScopedJavaUnicodeString rules(env, rules0); |
| 131 | UErrorCode status = U_ZERO_ERROR; |
| 132 | UCollator* c = ucol_openRules(rules.unicodeString().getBuffer(), rules.unicodeString().length(), |
| 133 | UColAttributeValue(mode), UCollationStrength(strength), NULL, &status); |
| 134 | icu4jni_error(env, status); |
| 135 | return static_cast<jint>(reinterpret_cast<uintptr_t>(c)); |
| 136 | } |
| 137 | |
| 138 | static jint previous(JNIEnv* env, jclass, jint address) { |
| 139 | UErrorCode status = U_ZERO_ERROR; |
| 140 | jint result = ucol_previous(toCollationElements(address), &status); |
Elliott Hughes | 9a00adf | 2009-10-05 16:01:35 -0700 | [diff] [blame] | 141 | icu4jni_error(env, status); |
| 142 | return result; |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 143 | } |
| 144 | |
Brian Carlstrom | 44e0e56 | 2010-05-06 23:44:16 -0700 | [diff] [blame] | 145 | static void reset(JNIEnv*, jclass, jint address) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 146 | ucol_reset(toCollationElements(address)); |
| 147 | } |
| 148 | |
| 149 | static jint safeClone(JNIEnv* env, jclass, jint address) { |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 150 | UErrorCode status = U_ZERO_ERROR; |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 151 | jint bufferSize = U_COL_SAFECLONE_BUFFERSIZE; |
| 152 | UCollator* c = ucol_safeClone(toCollator(address), NULL, &bufferSize, &status); |
| 153 | icu4jni_error(env, status); |
| 154 | return static_cast<jint>(reinterpret_cast<uintptr_t>(c)); |
| 155 | } |
| 156 | |
| 157 | static void setAttribute(JNIEnv* env, jclass, jint address, jint type, jint value) { |
| 158 | UErrorCode status = U_ZERO_ERROR; |
| 159 | ucol_setAttribute(toCollator(address), (UColAttribute)type, (UColAttributeValue)value, &status); |
Elliott Hughes | 9a00adf | 2009-10-05 16:01:35 -0700 | [diff] [blame] | 160 | icu4jni_error(env, status); |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 161 | } |
| 162 | |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 163 | static void setOffset(JNIEnv* env, jclass, jint address, jint offset) { |
Elliott Hughes | 9a00adf | 2009-10-05 16:01:35 -0700 | [diff] [blame] | 164 | UErrorCode status = U_ZERO_ERROR; |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 165 | ucol_setOffset(toCollationElements(address), offset, &status); |
Elliott Hughes | ebe438a | 2010-03-26 14:46:11 -0700 | [diff] [blame] | 166 | icu4jni_error(env, status); |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 167 | } |
| 168 | |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 169 | static void setText(JNIEnv* env, jclass, jint address, jstring source0) { |
| 170 | ScopedJavaUnicodeString source(env, source0); |
| 171 | UErrorCode status = U_ZERO_ERROR; |
| 172 | ucol_setText(toCollationElements(address), |
| 173 | source.unicodeString().getBuffer(), source.unicodeString().length(), &status); |
| 174 | icu4jni_error(env, 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 | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 178 | { "openCollator", "(Ljava/lang/String;)I", (void*) openCollator }, |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 179 | { "openCollatorFromRules", "(Ljava/lang/String;II)I", (void*) openCollatorFromRules }, |
| 180 | { "closeCollator", "(I)V", (void*) closeCollator }, |
| 181 | { "compare", "(ILjava/lang/String;Ljava/lang/String;)I", (void*) compare }, |
| 182 | { "getNormalization", "(I)I", (void*) getNormalization }, |
| 183 | { "setNormalization", "(II)V", (void*) setNormalization }, |
| 184 | { "getRules", "(I)Ljava/lang/String;", (void*) getRules }, |
| 185 | { "getSortKey", "(ILjava/lang/String;)[B", (void*) getSortKey }, |
| 186 | { "setAttribute", "(III)V", (void*) setAttribute }, |
| 187 | { "getAttribute", "(II)I", (void*) getAttribute }, |
| 188 | { "safeClone", "(I)I", (void*) safeClone }, |
| 189 | { "getCollationElementIterator", "(ILjava/lang/String;)I", (void*) getCollationElementIterator }, |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 190 | { "closeElements", "(I)V", (void*) closeElements }, |
| 191 | { "reset", "(I)V", (void*) reset }, |
| 192 | { "next", "(I)I", (void*) next }, |
| 193 | { "previous", "(I)I", (void*) previous }, |
| 194 | { "getMaxExpansion", "(II)I", (void*) getMaxExpansion }, |
| 195 | { "setText", "(ILjava/lang/String;)V", (void*) setText }, |
| 196 | { "getOffset", "(I)I", (void*) getOffset }, |
| 197 | { "setOffset", "(II)V", (void*) setOffset } |
| 198 | }; |
Elliott Hughes | 0596087 | 2010-05-26 17:45:07 -0700 | [diff] [blame^] | 199 | int register_com_ibm_icu4jni_text_NativeCollator(JNIEnv* env) { |
Elliott Hughes | 0808cae | 2010-04-23 16:15:38 -0700 | [diff] [blame] | 200 | return jniRegisterNativeMethods(env, "com/ibm/icu4jni/text/NativeCollation", |
The Android Open Source Project | adc854b | 2009-03-03 19:28:47 -0800 | [diff] [blame] | 201 | gMethods, NELEM(gMethods)); |
| 202 | } |