Home | History | Annotate | Download | only in native
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "JNIHelp.h"
     18 #include "AndroidSystemNatives.h"
     19 #include "unicode/uchar.h"
     20 #include <math.h>
     21 #include <stdlib.h>
     22 
     23 static jint digitImpl(JNIEnv*, jclass, jint codePoint, jint radix) {
     24     return u_digit(codePoint, radix);
     25 }
     26 
     27 static jint getTypeImpl(JNIEnv*, jclass, jint codePoint) {
     28     return u_charType(codePoint);
     29 }
     30 
     31 static jbyte getDirectionalityImpl(JNIEnv*, jclass, jint codePoint) {
     32     return u_charDirection(codePoint);
     33 }
     34 
     35 static jboolean isMirroredImpl(JNIEnv*, jclass, jint codePoint) {
     36     return u_isMirrored(codePoint);
     37 }
     38 
     39 static jint getNumericValueImpl(JNIEnv*, jclass, jint codePoint){
     40     // The letters A-Z in their uppercase ('\u0041' through '\u005A'),
     41     //                          lowercase ('\u0061' through '\u007A'),
     42     //             and full width variant ('\uFF21' through '\uFF3A'
     43     //                                 and '\uFF41' through '\uFF5A') forms
     44     // have numeric values from 10 through 35. This is independent of the
     45     // Unicode specification, which does not assign numeric values to these
     46     // char values.
     47     if (codePoint >= 0x41 && codePoint <= 0x5A) {
     48         return codePoint - 0x37;
     49     }
     50     if (codePoint >= 0x61 && codePoint <= 0x7A) {
     51         return codePoint - 0x57;
     52     }
     53     if (codePoint >= 0xFF21 && codePoint <= 0xFF3A) {
     54         return codePoint - 0xFF17;
     55     }
     56     if (codePoint >= 0xFF41 && codePoint <= 0xFF5A) {
     57         return codePoint - 0xFF37;
     58     }
     59 
     60     double result = u_getNumericValue(codePoint);
     61 
     62     if (result == U_NO_NUMERIC_VALUE) {
     63         return -1;
     64     } else if (result < 0 || floor(result + 0.5) != result) {
     65         return -2;
     66     }
     67 
     68     return result;
     69 }
     70 
     71 static jboolean isDefinedImpl(JNIEnv*, jclass, jint codePoint) {
     72     return u_isdefined(codePoint);
     73 }
     74 
     75 static jboolean isDigitImpl(JNIEnv*, jclass, jint codePoint) {
     76     return u_isdigit(codePoint);
     77 }
     78 
     79 static jboolean isIdentifierIgnorableImpl(JNIEnv*, jclass, jint codePoint) {
     80     // Java also returns TRUE for U+0085 Next Line (it omits U+0085 from whitespace ISO controls)
     81     if(codePoint == 0x0085) {
     82         return JNI_TRUE;
     83     }
     84     return u_isIDIgnorable(codePoint);
     85 }
     86 
     87 static jboolean isLetterImpl(JNIEnv*, jclass, jint codePoint) {
     88     return u_isalpha(codePoint);
     89 }
     90 
     91 static jboolean isLetterOrDigitImpl(JNIEnv*, jclass, jint codePoint) {
     92     return u_isalnum(codePoint);
     93 }
     94 
     95 static jboolean isSpaceCharImpl(JNIEnv*, jclass, jint codePoint) {
     96     return u_isJavaSpaceChar(codePoint);
     97 }
     98 
     99 static jboolean isTitleCaseImpl(JNIEnv*, jclass, jint codePoint) {
    100     return u_istitle(codePoint);
    101 }
    102 
    103 static jboolean isUnicodeIdentifierPartImpl(JNIEnv*, jclass, jint codePoint) {
    104     return u_isIDPart(codePoint);
    105 }
    106 
    107 static jboolean isUnicodeIdentifierStartImpl(JNIEnv*, jclass, jint codePoint) {
    108     return u_isIDStart(codePoint);
    109 }
    110 
    111 static jboolean isWhitespaceImpl(JNIEnv*, jclass, jint codePoint) {
    112     // Java omits U+0085
    113     if(codePoint == 0x0085) {
    114         return JNI_FALSE;
    115     }
    116     return u_isWhitespace(codePoint);
    117 }
    118 
    119 static jint toLowerCaseImpl(JNIEnv*, jclass, jint codePoint) {
    120     return u_tolower(codePoint);
    121 }
    122 
    123 static jint toTitleCaseImpl(JNIEnv*, jclass, jint codePoint) {
    124     return u_totitle(codePoint);
    125 }
    126 
    127 static jint toUpperCaseImpl(JNIEnv*, jclass, jint codePoint) {
    128     return u_toupper(codePoint);
    129 }
    130 
    131 static jboolean isUpperCaseImpl(JNIEnv*, jclass, jint codePoint) {
    132     return u_isupper(codePoint);
    133 }
    134 
    135 static jboolean isLowerCaseImpl(JNIEnv*, jclass, jint codePoint) {
    136     return u_islower(codePoint);
    137 }
    138 
    139 static int forNameImpl(JNIEnv* env, jclass, jstring blockName) {
    140     if (blockName == NULL) {
    141         jniThrowNullPointerException(env, NULL);
    142         return -1;
    143     }
    144     const char* bName = env->GetStringUTFChars(blockName, NULL);
    145     int result = u_getPropertyValueEnum(UCHAR_BLOCK, bName);
    146     env->ReleaseStringUTFChars(blockName, bName);
    147     return result;
    148 }
    149 
    150 static int ofImpl(JNIEnv*, jclass, jint codePoint) {
    151     return ublock_getCode(codePoint);
    152 }
    153 
    154 /*
    155  * JNI registration
    156  */
    157 static JNINativeMethod gMethods[] = {
    158     /* name, signature, funcPtr */
    159     { "digit", "(II)I", (void*) digitImpl },
    160     { "forName", "(Ljava/lang/String;)I", (void*) forNameImpl },
    161     { "getDirectionality", "(I)B", (void*) getDirectionalityImpl },
    162     { "getNumericValue", "(I)I", (void*) getNumericValueImpl },
    163     { "getType", "(I)I", (void*) getTypeImpl },
    164     { "isDefined", "(I)Z", (void*) isDefinedImpl },
    165     { "isDigit", "(I)Z", (void*) isDigitImpl },
    166     { "isIdentifierIgnorable", "(I)Z", (void*) isIdentifierIgnorableImpl },
    167     { "isLetter", "(I)Z", (void*) isLetterImpl },
    168     { "isLetterOrDigit", "(I)Z", (void*) isLetterOrDigitImpl },
    169     { "isLowerCase", "(I)Z", (void*) isLowerCaseImpl },
    170     { "isMirrored", "(I)Z", (void*) isMirroredImpl },
    171     { "isSpaceChar", "(I)Z", (void*) isSpaceCharImpl },
    172     { "isTitleCase", "(I)Z", (void*) isTitleCaseImpl },
    173     { "isUnicodeIdentifierPart", "(I)Z", (void*) isUnicodeIdentifierPartImpl },
    174     { "isUnicodeIdentifierStart", "(I)Z", (void*) isUnicodeIdentifierStartImpl },
    175     { "isUpperCase", "(I)Z", (void*) isUpperCaseImpl },
    176     { "isWhitespace", "(I)Z", (void*) isWhitespaceImpl },
    177     { "of", "(I)I", (void*) ofImpl },
    178     { "toLowerCase", "(I)I", (void*) toLowerCaseImpl },
    179     { "toTitleCase", "(I)I", (void*) toTitleCaseImpl },
    180     { "toUpperCase", "(I)I", (void*) toUpperCaseImpl },
    181 };
    182 
    183 int register_com_ibm_icu4jni_lang_UCharacter(JNIEnv* env) {
    184     return jniRegisterNativeMethods(env, "com/ibm/icu4jni/lang/UCharacter",
    185                 gMethods, NELEM(gMethods));
    186 }
    187