src/java.base/share/classes/java/lang/StringCoding.java
Print this page
*** 126,138 ****
private final boolean isTrusted;
private StringDecoder(Charset cs, String rcn) {
this.requestedCharsetName = rcn;
this.cs = cs;
! this.cd = cs.newDecoder()
! .onMalformedInput(CodingErrorAction.REPLACE)
! .onUnmappableCharacter(CodingErrorAction.REPLACE);
this.isTrusted = (cs.getClass().getClassLoader0() == null);
}
String charsetName() {
if (cs instanceof HistoricallyNamedCharset)
--- 126,137 ----
private final boolean isTrusted;
private StringDecoder(Charset cs, String rcn) {
this.requestedCharsetName = rcn;
this.cs = cs;
! this.cd = cs.newDecoder();
! setupDecoder(cd);
this.isTrusted = (cs.getClass().getClassLoader0() == null);
}
String charsetName() {
if (cs instanceof HistoricallyNamedCharset)
*** 153,183 ****
int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
return safeTrim(ca, clen, cs, isTrusted);
} else {
cd.reset();
ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
! CharBuffer cb = CharBuffer.wrap(ca);
! try {
! CoderResult cr = cd.decode(bb, cb, true);
! if (!cr.isUnderflow())
! cr.throwException();
! cr = cd.flush(cb);
! if (!cr.isUnderflow())
! cr.throwException();
! } catch (CharacterCodingException x) {
! // Substitution is always enabled,
! // so this shouldn't happen
! throw new Error(x);
}
! return safeTrim(ca, cb.position(), cs, isTrusted);
}
}
}
! static char[] decode(String charsetName, byte[] ba, int off, int len)
! throws UnsupportedEncodingException
! {
StringDecoder sd = deref(decoder);
String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
if ((sd == null) || !(csn.equals(sd.requestedCharsetName())
|| csn.equals(sd.charsetName()))) {
sd = null;
--- 152,192 ----
int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
return safeTrim(ca, clen, cs, isTrusted);
} else {
cd.reset();
ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
! return performDecode(cs, isTrusted, ca, cd, bb);
}
! }
!
! char[] decode(ByteBuffer bb) {
! int len = bb.remaining();
! int en = scale(len, cd.maxCharsPerByte());
! char[] ca = new char[en];
! if (len == 0)
! return ca;
!
! if (!isTrusted) {
! // copy the bytebuffer
! ByteBuffer originalByteBuffer = bb;
! bb = ByteBuffer.allocate(len)
! .put(originalByteBuffer);
! bb.position(0);
! }
!
! cd.reset();
!
! return performDecode(cs, isTrusted, ca, cd, bb);
}
}
+
+ static char[] decode(String charsetName, byte[] ba, int off, int len) throws UnsupportedEncodingException {
+ StringDecoder sd = getStringDecoder(charsetName);
+ return sd.decode(ba, off, len);
}
! private static StringDecoder getStringDecoder(String charsetName) throws UnsupportedEncodingException {
StringDecoder sd = deref(decoder);
String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
if ((sd == null) || !(csn.equals(sd.requestedCharsetName())
|| csn.equals(sd.charsetName()))) {
sd = null;
*** 188,198 ****
} catch (IllegalCharsetNameException x) {}
if (sd == null)
throw new UnsupportedEncodingException(csn);
set(decoder, sd);
}
! return sd.decode(ba, off, len);
}
static char[] decode(Charset cs, byte[] ba, int off, int len) {
// (1)We never cache the "external" cs, the only benefit of creating
// an additional StringDe/Encoder object to wrap it is to share the
--- 197,207 ----
} catch (IllegalCharsetNameException x) {}
if (sd == null)
throw new UnsupportedEncodingException(csn);
set(decoder, sd);
}
! return sd;
}
static char[] decode(Charset cs, byte[] ba, int off, int len) {
// (1)We never cache the "external" cs, the only benefit of creating
// an additional StringDe/Encoder object to wrap it is to share the
*** 213,237 ****
CharsetDecoder cd = cs.newDecoder();
int en = scale(len, cd.maxCharsPerByte());
char[] ca = new char[en];
if (len == 0)
return ca;
! boolean isTrusted = false;
! if (System.getSecurityManager() != null) {
! if (!(isTrusted = (cs.getClass().getClassLoader0() == null))) {
ba = Arrays.copyOfRange(ba, off, off + len);
off = 0;
}
! }
! cd.onMalformedInput(CodingErrorAction.REPLACE)
! .onUnmappableCharacter(CodingErrorAction.REPLACE)
! .reset();
if (cd instanceof ArrayDecoder) {
int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
return safeTrim(ca, clen, cs, isTrusted);
} else {
ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
CharBuffer cb = CharBuffer.wrap(ca);
try {
CoderResult cr = cd.decode(bb, cb, true);
if (!cr.isUnderflow())
cr.throwException();
--- 222,293 ----
CharsetDecoder cd = cs.newDecoder();
int en = scale(len, cd.maxCharsPerByte());
char[] ca = new char[en];
if (len == 0)
return ca;
!
! boolean isTrusted = isTrusted(cs);
! if (!isTrusted) {
ba = Arrays.copyOfRange(ba, off, off + len);
off = 0;
}
!
! setupDecoder(cd);
!
if (cd instanceof ArrayDecoder) {
int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
return safeTrim(ca, clen, cs, isTrusted);
} else {
ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
+ return performDecode(cs, isTrusted, ca, cd, bb);
+ }
+ }
+
+ static char[] decode(Charset cs, ByteBuffer bb) {
+ // See comment at top of decode(Charset,byte[],int,int)
+ CharsetDecoder cd = cs.newDecoder();
+ int len = bb.remaining();
+ int en = scale(len, cd.maxCharsPerByte());
+ char[] ca = new char[en];
+ if (len == 0)
+ return ca;
+
+ boolean isTrusted = isTrusted(cs);
+ if (!isTrusted) {
+ // copy the bytebuffer
+ ByteBuffer originalByteBuffer = bb;
+ bb = ByteBuffer.allocate(len)
+ .put(originalByteBuffer);
+ bb.position(0);
+ }
+
+ setupDecoder(cd);
+
+ return performDecode(cs, isTrusted, ca, cd, bb);
+ }
+
+ static char[] decode(String charsetName, ByteBuffer bb) throws UnsupportedEncodingException {
+ StringDecoder sd = getStringDecoder(charsetName);
+ return sd.decode(bb);
+ }
+
+ private static boolean isTrusted(Charset cs) {
+ return System.getSecurityManager() != null
+ // null classloader means the class is on the boot classpath
+ && cs.getClass().getClassLoader0() == null;
+ }
+
+ private static void setupDecoder(CharsetDecoder cd) {
+ cd.onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE)
+ .reset();
+ }
+
+ static char[] performDecode(
+ Charset cs, boolean isTrusted, char[] ca,
+ CharsetDecoder cd, ByteBuffer bb) {
+
CharBuffer cb = CharBuffer.wrap(ca);
try {
CoderResult cr = cd.decode(bb, cb, true);
if (!cr.isUnderflow())
cr.throwException();
*** 243,253 ****
// so this shouldn't happen
throw new Error(x);
}
return safeTrim(ca, cb.position(), cs, isTrusted);
}
- }
static char[] decode(byte[] ba, int off, int len) {
String csn = Charset.defaultCharset().name();
try {
// use charset name decode() variant which provides caching.
--- 299,308 ----
*** 304,334 ****
int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba);
return safeTrim(ba, blen, cs, isTrusted);
} else {
ce.reset();
ByteBuffer bb = ByteBuffer.wrap(ba);
! CharBuffer cb = CharBuffer.wrap(ca, off, len);
! try {
! CoderResult cr = ce.encode(cb, bb, true);
! if (!cr.isUnderflow())
! cr.throwException();
! cr = ce.flush(bb);
! if (!cr.isUnderflow())
! cr.throwException();
! } catch (CharacterCodingException x) {
! // Substitution is always enabled,
! // so this shouldn't happen
! throw new Error(x);
! }
return safeTrim(ba, bb.position(), cs, isTrusted);
}
}
}
static byte[] encode(String charsetName, char[] ca, int off, int len)
! throws UnsupportedEncodingException
! {
StringEncoder se = deref(encoder);
String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
if ((se == null) || !(csn.equals(se.requestedCharsetName())
|| csn.equals(se.charsetName()))) {
se = null;
--- 359,381 ----
int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba);
return safeTrim(ba, blen, cs, isTrusted);
} else {
ce.reset();
ByteBuffer bb = ByteBuffer.wrap(ba);
! StringCoding.encode(ca, off, len, bb, ce);
return safeTrim(ba, bb.position(), cs, isTrusted);
}
}
}
static byte[] encode(String charsetName, char[] ca, int off, int len)
! throws UnsupportedEncodingException {
! StringEncoder se = getStringEncoder(charsetName);
! return se.encode(ca, off, len);
! }
!
! private static StringEncoder getStringEncoder(String charsetName) throws UnsupportedEncodingException {
StringEncoder se = deref(encoder);
String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
if ((se == null) || !(csn.equals(se.requestedCharsetName())
|| csn.equals(se.charsetName()))) {
se = null;
*** 339,385 ****
} catch (IllegalCharsetNameException x) {}
if (se == null)
throw new UnsupportedEncodingException (csn);
set(encoder, se);
}
! return se.encode(ca, off, len);
}
static byte[] encode(Charset cs, char[] ca, int off, int len) {
CharsetEncoder ce = cs.newEncoder();
int en = scale(len, ce.maxBytesPerChar());
byte[] ba = new byte[en];
if (len == 0)
return ba;
! boolean isTrusted = false;
! if (System.getSecurityManager() != null) {
! if (!(isTrusted = (cs.getClass().getClassLoader0() == null))) {
ca = Arrays.copyOfRange(ca, off, off + len);
off = 0;
}
! }
! ce.onMalformedInput(CodingErrorAction.REPLACE)
! .onUnmappableCharacter(CodingErrorAction.REPLACE)
! .reset();
if (ce instanceof ArrayEncoder) {
int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba);
return safeTrim(ba, blen, cs, isTrusted);
} else {
ByteBuffer bb = ByteBuffer.wrap(ba);
CharBuffer cb = CharBuffer.wrap(ca, off, len);
try {
! CoderResult cr = ce.encode(cb, bb, true);
if (!cr.isUnderflow())
cr.throwException();
! cr = ce.flush(bb);
if (!cr.isUnderflow())
cr.throwException();
} catch (CharacterCodingException x) {
throw new Error(x);
}
- return safeTrim(ba, bb.position(), cs, isTrusted);
}
}
static byte[] encode(char[] ca, int off, int len) {
String csn = Charset.defaultCharset().name();
try {
--- 386,468 ----
} catch (IllegalCharsetNameException x) {}
if (se == null)
throw new UnsupportedEncodingException (csn);
set(encoder, se);
}
! se.ce.reset();
! return se;
}
static byte[] encode(Charset cs, char[] ca, int off, int len) {
CharsetEncoder ce = cs.newEncoder();
int en = scale(len, ce.maxBytesPerChar());
byte[] ba = new byte[en];
if (len == 0)
return ba;
! boolean isTrusted = isTrusted(cs);
! if (!isTrusted) {
ca = Arrays.copyOfRange(ca, off, off + len);
off = 0;
}
! setupEncoder(ce);
if (ce instanceof ArrayEncoder) {
int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba);
return safeTrim(ba, blen, cs, isTrusted);
} else {
ByteBuffer bb = ByteBuffer.wrap(ba);
+ encode(ca, off, len, bb, ce);
+ return safeTrim(ba, bb.position(), cs, isTrusted);
+ }
+ }
+
+
+ static int encode(Charset cs, char[] ca, int off, int len, byte[] destBuffer, int destOffset) {
+ ByteBuffer bb = ByteBuffer.wrap(destBuffer, destOffset, destBuffer.length - destOffset);
+ return encode(cs, ca, off, len, bb);
+ }
+
+ static int encode(Charset cs, char[] ca, int off, int len, ByteBuffer destBuffer) {
+ CharsetEncoder ce = cs.newEncoder();
+ return encodeBuffer(ca, off, len, destBuffer, ce);
+ }
+
+ static int encode(String charsetName, char[] ca, int off, int len, byte[] destBuffer, int destOffset) throws UnsupportedEncodingException {
+ ByteBuffer bb = ByteBuffer.wrap(destBuffer, destOffset, destBuffer.length - destOffset);
+ return encode(charsetName, ca, off, len, bb);
+ }
+
+ static int encode(String charsetName, char[] ca, int off, int len, ByteBuffer destBuffer) throws UnsupportedEncodingException {
+ StringEncoder se = getStringEncoder(charsetName);
+ return encodeBuffer(ca, off, len, destBuffer, se.ce);
+ }
+
+ // encode(charsetName, value, 0, value.length, destBuffer, destOffset);
+
+ private static int encodeBuffer(char[] ca, int off, int len, ByteBuffer destBuffer, CharsetEncoder ce) {
+ int originalPosition = destBuffer.position();
+ encode(ca, off, len, destBuffer, ce);
+ return destBuffer.position() - originalPosition;
+ }
+
+ private static void encode(char[] ca, int off, int len, ByteBuffer destBuffer, CharsetEncoder ce) {
CharBuffer cb = CharBuffer.wrap(ca, off, len);
try {
! CoderResult cr = ce.encode(cb, destBuffer, true);
if (!cr.isUnderflow())
cr.throwException();
! cr = ce.flush(destBuffer);
if (!cr.isUnderflow())
cr.throwException();
} catch (CharacterCodingException x) {
throw new Error(x);
}
}
+
+ private static void setupEncoder(CharsetEncoder encoder) {
+ encoder.onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE)
+ .reset();
}
static byte[] encode(char[] ca, int off, int len) {
String csn = Charset.defaultCharset().name();
try {