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 "unicode/uscript.h"
     24 #include <math.h>
     25 #include <stdio.h> // For BUFSIZ
     26 #include <stdlib.h>
     27 
     28 static jint Character_digitImpl(JNIEnv*, jclass, jint codePoint, jint radix) {
     29     return u_digit(codePoint, radix);
     30 }
     31 
     32 static jint Character_getTypeImpl(JNIEnv*, jclass, jint codePoint) {
     33     return u_charType(codePoint);
     34 }
     35 
     36 static jbyte Character_getIcuDirectionality(JNIEnv*, jclass, jint codePoint) {
     37     return u_charDirection(codePoint);
     38 }
     39 
     40 static jboolean Character_isMirroredImpl(JNIEnv*, jclass, jint codePoint) {
     41     return u_isMirrored(codePoint);
     42 }
     43 
     44 static jstring Character_getNameImpl(JNIEnv* env, jclass, jint codePoint) {
     45     // U_UNICODE_CHAR_NAME gives us the modern names for characters. For control characters,
     46     // we need U_EXTENDED_CHAR_NAME to get "NULL" rather than "BASIC LATIN 0" and so on.
     47     // We could just use U_EXTENDED_CHAR_NAME except that it returns strings for characters
     48     // that aren't unassigned but that don't have names, and those strings aren't in the form
     49     // Java specifies.
     50     bool isControl = (codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f));
     51     UCharNameChoice nameType = isControl ? U_EXTENDED_CHAR_NAME : U_UNICODE_CHAR_NAME;
     52     UErrorCode status = U_ZERO_ERROR;
     53     char buf[BUFSIZ]; // TODO: is there a more sensible upper bound?
     54     int32_t byteCount = u_charName(codePoint, nameType, &buf[0], sizeof(buf), &status);
     55     return (U_FAILURE(status) || byteCount == 0) ? NULL : env->NewStringUTF(buf);
     56 }
     57 
     58 static jint Character_getNumericValueImpl(JNIEnv*, jclass, jint codePoint) {
     59     double result = u_getNumericValue(codePoint);
     60     if (result == U_NO_NUMERIC_VALUE) {
     61         return -1;
     62     } else if (result < 0 || floor(result + 0.5) != result) {
     63         return -2;
     64     }
     65     return static_cast<jint>(result);
     66 }
     67 
     68 static jboolean Character_isDefinedImpl(JNIEnv*, jclass, jint codePoint) {
     69     return u_isdefined(codePoint);
     70 }
     71 
     72 static jboolean Character_isDigitImpl(JNIEnv*, jclass, jint codePoint) {
     73     return u_isdigit(codePoint);
     74 }
     75 
     76 static jboolean Character_isIdentifierIgnorableImpl(JNIEnv*, jclass, jint codePoint) {
     77     return u_isIDIgnorable(codePoint);
     78 }
     79 
     80 static jboolean Character_isLetterImpl(JNIEnv*, jclass, jint codePoint) {
     81     return u_isalpha(codePoint);
     82 }
     83 
     84 static jboolean Character_isLetterOrDigitImpl(JNIEnv*, jclass, jint codePoint) {
     85     return u_isalnum(codePoint);
     86 }
     87 
     88 static jboolean Character_isSpaceCharImpl(JNIEnv*, jclass, jint codePoint) {
     89     return u_isJavaSpaceChar(codePoint);
     90 }
     91 
     92 static jboolean Character_isTitleCaseImpl(JNIEnv*, jclass, jint codePoint) {
     93     return u_istitle(codePoint);
     94 }
     95 
     96 static jboolean Character_isUnicodeIdentifierPartImpl(JNIEnv*, jclass, jint codePoint) {
     97     return u_isIDPart(codePoint);
     98 }
     99 
    100 static jboolean Character_isUnicodeIdentifierStartImpl(JNIEnv*, jclass, jint codePoint) {
    101     return u_isIDStart(codePoint);
    102 }
    103 
    104 static jboolean Character_isWhitespaceImpl(JNIEnv*, jclass, jint codePoint) {
    105     return u_isWhitespace(codePoint);
    106 }
    107 
    108 static jint Character_toLowerCaseImpl(JNIEnv*, jclass, jint codePoint) {
    109     return u_tolower(codePoint);
    110 }
    111 
    112 static jint Character_toTitleCaseImpl(JNIEnv*, jclass, jint codePoint) {
    113     return u_totitle(codePoint);
    114 }
    115 
    116 static jint Character_toUpperCaseImpl(JNIEnv*, jclass, jint codePoint) {
    117     return u_toupper(codePoint);
    118 }
    119 
    120 static jboolean Character_isUpperCaseImpl(JNIEnv*, jclass, jint codePoint) {
    121     return u_isupper(codePoint);
    122 }
    123 
    124 static jboolean Character_isLowerCaseImpl(JNIEnv*, jclass, jint codePoint) {
    125     return u_islower(codePoint);
    126 }
    127 
    128 static int Character_unicodeBlockForName(JNIEnv* env, jclass, jstring javaBlockName) {
    129     ScopedUtfChars blockName(env, javaBlockName);
    130     if (blockName.c_str() == NULL) {
    131         return 0;
    132     }
    133     return u_getPropertyValueEnum(UCHAR_BLOCK, blockName.c_str());
    134 }
    135 
    136 static int Character_unicodeBlockForCodePoint(JNIEnv*, jclass, jint codePoint) {
    137     return ublock_getCode(codePoint);
    138 }
    139 
    140 static int Character_unicodeScriptForName(JNIEnv* env, jclass, jstring javaScriptName) {
    141     ScopedUtfChars scriptName(env, javaScriptName);
    142     if (scriptName.c_str() == NULL) {
    143         return -1;
    144     }
    145 
    146     return u_getPropertyValueEnum(UCHAR_SCRIPT, scriptName.c_str());
    147 }
    148 
    149 static int Character_unicodeScriptForCodePoint(JNIEnv*, jclass, jint codePoint) {
    150     UErrorCode status = U_ZERO_ERROR;
    151     const UScriptCode script = uscript_getScript(codePoint, &status);
    152     if (status != U_ZERO_ERROR) {
    153         return -1;
    154     }
    155 
    156     return script;
    157 }
    158 
    159 static jboolean Character_isAlphabetic(JNIEnv*, jclass, jint codePoint) {
    160   return u_hasBinaryProperty(codePoint, UCHAR_ALPHABETIC);
    161 }
    162 
    163 static jboolean Character_isIdeographic(JNIEnv*, jclass, jint codePoint) {
    164   return u_hasBinaryProperty(codePoint, UCHAR_IDEOGRAPHIC);
    165 }
    166 
    167 static JNINativeMethod gMethods[] = {
    168     NATIVE_METHOD(Character, digitImpl, "!(II)I"),
    169     NATIVE_METHOD(Character, getIcuDirectionality, "!(I)B"),
    170     NATIVE_METHOD(Character, getNameImpl, "(I)Ljava/lang/String;"),
    171     NATIVE_METHOD(Character, getNumericValueImpl, "!(I)I"),
    172     NATIVE_METHOD(Character, getTypeImpl, "!(I)I"),
    173     NATIVE_METHOD(Character, isAlphabetic, "!(I)Z"),
    174     NATIVE_METHOD(Character, isDefinedImpl, "!(I)Z"),
    175     NATIVE_METHOD(Character, isDigitImpl, "!(I)Z"),
    176     NATIVE_METHOD(Character, isIdentifierIgnorableImpl, "!(I)Z"),
    177     NATIVE_METHOD(Character, isIdeographic, "!(I)Z"),
    178     NATIVE_METHOD(Character, isLetterImpl, "!(I)Z"),
    179     NATIVE_METHOD(Character, isLetterOrDigitImpl, "!(I)Z"),
    180     NATIVE_METHOD(Character, isLowerCaseImpl, "!(I)Z"),
    181     NATIVE_METHOD(Character, isMirroredImpl, "!(I)Z"),
    182     NATIVE_METHOD(Character, isSpaceCharImpl, "!(I)Z"),
    183     NATIVE_METHOD(Character, isTitleCaseImpl, "!(I)Z"),
    184     NATIVE_METHOD(Character, isUnicodeIdentifierPartImpl, "!(I)Z"),
    185     NATIVE_METHOD(Character, isUnicodeIdentifierStartImpl, "!(I)Z"),
    186     NATIVE_METHOD(Character, isUpperCaseImpl, "!(I)Z"),
    187     NATIVE_METHOD(Character, isWhitespaceImpl, "!(I)Z"),
    188     NATIVE_METHOD(Character, toLowerCaseImpl, "!(I)I"),
    189     NATIVE_METHOD(Character, toTitleCaseImpl, "!(I)I"),
    190     NATIVE_METHOD(Character, toUpperCaseImpl, "!(I)I"),
    191     NATIVE_METHOD(Character, unicodeBlockForName, "(Ljava/lang/String;)I"),
    192     NATIVE_METHOD(Character, unicodeBlockForCodePoint, "!(I)I"),
    193     NATIVE_METHOD(Character, unicodeScriptForName, "(Ljava/lang/String;)I"),
    194     NATIVE_METHOD(Character, unicodeScriptForCodePoint, "!(I)I"),
    195 };
    196 void register_java_lang_Character(JNIEnv* env) {
    197     jniRegisterNativeMethods(env, "java/lang/Character", gMethods, NELEM(gMethods));
    198 }
    199