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 jstring Character_getNameImpl(JNIEnv* env, jclass, jint codePoint) {
     43     // U_UNICODE_CHAR_NAME gives us the modern names for characters. For control characters,
     44     // we need U_EXTENDED_CHAR_NAME to get "NULL" rather than "BASIC LATIN 0" and so on.
     45     // We could just use U_EXTENDED_CHAR_NAME except that it returns strings for characters
     46     // that aren't unassigned but that don't have names, and those strings aren't in the form
     47     // Java specifies.
     48     bool isControl = (codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f));
     49     UCharNameChoice nameType = isControl ? U_EXTENDED_CHAR_NAME : U_UNICODE_CHAR_NAME;
     50     UErrorCode status = U_ZERO_ERROR;
     51     char buf[BUFSIZ]; // TODO: is there a more sensible upper bound?
     52     int32_t byteCount = u_charName(codePoint, nameType, &buf[0], sizeof(buf), &status);
     53     return (U_FAILURE(status) || byteCount == 0) ? NULL : env->NewStringUTF(buf);
     54 }
     55 
     56 static jint Character_getNumericValueImpl(JNIEnv*, jclass, jint codePoint) {
     57     double result = u_getNumericValue(codePoint);
     58     if (result == U_NO_NUMERIC_VALUE) {
     59         return -1;
     60     } else if (result < 0 || floor(result + 0.5) != result) {
     61         return -2;
     62     }
     63     return static_cast<jint>(result);
     64 }
     65 
     66 static jboolean Character_isDefinedImpl(JNIEnv*, jclass, jint codePoint) {
     67     return u_isdefined(codePoint);
     68 }
     69 
     70 static jboolean Character_isDigitImpl(JNIEnv*, jclass, jint codePoint) {
     71     return u_isdigit(codePoint);
     72 }
     73 
     74 static jboolean Character_isIdentifierIgnorableImpl(JNIEnv*, jclass, jint codePoint) {
     75     return u_isIDIgnorable(codePoint);
     76 }
     77 
     78 static jboolean Character_isLetterImpl(JNIEnv*, jclass, jint codePoint) {
     79     return u_isalpha(codePoint);
     80 }
     81 
     82 static jboolean Character_isLetterOrDigitImpl(JNIEnv*, jclass, jint codePoint) {
     83     return u_isalnum(codePoint);
     84 }
     85 
     86 static jboolean Character_isSpaceCharImpl(JNIEnv*, jclass, jint codePoint) {
     87     return u_isJavaSpaceChar(codePoint);
     88 }
     89 
     90 static jboolean Character_isTitleCaseImpl(JNIEnv*, jclass, jint codePoint) {
     91     return u_istitle(codePoint);
     92 }
     93 
     94 static jboolean Character_isUnicodeIdentifierPartImpl(JNIEnv*, jclass, jint codePoint) {
     95     return u_isIDPart(codePoint);
     96 }
     97 
     98 static jboolean Character_isUnicodeIdentifierStartImpl(JNIEnv*, jclass, jint codePoint) {
     99     return u_isIDStart(codePoint);
    100 }
    101 
    102 static jboolean Character_isWhitespaceImpl(JNIEnv*, jclass, jint codePoint) {
    103     return u_isWhitespace(codePoint);
    104 }
    105 
    106 static jint Character_toLowerCaseImpl(JNIEnv*, jclass, jint codePoint) {
    107     return u_tolower(codePoint);
    108 }
    109 
    110 static jint Character_toTitleCaseImpl(JNIEnv*, jclass, jint codePoint) {
    111     return u_totitle(codePoint);
    112 }
    113 
    114 static jint Character_toUpperCaseImpl(JNIEnv*, jclass, jint codePoint) {
    115     return u_toupper(codePoint);
    116 }
    117 
    118 static jboolean Character_isUpperCaseImpl(JNIEnv*, jclass, jint codePoint) {
    119     return u_isupper(codePoint);
    120 }
    121 
    122 static jboolean Character_isLowerCaseImpl(JNIEnv*, jclass, jint codePoint) {
    123     return u_islower(codePoint);
    124 }
    125 
    126 static int Character_forNameImpl(JNIEnv* env, jclass, jstring javaBlockName) {
    127     ScopedUtfChars blockName(env, javaBlockName);
    128     if (blockName.c_str() == NULL) {
    129         return 0;
    130     }
    131     return u_getPropertyValueEnum(UCHAR_BLOCK, blockName.c_str());
    132 }
    133 
    134 static int Character_ofImpl(JNIEnv*, jclass, jint codePoint) {
    135     return ublock_getCode(codePoint);
    136 }
    137 
    138 static JNINativeMethod gMethods[] = {
    139     NATIVE_METHOD(Character, digitImpl, "!(II)I"),
    140     NATIVE_METHOD(Character, forNameImpl, "(Ljava/lang/String;)I"),
    141     NATIVE_METHOD(Character, getDirectionalityImpl, "!(I)B"),
    142     NATIVE_METHOD(Character, getNameImpl, "(I)Ljava/lang/String;"),
    143     NATIVE_METHOD(Character, getNumericValueImpl, "!(I)I"),
    144     NATIVE_METHOD(Character, getTypeImpl, "!(I)I"),
    145     NATIVE_METHOD(Character, isDefinedImpl, "!(I)Z"),
    146     NATIVE_METHOD(Character, isDigitImpl, "!(I)Z"),
    147     NATIVE_METHOD(Character, isIdentifierIgnorableImpl, "!(I)Z"),
    148     NATIVE_METHOD(Character, isLetterImpl, "!(I)Z"),
    149     NATIVE_METHOD(Character, isLetterOrDigitImpl, "!(I)Z"),
    150     NATIVE_METHOD(Character, isLowerCaseImpl, "!(I)Z"),
    151     NATIVE_METHOD(Character, isMirroredImpl, "!(I)Z"),
    152     NATIVE_METHOD(Character, isSpaceCharImpl, "!(I)Z"),
    153     NATIVE_METHOD(Character, isTitleCaseImpl, "!(I)Z"),
    154     NATIVE_METHOD(Character, isUnicodeIdentifierPartImpl, "!(I)Z"),
    155     NATIVE_METHOD(Character, isUnicodeIdentifierStartImpl, "!(I)Z"),
    156     NATIVE_METHOD(Character, isUpperCaseImpl, "!(I)Z"),
    157     NATIVE_METHOD(Character, isWhitespaceImpl, "!(I)Z"),
    158     NATIVE_METHOD(Character, ofImpl, "!(I)I"),
    159     NATIVE_METHOD(Character, toLowerCaseImpl, "!(I)I"),
    160     NATIVE_METHOD(Character, toTitleCaseImpl, "!(I)I"),
    161     NATIVE_METHOD(Character, toUpperCaseImpl, "!(I)I"),
    162 };
    163 void register_java_lang_Character(JNIEnv* env) {
    164     jniRegisterNativeMethods(env, "java/lang/Character", gMethods, NELEM(gMethods));
    165 }
    166