Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions src/java.base/share/classes/java/lang/String.java
Original file line number Diff line number Diff line change
Expand Up @@ -914,11 +914,10 @@ private static <E extends Exception> byte[] encodeWithEncoder(
return ba;
}

int blen = (coder == LATIN1) ? ae.encodeFromLatin1(val, 0, len, ba)
: ae.encodeFromUTF16(val, 0, len, ba);
if (blen != -1) {
return trimArray(ba, blen);
}
int blen = coder == LATIN1
? ae.encodeFromLatin1(val, 0, len, ba, 0)
: ae.encodeFromUTF16(val, 0, len, ba, 0);
return trimArray(ba, blen);
}

byte[] ba = new byte[en];
Expand Down
24 changes: 8 additions & 16 deletions src/java.base/share/classes/sun/nio/cs/ArrayEncoder.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 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
Expand All @@ -25,25 +25,17 @@

package sun.nio.cs;

/*
* FastPath char[]/byte[] -> byte[] encoder, REPLACE on malformed input or
* unmappable input.
/**
* Fast-path for {@code byte[]}-to-{@code byte[]} encoding,
* {@link java.nio.charset.CodingErrorAction#REPLACE REPLACE} on malformed
* input, or unmappable input.
*/

public interface ArrayEncoder {

// is only used by j.u.zip.ZipCoder for utf8
int encode(char[] src, int off, int len, byte[] dst);
int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst, int dp);

default int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
return -1;
}
int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst, int dp);

default int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
return -1;
}
boolean isASCIICompatible();

default boolean isASCIICompatible() {
return false;
}
}
47 changes: 2 additions & 45 deletions src/java.base/share/classes/sun/nio/cs/CESU_8.java
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,7 @@ public int decode(byte[] sa, int sp, int len, char[] da) {
}
}

