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