Home | History | Annotate | Download | only in native
      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