From 18a494570872b0b6effe85957f21459f79de0b56 Mon Sep 17 00:00:00 2001 From: Tatsunori Uchino Date: Thu, 24 Jul 2025 23:43:34 +0900 Subject: [PATCH 01/10] 8364007: Add overload without arguments to codePointCount in String etc. --- .../java/lang/AbstractStringBuilder.java | 18 +++++++++ .../share/classes/java/lang/Character.java | 37 +++++++++++++++++++ .../share/classes/java/lang/String.java | 15 ++++++++ .../share/classes/java/lang/StringBuffer.java | 8 ++++ .../classes/java/util/regex/Pattern.java | 4 +- .../jdk/internal/icu/impl/NormalizerImpl.java | 4 +- .../internal/xsltc/runtime/BasisLibrary.java | 4 +- .../jdk/internal/org/jline/keymap/KeyMap.java | 2 +- .../com/sun/tools/jdeps/JdepsTask.java | 4 +- .../jdk/jpackage/internal/Arguments.java | 2 +- .../java/lang/Character/Supplementary.java | 12 +++++- test/jdk/java/lang/String/Supplementary.java | 8 +++- .../lang/StringBuilder/Supplementary.java | 11 ++++-- 13 files changed, 112 insertions(+), 17 deletions(-) diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index d317557cbb19c..7390bc76b43ae 100644 --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -529,6 +529,24 @@ public int codePointCount(int beginIndex, int endIndex) { return StringUTF16.codePointCountSB(value, beginIndex, endIndex); } + /** + * Returns the number of Unicode code points in + * this sequence. Unpaired surrogates count + * as one code point each. + * + * @return the number of Unicode code points in this String + * @since 26 + */ + public int codePointCount() { + byte coder = this.coder; + int count = this.count; + byte[] value = this.value; + if (isLatin1(coder)) { + return value.length; + } + return StringUTF16.codePointCount(value, count, value.length >> 1); + } + /** * Returns the index within this sequence that is offset from the * given {@code index} by {@code codePointOffset} code diff --git a/src/java.base/share/classes/java/lang/Character.java b/src/java.base/share/classes/java/lang/Character.java index a439a90761d48..e67dff896333f 100644 --- a/src/java.base/share/classes/java/lang/Character.java +++ b/src/java.base/share/classes/java/lang/Character.java @@ -9952,6 +9952,29 @@ public static int codePointCount(CharSequence seq, int beginIndex, int endIndex) return n; } + /** + * Returns the number of Unicode code points in the text range of + * the specified char sequence. Unpaired surrogates count as one + * code point each. + * + * @param seq the char sequence + * @return the number of Unicode code points in the char sequence + * @throws NullPointerException if {@code seq} is null. + * @since 26 + */ + public static int codePointCount(CharSequence seq) { + final int length = seq.length(); + int n = length; + for (int i = 0; i < length; ) { + if (isHighSurrogate(seq.charAt(i++)) && i < length && + isLowSurrogate(seq.charAt(i))) { + n--; + i++; + } + } + return n; + } + /** * Returns the number of Unicode code points in a subarray of the * {@code char} array argument. The {@code offset} @@ -9976,6 +9999,20 @@ public static int codePointCount(char[] a, int offset, int count) { return codePointCountImpl(a, offset, count); } + /** + * Returns the number of Unicode code points in the + * {@code char} array argument. Unpaired + * surrogates count as one code point each. + * + * @param a the {@code char} array + * @return the number of Unicode code points in the char array + * @throws NullPointerException if {@code a} is null. + * @since 26 + */ + public static int codePointCount(char[] a) { + return codePointCountImpl(a, 0, a.length); + } + static int codePointCountImpl(char[] a, int offset, int count) { int endIndex = offset + count; int n = count; diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index 76566de089c8f..056fbeb637ee4 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -1714,6 +1714,21 @@ public int codePointCount(int beginIndex, int endIndex) { return StringUTF16.codePointCount(value, beginIndex, endIndex); } + /** + * Returns the number of Unicode code points in + * this {@code String}. Unpaired surrogates count + * as one code point each. + * + * @return the number of Unicode code points in this String + * @since 26 + */ + public int codePointCount() { + if (isLatin1()) { + return value.length; + } + return StringUTF16.codePointCount(value, 0, value.length >> 1); + } + /** * Returns the index within this {@code String} that is * offset from the given {@code index} by diff --git a/src/java.base/share/classes/java/lang/StringBuffer.java b/src/java.base/share/classes/java/lang/StringBuffer.java index 2546a84f39cae..8b216e4549e90 100644 --- a/src/java.base/share/classes/java/lang/StringBuffer.java +++ b/src/java.base/share/classes/java/lang/StringBuffer.java @@ -270,6 +270,14 @@ public synchronized int codePointCount(int beginIndex, int endIndex) { return super.codePointCount(beginIndex, endIndex); } + /** + * @since 26 + */ + @Override + public synchronized int codePointCount() { + return super.codePointCount(); + } + /** * @throws IndexOutOfBoundsException {@inheritDoc} * @since 1.5 diff --git a/src/java.base/share/classes/java/util/regex/Pattern.java b/src/java.base/share/classes/java/util/regex/Pattern.java index b7f03c1b0afc0..d66ac59d1a518 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -1658,7 +1658,7 @@ private static void normalizeSlice(String src, int off, int limit, String seq = src.substring(off, j); String nfd = Normalizer.normalize(seq, Normalizer.Form.NFD); off = j; - if (nfd.codePointCount(0, nfd.length()) > 1) { + if (nfd.codePointCount() > 1) { ch0 = nfd.codePointAt(0); ch1 = nfd.codePointAt(Character.charCount(ch0)); if (Character.getType(ch1) == Character.NON_SPACING_MARK) { @@ -4157,7 +4157,7 @@ boolean match(Matcher matcher, int i, CharSequence seq) { while (i + n < j) { String nfc = Normalizer.normalize( seq.toString().substring(i, j), Normalizer.Form.NFC); - if (nfc.codePointCount(0, nfc.length()) == 1) { + if (nfc.codePointCount() == 1) { if (predicate.is(nfc.codePointAt(0)) && next.match(matcher, j, seq)) { return true; diff --git a/src/java.base/share/classes/jdk/internal/icu/impl/NormalizerImpl.java b/src/java.base/share/classes/jdk/internal/icu/impl/NormalizerImpl.java index 82f294c31cf26..1b94a0bc23084 100644 --- a/src/java.base/share/classes/jdk/internal/icu/impl/NormalizerImpl.java +++ b/src/java.base/share/classes/jdk/internal/icu/impl/NormalizerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1906,7 +1906,7 @@ public static String canonicalDecomposeWithSingleQuotation(String string) { pStart = 0; p = norm.toCharArray(); length = p.length; - int cpNum = norm.codePointCount(0, length); + int cpNum = norm.codePointCount(); cc= UCharacter.getCombiningClass(norm.codePointAt(0)); trailCC= UCharacter.getCombiningClass(norm.codePointAt(cpNum-1)); if (length == 1) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java index bb976e4c6eb4a..16fe65758cf4c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -1685,7 +1685,7 @@ public static String mapQNameToJavaName (String base ) { * complementary characters */ public static int getStringLength(String str) { - return str.codePointCount(0,str.length()); + return str.codePointCount(); } //-- End utility functions diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java index a8a90ea5e0dcf..d4338c10a1783 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java @@ -315,7 +315,7 @@ public T getBound(CharSequence keySeq, int[] remaining) { if (keySeq != null && keySeq.length() > 0) { char c = keySeq.charAt(0); if (c >= mapping.length) { - remaining[0] = Character.codePointCount(keySeq, 0, keySeq.length()); + remaining[0] = Character.codePointCount(keySeq); return null; } else { if (mapping[c] instanceof KeyMap) { diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java index b73daee66deb3..192b6fe1afbc5 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java @@ -790,8 +790,8 @@ boolean run(JdepsConfiguration config, JdepsWriter writer, Type type) String replacementApiTitle = getMessage("public.api.replacement.column.header"); log.format("%-40s %s%n", internalApiTitle, replacementApiTitle); log.format("%-40s %s%n", - "-".repeat(internalApiTitle.codePointCount(0, internalApiTitle.length())), - "-".repeat(replacementApiTitle.codePointCount(0, replacementApiTitle.length()))); + "-".repeat(internalApiTitle.codePointCount()), + "-".repeat(replacementApiTitle.codePointCount())); jdkInternals.entrySet() .forEach(e -> { String key = e.getKey(); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java index 4700231a16248..08b32232f2670 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java @@ -817,7 +817,7 @@ private static String unquoteIfNeeded(String in) { // Use code points to preserve non-ASCII chars StringBuilder sb = new StringBuilder(); - int codeLen = in.codePointCount(0, in.length()); + int codeLen = in.codePointCount(); int quoteChar = -1; for (int i = 0; i < codeLen; i++) { int code = in.codePointAt(i); diff --git a/test/jdk/java/lang/Character/Supplementary.java b/test/jdk/java/lang/Character/Supplementary.java index acb162ad94742..9ea1823d6fd56 100644 --- a/test/jdk/java/lang/Character/Supplementary.java +++ b/test/jdk/java/lang/Character/Supplementary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -334,6 +334,8 @@ static void test03(char[] a) { /** * Test codePointCount(CharSequence, int, int) * codePointCount(char[], int, int, int, int) + * codePointCount(CharSequence) + * codePointCount(char[]) */ static void test04(String str) { int length = str.length(); @@ -347,9 +349,15 @@ static void test04(String str) { checkCodePointCount(a, n, m); } + int n = Character.codePointCount(str); + int m = codePointCount(str); + checkCodePointCount(str, n, m); + n = Character.codePointCount(a); + checkCodePointCount(a, n, m); + // test special cases length = str.length(); - int n = Character.codePointCount(str, 0, 0); + n = Character.codePointCount(str, 0, 0); checkCodePointCount(str, n, 0); n = Character.codePointCount(str, length, length); checkCodePointCount(str, n, 0); diff --git a/test/jdk/java/lang/String/Supplementary.java b/test/jdk/java/lang/String/Supplementary.java index 3fc8c70bd5c28..bb94bb88ec71a 100644 --- a/test/jdk/java/lang/String/Supplementary.java +++ b/test/jdk/java/lang/String/Supplementary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -388,7 +388,7 @@ static void test7() { /** * Test codePointCount(int, int) * - * This test case assumes that + * This test case assumes that Character.codePointCount() & * Character.codePointCount(CharSequence, int, int) works * correctly. */ @@ -419,6 +419,10 @@ static void test8() { result, expected); } + int result = str.codePointCount(); + int expected = Character.codePointCount(); + check(result != expected, "substring:codePointCount()", result, expected); + // test exceptions testCodePointCount(null, 0, 0, NullPointerException.class); testCodePointCount(str, -1, length, IndexOutOfBoundsException.class); diff --git a/test/jdk/java/lang/StringBuilder/Supplementary.java b/test/jdk/java/lang/StringBuilder/Supplementary.java index a13b0f44fb2bf..f775107c088b4 100644 --- a/test/jdk/java/lang/StringBuilder/Supplementary.java +++ b/test/jdk/java/lang/StringBuilder/Supplementary.java @@ -215,11 +215,11 @@ static void test4() { } /** - * Test codePointCount(int, int) + * Test codePointCount(int, int) & codePointCount() * * This test case assumes that - * Character.codePointCount(CharSequence, int, int) works - * correctly. + * Character.codePointCount(CharSequence, int, int) & + * Character.codePointCount(CharSequence) works correctly. */ static void test5() { for (int i = 0; i < input.length; i++) { @@ -239,6 +239,11 @@ static void test5() { result, expected); } + + int result = sb.codePointCount(); + int expected = Character.codePointCount(sb); + check(result != expected, "codePointCount()", result, expected); + // test exceptions testCodePointCount(null, 0, 0, NullPointerException.class); testCodePointCount(sb, -1, length, IndexOutOfBoundsException.class); From 6f2e1d2b3a76a41c8b69d61b8a6a82211494c0ac Mon Sep 17 00:00:00 2001 From: Tatsunori Uchino Date: Thu, 24 Jul 2025 23:54:17 +0900 Subject: [PATCH 02/10] Remove trailing spaces --- test/jdk/java/lang/Character/Supplementary.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/java/lang/Character/Supplementary.java b/test/jdk/java/lang/Character/Supplementary.java index 9ea1823d6fd56..e8a5a99888877 100644 --- a/test/jdk/java/lang/Character/Supplementary.java +++ b/test/jdk/java/lang/Character/Supplementary.java @@ -354,7 +354,7 @@ static void test04(String str) { checkCodePointCount(str, n, m); n = Character.codePointCount(a); checkCodePointCount(a, n, m); - + // test special cases length = str.length(); n = Character.codePointCount(str, 0, 0); From 12c12cbf2f73b9935dfccbdf21204725f2c903f2 Mon Sep 17 00:00:00 2001 From: Tatsunori Uchino Date: Sat, 26 Jul 2025 15:59:38 +0900 Subject: [PATCH 03/10] Fix test --- test/jdk/java/lang/String/Supplementary.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/java/lang/String/Supplementary.java b/test/jdk/java/lang/String/Supplementary.java index bb94bb88ec71a..ead3d006f6b32 100644 --- a/test/jdk/java/lang/String/Supplementary.java +++ b/test/jdk/java/lang/String/Supplementary.java @@ -420,7 +420,7 @@ static void test8() { } int result = str.codePointCount(); - int expected = Character.codePointCount(); + int expected = Character.codePointCount(str); check(result != expected, "substring:codePointCount()", result, expected); // test exceptions From 444163b4d9773384f72dcd29737eb647f8d538b3 Mon Sep 17 00:00:00 2001 From: Tatsunori Uchino Date: Sat, 26 Jul 2025 16:03:25 +0900 Subject: [PATCH 04/10] Fix how to get code point count in StringBuilder Co-authored-By: Chen Liang --- .../share/classes/java/lang/AbstractStringBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index 7390bc76b43ae..ed8588c0cda01 100644 --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -542,9 +542,9 @@ public int codePointCount() { int count = this.count; byte[] value = this.value; if (isLatin1(coder)) { - return value.length; + return count; } - return StringUTF16.codePointCount(value, count, value.length >> 1); + return StringUTF16.codePointCount(value, 0, count); } /** From af3fe8b95caef71a4ee4022ae8605032de6bba5d Mon Sep 17 00:00:00 2001 From: Tatsunori Uchino Date: Sat, 26 Jul 2025 16:14:55 +0900 Subject: [PATCH 05/10] Fix copyright year Co-authored-by: Mikhail Yankelevich --- test/jdk/java/lang/StringBuilder/Supplementary.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/java/lang/StringBuilder/Supplementary.java b/test/jdk/java/lang/StringBuilder/Supplementary.java index f775107c088b4..32e84be36fc47 100644 --- a/test/jdk/java/lang/StringBuilder/Supplementary.java +++ b/test/jdk/java/lang/StringBuilder/Supplementary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it From 63eb4a7d29b9c5e341bc1788f5c108fd8ad8746a Mon Sep 17 00:00:00 2001 From: Tatsunori Uchino Date: Sat, 26 Jul 2025 17:30:39 +0900 Subject: [PATCH 06/10] Discard changes out of than java.base --- .../org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java | 4 ++-- .../share/classes/jdk/internal/org/jline/keymap/KeyMap.java | 2 +- .../share/classes/com/sun/tools/jdeps/JdepsTask.java | 4 ++-- .../share/classes/jdk/jpackage/internal/Arguments.java | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java index 16fe65758cf4c..bb976e4c6eb4a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -1685,7 +1685,7 @@ public static String mapQNameToJavaName (String base ) { * complementary characters */ public static int getStringLength(String str) { - return str.codePointCount(); + return str.codePointCount(0,str.length()); } //-- End utility functions diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java index d4338c10a1783..a8a90ea5e0dcf 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java @@ -315,7 +315,7 @@ public T getBound(CharSequence keySeq, int[] remaining) { if (keySeq != null && keySeq.length() > 0) { char c = keySeq.charAt(0); if (c >= mapping.length) { - remaining[0] = Character.codePointCount(keySeq); + remaining[0] = Character.codePointCount(keySeq, 0, keySeq.length()); return null; } else { if (mapping[c] instanceof KeyMap) { diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java index 192b6fe1afbc5..b73daee66deb3 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java @@ -790,8 +790,8 @@ boolean run(JdepsConfiguration config, JdepsWriter writer, Type type) String replacementApiTitle = getMessage("public.api.replacement.column.header"); log.format("%-40s %s%n", internalApiTitle, replacementApiTitle); log.format("%-40s %s%n", - "-".repeat(internalApiTitle.codePointCount()), - "-".repeat(replacementApiTitle.codePointCount())); + "-".repeat(internalApiTitle.codePointCount(0, internalApiTitle.length())), + "-".repeat(replacementApiTitle.codePointCount(0, replacementApiTitle.length()))); jdkInternals.entrySet() .forEach(e -> { String key = e.getKey(); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java index 08b32232f2670..4700231a16248 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java @@ -817,7 +817,7 @@ private static String unquoteIfNeeded(String in) { // Use code points to preserve non-ASCII chars StringBuilder sb = new StringBuilder(); - int codeLen = in.codePointCount(); + int codeLen = in.codePointCount(0, in.length()); int quoteChar = -1; for (int i = 0; i < codeLen; i++) { int code = in.codePointAt(i); From 8d4840b671e9f541752d172a79f820abd72d190a Mon Sep 17 00:00:00 2001 From: Tatsunori Uchino Date: Sat, 26 Jul 2025 18:03:16 +0900 Subject: [PATCH 07/10] Discard changes on code whose form is not `str.codePointCount(0, str.length())` --- .../share/classes/jdk/internal/icu/impl/NormalizerImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/icu/impl/NormalizerImpl.java b/src/java.base/share/classes/jdk/internal/icu/impl/NormalizerImpl.java index 1b94a0bc23084..82f294c31cf26 100644 --- a/src/java.base/share/classes/jdk/internal/icu/impl/NormalizerImpl.java +++ b/src/java.base/share/classes/jdk/internal/icu/impl/NormalizerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1906,7 +1906,7 @@ public static String canonicalDecomposeWithSingleQuotation(String string) { pStart = 0; p = norm.toCharArray(); length = p.length; - int cpNum = norm.codePointCount(); + int cpNum = norm.codePointCount(0, length); cc= UCharacter.getCombiningClass(norm.codePointAt(0)); trailCC= UCharacter.getCombiningClass(norm.codePointAt(cpNum-1)); if (length == 1) { From 1e7da59d46f9e97f9a09df43a98127af97540cbc Mon Sep 17 00:00:00 2001 From: Tatsunori Uchino Date: Sat, 26 Jul 2025 18:26:56 +0900 Subject: [PATCH 08/10] Update `@bug` entries in test class doc comments --- test/jdk/java/lang/Character/Supplementary.java | 2 +- test/jdk/java/lang/String/Supplementary.java | 5 +++-- test/jdk/java/lang/StringBuffer/Supplementary.java | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/test/jdk/java/lang/Character/Supplementary.java b/test/jdk/java/lang/Character/Supplementary.java index e8a5a99888877..475d6870bd6e0 100644 --- a/test/jdk/java/lang/Character/Supplementary.java +++ b/test/jdk/java/lang/Character/Supplementary.java @@ -23,7 +23,7 @@ /* * @test - * @bug 4533872 4985214 4985217 4993841 5017268 5017280 8298033 + * @bug 4533872 4985214 4985217 4993841 5017268 5017280 8298033 8364007 * @summary Unit tests for supplementary character support (JSR-204) * @compile Supplementary.java * @run main/timeout=600 Supplementary diff --git a/test/jdk/java/lang/String/Supplementary.java b/test/jdk/java/lang/String/Supplementary.java index ead3d006f6b32..35c67139f6985 100644 --- a/test/jdk/java/lang/String/Supplementary.java +++ b/test/jdk/java/lang/String/Supplementary.java @@ -24,7 +24,7 @@ /* * * @test - * @bug 4533872 4915683 4922962 4985217 5017280 6242664 6588260 + * @bug 4533872 4915683 4922962 4985217 5017280 6242664 6588260 8364007 * @summary Unit tests for supplementary character support (JSR-204) */ @@ -386,7 +386,8 @@ static void test7() { } /** - * Test codePointCount(int, int) + * Test codePointCount(int, int) & + * codePointCount() * * This test case assumes that Character.codePointCount() & * Character.codePointCount(CharSequence, int, int) works diff --git a/test/jdk/java/lang/StringBuffer/Supplementary.java b/test/jdk/java/lang/StringBuffer/Supplementary.java index 0cc56cc377817..aca97c4140d52 100644 --- a/test/jdk/java/lang/StringBuffer/Supplementary.java +++ b/test/jdk/java/lang/StringBuffer/Supplementary.java @@ -24,7 +24,7 @@ /* * * @test - * @bug 4533872 4915683 4985217 5017280 6937112 + * @bug 4533872 4915683 4985217 5017280 6937112 8364007 * @summary Unit tests for supplementary character support (JSR-204) */ From 4811c9df90c79f1fe7e47910dd88d10764f7cca2 Mon Sep 17 00:00:00 2001 From: Tatsunori Uchino Date: Sat, 26 Jul 2025 19:05:05 +0900 Subject: [PATCH 09/10] Add default implementation on codePointCount in CharSequence --- .../share/classes/java/lang/CharSequence.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/java.base/share/classes/java/lang/CharSequence.java b/src/java.base/share/classes/java/lang/CharSequence.java index 2732ee35933d6..e66d50b4d6d28 100644 --- a/src/java.base/share/classes/java/lang/CharSequence.java +++ b/src/java.base/share/classes/java/lang/CharSequence.java @@ -253,6 +253,31 @@ public int nextInt() { false); } + /** + * Returns the number of Unicode code points in + * this sequence. Unpaired surrogates count + * as one code point each. + * + * @return the number of Unicode code points in this sequence + * @since 26 + */ + public default int codePointCount() { + final int length = length(); + int n = length; + final int lastIndex = length - 1; + + // i < lastIndex works properly even for an empty sequence + // thank to the fact that the length/index type in Java is signed + for (int i = 0; i < lastIndex;) { + if (Character.isHighSurrogate(charAt(i++)) && Character.isLowSurrogate(charAt(i))) { + n--; + i++; + } + } + + return n; + } + /** * Compares two {@code CharSequence} instances lexicographically. Returns a * negative value, zero, or a positive value if the first sequence is lexicographically From 0e55e35c5ad8f18e50a9a6f6073164db034798d7 Mon Sep 17 00:00:00 2001 From: Tatsunori Uchino Date: Sat, 26 Jul 2025 19:06:58 +0900 Subject: [PATCH 10/10] Update `@bug` in correct file --- test/jdk/java/lang/StringBuffer/Supplementary.java | 2 +- test/jdk/java/lang/StringBuilder/Supplementary.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/jdk/java/lang/StringBuffer/Supplementary.java b/test/jdk/java/lang/StringBuffer/Supplementary.java index aca97c4140d52..0cc56cc377817 100644 --- a/test/jdk/java/lang/StringBuffer/Supplementary.java +++ b/test/jdk/java/lang/StringBuffer/Supplementary.java @@ -24,7 +24,7 @@ /* * * @test - * @bug 4533872 4915683 4985217 5017280 6937112 8364007 + * @bug 4533872 4915683 4985217 5017280 6937112 * @summary Unit tests for supplementary character support (JSR-204) */ diff --git a/test/jdk/java/lang/StringBuilder/Supplementary.java b/test/jdk/java/lang/StringBuilder/Supplementary.java index 32e84be36fc47..075bd2b89227b 100644 --- a/test/jdk/java/lang/StringBuilder/Supplementary.java +++ b/test/jdk/java/lang/StringBuilder/Supplementary.java @@ -24,7 +24,7 @@ /* * * @test - * @bug 4533872 4915683 4985217 5017280 + * @bug 4533872 4915683 4985217 5017280 8364007 * @summary Unit tests for supplementary character support (JSR-204) */