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