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 #include "JNIHelp.h" 18 #include "AndroidSystemNatives.h" 19 #include "unicode/uchar.h" 20 #include <math.h> 21 #include <stdlib.h> 22 23 static jint digitImpl(JNIEnv*, jclass, jint codePoint, jint radix) { 24 return u_digit(codePoint, radix); 25 } 26 27 static jint getTypeImpl(JNIEnv*, jclass, jint codePoint) { 28 return u_charType(codePoint); 29 } 30 31 static jbyte getDirectionalityImpl(JNIEnv*, jclass, jint codePoint) { 32 return u_charDirection(codePoint); 33 } 34 35 static jboolean isMirroredImpl(JNIEnv*, jclass, jint codePoint) { 36 return u_isMirrored(codePoint); 37 } 38 39 static jint getNumericValueImpl(JNIEnv*, jclass, jint codePoint){ 40 // The letters A-Z in their uppercase ('\u0041' through '\u005A'), 41 // lowercase ('\u0061' through '\u007A'), 42 // and full width variant ('\uFF21' through '\uFF3A' 43 // and '\uFF41' through '\uFF5A') forms 44 // have numeric values from 10 through 35. This is independent of the 45 // Unicode specification, which does not assign numeric values to these 46 // char values. 47 if (codePoint >= 0x41 && codePoint <= 0x5A) { 48 return codePoint - 0x37; 49 } 50 if (codePoint >= 0x61 && codePoint <= 0x7A) { 51 return codePoint - 0x57; 52 } 53 if (codePoint >= 0xFF21 && codePoint <= 0xFF3A) { 54 return codePoint - 0xFF17; 55 } 56 if (codePoint >= 0xFF41 && codePoint <= 0xFF5A) { 57 return codePoint - 0xFF37; 58 } 59 60 double result = u_getNumericValue(codePoint); 61 62 if (result == U_NO_NUMERIC_VALUE) { 63 return -1; 64 } else if (result < 0 || floor(result + 0.5) != result) { 65 return -2; 66 } 67 68 return result; 69 } 70 71 static jboolean isDefinedImpl(JNIEnv*, jclass, jint codePoint) { 72 return u_isdefined(codePoint); 73 } 74 75 static jboolean isDigitImpl(JNIEnv*, jclass, jint codePoint) { 76 return u_isdigit(codePoint); 77 } 78 79 static jboolean isIdentifierIgnorableImpl(JNIEnv*, jclass, jint codePoint) { 80 // Java also returns TRUE for U+0085 Next Line (it omits U+0085 from whitespace ISO controls) 81 if(codePoint == 0x0085) { 82 return JNI_TRUE; 83 } 84 return u_isIDIgnorable(codePoint); 85 } 86 87 static jboolean isLetterImpl(JNIEnv*, jclass, jint codePoint) { 88 return u_isalpha(codePoint); 89 } 90 91 static jboolean isLetterOrDigitImpl(JNIEnv*, jclass, jint codePoint) { 92 return u_isalnum(codePoint); 93 } 94 95 static jboolean isSpaceCharImpl(JNIEnv*, jclass, jint codePoint) { 96 return u_isJavaSpaceChar(codePoint); 97 } 98 99 static jboolean isTitleCaseImpl(JNIEnv*, jclass, jint codePoint) { 100 return u_istitle(codePoint); 101 } 102 103 static jboolean isUnicodeIdentifierPartImpl(JNIEnv*, jclass, jint codePoint) { 104 return u_isIDPart(codePoint); 105 } 106 107 static jboolean isUnicodeIdentifierStartImpl(JNIEnv*, jclass, jint codePoint) { 108 return u_isIDStart(codePoint); 109 } 110 111 static jboolean isWhitespaceImpl(JNIEnv*, jclass, jint codePoint) { 112 // Java omits U+0085 113 if(codePoint == 0x0085) { 114 return JNI_FALSE; 115 } 116 return u_isWhitespace(codePoint); 117 } 118 119 static jint toLowerCaseImpl(JNIEnv*, jclass, jint codePoint) { 120 return u_tolower(codePoint); 121 } 122 123 static jint toTitleCaseImpl(JNIEnv*, jclass, jint codePoint) { 124 return u_totitle(codePoint); 125 } 126 127 static jint toUpperCaseImpl(JNIEnv*, jclass, jint codePoint) { 128 return u_toupper(codePoint); 129 } 130 131 static jboolean isUpperCaseImpl(JNIEnv*, jclass, jint codePoint) { 132 return u_isupper(codePoint); 133 } 134 135 static jboolean isLowerCaseImpl(JNIEnv*, jclass, jint codePoint) { 136 return u_islower(codePoint); 137 } 138 139 static int forNameImpl(JNIEnv* env, jclass, jstring blockName) { 140 if (blockName == NULL) { 141 jniThrowNullPointerException(env, NULL); 142 return -1; 143 } 144 const char* bName = env->GetStringUTFChars(blockName, NULL); 145 int result = u_getPropertyValueEnum(UCHAR_BLOCK, bName); 146 env->ReleaseStringUTFChars(blockName, bName); 147 return result; 148 } 149 150 static int ofImpl(JNIEnv*, jclass, jint codePoint) { 151 return ublock_getCode(codePoint); 152 } 153 154 /* 155 * JNI registration 156 */ 157 static JNINativeMethod gMethods[] = { 158 /* name, signature, funcPtr */ 159 { "digit", "(II)I", (void*) digitImpl }, 160 { "forName", "(Ljava/lang/String;)I", (void*) forNameImpl }, 161 { "getDirectionality", "(I)B", (void*) getDirectionalityImpl }, 162 { "getNumericValue", "(I)I", (void*) getNumericValueImpl }, 163 { "getType", "(I)I", (void*) getTypeImpl }, 164 { "isDefined", "(I)Z", (void*) isDefinedImpl }, 165 { "isDigit", "(I)Z", (void*) isDigitImpl }, 166 { "isIdentifierIgnorable", "(I)Z", (void*) isIdentifierIgnorableImpl }, 167 { "isLetter", "(I)Z", (void*) isLetterImpl }, 168 { "isLetterOrDigit", "(I)Z", (void*) isLetterOrDigitImpl }, 169 { "isLowerCase", "(I)Z", (void*) isLowerCaseImpl }, 170 { "isMirrored", "(I)Z", (void*) isMirroredImpl }, 171 { "isSpaceChar", "(I)Z", (void*) isSpaceCharImpl }, 172 { "isTitleCase", "(I)Z", (void*) isTitleCaseImpl }, 173 { "isUnicodeIdentifierPart", "(I)Z", (void*) isUnicodeIdentifierPartImpl }, 174 { "isUnicodeIdentifierStart", "(I)Z", (void*) isUnicodeIdentifierStartImpl }, 175 { "isUpperCase", "(I)Z", (void*) isUpperCaseImpl }, 176 { "isWhitespace", "(I)Z", (void*) isWhitespaceImpl }, 177 { "of", "(I)I", (void*) ofImpl }, 178 { "toLowerCase", "(I)I", (void*) toLowerCaseImpl }, 179 { "toTitleCase", "(I)I", (void*) toTitleCaseImpl }, 180 { "toUpperCase", "(I)I", (void*) toUpperCaseImpl }, 181 }; 182 183 int register_com_ibm_icu4jni_lang_UCharacter(JNIEnv* env) { 184 return jniRegisterNativeMethods(env, "com/ibm/icu4jni/lang/UCharacter", 185 gMethods, NELEM(gMethods)); 186 } 187