diff --git a/src/java.base/share/classes/java/io/Reader.java b/src/java.base/share/classes/java/io/Reader.java index 1654156bee19a..f882a939fbcaf 100644 --- a/src/java.base/share/classes/java/io/Reader.java +++ b/src/java.base/share/classes/java/io/Reader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -193,16 +193,7 @@ public int read(char[] cbuf, int off, int len) throws IOException { if (next >= length) return -1; int n = Math.min(length - next, len); - switch (cs) { - case String s -> s.getChars(next, next + n, cbuf, off); - case StringBuilder sb -> sb.getChars(next, next + n, cbuf, off); - case StringBuffer sb -> sb.getChars(next, next + n, cbuf, off); - case CharBuffer cb -> cb.get(next, cbuf, off, n); - default -> { - for (int i = 0; i < n; i++) - cbuf[off + i] = cs.charAt(next + i); - } - } + cs.getChars(next, next + n, cbuf, off); next += n; return n; } diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index b8d209b8a6e24..c83effb0b45b1 100644 --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -488,33 +488,9 @@ public int offsetByCodePoints(int index, int codePointOffset) { } /** - * Characters are copied from this sequence into the - * destination character array {@code dst}. The first character to - * be copied is at index {@code srcBegin}; the last character to - * be copied is at index {@code srcEnd-1}. The total number of - * characters to be copied is {@code srcEnd-srcBegin}. The - * characters are copied into the subarray of {@code dst} starting - * at index {@code dstBegin} and ending at index: - *
{@code
- * dstbegin + (srcEnd-srcBegin) - 1
- * }
- *
- * @param srcBegin start copying at this offset.
- * @param srcEnd stop copying at this offset.
- * @param dst the array to copy the data into.
- * @param dstBegin offset into {@code dst}.
- * @throws IndexOutOfBoundsException if any of the following is true:
- * {@code
+ * dstbegin + (srcEnd-srcBegin) - 1
+ * }
+ *
+ * @param srcBegin start copying at this offset.
+ * @param srcEnd stop copying at this offset.
+ * @param dst the array to copy the data into.
+ * @param dstBegin offset into {@code dst}.
+ * @throws IndexOutOfBoundsException if any of the following is true:
+ * - * The first character to be copied is at index {@code srcBegin}; - * the last character to be copied is at index {@code srcEnd-1} - * (thus the total number of characters to be copied is - * {@code srcEnd-srcBegin}). The characters are copied into the - * subarray of {@code dst} starting at index {@code dstBegin} - * and ending at index: - *
- * - * @param srcBegin index of the first character in the string - * to copy. - * @param srcEnd index after the last character in the string - * to copy. - * @param dst the destination array. - * @param dstBegin the start offset in the destination array. - * @throws IndexOutOfBoundsException If any of the following - * is true: - *- * dstBegin + (srcEnd-srcBegin) - 1 - *
This method transfers {@code srcEnd-srcBegin} characters from this
+ * buffer into the given array, starting at index {@code srcBegin} in this
+ * buffer and at offset {@code dstBegin} in the array. The position of this
+ * buffer is unchanged.
+ *
+ * @param srcBegin
+ * The index in this buffer from which the first character will be
+ * read; must be non-negative and less than {@code limit()}
+ *
+ * @param srcEnd
+ * The index in this buffer directly before the last character to
+ * read; must be non-negative and less or equal than {@code limit()}
+ * and must be greater or equal than {@code srcBegin}
+ *
+ * @param dst
+ * The destination array
+ *
+ * @param dstBegin
+ * The offset within the array of the first character to be
+ * written; must be non-negative and less than {@code dst.length}
+ *
+ * @throws IndexOutOfBoundsException
+ * If the preconditions on the {@code srcBegin}, {@code srcEnd},
+ * and {@code dstBegin} parameters do not hold
+ *
+ * @implSpec This method is equivalent to
+ * {@code get(srcBegin, dst, dstBegin, srcEnd - srcBegin)}.
+ *
+ * @since 25
+ */
+ @Override
+ public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) {
+ get(srcBegin, dst, dstBegin, srcEnd - srcBegin);
+ }
+
/**
* Returns a string containing the characters in this buffer.
*
diff --git a/test/jdk/java/lang/CharSequence/GetChars.java b/test/jdk/java/lang/CharSequence/GetChars.java
new file mode 100644
index 0000000000000..5d0594a08975a
--- /dev/null
+++ b/test/jdk/java/lang/CharSequence/GetChars.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @bug 8343110
+ * @summary Check for expected behavior of default implementation of
+ * CharSequence.getChars().
+ * @run testng GetChars
+ */
+public class GetChars {
+ private static CharSequence CS = new CharSequence() {
+ @Override
+ public int length() {
+ return 4;
+ }
+
+ @Override
+ public char charAt(int index) {
+ return "Test".charAt(index);
+ }
+
+ @Override
+ public CharSequence subSequence(int start, int end) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ @Test
+ public void testExactCopy() {
+ var dst = new char[4];
+ CS.getChars(0, 4, dst, 0);
+ Assert.assertEquals(dst, new char[] {'T', 'e', 's', 't'});
+ }
+
+ @Test
+ public void testPartialCopy() {
+ var dst = new char[2];
+ CS.getChars(1, 3, dst, 0);
+ Assert.assertEquals(dst, new char[] {'e', 's'});
+ }
+
+ @Test
+ public void testPositionedCopy() {
+ var dst = new char[] {1, 2, 3, 4, 5, 6};
+ CS.getChars(0, 4, dst, 1);
+ Assert.assertEquals(dst, new char[] {1, 'T', 'e', 's', 't', 6});
+ }
+
+ @Test
+ public void testSrcBeginIsNegative() {
+ Assert.assertThrows(IndexOutOfBoundsException.class,
+ () -> CS.getChars(-1, 3, new char[4], 0));
+ }
+
+ @Test
+ public void testDstBeginIsNegative() {
+ Assert.assertThrows(IndexOutOfBoundsException.class,
+ () -> CS.getChars(0, 4, new char[4], -1));
+ }
+
+ @Test
+ public void testSrcBeginIsGreaterThanSrcEnd() {
+ Assert.assertThrows(IndexOutOfBoundsException.class,
+ () -> CS.getChars(4, 0, new char[4], 0));
+ }
+
+ @Test
+ public void testSrcEndIsGreaterThanSequenceLength() {
+ Assert.assertThrows(IndexOutOfBoundsException.class,
+ () -> CS.getChars(0, 5, new char[4], 0));
+ }
+
+ @Test
+ public void testRequestedLengthIsGreaterThanDstLength() {
+ Assert.assertThrows(IndexOutOfBoundsException.class,
+ () -> CS.getChars(0, 4, new char[3], 0));
+ }
+
+ @Test
+ public void testDstIsNull() {
+ Assert.assertThrows(NullPointerException.class,
+ () -> CS.getChars(0, 4, null, 0));
+ }
+
+}
diff --git a/test/jdk/java/nio/Buffer/GetChars.java b/test/jdk/java/nio/Buffer/GetChars.java
new file mode 100644
index 0000000000000..8633482871751
--- /dev/null
+++ b/test/jdk/java/nio/Buffer/GetChars.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * @test
+ * @bug 8343110
+ * @summary Check for expected behavior of CharBuffer.getChars().
+ * @run testng GetChars
+ * @key randomness
+ */
+public class GetChars {
+ private static CharBuffer CB = CharBuffer.wrap("Test");
+
+ @Test
+ public void testExactCopy() {
+ var dst = new char[4];
+ CB.getChars(0, 4, dst, 0);
+ Assert.assertEquals(dst, new char[] {'T', 'e', 's', 't'});
+ }
+
+ @Test
+ public void testPartialCopy() {
+ var dst = new char[2];
+ CB.getChars(1, 3, dst, 0);
+ Assert.assertEquals(dst, new char[] {'e', 's'});
+ }
+
+ @Test
+ public void testPositionedCopy() {
+ var dst = new char[] {1, 2, 3, 4, 5, 6};
+ CB.getChars(0, 4, dst, 1);
+ Assert.assertEquals(dst, new char[] {1, 'T', 'e', 's', 't', 6});
+ }
+
+ @Test
+ public void testSrcBeginIsNegative() {
+ Assert.assertThrows(IndexOutOfBoundsException.class,
+ () -> CB.getChars(-1, 3, new char[4], 0));
+ }
+
+ @Test
+ public void testDstBeginIsNegative() {
+ Assert.assertThrows(IndexOutOfBoundsException.class,
+ () -> CB.getChars(0, 4, new char[4], -1));
+ }
+
+ @Test
+ public void testSrcBeginIsGreaterThanSrcEnd() {
+ Assert.assertThrows(IndexOutOfBoundsException.class,
+ () -> CB.getChars(4, 0, new char[4], 0));
+ }
+
+ @Test
+ public void testSrcEndIsGreaterThanSequenceLength() {
+ Assert.assertThrows(IndexOutOfBoundsException.class,
+ () -> CB.getChars(0, 5, new char[4], 0));
+ }
+
+ @Test
+ public void testRequestedLengthIsGreaterThanDstLength() {
+ Assert.assertThrows(IndexOutOfBoundsException.class,
+ () -> CB.getChars(0, 4, new char[3], 0));
+ }
+
+ @Test
+ public void testDstIsNull() {
+ Assert.assertThrows(NullPointerException.class,
+ () -> CB.getChars(0, 4, null, 0));
+ }
+
+ private static final Random RAND = new Random();
+ private static final int SIZE = 128 + RAND.nextInt(1024);
+
+ /**
+ * Randomize the char buffer's position and limit.
+ */
+ private static CharBuffer randomizeRange(CharBuffer cb) {
+ int mid = cb.capacity() >>> 1;
+ int start = RAND.nextInt(mid + 1); // from 0 to mid
+ int end = mid + RAND.nextInt(cb.capacity() - mid + 1); // from mid to capacity
+ cb.position(start);
+ cb.limit(end);
+ return cb;
+ }
+
+ /**
+ * Randomize the char buffer's contents, position and limit.
+ */
+ private static CharBuffer randomize(CharBuffer cb) {
+ while (cb.hasRemaining()) {
+ cb.put((char)RAND.nextInt());
+ }
+ return randomizeRange(cb);
+ }
+
+ /**
+ * Sums the remaining chars in the char buffer.
+ */
+ private static int intSum(CharBuffer cb) {
+ int sum = 0;
+ cb.mark();
+ while (cb.hasRemaining()) {
+ sum += cb.get();
+ }
+ cb.reset();
+ return sum;
+ }
+
+ /**
+ * Sums the chars in the char array.
+ */
+ private static int intSum(char[] ca) {
+ int sum = 0;
+ for (int i = 0; i < ca.length; i++)
+ sum += ca[i];
+ return sum;
+ }
+
+ /**
+ * Creates char buffers to test, adding them to the given list.
+ */
+ private static void addCases(CharBuffer cb, List