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
toCollator(jint address)22 static UCollator* toCollator(jint address) {
23 return reinterpret_cast<UCollator*>(static_cast<uintptr_t>(address));
24 }
25
toCollationElements(jint address)26 static UCollationElements* toCollationElements(jint address) {
27 return reinterpret_cast<UCollationElements*>(static_cast<uintptr_t>(address));
28 }
29
NativeCollation_closeCollator(JNIEnv *,jclass,jint address)30 static void NativeCollation_closeCollator(JNIEnv*, jclass, jint address) {
31 ucol_close(toCollator(address));
32 }
33
NativeCollation_closeElements(JNIEnv *,jclass,jint address)34 static void NativeCollation_closeElements(JNIEnv*, jclass, jint address) {
35 ucol_closeElements(toCollationElements(address));
36 }
37
NativeCollation_compare(JNIEnv * env,jclass,jint address,jstring javaLhs,jstring javaRhs)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
NativeCollation_getAttribute(JNIEnv * env,jclass,jint address,jint type)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
NativeCollation_getCollationElementIterator(JNIEnv * env,jclass,jint address,jstring javaSource)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
NativeCollation_getMaxExpansion(JNIEnv *,jclass,jint address,jint order)68 static jint NativeCollation_getMaxExpansion(JNIEnv*, jclass, jint address, jint order) {
69 return ucol_getMaxExpansion(toCollationElements(address), order);
70 }
71
NativeCollation_getOffset(JNIEnv *,jclass,jint address)72 static jint NativeCollation_getOffset(JNIEnv*, jclass, jint address) {
73 return ucol_getOffset(toCollationElements(address));
74 }
75
NativeCollation_getRules(JNIEnv * env,jclass,jint address)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
NativeCollation_getSortKey(JNIEnv * env,jclass,jint address,jstring javaSource)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
NativeCollation_next(JNIEnv * env,jclass,jint address)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
NativeCollation_openCollator(JNIEnv * env,jclass,jstring localeName)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
NativeCollation_openCollatorFromRules(JNIEnv * env,jclass,jstring javaRules,jint mode,jint strength)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
NativeCollation_previous(JNIEnv * env,jclass,jint address)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
NativeCollation_reset(JNIEnv *,jclass,jint address)143 static void NativeCollation_reset(JNIEnv*, jclass, jint address) {
144 ucol_reset(toCollationElements(address));
145 }
146
NativeCollation_safeClone(JNIEnv * env,jclass,jint address)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
NativeCollation_setAttribute(JNIEnv * env,jclass,jint address,jint type,jint value)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
NativeCollation_setOffset(JNIEnv * env,jclass,jint address,jint offset)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
NativeCollation_setText(JNIEnv * env,jclass,jint address,jstring javaSource)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 };
register_libcore_icu_NativeCollation(JNIEnv * env)197 void register_libcore_icu_NativeCollation(JNIEnv* env) {
198 jniRegisterNativeMethods(env, "libcore/icu/NativeCollation", gMethods, NELEM(gMethods));
199 }
200