blob: abad16a01b9546d0278d36270434e4749445f674 [file] [log] [blame]
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "UCharacter"
#include "JNIHelp.h"
#include "ScopedJavaUnicodeString.h"
#include "ScopedUtfChars.h"
#include "unicode/locid.h"
#include "unicode/uchar.h"
#include <math.h>
#include <stdlib.h>
static jint digitImpl(JNIEnv*, jclass, jint codePoint, jint radix) {
return u_digit(codePoint, radix);
}
static jint getTypeImpl(JNIEnv*, jclass, jint codePoint) {
return u_charType(codePoint);
}
static jbyte getDirectionalityImpl(JNIEnv*, jclass, jint codePoint) {
return u_charDirection(codePoint);
}
static jboolean isMirroredImpl(JNIEnv*, jclass, jint codePoint) {
return u_isMirrored(codePoint);
}
static jint getNumericValueImpl(JNIEnv*, jclass, jint codePoint){
// The letters A-Z in their uppercase ('\u0041' through '\u005A'),
// lowercase ('\u0061' through '\u007A'),
// and full width variant ('\uFF21' through '\uFF3A'
// and '\uFF41' through '\uFF5A') forms
// have numeric values from 10 through 35. This is independent of the
// Unicode specification, which does not assign numeric values to these
// char values.
if (codePoint >= 0x41 && codePoint <= 0x5A) {
return codePoint - 0x37;
}
if (codePoint >= 0x61 && codePoint <= 0x7A) {
return codePoint - 0x57;
}
if (codePoint >= 0xFF21 && codePoint <= 0xFF3A) {
return codePoint - 0xFF17;
}
if (codePoint >= 0xFF41 && codePoint <= 0xFF5A) {
return codePoint - 0xFF37;
}
double result = u_getNumericValue(codePoint);
if (result == U_NO_NUMERIC_VALUE) {
return -1;
} else if (result < 0 || floor(result + 0.5) != result) {
return -2;
}
return result;
}
static jboolean isDefinedImpl(JNIEnv*, jclass, jint codePoint) {
return u_isdefined(codePoint);
}
static jboolean isDigitImpl(JNIEnv*, jclass, jint codePoint) {
return u_isdigit(codePoint);
}
static jboolean isIdentifierIgnorableImpl(JNIEnv*, jclass, jint codePoint) {
// Java also returns TRUE for U+0085 Next Line (it omits U+0085 from whitespace ISO controls)
if(codePoint == 0x0085) {
return JNI_TRUE;
}
return u_isIDIgnorable(codePoint);
}
static jboolean isLetterImpl(JNIEnv*, jclass, jint codePoint) {
return u_isalpha(codePoint);
}
static jboolean isLetterOrDigitImpl(JNIEnv*, jclass, jint codePoint) {
return u_isalnum(codePoint);
}
static jboolean isSpaceCharImpl(JNIEnv*, jclass, jint codePoint) {
return u_isJavaSpaceChar(codePoint);
}
static jboolean isTitleCaseImpl(JNIEnv*, jclass, jint codePoint) {
return u_istitle(codePoint);
}
static jboolean isUnicodeIdentifierPartImpl(JNIEnv*, jclass, jint codePoint) {
return u_isIDPart(codePoint);
}
static jboolean isUnicodeIdentifierStartImpl(JNIEnv*, jclass, jint codePoint) {
return u_isIDStart(codePoint);
}
static jboolean isWhitespaceImpl(JNIEnv*, jclass, jint codePoint) {
// Java omits U+0085
if(codePoint == 0x0085) {
return JNI_FALSE;
}
return u_isWhitespace(codePoint);
}
static jint toLowerCaseImpl(JNIEnv*, jclass, jint codePoint) {
return u_tolower(codePoint);
}
static jint toTitleCaseImpl(JNIEnv*, jclass, jint codePoint) {
return u_totitle(codePoint);
}
static jint toUpperCaseImpl(JNIEnv*, jclass, jint codePoint) {
return u_toupper(codePoint);
}
static jstring toLowerCaseStringImpl(JNIEnv* env, jclass, jstring javaString, jstring localeName) {
ScopedJavaUnicodeString scopedString(env, javaString);
UnicodeString& s(scopedString.unicodeString());
UnicodeString original(s);
s.toLower(Locale::createFromName(ScopedUtfChars(env, localeName).c_str()));
return s == original ? javaString : env->NewString(s.getBuffer(), s.length());
}
static jstring toUpperCaseStringImpl(JNIEnv* env, jclass, jstring javaString, jstring localeName) {
ScopedJavaUnicodeString scopedString(env, javaString);
UnicodeString& s(scopedString.unicodeString());
UnicodeString original(s);
s.toUpper(Locale::createFromName(ScopedUtfChars(env, localeName).c_str()));
return s == original ? javaString : env->NewString(s.getBuffer(), s.length());
}
static jboolean isUpperCaseImpl(JNIEnv*, jclass, jint codePoint) {
return u_isupper(codePoint);
}
static jboolean isLowerCaseImpl(JNIEnv*, jclass, jint codePoint) {
return u_islower(codePoint);
}
static int forNameImpl(JNIEnv* env, jclass, jstring blockName) {
if (blockName == NULL) {
jniThrowNullPointerException(env, NULL);
return -1;
}
const char* bName = env->GetStringUTFChars(blockName, NULL);
int result = u_getPropertyValueEnum(UCHAR_BLOCK, bName);
env->ReleaseStringUTFChars(blockName, bName);
return result;
}
static int ofImpl(JNIEnv*, jclass, jint codePoint) {
return ublock_getCode(codePoint);
}
static JNINativeMethod gMethods[] = {
{ "digit", "(II)I", (void*) digitImpl },
{ "forName", "(Ljava/lang/String;)I", (void*) forNameImpl },
{ "getDirectionality", "(I)B", (void*) getDirectionalityImpl },
{ "getNumericValue", "(I)I", (void*) getNumericValueImpl },
{ "getType", "(I)I", (void*) getTypeImpl },
{ "isDefined", "(I)Z", (void*) isDefinedImpl },
{ "isDigit", "(I)Z", (void*) isDigitImpl },
{ "isIdentifierIgnorable", "(I)Z", (void*) isIdentifierIgnorableImpl },
{ "isLetter", "(I)Z", (void*) isLetterImpl },
{ "isLetterOrDigit", "(I)Z", (void*) isLetterOrDigitImpl },
{ "isLowerCase", "(I)Z", (void*) isLowerCaseImpl },
{ "isMirrored", "(I)Z", (void*) isMirroredImpl },
{ "isSpaceChar", "(I)Z", (void*) isSpaceCharImpl },
{ "isTitleCase", "(I)Z", (void*) isTitleCaseImpl },
{ "isUnicodeIdentifierPart", "(I)Z", (void*) isUnicodeIdentifierPartImpl },
{ "isUnicodeIdentifierStart", "(I)Z", (void*) isUnicodeIdentifierStartImpl },
{ "isUpperCase", "(I)Z", (void*) isUpperCaseImpl },
{ "isWhitespace", "(I)Z", (void*) isWhitespaceImpl },
{ "of", "(I)I", (void*) ofImpl },
{ "toLowerCase", "(I)I", (void*) toLowerCaseImpl },
{ "toTitleCase", "(I)I", (void*) toTitleCaseImpl },
{ "toUpperCase", "(I)I", (void*) toUpperCaseImpl },
{ "toLowerCase", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void*) toLowerCaseStringImpl },
{ "toUpperCase", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void*) toUpperCaseStringImpl },
};
int register_com_ibm_icu4jni_lang_UCharacter(JNIEnv* env) {
return jniRegisterNativeMethods(env, "com/ibm/icu4jni/lang/UCharacter",
gMethods, NELEM(gMethods));
}