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