summaryrefslogtreecommitdiffstats
path: root/icu/src/main/native/CollationInterface.c
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commitfdb2704414a9ed92394ada0d1395e4db86889465 (patch)
tree9b591a4a50054274a197f02b3ccb51313681879f /icu/src/main/native/CollationInterface.c
downloadlibcore-fdb2704414a9ed92394ada0d1395e4db86889465.zip
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.gz
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.bz2
Initial Contribution
Diffstat (limited to 'icu/src/main/native/CollationInterface.c')
-rw-r--r--icu/src/main/native/CollationInterface.c589
1 files changed, 589 insertions, 0 deletions
diff --git a/icu/src/main/native/CollationInterface.c b/icu/src/main/native/CollationInterface.c
new file mode 100644
index 0000000..86246ac
--- /dev/null
+++ b/icu/src/main/native/CollationInterface.c
@@ -0,0 +1,589 @@
+/**
+*******************************************************************************
+* 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) {
+
+ UErrorCode status = U_ZERO_ERROR;
+ const UCollator *collator = (const UCollator *)(int)address;
+ if(U_FAILURE(status)){
+ icu4jni_error(env, status);
+ }
+ return (jint)ucol_getAttribute(collator,UCOL_NORMALIZATION_MODE,&status);
+
+}
+
+/**
+* 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) {
+
+ UErrorCode status = U_ZERO_ERROR;
+ const UCollator *collator = (const UCollator *)(int)address;
+ if(U_FAILURE(status)){
+ icu4jni_error(env, status);
+ }
+ ucol_setAttribute(collator,UCOL_NORMALIZATION_MODE,mode,&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 *)(int)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) {
+ jint result;
+ UErrorCode status = U_ZERO_ERROR;
+
+ result = (jint)ucol_open(NULL, &status);
+ if ( icu4jni_error(env, status) != FALSE)
+ return 0;
+
+ 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, 0);
+ jint result=0;
+ UErrorCode status = U_ZERO_ERROR;
+
+ if(localestr){
+ result = (jint)ucol_open(localestr, &status);
+ (*env)->ReleaseStringUTFChars(env, locale, localestr);
+ icu4jni_error(env, status);
+ }else{
+ icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR);
+ }
+ 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));
+}
+