• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Character_digitImpl(JNIEnv *,jclass,jint codePoint,jint radix)26 static jint Character_digitImpl(JNIEnv*, jclass, jint codePoint, jint radix) {
27     return u_digit(codePoint, radix);
28 }
29 
Character_getTypeImpl(JNIEnv *,jclass,jint codePoint)30 static jint Character_getTypeImpl(JNIEnv*, jclass, jint codePoint) {
31     return u_charType(codePoint);
32 }
33 
Character_getDirectionalityImpl(JNIEnv *,jclass,jint codePoint)34 static jbyte Character_getDirectionalityImpl(JNIEnv*, jclass, jint codePoint) {
35     return u_charDirection(codePoint);
36 }
37 
Character_isMirroredImpl(JNIEnv *,jclass,jint codePoint)38 static jboolean Character_isMirroredImpl(JNIEnv*, jclass, jint codePoint) {
39     return u_isMirrored(codePoint);
40 }
41 
Character_getNameImpl(JNIEnv * env,jclass,jint codePoint)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 
Character_getNumericValueImpl(JNIEnv *,jclass,jint codePoint)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 
Character_isDefinedImpl(JNIEnv *,jclass,jint codePoint)66 static jboolean Character_isDefinedImpl(JNIEnv*, jclass, jint codePoint) {
67     return u_isdefined(codePoint);
68 }
69 
Character_isDigitImpl(JNIEnv *,jclass,jint codePoint)70 static jboolean Character_isDigitImpl(JNIEnv*, jclass, jint codePoint) {
71     return u_isdigit(codePoint);
72 }
73 
Character_isIdentifierIgnorableImpl(JNIEnv *,jclass,jint codePoint)74 static jboolean Character_isIdentifierIgnorableImpl(JNIEnv*, jclass, jint codePoint) {
75     return u_isIDIgnorable(codePoint);
76 }
77 
Character_isLetterImpl(JNIEnv *,jclass,jint codePoint)78 static jboolean Character_isLetterImpl(JNIEnv*, jclass, jint codePoint) {
79     return u_isalpha(codePoint);
80 }
81 
Character_isLetterOrDigitImpl(JNIEnv *,jclass,jint codePoint)82 static jboolean Character_isLetterOrDigitImpl(JNIEnv*, jclass, jint codePoint) {
83     return u_isalnum(codePoint);
84 }
85 
Character_isSpaceCharImpl(JNIEnv *,jclass,jint codePoint)86 static jboolean Character_isSpaceCharImpl(JNIEnv*, jclass, jint codePoint) {
87     return u_isJavaSpaceChar(codePoint);
88 }
89 
Character_isTitleCaseImpl(JNIEnv *,jclass,jint codePoint)90 static jboolean Character_isTitleCaseImpl(JNIEnv*, jclass, jint codePoint) {
91     return u_istitle(codePoint);
92 }
93 
Character_isUnicodeIdentifierPartImpl(JNIEnv *,jclass,jint codePoint)94 static jboolean Character_isUnicodeIdentifierPartImpl(JNIEnv*, jclass, jint codePoint) {
95     return u_isIDPart(codePoint);
96 }
97 
Character_isUnicodeIdentifierStartImpl(JNIEnv *,jclass,jint codePoint)98 static jboolean Character_isUnicodeIdentifierStartImpl(JNIEnv*, jclass, jint codePoint) {
99     return u_isIDStart(codePoint);
100 }
101 
Character_isWhitespaceImpl(JNIEnv *,jclass,jint codePoint)102 static jboolean Character_isWhitespaceImpl(JNIEnv*, jclass, jint codePoint) {
103     return u_isWhitespace(codePoint);
104 }
105 
Character_toLowerCaseImpl(JNIEnv *,jclass,jint codePoint)106 static jint Character_toLowerCaseImpl(JNIEnv*, jclass, jint codePoint) {
107     return u_tolower(codePoint);
108 }
109 
Character_toTitleCaseImpl(JNIEnv *,jclass,jint codePoint)110 static jint Character_toTitleCaseImpl(JNIEnv*, jclass, jint codePoint) {
111     return u_totitle(codePoint);
112 }
113 
Character_toUpperCaseImpl(JNIEnv *,jclass,jint codePoint)114 static jint Character_toUpperCaseImpl(JNIEnv*, jclass, jint codePoint) {
115     return u_toupper(codePoint);
116 }
117 
Character_isUpperCaseImpl(JNIEnv *,jclass,jint codePoint)118 static jboolean Character_isUpperCaseImpl(JNIEnv*, jclass, jint codePoint) {
119     return u_isupper(codePoint);
120 }
121 
Character_isLowerCaseImpl(JNIEnv *,jclass,jint codePoint)122 static jboolean Character_isLowerCaseImpl(JNIEnv*, jclass, jint codePoint) {
123     return u_islower(codePoint);
124 }
125 
Character_forNameImpl(JNIEnv * env,jclass,jstring javaBlockName)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 
Character_ofImpl(JNIEnv *,jclass,jint codePoint)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 };
register_java_lang_Character(JNIEnv * env)163 void register_java_lang_Character(JNIEnv* env) {
164     jniRegisterNativeMethods(env, "java/lang/Character", gMethods, NELEM(gMethods));
165 }
166