| /** |
| ******************************************************************************* |
| * Copyright (C) 1996-2005, International Business Machines Corporation and * |
| * others. All Rights Reserved. * |
| ******************************************************************************* |
| * |
| ******************************************************************************* |
| */ |
| |
| #include "JNIHelp.h" |
| #include "AndroidSystemNatives.h" |
| #include "ErrorCode.h" |
| #include "unicode/ucol.h" |
| #include "unicode/ucoleitr.h" |
| #include "ucol_imp.h" |
| |
| |
| /** |
| * Closing a C UCollator with the argument locale rules. |
| * Note determining if a collator currently exist for the caller is to be handled |
| * by the caller. Hence if the caller has a existing collator, it is his |
| * responsibility to delete first before calling this method. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address of the C UCollator |
| */ |
| static void closeCollator(JNIEnv *env, jclass obj, |
| jint address) { |
| |
| UCollator *collator = (UCollator *)(int)address; |
| ucol_close(collator); |
| } |
| |
| |
| /** |
| * Close a C collation element iterator. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address of C collation element iterator to close. |
| */ |
| static void closeElements(JNIEnv *env, jclass obj, |
| jint address) { |
| |
| UCollationElements *iterator = (UCollationElements *)(int)address; |
| ucol_closeElements(iterator); |
| } |
| |
| /** |
| * Compare two strings. |
| * The strings will be compared using the normalization mode and options |
| * specified in openCollator or openCollatorFromRules |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address address of the c collator |
| * @param source The source string. |
| * @param target The target string. |
| * @return result of the comparison, UCOL_EQUAL, UCOL_GREATER or UCOL_LESS |
| */ |
| static jint compare(JNIEnv *env, jclass obj, jint address, |
| jstring source, jstring target) { |
| |
| const UCollator *collator = (const UCollator *)(int)address; |
| jint result = -2; |
| if(collator){ |
| jsize srclength = (*env)->GetStringLength(env, source); |
| const UChar *srcstr = (const UChar *)(*env)->GetStringCritical(env,source,0); |
| if(srcstr){ |
| jsize tgtlength = (*env)->GetStringLength(env, target); |
| const UChar *tgtstr = (const UChar *)(*env)->GetStringCritical(env,target,0); |
| if(tgtstr){ |
| result = ucol_strcoll(collator, srcstr, srclength, tgtstr, tgtlength); |
| (*env)->ReleaseStringCritical(env, source, srcstr); |
| (*env)->ReleaseStringCritical(env, target, tgtstr); |
| return result; |
| }else{ |
| icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR); |
| } |
| }else{ |
| icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR); |
| } |
| }else{ |
| icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR); |
| } |
| return result; |
| } |
| |
| /** |
| * Universal attribute getter |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address address of the C collator |
| * @param type type of attribute to be set |
| * @return attribute value |
| * @exception thrown when error occurs while getting attribute value |
| */ |
| static jint getAttribute(JNIEnv *env, jclass obj, jint address, |
| jint type) { |
| |
| const UCollator *collator = (const UCollator *)(int)address; |
| UErrorCode status = U_ZERO_ERROR; |
| if(collator){ |
| jint result = (jint)ucol_getAttribute(collator, (UColAttribute)type, |
| &status); |
| if (icu4jni_error(env, status) != FALSE){ |
| return (jint)UCOL_DEFAULT; |
| } |
| return result; |
| }else{ |
| icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR); |
| } |
| return (jint)UCOL_DEFAULT; |
| } |
| |
| /** |
| * Create a CollationElementIterator object that will iterator over the elements |
| * in a string, using the collation rules defined in this RuleBasedCollatorJNI |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address address of C collator |
| * @param source string to iterate over |
| * @return address of C collationelement |
| */ |
| static jint getCollationElementIterator(JNIEnv *env, |
| jclass obj, jint address, jstring source) { |
| |
| UErrorCode status = U_ZERO_ERROR; |
| UCollator *collator = (UCollator *)(int)address; |
| jint result=0; |
| if(collator){ |
| jsize srclength = (*env)->GetStringLength(env, source); |
| const UChar *srcstr = (const UChar *)(*env)->GetStringCritical(env,source,0); |
| if(srcstr){ |
| result = (jint)(ucol_openElements(collator, srcstr, srclength, &status)); |
| |
| (*env)->ReleaseStringCritical(env, source, srcstr); |
| icu4jni_error(env, status); |
| }else{ |
| icu4jni_error(env, U_ILLEGAL_ARGUMENT_ERROR); |
| } |
| }else{ |
| icu4jni_error(env, U_ILLEGAL_ARGUMENT_ERROR); |
| } |
| return result; |
| } |
| |
| /** |
| * Get the maximum length of any expansion sequences that end with the specified |
| * comparison order. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address of the C collation element iterator containing the text. |
| * @param order collation order returned by previous or next. |
| * @return maximum length of any expansion sequences ending with the specified |
| * order or 1 if collation order does not occur at the end of any |
| * expansion sequence. |
| */ |
| static jint getMaxExpansion(JNIEnv *env, jclass obj, |
| jint address, jint order) { |
| |
| UCollationElements *iterator = (UCollationElements *)(int)address; |
| return ucol_getMaxExpansion(iterator, order); |
| } |
| |
| /** |
| * Get the normalization mode for this object. |
| * The normalization mode influences how strings are compared. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address of C collator |
| * @return normalization mode; one of the values from NormalizerEnum |
| */ |
| static jint getNormalization(JNIEnv *env, jclass obj, |
| jint address) { |
| |
| const UCollator* collator = (const UCollator*) address; |
| UErrorCode status = U_ZERO_ERROR; |
| jint result = ucol_getAttribute(collator, UCOL_NORMALIZATION_MODE, &status); |
| icu4jni_error(env, status); |
| return result; |
| } |
| |
| /** |
| * Set the normalization mode for this object. |
| * The normalization mode influences how strings are compared. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address of C collator |
| * @param mode the normalization mode |
| */ |
| static void setNormalization(JNIEnv *env, jclass obj, jint address, |
| jint mode) { |
| |
| const UCollator* collator = (const UCollator*) address; |
| UErrorCode status = U_ZERO_ERROR; |
| ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, mode, &status); |
| icu4jni_error(env, status); |
| } |
| |
| |
| /** |
| * Get the offset of the current source character. |
| * This is an offset into the text of the character containing the current |
| * collation elements. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param addresss of the C collation elements iterator to query. |
| * @return offset of the current source character. |
| */ |
| static jint getOffset(JNIEnv *env, jclass obj, jint address) { |
| |
| UCollationElements *iterator = (UCollationElements *)(int)address; |
| return ucol_getOffset(iterator); |
| } |
| |
| /** |
| * Get the collation rules from a UCollator. |
| * The rules will follow the rule syntax. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address the address of the C collator |
| * @return collation rules. |
| */ |
| static jstring getRules(JNIEnv *env, jclass obj, |
| jint address) { |
| |
| const UCollator *collator = (const UCollator *)(int)address; |
| int32_t length=0; |
| const UChar *rules = ucol_getRules(collator, &length); |
| return (*env)->NewString(env, rules, length); |
| } |
| |
| /** |
| * Get a sort key for the argument string |
| * Sort keys may be compared using java.util.Arrays.equals |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address address of the C collator |
| * @param source string for key to be generated |
| * @return sort key |
| */ |
| static jbyteArray getSortKey(JNIEnv *env, jclass obj, |
| jint address, jstring source) { |
| |
| const UCollator *collator = (const UCollator *)(int)address; |
| jbyteArray result; |
| if(collator && source){ |
| // BEGIN android-added |
| if(!source) { |
| return NULL; |
| } |
| // END android-added |
| jsize srclength = (*env)->GetStringLength(env, source); |
| const UChar *srcstr = (const UChar *)(*env)->GetStringCritical(env,source, 0); |
| if(srcstr){ |
| // BEGIN android-changed |
| uint8_t bytearray[UCOL_MAX_BUFFER * 2]; |
| uint8_t *largerbytearray = NULL; |
| uint8_t *usedbytearray = bytearray; |
| |
| jint bytearraysize = ucol_getSortKey(collator, srcstr, srclength, bytearray, |
| sizeof(bytearray) - 1); |
| |
| if (bytearraysize > sizeof(bytearray) - 1) { |
| // didn't fit, try again with a larger buffer. |
| largerbytearray = malloc(bytearraysize + 1); |
| usedbytearray = largerbytearray; |
| bytearraysize = ucol_getSortKey(collator, srcstr, srclength, largerbytearray, |
| bytearraysize); |
| } |
| |
| (*env)->ReleaseStringCritical(env, source, srcstr); |
| |
| if (bytearraysize == 0) { |
| free(largerbytearray); |
| return NULL; |
| } |
| |
| /* no problem converting uint8_t to int8_t, gives back the correct value |
| * tried and tested |
| */ |
| result = (*env)->NewByteArray(env, bytearraysize); |
| (*env)->SetByteArrayRegion(env, result, 0, bytearraysize, usedbytearray); |
| free(largerbytearray); |
| // END android-changed |
| }else{ |
| icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR); |
| } |
| }else{ |
| icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a hash of this collation object |
| * Note this method is not complete, it only returns 0 at the moment. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address address of C collator |
| * @return hash of this collation object |
| */ |
| static jint hashCode(JNIEnv *env, jclass obj, jint address) { |
| |
| UCollator *collator = (UCollator *)(int)address; |
| int32_t length=0; |
| const UChar *rules = ucol_getRules(collator, &length); |
| /* temporary commented out |
| * return uhash_hashUCharsN(rules, length); |
| */ |
| return 0; |
| } |
| |
| /** |
| * Get the ordering priority of the next collation element in the text. |
| * A single character may contain more than one collation element. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address if C collation elements containing the text. |
| * @return next collation elements ordering, otherwise returns NULLORDER if an |
| * error has occured or if the end of string has been reached |
| */ |
| static jint next(JNIEnv *env, jclass obj, jint address) { |
| UCollationElements *iterator = (UCollationElements *) address; |
| UErrorCode status = U_ZERO_ERROR; |
| jint result = ucol_next(iterator, &status); |
| icu4jni_error(env, status); |
| return result; |
| } |
| |
| /** |
| * Opening a new C UCollator with the default locale. |
| * Note determining if a collator currently exist for the caller is to be handled |
| * by the caller. Hence if the caller has a existing collator, it is his |
| * responsibility to delete first before calling this method. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @return address of the new C UCollator |
| * @exception thrown if creation of the UCollator fails |
| */ |
| static jint openCollator__(JNIEnv *env, jclass obj) { |
| UErrorCode status = U_ZERO_ERROR; |
| jint result = ucol_open(NULL, &status); |
| icu4jni_error(env, status); |
| return result; |
| } |
| |
| |
| /** |
| * Opening a new C UCollator with the argument locale rules. |
| * Note determining if a collator currently exist for the caller is to be handled |
| * by the caller. Hence if the caller has a existing collator, it is his |
| * responsibility to delete first before calling this method. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param locale name |
| * @return address of the new C UCollator |
| * @exception thrown if creation of the UCollator fails |
| */ |
| static jint openCollator__Ljava_lang_String_2(JNIEnv *env, |
| jclass obj, jstring locale) { |
| |
| /* this will be null terminated */ |
| const char* localeStr = (*env)->GetStringUTFChars(env, locale, NULL); |
| if (localeStr == NULL) { |
| icu4jni_error(env, U_ILLEGAL_ARGUMENT_ERROR); |
| return 0; |
| } |
| |
| UErrorCode status = U_ZERO_ERROR; |
| jint result = ucol_open(localeStr, &status); |
| (*env)->ReleaseStringUTFChars(env, locale, localeStr); |
| icu4jni_error(env, status); |
| return result; |
| } |
| |
| /** |
| * Opening a new C UCollator with the argument locale rules. |
| * Note determining if a collator currently exist for the caller is to be |
| * handled by the caller. Hence if the caller has a existing collator, it is his |
| * responsibility to delete first before calling this method. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param rules set of collation rules |
| * @param normalizationmode normalization mode |
| * @param strength collation strength |
| * @return address of the new C UCollator |
| * @exception thrown if creation of the UCollator fails |
| */ |
| static jint openCollatorFromRules(JNIEnv *env, jclass obj, |
| jstring rules, jint normalizationmode, jint strength) { |
| |
| jsize ruleslength = (*env)->GetStringLength(env, rules); |
| const UChar *rulestr = (const UChar *)(*env)->GetStringCritical(env,rules, 0); |
| UErrorCode status = U_ZERO_ERROR; |
| jint result = 0; |
| if(rulestr){ |
| result = (jint)ucol_openRules(rulestr, ruleslength, |
| (UColAttributeValue)normalizationmode, |
| (UCollationStrength)strength, NULL, &status); |
| |
| (*env)->ReleaseStringCritical(env, rules, rulestr); |
| icu4jni_error(env, status); |
| }else{ |
| icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR); |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Get the ordering priority of the previous collation element in the text. |
| * A single character may contain more than one collation element. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address of the C collation element iterator containing the text. |
| * @return previous collation element ordering, otherwise returns NULLORDER if |
| * an error has occured or if the start of string has been reached |
| * @exception thrown when retrieval of previous collation element fails. |
| */ |
| static jint previous(JNIEnv *env, jclass obj, jint address) { |
| |
| UCollationElements *iterator = (UCollationElements *)(int)address; |
| UErrorCode status = U_ZERO_ERROR; |
| jint result = ucol_previous(iterator, &status); |
| |
| icu4jni_error(env, status); |
| return result; |
| } |
| |
| |
| /** |
| * Reset the collation elements to their initial state. |
| * This will move the 'cursor' to the beginning of the text. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address of C collation element iterator to reset. |
| */ |
| static void reset(JNIEnv *env, jclass obj, jint address) { |
| |
| UCollationElements *iterator = (UCollationElements *)(int)address; |
| ucol_reset(iterator); |
| } |
| |
| /** |
| * Thread safe cloning operation |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address address of C collator to be cloned |
| * @return address of the new clone |
| * @exception thrown when error occurs while cloning |
| */ |
| static jint safeClone(JNIEnv *env, jclass obj, jint address) { |
| |
| const UCollator *collator = (const UCollator *)(int)address; |
| UErrorCode status = U_ZERO_ERROR; |
| jint result; |
| jint buffersize = U_COL_SAFECLONE_BUFFERSIZE; |
| |
| result = (jint)ucol_safeClone(collator, NULL, &buffersize, &status); |
| |
| if ( icu4jni_error(env, status) != FALSE) { |
| return 0; |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Universal attribute setter. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address address of the C collator |
| * @param type type of attribute to be set |
| * @param value attribute value |
| * @exception thrown when error occurs while setting attribute value |
| */ |
| static void setAttribute(JNIEnv *env, jclass obj, jint address, |
| jint type, jint value) { |
| |
| UCollator *collator = (UCollator *)(int)address; |
| UErrorCode status = U_ZERO_ERROR; |
| ucol_setAttribute(collator, (UColAttribute)type, (UColAttributeValue)value, |
| &status); |
| icu4jni_error(env, status); |
| } |
| |
| /** |
| * Set the offset of the current source character. |
| * This is an offset into the text of the character to be processed. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address of the C collation element iterator to set. |
| * @param offset The desired character offset. |
| * @exception thrown when offset setting fails |
| */ |
| static void setOffset(JNIEnv *env, jclass obj, jint address, |
| jint offset) { |
| |
| UCollationElements *iterator = (UCollationElements *)(int)address; |
| UErrorCode status = U_ZERO_ERROR; |
| |
| ucol_setOffset(iterator, offset, &status); |
| icu4jni_error(env, status); |
| } |
| |
| /** |
| * Set the text containing the collation elements. |
| * @param env JNI environment |
| * @param obj RuleBasedCollatorJNI object |
| * @param address of the C collation element iterator to be set |
| * @param source text containing the collation elements. |
| * @exception thrown when error occurs while setting offset |
| */ |
| static void setText(JNIEnv *env, jclass obj, jint address, |
| jstring source) { |
| |
| UCollationElements *iterator = (UCollationElements *)(int)address; |
| UErrorCode status = U_ZERO_ERROR; |
| int strlength = (*env)->GetStringLength(env, source); |
| const UChar *str = (const UChar *)(*env)->GetStringCritical(env, source, 0); |
| |
| ucol_setText(iterator, str, strlength, &status); |
| (*env)->ReleaseStringCritical(env, source, str); |
| |
| icu4jni_error(env, status); |
| } |
| |
| // BEGIN android-added |
| static jstring getAvailableLocalesImpl(JNIEnv *env, jclass clazz, jint index) { |
| |
| const char * locale = ucol_getAvailable(index); |
| |
| return (*env)->NewStringUTF(env, locale); |
| |
| } |
| |
| static jint getAvailableLocalesCountImpl(JNIEnv *env, jclass clazz) { |
| return ucol_countAvailable(); |
| } |
| // END android-added |
| |
| /* |
| * JNI registratio |
| */ |
| static JNINativeMethod gMethods[] = { |
| /* name, signature, funcPtr */ |
| // BEGIN android-added |
| { "getAvailableLocalesImpl", "(I)Ljava/lang/String;", (void*) getAvailableLocalesImpl }, |
| { "getAvailableLocalesCountImpl", "()I", (void*) getAvailableLocalesCountImpl }, |
| // END android-added |
| { "openCollator", "()I", (void*) openCollator__ }, |
| { "openCollator", "(Ljava/lang/String;)I", (void*) openCollator__Ljava_lang_String_2 }, |
| { "openCollatorFromRules", "(Ljava/lang/String;II)I", (void*) openCollatorFromRules }, |
| { "closeCollator", "(I)V", (void*) closeCollator }, |
| { "compare", "(ILjava/lang/String;Ljava/lang/String;)I", (void*) compare }, |
| { "getNormalization", "(I)I", (void*) getNormalization }, |
| { "setNormalization", "(II)V", (void*) setNormalization }, |
| { "getRules", "(I)Ljava/lang/String;", (void*) getRules }, |
| { "getSortKey", "(ILjava/lang/String;)[B", (void*) getSortKey }, |
| { "setAttribute", "(III)V", (void*) setAttribute }, |
| { "getAttribute", "(II)I", (void*) getAttribute }, |
| { "safeClone", "(I)I", (void*) safeClone }, |
| { "getCollationElementIterator", "(ILjava/lang/String;)I", (void*) getCollationElementIterator }, |
| { "hashCode", "(I)I", (void*) hashCode }, |
| { "closeElements", "(I)V", (void*) closeElements }, |
| { "reset", "(I)V", (void*) reset }, |
| { "next", "(I)I", (void*) next }, |
| { "previous", "(I)I", (void*) previous }, |
| { "getMaxExpansion", "(II)I", (void*) getMaxExpansion }, |
| { "setText", "(ILjava/lang/String;)V", (void*) setText }, |
| { "getOffset", "(I)I", (void*) getOffset }, |
| { "setOffset", "(II)V", (void*) setOffset } |
| }; |
| |
| int register_com_ibm_icu4jni_text_NativeCollator(JNIEnv *_env) { |
| return jniRegisterNativeMethods(_env, "com/ibm/icu4jni/text/NativeCollation", |
| gMethods, NELEM(gMethods)); |
| } |