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 #define LOG_TAG "Character"
     18 
     19 #include "JNIHelp.h"
     20 #include "JniConstants.h"
     21 #include "ScopedUtfChars.h"
     22 #include "unicode/uchar.h"
     23 #include <math.h>
     24 #include <stdlib.h>
     25 
     26 static jint Character_digitImpl(JNIEnv*, jclass, jint codePoint, jint radix) {
     27     return u_digit(codePoint, radix);
     28 }
     29 
     30 static jint Character_getTypeImpl(JNIEnv*, jclass, jint codePoint) {
     31     return u_charType(codePoint);
     32 }
     33 
     34 static jbyte Character_getDirectionalityImpl(JNIEnv*, jclass, jint codePoint) {
     35     return u_charDirection(codePoint);
     36 }
     37 
     38 static jboolean Character_isMirroredImpl(JNIEnv*, jclass, jint codePoint) {
     39     return u_isMirrored(codePoint);
     40 }
     41 
     42 static jint Character_getNumericValueImpl(JNIEnv*, jclass, jint codePoint){
     43     // The letters A-Z in their uppercase ('\u0041' through '\u005A'),
     44     //                          lowercase ('\u0061' through '\u007A'),
     45     //             and full width variant ('\uFF21' through '\uFF3A'
     46     //                                 and '\uFF41' through '\uFF5A') forms
     47     // have numeric values from 10 through 35. This is independent of the
     48     // Unicode specification, which does not assign numeric values to these
     49     // char values.
     50     if (codePoint >= 0x41 && codePoint <= 0x5A) {
     51         return codePoint - 0x37;
     52     }
     53     if (codePoint >= 0x61 && codePoint <= 0x7A) {
     54         return codePoint - 0x57;
     55     }
     56     if (codePoint >= 0xFF21 && codePoint <= 0xFF3A) {
     57         return codePoint - 0xFF17;
     58     }
     59     if (codePoint >= 0xFF41 && codePoint <= 0xFF5A) {
     60         return codePoint - 0xFF37;
     61     }
     62 
     63     double result = u_getNumericValue(codePoint);
     64 
     65     if (result == U_NO_NUMERIC_VALUE) {
     66         return -1;
     67     } else if (result < 0 || floor(result + 0.5) != result) {
     68         return -2;
     69     }
     70 
     71     return result;
     72 }
     73 
     74 static jboolean Character_isDefinedImpl(JNIEnv*, jclass, jint codePoint) {
     75     return u_isdefined(codePoint);
     76 }
     77 
     78 static jboolean Character_isDigitImpl(JNIEnv*, jclass, jint codePoint) {
     79     return u_isdigit(codePoint);
     80 }
     81 
     82 static jboolean Character_isIdentifierIgnorableImpl(JNIEnv*, jclass, jint codePoint) {
     83     // Java also returns true for U+0085 Next Line (it omits U+0085 from whitespace ISO controls).
     84     if(codePoint == 0x0085) {
     85         return JNI_TRUE;
     86     }
     87     return u_isIDIgnorable(codePoint);
     88 }
     89 
     90 static jboolean Character_isLetterImpl(JNIEnv*, jclass, jint codePoint) {
     91     return u_isalpha(codePoint);
     92 }
     93 
     94 static jboolean Character_isLetterOrDigitImpl(JNIEnv*, jclass, jint codePoint) {
     95     return u_isalnum(codePoint);
     96 }
     97 
     98 static jboolean Character_isSpaceCharImpl(JNIEnv*, jclass, jint codePoint) {
     99     return u_isJavaSpaceChar(codePoint);
    100 }
    101 
    102 static jboolean Character_isTitleCaseImpl(JNIEnv*, jclass, jint codePoint) {
    103     return u_istitle(codePoint);
    104 }
    105 
    106 static jboolean Character_isUnicodeIdentifierPartImpl(JNIEnv*, jclass, jint codePoint) {
    107     return u_isIDPart(codePoint);
    108 }
    109 
    110 static jboolean Character_isUnicodeIdentifierStartImpl(JNIEnv*, jclass, jint codePoint) {
    111     return u_isIDStart(codePoint);
    112 }
    113 
    114 static jboolean Character_isWhitespaceImpl(JNIEnv*, jclass, jint codePoint) {
    115     // Java omits U+0085
    116     if(codePoint == 0x0085) {
    117         return JNI_FALSE;
    118     }
    119     return u_isWhitespace(codePoint);
    120 }
    121 
    122 static jint Character_toLowerCaseImpl(JNIEnv*, jclass, jint codePoint) {
    123     return u_tolower(codePoint);
    124 }
    125 
    126 static jint Character_toTitleCaseImpl(JNIEnv*, jclass, jint codePoint) {
    127     return u_totitle(codePoint);
    128 }
    129 
    130 static jint Character_toUpperCaseImpl(JNIEnv*, jclass, jint codePoint) {
    131     return u_toupper(codePoint);
    132 }
    133 
    134 static jboolean Character_isUpperCaseImpl(JNIEnv*, jclass, jint codePoint) {
    135     return u_isupper(codePoint);
    136 }
    137 
    138 static jboolean Character_isLowerCaseImpl(JNIEnv*, jclass, jint codePoint) {
    139     return u_islower(codePoint);
    140 }
    141 
    142 static int Character_forNameImpl(JNIEnv* env, jclass, jstring javaBlockName) {
    143     ScopedUtfChars blockName(env, javaBlockName);
    144     if (blockName.c_str() == NULL) {
    145         return 0;
    146     }
    147     return u_getPropertyValueEnum(UCHAR_BLOCK, blockName.c_str());
    148 }
    149 
    150 static int Character_ofImpl(JNIEnv*, jclass, jint codePoint) {
    151     return ublock_getCode(codePoint);
    152 }
    153 
    154 static JNINativeMethod gMethods[] = {
    155     NATIVE_METHOD(Character, digitImpl, "(II)I"),
    156     NATIVE_METHOD(Character, forNameImpl, "(Ljava/lang/String;)I"),
    157     NATIVE_METHOD(Character, getDirectionalityImpl, "(I)B"),
    158     NATIVE_METHOD(Character, getNumericValueImpl, "(I)I"),
    159     NATIVE_METHOD(Character, getTypeImpl, "(I)I"),
    160     NATIVE_METHOD(Character, isDefinedImpl, "(I)Z"),
    161     NATIVE_METHOD(Character, isDigitImpl, "(I)Z"),
    162     NATIVE_METHOD(Character, isIdentifierIgnorableImpl, "(I)Z"),
    163     NATIVE_METHOD(Character, isLetterImpl, "(I)Z"),
    164     NATIVE_METHOD(Character, isLetterOrDigitImpl, "(I)Z"),
    165     NATIVE_METHOD(Character, isLowerCaseImpl, "(I)Z"),
    166     NATIVE_METHOD(Character, isMirroredImpl, "(I)Z"),
    167     NATIVE_METHOD(Character, isSpaceCharImpl, "(I)Z"),
    168     NATIVE_METHOD(Character, isTitleCaseImpl, "(I)Z"),
    169     NATIVE_METHOD(Character, isUnicodeIdentifierPartImpl, "(I)Z"),
    170     NATIVE_METHOD(Character, isUnicodeIdentifierStartImpl, "(I)Z"),
    171     NATIVE_METHOD(Character, isUpperCaseImpl, "(I)Z"),
    172     NATIVE_METHOD(Character, isWhitespaceImpl, "(I)Z"),
    173     NATIVE_METHOD(Character, ofImpl, "(I)I"),
    174     NATIVE_METHOD(Character, toLowerCaseImpl, "(I)I"),
    175     NATIVE_METHOD(Character, toTitleCaseImpl, "(I)I"),
    176     NATIVE_METHOD(Character, toUpperCaseImpl, "(I)I"),
    177 };
    178 int register_java_lang_Character(JNIEnv* env) {
    179     return jniRegisterNativeMethods(env, "java/lang/Character", gMethods, NELEM(gMethods));
    180 }
    181