Merge "CertPathSpi: fix encoding arg name"
diff --git a/luni/src/main/java/libcore/icu/AlphabeticIndex.java b/luni/src/main/java/libcore/icu/AlphabeticIndex.java
index 534e14a..efd45e9 100644
--- a/luni/src/main/java/libcore/icu/AlphabeticIndex.java
+++ b/luni/src/main/java/libcore/icu/AlphabeticIndex.java
@@ -22,6 +22,56 @@
* Exposes icu4c's AlphabeticIndex.
*/
public final class AlphabeticIndex {
+
+ /**
+ * Exposes icu4c's ImmutableIndex (new to icu 51). This exposes a read-only,
+ * thread safe snapshot view of an AlphabeticIndex at the moment it was
+ * created, and allows for random access to buckets by index.
+ */
+ public static final class ImmutableIndex {
+ private long peer;
+
+ private ImmutableIndex(long peer) {
+ this.peer = peer;
+ }
+
+ @Override protected synchronized void finalize() throws Throwable {
+ try {
+ destroy(peer);
+ peer = 0;
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * Returns the number of the label buckets in this index.
+ */
+ public int getBucketCount() {
+ return getBucketCount(peer);
+ }
+
+ /**
+ * Returns the index of the bucket in which 's' should appear.
+ * Function is synchronized because underlying routine walks an iterator
+ * whose state is maintained inside the index object.
+ */
+ public int getBucketIndex(String s) {
+ return getBucketIndex(peer, s);
+ }
+
+ /**
+ * Returns the label for the bucket at the given index (as returned by getBucketIndex).
+ */
+ public String getBucketLabel(int index) {
+ return getBucketLabel(peer, index);
+ }
+
+ private static native int getBucketCount(long peer);
+ private static native int getBucketIndex(long peer, String s);
+ private static native String getBucketLabel(long peer, int index);
+ }
+
private long peer;
/**
@@ -48,16 +98,18 @@
* it remains that of the locale that was originally specified
* when creating this index.
*/
- public synchronized void addLabels(Locale locale) {
+ public synchronized AlphabeticIndex addLabels(Locale locale) {
addLabels(peer, locale.toString());
+ return this;
}
/**
* Adds the index characters in the range between the specified start and
* end code points, inclusive.
*/
- public synchronized void addLabelRange(int codePointStart, int codePointEnd) {
+ public synchronized AlphabeticIndex addLabelRange(int codePointStart, int codePointEnd) {
addLabelRange(peer, codePointStart, codePointEnd);
+ return this;
}
/**
@@ -79,10 +131,17 @@
/**
* Returns the label for the bucket at the given index (as returned by getBucketIndex).
*/
- public String getBucketLabel(int index) {
+ public synchronized String getBucketLabel(int index) {
return getBucketLabel(peer, index);
}
+ /**
+ * Returns an ImmutableIndex created from this AlphabeticIndex.
+ */
+ public synchronized ImmutableIndex getImmutableIndex() {
+ return new ImmutableIndex(buildImmutableIndex(peer));
+ }
+
private static native long create(String locale);
private static native void destroy(long peer);
private static native void addLabels(long peer, String locale);
@@ -90,4 +149,5 @@
private static native int getBucketCount(long peer);
private static native int getBucketIndex(long peer, String s);
private static native String getBucketLabel(long peer, int index);
+ private static native long buildImmutableIndex(long peer);
}
diff --git a/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp b/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
index bda80c0..b815853 100644
--- a/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
+++ b/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
@@ -113,6 +113,56 @@
return env->NewString(label.getBuffer(), label.length());
}
+static jlong AlphabeticIndex_buildImmutableIndex(JNIEnv* env, jclass, jlong peer) {
+ AlphabeticIndex* ai = fromPeer(peer);
+ UErrorCode status = U_ZERO_ERROR;
+ AlphabeticIndex::ImmutableIndex* ii = ai->buildImmutableIndex(status);
+ if (maybeThrowIcuException(env, "AlphabeticIndex::buildImmutableIndex", status)) {
+ return 0;
+ }
+ return reinterpret_cast<uintptr_t>(ii);
+}
+
+static AlphabeticIndex::ImmutableIndex* immutableIndexFromPeer(jlong peer) {
+ return reinterpret_cast<AlphabeticIndex::ImmutableIndex*>(static_cast<uintptr_t>(peer));
+}
+
+static jint ImmutableIndex_getBucketCount(JNIEnv*, jclass, jlong peer) {
+ AlphabeticIndex::ImmutableIndex* ii = immutableIndexFromPeer(peer);
+ return ii->getBucketCount();
+}
+
+static jint ImmutableIndex_getBucketIndex(JNIEnv* env, jclass, jlong peer, jstring javaString) {
+ AlphabeticIndex::ImmutableIndex* ii = immutableIndexFromPeer(peer);
+ ScopedJavaUnicodeString string(env, javaString);
+ if (!string.valid()) {
+ return -1;
+ }
+ UErrorCode status = U_ZERO_ERROR;
+ jint result = ii->getBucketIndex(string.unicodeString(), status);
+ if (maybeThrowIcuException(env, "AlphabeticIndex::ImmutableIndex::getBucketIndex", status)) {
+ return -1;
+ }
+ return result;
+}
+
+static jstring ImmutableIndex_getBucketLabel(JNIEnv* env, jclass, jlong peer, jint index) {
+ AlphabeticIndex::ImmutableIndex* ii = immutableIndexFromPeer(peer);
+ const AlphabeticIndex::Bucket* bucket = ii->getBucket(index);
+ if (bucket == NULL) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "Invalid index: %d", index);
+ return NULL;
+ }
+
+ // Return "" for the underflow/inflow/overflow buckets.
+ if (bucket->getLabelType() != U_ALPHAINDEX_NORMAL) {
+ return env->NewStringUTF("");
+ }
+
+ const UnicodeString& label(bucket->getLabel());
+ return env->NewString(label.getBuffer(), label.length());
+}
+
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(AlphabeticIndex, create, "(Ljava/lang/String;)J"),
NATIVE_METHOD(AlphabeticIndex, destroy, "(J)V"),
@@ -121,7 +171,14 @@
NATIVE_METHOD(AlphabeticIndex, getBucketCount, "(J)I"),
NATIVE_METHOD(AlphabeticIndex, getBucketIndex, "(JLjava/lang/String;)I"),
NATIVE_METHOD(AlphabeticIndex, getBucketLabel, "(JI)Ljava/lang/String;"),
+ NATIVE_METHOD(AlphabeticIndex, buildImmutableIndex, "(J)J"),
+};
+static JNINativeMethod gImmutableIndexMethods[] = {
+ NATIVE_METHOD(ImmutableIndex, getBucketCount, "(J)I"),
+ NATIVE_METHOD(ImmutableIndex, getBucketIndex, "(JLjava/lang/String;)I"),
+ NATIVE_METHOD(ImmutableIndex, getBucketLabel, "(JI)Ljava/lang/String;"),
};
void register_libcore_icu_AlphabeticIndex(JNIEnv* env) {
jniRegisterNativeMethods(env, "libcore/icu/AlphabeticIndex", gMethods, NELEM(gMethods));
+ jniRegisterNativeMethods(env, "libcore/icu/AlphabeticIndex$ImmutableIndex", gImmutableIndexMethods, NELEM(gImmutableIndexMethods));
}
diff --git a/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java b/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java
index e4b90ea..c1f73eb 100644
--- a/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java
+++ b/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java
@@ -19,22 +19,26 @@
import java.util.Locale;
public class AlphabeticIndexTest extends junit.framework.TestCase {
- private static void assertHasLabel(AlphabeticIndex ai, String string, String expectedLabel) {
- ai.addLabels(Locale.US);
- int index = ai.getBucketIndex(string);
- String label = ai.getBucketLabel(index);
+ private static AlphabeticIndex.ImmutableIndex createIndex(Locale locale) {
+ return new AlphabeticIndex(locale).addLabels(Locale.US)
+ .getImmutableIndex();
+ }
+
+ private static void assertHasLabel(AlphabeticIndex.ImmutableIndex ii, String string, String expectedLabel) {
+ int index = ii.getBucketIndex(string);
+ String label = ii.getBucketLabel(index);
assertEquals(expectedLabel, label);
}
public void test_en() throws Exception {
// English [A-Z]
- AlphabeticIndex en = new AlphabeticIndex(Locale.ENGLISH);
+ AlphabeticIndex.ImmutableIndex en = createIndex(Locale.ENGLISH);
assertHasLabel(en, "Allen", "A");
assertHasLabel(en, "allen", "A");
}
public void test_ja() throws Exception {
- AlphabeticIndex ja = new AlphabeticIndex(Locale.JAPANESE);
+ AlphabeticIndex.ImmutableIndex ja = createIndex(Locale.JAPANESE);
// Japanese
// sorts hiragana/katakana, Kanji/Chinese, English, other
@@ -61,7 +65,7 @@
public void test_ko() throws Exception {
// Korean (sorts Korean, then English)
// …, ᄀ, ᄂ, ᄃ, ᄅ, ᄆ, ᄇ, ᄉ, ᄋ, ᄌ, ᄎ, ᄏ, ᄐ, ᄑ, ᄒ, …
- AlphabeticIndex ko = new AlphabeticIndex(Locale.KOREAN);
+ AlphabeticIndex.ImmutableIndex ko = createIndex(Locale.KOREAN);
assertHasLabel(ko, "\u1100", "\u1100");
assertHasLabel(ko, "\u3131", "\u1100");
assertHasLabel(ko, "\u1101", "\u1100");
@@ -71,7 +75,7 @@
public void test_cs() throws Exception {
// Czech
// …, [A-C], Č,[D-H], CH, [I-R], Ř, S, Š, [T-Z], Ž, …
- AlphabeticIndex cs = new AlphabeticIndex(new Locale("cs"));
+ AlphabeticIndex.ImmutableIndex cs = createIndex(new Locale("cs"));
assertHasLabel(cs, "Cena", "C");
assertHasLabel(cs, "Čáp", "\u010c");
assertHasLabel(cs, "Ruda", "R");
@@ -85,14 +89,14 @@
public void test_fr() throws Exception {
// French: [A-Z] (no accented chars)
- AlphabeticIndex fr = new AlphabeticIndex(Locale.FRENCH);
+ AlphabeticIndex.ImmutableIndex fr = createIndex(Locale.FRENCH);
assertHasLabel(fr, "Øfer", "O");
assertHasLabel(fr, "Œster", "O");
}
public void test_da() throws Exception {
// Danish: [A-Z], Æ, Ø, Å
- AlphabeticIndex da = new AlphabeticIndex(new Locale("da"));
+ AlphabeticIndex.ImmutableIndex da = createIndex(new Locale("da"));
assertHasLabel(da, "Ænes", "\u00c6");
assertHasLabel(da, "Øfer", "\u00d8");
assertHasLabel(da, "Œster", "\u00d8");
@@ -101,14 +105,14 @@
public void test_de() throws Exception {
// German: [A-Z] (no ß or umlauted characters in standard alphabet)
- AlphabeticIndex de = new AlphabeticIndex(Locale.GERMAN);
+ AlphabeticIndex.ImmutableIndex de = createIndex(Locale.GERMAN);
assertHasLabel(de, "ßind", "S");
}
public void test_th() throws Exception {
// Thai (sorts English then Thai)
// …, ก, ข, ฃ, ค, ฅ, ฆ, ง, จ, ฉ, ช, ซ, ฌ, ญ, ฎ, ฏ, ฐ, ฑ, ฒ, ณ, ด, ต, ถ, ท, ธ, น, บ, ป, ผ, ฝ, พ, ฟ, ภ, ม, ย, ร, ฤ, ล, ฦ, ว, ศ, ษ, ส, ห, ฬ, อ, ฮ, …,
- AlphabeticIndex th = new AlphabeticIndex(new Locale("th"));
+ AlphabeticIndex.ImmutableIndex th = createIndex(new Locale("th"));
assertHasLabel(th, "\u0e2d\u0e07\u0e04\u0e4c\u0e40\u0e25\u0e47\u0e01", "\u0e2d");
assertHasLabel(th, "\u0e2a\u0e34\u0e07\u0e2b\u0e40\u0e2a\u0e19\u0e35", "\u0e2a");
}
@@ -116,21 +120,21 @@
public void test_ar() throws Exception {
// Arabic (sorts English then Arabic)
// …, ا, ب, ت, ث, ج, ح, خ, د, ذ, ر, ز, س, ش, ص, ض, ط, ظ, ع, غ, ف, ق, ك, ل, م, ن, ه, و, ي, …
- AlphabeticIndex ar = new AlphabeticIndex(new Locale("ar"));
+ AlphabeticIndex.ImmutableIndex ar = createIndex(new Locale("ar"));
assertHasLabel(ar, "\u0646\u0648\u0631", /* Noor */ "\u0646");
}
public void test_he() throws Exception {
// Hebrew (sorts English then Hebrew)
// …, א, ב, ג, ד, ה, ו, ז, ח, ט, י, כ, ל, מ, נ, ס, ע, פ, צ, ק, ר, ש, ת, …
- AlphabeticIndex he = new AlphabeticIndex(new Locale("he"));
+ AlphabeticIndex.ImmutableIndex he = createIndex(new Locale("he"));
assertHasLabel(he, "\u05e4\u05e8\u05d9\u05d3\u05de\u05df", "\u05e4");
}
public void test_zh_CN() throws Exception {
// Simplified Chinese (default collator Pinyin): [A-Z]
// Shen/Chen (simplified): should be, usually, 'S' for name collator and 'C' for apps/other
- AlphabeticIndex zh_CN = new AlphabeticIndex(new Locale("zh", "CN"));
+ AlphabeticIndex.ImmutableIndex zh_CN = createIndex(new Locale("zh", "CN"));
// Jia/Gu: should be, usually, 'J' for name collator and 'G' for apps/other
assertHasLabel(zh_CN, "\u8d3e", "J");
@@ -145,7 +149,7 @@
// Traditional Chinese
// …, 一, 丁, 丈, 不, 且, 丞, 串, 並, 亭, 乘, 乾, 傀, 亂, 僎, 僵, 儐, 償, 叢, 儳, 嚴, 儷, 儻, 囌, 囑, 廳, …
// Shen/Chen
- AlphabeticIndex zh_TW = new AlphabeticIndex(new Locale("zh", "TW"));
+ AlphabeticIndex.ImmutableIndex zh_TW = createIndex(new Locale("zh", "TW"));
assertHasLabel(zh_TW, "\u6c88", "\u4e32");
assertHasLabel(zh_TW, "\u700b", "\u53e2");
// Jia/Gu
@@ -170,24 +174,24 @@
}
public void test_getBucketIndex_NPE() throws Exception {
- AlphabeticIndex ai = new AlphabeticIndex(Locale.US);
+ AlphabeticIndex.ImmutableIndex ii = createIndex(Locale.US);
try {
- ai.getBucketIndex(null);
+ ii.getBucketIndex(null);
fail();
} catch (NullPointerException expected) {
}
}
public void test_getBucketLabel_invalid() throws Exception {
- AlphabeticIndex ai = new AlphabeticIndex(Locale.US);
+ AlphabeticIndex.ImmutableIndex ii = createIndex(Locale.US);
try {
- ai.getBucketLabel(-1);
+ ii.getBucketLabel(-1);
fail();
} catch (IllegalArgumentException expected) {
}
try {
- ai.getBucketLabel(123456);
+ ii.getBucketLabel(123456);
fail();
} catch (IllegalArgumentException expected) {
}