diff options
| author | 2018-11-27 12:40:23 +0000 | |
|---|---|---|
| committer | 2018-11-28 18:15:57 +0000 | |
| commit | c1463eccd4af9b52aa387c6475d29fcafe2228b7 (patch) | |
| tree | 2eb730cdf6dd68e104d07de38a8d418b0996ad09 | |
| parent | fb9335b8867eeeb6b26c6ad672dfa5a88b3f153f (diff) | |
Fix max directionality in AndroidCharacter.getDirectionalities
U_CHAR_DIRECTION_COUNT has been used for boundary check for conversion
of directionality between ICU and Libcore.
However, the max directionality in ICU has been incresed from 18 to 22 since Unicode 6.3
https://github.com/unicode-org/icu/commit/2982958b06e#diff-c46912f650de1f607d39dd8d81fb4b57
But the max directionality has not been chagned in libcore, and thus it
will return undefined value in directionality_map.
Also, this commit also replaces @Deprecated API U_EA_COUNT
by u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH).
Bug: 120073244
Bug: 117094880
Test: AndroidCharacterTest
Change-Id: I39918bdd4b06d0f1e95ad923594a28a0afc82b9e
| -rw-r--r-- | core/jni/android_text_AndroidCharacter.cpp | 14 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/text/AndroidCharacterTest.java | 77 |
2 files changed, 85 insertions, 6 deletions
diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp index 8885aac49064..9bba13a6930e 100644 --- a/core/jni/android_text_AndroidCharacter.cpp +++ b/core/jni/android_text_AndroidCharacter.cpp @@ -25,9 +25,10 @@ #include "unicode/uchar.h" #define PROPERTY_UNDEFINED (-1) +#define JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY 18 // ICU => JDK mapping -static int directionality_map[U_CHAR_DIRECTION_COUNT] = { +static int directionality_map[JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY + 1] = { 0, // U_LEFT_TO_RIGHT (0) => DIRECTIONALITY_LEFT_TO_RIGHT (0) 1, // U_RIGHT_TO_LEFT (1) => DIRECTIONALITY_RIGHT_TO_LEFT (1) 3, // U_EUROPEAN_NUMBER (2) => DIRECTIONALITY_EUROPEAN_NUMBER (3) @@ -75,7 +76,7 @@ static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray, int c = 0x00010000 + ((src[i] - 0xD800) << 10) + (src[i + 1] & 0x3FF); int dir = u_charDirection(c); - if (dir < 0 || dir >= U_CHAR_DIRECTION_COUNT) + if (dir < 0 || dir > JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY) dir = PROPERTY_UNDEFINED; else dir = directionality_map[dir]; @@ -85,7 +86,7 @@ static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray, } else { int c = src[i]; int dir = u_charDirection(c); - if (dir < 0 || dir >= U_CHAR_DIRECTION_COUNT) + if (dir < 0 || dir > JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY) dest[i] = PROPERTY_UNDEFINED; else dest[i] = directionality_map[dir]; @@ -96,7 +97,7 @@ static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray, static jint getEastAsianWidth(JNIEnv* env, jobject obj, jchar input) { int width = u_getIntPropertyValue(input, UCHAR_EAST_ASIAN_WIDTH); - if (width < 0 || width >= U_EA_COUNT) + if (width < 0 || width > u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH)) width = PROPERTY_UNDEFINED; return width; @@ -121,6 +122,7 @@ static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray, return; } + int maxWidth = u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH); for (int i = 0; i < count; i++) { const int srci = start + i; if (src[srci] >= 0xD800 && src[srci] <= 0xDBFF && @@ -129,7 +131,7 @@ static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray, int c = 0x00010000 + ((src[srci] - 0xD800) << 10) + (src[srci + 1] & 0x3FF); int width = u_getIntPropertyValue(c, UCHAR_EAST_ASIAN_WIDTH); - if (width < 0 || width >= U_EA_COUNT) + if (width < 0 || width > maxWidth) width = PROPERTY_UNDEFINED; dest[i++] = width; @@ -137,7 +139,7 @@ static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray, } else { int c = src[srci]; int width = u_getIntPropertyValue(c, UCHAR_EAST_ASIAN_WIDTH); - if (width < 0 || width >= U_EA_COUNT) + if (width < 0 || width > maxWidth) width = PROPERTY_UNDEFINED; dest[i] = width; diff --git a/core/tests/coretests/src/android/text/AndroidCharacterTest.java b/core/tests/coretests/src/android/text/AndroidCharacterTest.java new file mode 100644 index 000000000000..d976adb14ef3 --- /dev/null +++ b/core/tests/coretests/src/android/text/AndroidCharacterTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2018 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,d + * 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. + */ + +package android.text; + +import static org.junit.Assert.assertArrayEquals; + +import android.platform.test.annotations.Presubmit; +import android.support.test.filters.SmallTest; + +import org.junit.Test; + +@Presubmit +@SmallTest +public class AndroidCharacterTest { + + @Test + public void testGetDirectionalities_nonSupplementaryCharacters() { + int size = Character.MAX_VALUE + 1 + - (Character.MAX_SURROGATE - Character.MIN_SURROGATE + 1); + char[] chars = new char[size]; + byte[] java_lang_results = new byte[size]; + int index = 0; + for (int cp = 0; cp <= Character.MAX_VALUE; cp++) { + // Exempt unassigned code point due to b/120074586 + if (Character.getType(cp) != Character.UNASSIGNED) { + if (cp < Character.MIN_SURROGATE || cp > Character.MAX_SURROGATE) { + chars[index] = (char) cp; + java_lang_results[index] = Character.getDirectionality(cp); + index++; + } + } + } + + byte[] android_text_results = new byte[size]; + AndroidCharacter.getDirectionalities(chars, android_text_results, index); + assertArrayEquals(java_lang_results, android_text_results); + } + + @Test + public void testGetDirectionalities_supplementaryCharacters() { + int maxNumberOfChars = Character.MAX_CODE_POINT - Character.MIN_SUPPLEMENTARY_CODE_POINT + + 1; + int size = maxNumberOfChars * 2; + char[] chars = new char[size]; + byte[] java_lang_results = new byte[size]; + int index = 0; + for (int cp = Character.MIN_SUPPLEMENTARY_CODE_POINT; cp <= Character.MAX_CODE_POINT; + cp++) { + // Exempt unassigned code point due to b/120074586 + if (Character.getType(cp) != Character.UNASSIGNED) { + chars[index] = Character.highSurrogate(cp); + chars[index + 1] = Character.lowSurrogate(cp); + java_lang_results[index] = java_lang_results[index + 1] = Character + .getDirectionality(cp); + index += 2; + } + } + + byte[] android_text_results = new byte[size]; + AndroidCharacter.getDirectionalities(chars, android_text_results, index); + assertArrayEquals(java_lang_results, android_text_results); + } +} |