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