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 {