private static class Encoder extends CharsetEncoder
implements ArrayEncoder {
private static class Encoder extends CharsetEncoder {

private Encoder(Charset cs) {
super(cs, 1.1f, 3.0f);
Expand Down Expand Up @@ -544,48 +543,6 @@ protected final CoderResult encodeLoop(CharBuffer src,
return encodeBufferLoop(src, dst);
}

// returns -1 if there is malformed char(s) and the
// "action" for malformed input is not REPLACE.
public int encode(char[] sa, int sp, int len, byte[] da) {
int sl = sp + len;
int dp = 0;

// Handle ASCII-only prefix
int n = JLA.encodeASCII(sa, sp, da, dp, Math.min(len, da.length));
sp += n;
dp += n;

while (sp < sl) {
char c = sa[sp++];
if (c < 0x80) {
// Have at most seven bits
da[dp++] = (byte)c;
} else if (c < 0x800) {
// 2 bytes, 11 bits
da[dp++] = (byte)(0xc0 | (c >> 6));
da[dp++] = (byte)(0x80 | (c & 0x3f));
} else if (Character.isSurrogate(c)) {
if (sgp == null)
sgp = new Surrogate.Parser();
int uc = sgp.parse(c, sa, sp - 1, sl);
if (uc < 0) {
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
da[dp++] = replacement()[0];
} else {
to3Bytes(da, dp, Character.highSurrogate(uc));
dp += 3;
to3Bytes(da, dp, Character.lowSurrogate(uc));
dp += 3;
sp++; // 2 chars
}
} else {
// 3 bytes, 16 bits
to3Bytes(da, dp, c);
dp += 3;
}
}
return dp;
}
}

}
85 changes: 4 additions & 81 deletions src/java.base/share/classes/sun/nio/cs/DoubleByte.java
Original file line number Diff line number Diff line change
Expand Up @@ -682,40 +682,7 @@ protected void implReplaceWith(byte[] newReplacement) {
}

@Override
public int encode(char[] src, int sp, int len, byte[] dst) {
int dp = 0;
int sl = sp + len;
if (isASCIICompatible) {
int n = JLA.encodeASCII(src, sp, dst, dp, len);
sp += n;
dp += n;
}
while (sp < sl) {
char c = src[sp++];
int bb = encodeChar(c);
if (bb == UNMAPPABLE_ENCODING) {
if (Character.isHighSurrogate(c) && sp < sl &&
Character.isLowSurrogate(src[sp])) {
sp++;
}
dst[dp++] = repl[0];
if (repl.length > 1)
dst[dp++] = repl[1];
continue;
} //else
if (bb > MAX_SINGLEBYTE) { // DoubleByte
dst[dp++] = (byte)(bb >> 8);
dst[dp++] = (byte)bb;
} else { // SingleByte
dst[dp++] = (byte)bb;
}
}
return dp;
}

@Override
public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
int dp = 0;
public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst, int dp) {
int sl = sp + len;
while (sp < sl) {
char c = (char)(src[sp++] & 0xff);
Expand All @@ -740,8 +707,7 @@ public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
}

@Override
public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
int dp = 0;
public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst, int dp) {
int sl = sp + len;
while (sp < sl) {
char c = StringUTF16.getChar(src, sp++);
Expand Down Expand Up @@ -1000,49 +966,7 @@ protected CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) {
}

@Override
public int encode(char[] src, int sp, int len, byte[] dst) {
int dp = 0;
int sl = sp + len;
while (sp < sl) {
char c = src[sp++];
int bb = encodeChar(c);

if (bb == UNMAPPABLE_ENCODING) {
if (Character.isHighSurrogate(c) && sp < sl &&
Character.isLowSurrogate(src[sp])) {
sp++;
}
dst[dp++] = repl[0];
if (repl.length > 1)
dst[dp++] = repl[1];
continue;
} //else
if (bb > MAX_SINGLEBYTE) { // DoubleByte
if (currentState == SBCS) {
currentState = DBCS;
dst[dp++] = SO;
}
dst[dp++] = (byte)(bb >> 8);
dst[dp++] = (byte)bb;
} else { // SingleByte
if (currentState == DBCS) {
currentState = SBCS;
dst[dp++] = SI;
}
dst[dp++] = (byte)bb;
}
}

if (currentState == DBCS) {
currentState = SBCS;
dst[dp++] = SI;
}
return dp;
}

@Override
public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
int dp = 0;
public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst, int dp) {
int sl = sp + len;
while (sp < sl) {
char c = (char)(src[sp++] & 0xff);
Expand Down Expand Up @@ -1077,8 +1001,7 @@ public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
}

@Override
public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
int dp = 0;
public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst, int dp) {
int sl = sp + len;
while (sp < sl) {
char c = StringUTF16.getChar(src, sp++);
Expand Down
32 changes: 2 additions & 30 deletions src/java.base/share/classes/sun/nio/cs/HKSCS.java
Original file line number Diff line number Diff line change
Expand Up @@ -352,37 +352,9 @@ protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
return encodeBufferLoop(src, dst);
}

public int encode(char[] src, int sp, int len, byte[] dst) {
int dp = 0;
int sl = sp + len;
while (sp < sl) {
char c = src[sp++];
int bb = encodeChar(c);
if (bb == UNMAPPABLE_ENCODING) {
if (!Character.isHighSurrogate(c) || sp == sl ||
!Character.isLowSurrogate(src[sp]) ||
(bb = encodeSupp(Character.toCodePoint(c, src[sp++])))
== UNMAPPABLE_ENCODING) {
dst[dp++] = repl[0];
if (repl.length > 1)
dst[dp++] = repl[1];
continue;
}
}
if (bb > MAX_SINGLEBYTE) { // DoubleByte
dst[dp++] = (byte)(bb >> 8);
dst[dp++] = (byte)bb;
} else { // SingleByte
dst[dp++] = (byte)bb;
}
}
return dp;
}

public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
int dp = 0;
@Override
public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst, int dp) {
int sl = sp + len;
int dl = dst.length;
while (sp < sl) {
char c = StringUTF16.getChar(src, sp++);
int bb = encodeChar(c);
Expand Down
29 changes: 2 additions & 27 deletions src/java.base/share/classes/sun/nio/cs/SingleByte.java
Original file line number Diff line number Diff line change
Expand Up @@ -290,32 +290,8 @@ protected void implReplaceWith(byte[] newReplacement) {
repl = newReplacement[0];
}

public int encode(char[] src, int sp, int len, byte[] dst) {
int dp = 0;
int sl = sp + Math.min(len, dst.length);
while (sp < sl) {
char c = src[sp++];
int b = encode(c);
if (b != UNMAPPABLE_ENCODING) {
dst[dp++] = (byte)b;
continue;
}
if (Character.isHighSurrogate(c) && sp < sl &&
Character.isLowSurrogate(src[sp])) {
if (len > dst.length) {
sl++;
len--;
}
sp++;
}
dst[dp++] = repl;
}
return dp;
}

@Override
public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
int dp = 0;
public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst, int dp) {
int sl = sp + Math.min(len, dst.length);
while (sp < sl) {
char c = (char)(src[sp++] & 0xff);
Expand All @@ -330,8 +306,7 @@ public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
}

@Override
public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
int dp = 0;
public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst, int dp) {
int sl = sp + Math.min(len, dst.length);
while (sp < sl) {
char c = StringUTF16.getChar(src, sp++);
Expand Down
4 changes: 2 additions & 2 deletions test/jdk/sun/nio/cs/TestEncoderReplaceLatin1.java
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ static void testCharsetEncoderReplace(CharsetEncoder encoder, char[] unmappable,
/**
* Verifies {@linkplain CoderResult#isUnmappable() unmappable} character
* {@linkplain CodingErrorAction#REPLACE replacement} using {@link
* ArrayEncoder#encodeFromLatin1(byte[], int, int, byte[])
* ArrayEncoder#encodeFromLatin1(byte[], int, int, byte[], int)
* ArrayEncoder::encodeFromLatin1}.
*/
private static void testArrayEncoderLatin1Replace(CharsetEncoder encoder, char unmappable, byte[] replacement) {
Expand All @@ -202,7 +202,7 @@ private static void testArrayEncoderLatin1Replace(CharsetEncoder encoder, char u
}
byte[] sa = {(byte) unmappable};
byte[] da = new byte[replacement.length];
int dp = arrayEncoder.encodeFromLatin1(sa, 0, 1, da);
int dp = arrayEncoder.encodeFromLatin1(sa, 0, 1, da, 0);
assertTrue(dp == replacement.length && Arrays.equals(da, replacement), () -> {
Object context = Map.of(
"dp", dp,
Expand Down
4 changes: 2 additions & 2 deletions test/jdk/sun/nio/cs/TestEncoderReplaceUTF16.java
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ private static byte[] utf16Bytes(char[] cs) {
/**
* Verifies {@linkplain CoderResult#isUnmappable() unmappable} character
* {@linkplain CodingErrorAction#REPLACE replacement} using {@link
* ArrayEncoder#encodeFromUTF16(byte[], int, int, byte[])
* ArrayEncoder#encodeFromUTF16(byte[], int, int, byte[], int)
* ArrayEncoder::encodeFromUTF16}.
*/
private static void testArrayEncoderUTF16Replace(CharsetEncoder encoder, byte[] unmappableUTF16Bytes, byte[] replacement) {
Expand All @@ -191,7 +191,7 @@ private static void testArrayEncoderUTF16Replace(CharsetEncoder encoder, byte[]
return;
}
byte[] da = new byte[replacement.length];
int dp = arrayEncoder.encodeFromUTF16(unmappableUTF16Bytes, 0, unmappableUTF16Bytes.length >>> 1, da);
int dp = arrayEncoder.encodeFromUTF16(unmappableUTF16Bytes, 0, unmappableUTF16Bytes.length >>> 1, da, 0);
assertTrue(dp == replacement.length && Arrays.equals(da, replacement), () -> {
Object context = Map.of(
"dp", dp,
Expand Down
Loading