internal StringEncoder(Charset cs, String rcn) { this.RequestedCharsetName_Renamed = rcn; this.Cs = cs; this.Ce = cs.NewEncoder().OnMalformedInput(CodingErrorAction.REPLACE).OnUnmappableCharacter(CodingErrorAction.REPLACE); this.IsTrusted = (cs.GetType().ClassLoader0 == null); }
internal static sbyte[] Encode(Charset cs, char[] ca, int off, int len) { CharsetEncoder ce = cs.NewEncoder(); int en = Scale(len, ce.MaxBytesPerChar()); sbyte[] ba = new sbyte[en]; if (len == 0) { return(ba); } bool isTrusted = false; if (System.SecurityManager != null) { if (!(isTrusted = (cs.GetType().ClassLoader0 == null))) { ca = Arrays.CopyOfRange(ca, off, off + len); off = 0; } } ce.OnMalformedInput(CodingErrorAction.REPLACE).OnUnmappableCharacter(CodingErrorAction.REPLACE).Reset(); if (ce is 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.Underflow) { cr.ThrowException(); } cr = ce.Flush(bb); if (!cr.Underflow) { cr.ThrowException(); } } catch (CharacterCodingException x) { throw new Error(x); } return(SafeTrim(ba, bb.Position(), cs, isTrusted)); } }
internal static char[] Decode(Charset cs, sbyte[] 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 // de/encode() method. These SD/E objects are short-lifed, the young-gen // gc should be able to take care of them well. But the best approash // is still not to generate them if not really necessary. // (2)The defensive copy of the input byte/char[] has a big performance // impact, as well as the outgoing result byte/char[]. Need to do the // optimization check of (sm==null && classLoader0==null) for both. // (3)getClass().getClassLoader0() is expensive // (4)There might be a timing gap in isTrusted setting. getClassLoader0() // is only chcked (and then isTrusted gets set) when (SM==null). It is // possible that the SM==null for now but then SM is NOT null later // when safeTrim() is invoked...the "safe" way to do is to redundant // check (... && (isTrusted || SM == null || getClassLoader0())) in trim // but it then can be argued that the SM is null when the opertaion // is started... CharsetDecoder cd = cs.NewDecoder(); int en = Scale(len, cd.MaxCharsPerByte()); char[] ca = new char[en]; if (len == 0) { return(ca); } bool isTrusted = false; if (System.SecurityManager != null) { if (!(isTrusted = (cs.GetType().ClassLoader0 == null))) { ba = Arrays.CopyOfRange(ba, off, off + len); off = 0; } } cd.OnMalformedInput(CodingErrorAction.REPLACE).OnUnmappableCharacter(CodingErrorAction.REPLACE).Reset(); if (cd is 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.Underflow) { cr.ThrowException(); } cr = cd.Flush(cb); if (!cr.Underflow) { 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)); } }