| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.nio.cs;  | 
 | 
 | 
 | 
import java.nio.Buffer;  | 
 | 
import java.nio.ByteBuffer;  | 
 | 
import java.nio.CharBuffer;  | 
 | 
import java.nio.charset.Charset;  | 
 | 
import java.nio.charset.CharsetDecoder;  | 
 | 
import java.nio.charset.CharsetEncoder;  | 
 | 
import java.nio.charset.CoderResult;  | 
 | 
import java.util.Arrays;  | 
 | 
import static sun.nio.cs.CharsetMapping.*;  | 
 | 
 | 
 | 
public class SingleByte  | 
 | 
{ | 
 | 
    private static final CoderResult withResult(CoderResult cr,  | 
 | 
                                                Buffer src, int sp,  | 
 | 
                                                Buffer dst, int dp)  | 
 | 
    { | 
 | 
        src.position(sp - src.arrayOffset());  | 
 | 
        dst.position(dp - dst.arrayOffset());  | 
 | 
        return cr;  | 
 | 
    }  | 
 | 
 | 
 | 
    final public static class Decoder extends CharsetDecoder  | 
 | 
                                      implements ArrayDecoder { | 
 | 
        private final char[] b2c;  | 
 | 
 | 
 | 
        public Decoder(Charset cs, char[] b2c) { | 
 | 
            super(cs, 1.0f, 1.0f);  | 
 | 
            this.b2c = b2c;  | 
 | 
        }  | 
 | 
 | 
 | 
        private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) { | 
 | 
            byte[] sa = src.array();  | 
 | 
            int sp = src.arrayOffset() + src.position();  | 
 | 
            int sl = src.arrayOffset() + src.limit();  | 
 | 
 | 
 | 
            char[] da = dst.array();  | 
 | 
            int dp = dst.arrayOffset() + dst.position();  | 
 | 
            int dl = dst.arrayOffset() + dst.limit();  | 
 | 
 | 
 | 
            CoderResult cr = CoderResult.UNDERFLOW;  | 
 | 
            if ((dl - dp) < (sl - sp)) { | 
 | 
                sl = sp + (dl - dp);  | 
 | 
                cr = CoderResult.OVERFLOW;  | 
 | 
            }  | 
 | 
 | 
 | 
            while (sp < sl) { | 
 | 
                char c = decode(sa[sp]);  | 
 | 
                if (c == UNMAPPABLE_DECODING) { | 
 | 
                    return withResult(CoderResult.unmappableForLength(1),  | 
 | 
                               src, sp, dst, dp);  | 
 | 
                }  | 
 | 
                da[dp++] = c;  | 
 | 
                sp++;  | 
 | 
            }  | 
 | 
            return withResult(cr, src, sp, dst, dp);  | 
 | 
        }  | 
 | 
 | 
 | 
        private CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) { | 
 | 
            int mark = src.position();  | 
 | 
            try { | 
 | 
                while (src.hasRemaining()) { | 
 | 
                    char c = decode(src.get());  | 
 | 
                    if (c == UNMAPPABLE_DECODING)  | 
 | 
                        return CoderResult.unmappableForLength(1);  | 
 | 
                    if (!dst.hasRemaining())  | 
 | 
                        return CoderResult.OVERFLOW;  | 
 | 
                    dst.put(c);  | 
 | 
                    mark++;  | 
 | 
                }  | 
 | 
                return CoderResult.UNDERFLOW;  | 
 | 
            } finally { | 
 | 
                src.position(mark);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) { | 
 | 
            if (src.hasArray() && dst.hasArray())  | 
 | 
                return decodeArrayLoop(src, dst);  | 
 | 
            else  | 
 | 
                return decodeBufferLoop(src, dst);  | 
 | 
        }  | 
 | 
 | 
 | 
        public final char decode(int b) { | 
 | 
            return b2c[b + 128];  | 
 | 
        }  | 
 | 
 | 
 | 
        private char repl = '\uFFFD';  | 
 | 
        protected void implReplaceWith(String newReplacement) { | 
 | 
            repl = newReplacement.charAt(0);  | 
 | 
        }  | 
 | 
 | 
 | 
        public int decode(byte[] src, int sp, int len, char[] dst) { | 
 | 
            if (len > dst.length)  | 
 | 
                len = dst.length;  | 
 | 
            int dp = 0;  | 
 | 
            while (dp < len) { | 
 | 
                dst[dp] = decode(src[sp++]);  | 
 | 
                if (dst[dp] == UNMAPPABLE_DECODING) { | 
 | 
                    dst[dp] = repl;  | 
 | 
                }  | 
 | 
                dp++;  | 
 | 
            }  | 
 | 
            return dp;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    final public static class Encoder extends CharsetEncoder  | 
 | 
                                      implements ArrayEncoder { | 
 | 
        private Surrogate.Parser sgp;  | 
 | 
        private final char[] c2b;  | 
 | 
        private final char[] c2bIndex;  | 
 | 
 | 
 | 
        public Encoder(Charset cs, char[] c2b, char[] c2bIndex) { | 
 | 
            super(cs, 1.0f, 1.0f);  | 
 | 
            this.c2b = c2b;  | 
 | 
            this.c2bIndex = c2bIndex;  | 
 | 
        }  | 
 | 
 | 
 | 
        public boolean canEncode(char c) { | 
 | 
            return encode(c) != UNMAPPABLE_ENCODING;  | 
 | 
        }  | 
 | 
 | 
 | 
        public boolean isLegalReplacement(byte[] repl) { | 
 | 
            return ((repl.length == 1 && repl[0] == (byte)'?') ||  | 
 | 
                    super.isLegalReplacement(repl));  | 
 | 
        }  | 
 | 
 | 
 | 
        private CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) { | 
 | 
            char[] sa = src.array();  | 
 | 
            int sp = src.arrayOffset() + src.position();  | 
 | 
            int sl = src.arrayOffset() + src.limit();  | 
 | 
 | 
 | 
            byte[] da = dst.array();  | 
 | 
            int dp = dst.arrayOffset() + dst.position();  | 
 | 
            int dl = dst.arrayOffset() + dst.limit();  | 
 | 
 | 
 | 
            CoderResult cr = CoderResult.UNDERFLOW;  | 
 | 
            if ((dl - dp) < (sl - sp)) { | 
 | 
                sl = sp + (dl - dp);  | 
 | 
                cr = CoderResult.OVERFLOW;  | 
 | 
            }  | 
 | 
 | 
 | 
            while (sp < sl) { | 
 | 
                char c = sa[sp];  | 
 | 
                int b = encode(c);  | 
 | 
                if (b == UNMAPPABLE_ENCODING) { | 
 | 
                    if (Character.isSurrogate(c)) { | 
 | 
                        if (sgp == null)  | 
 | 
                            sgp = new Surrogate.Parser();  | 
 | 
                        if (sgp.parse(c, sa, sp, sl) < 0)  | 
 | 
                            return withResult(sgp.error(), src, sp, dst, dp);  | 
 | 
                        return withResult(sgp.unmappableResult(), src, sp, dst, dp);  | 
 | 
                    }  | 
 | 
                    return withResult(CoderResult.unmappableForLength(1),  | 
 | 
                               src, sp, dst, dp);  | 
 | 
                }  | 
 | 
                da[dp++] = (byte)b;  | 
 | 
                sp++;  | 
 | 
            }  | 
 | 
            return withResult(cr, src, sp, dst, dp);  | 
 | 
        }  | 
 | 
 | 
 | 
        private CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) { | 
 | 
            int mark = src.position();  | 
 | 
            try { | 
 | 
                while (src.hasRemaining()) { | 
 | 
                    char c = src.get();  | 
 | 
                    int b = encode(c);  | 
 | 
                    if (b == UNMAPPABLE_ENCODING) { | 
 | 
                        if (Character.isSurrogate(c)) { | 
 | 
                            if (sgp == null)  | 
 | 
                                sgp = new Surrogate.Parser();  | 
 | 
                            if (sgp.parse(c, src) < 0)  | 
 | 
                                return sgp.error();  | 
 | 
                            return sgp.unmappableResult();  | 
 | 
                        }  | 
 | 
                        return CoderResult.unmappableForLength(1);  | 
 | 
                    }  | 
 | 
                    if (!dst.hasRemaining())  | 
 | 
                        return CoderResult.OVERFLOW;  | 
 | 
                    dst.put((byte)b);  | 
 | 
                    mark++;  | 
 | 
                }  | 
 | 
                return CoderResult.UNDERFLOW;  | 
 | 
            } finally { | 
 | 
                src.position(mark);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) { | 
 | 
            if (src.hasArray() && dst.hasArray())  | 
 | 
                return encodeArrayLoop(src, dst);  | 
 | 
            else  | 
 | 
                return encodeBufferLoop(src, dst);  | 
 | 
        }  | 
 | 
 | 
 | 
        public final int encode(char ch) { | 
 | 
            char index = c2bIndex[ch >> 8];  | 
 | 
            if (index == UNMAPPABLE_ENCODING)  | 
 | 
                return UNMAPPABLE_ENCODING;  | 
 | 
            return c2b[index + (ch & 0xff)];  | 
 | 
        }  | 
 | 
 | 
 | 
        private byte repl = (byte)'?';  | 
 | 
        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;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    public static void initC2B(char[] b2c, char[] c2bNR,  | 
 | 
                               char[] c2b, char[] c2bIndex) { | 
 | 
        for (int i = 0; i < c2bIndex.length; i++)  | 
 | 
            c2bIndex[i] = UNMAPPABLE_ENCODING;  | 
 | 
        for (int i = 0; i < c2b.length; i++)  | 
 | 
            c2b[i] = UNMAPPABLE_ENCODING;  | 
 | 
        int off = 0;  | 
 | 
        for (int i = 0; i < b2c.length; i++) { | 
 | 
            char c = b2c[i];  | 
 | 
            if (c == UNMAPPABLE_DECODING)  | 
 | 
                continue;  | 
 | 
            int index = (c >> 8);  | 
 | 
            if (c2bIndex[index] == UNMAPPABLE_ENCODING) { | 
 | 
                c2bIndex[index] = (char)off;  | 
 | 
                off += 0x100;  | 
 | 
            }  | 
 | 
            index = c2bIndex[index] + (c & 0xff);  | 
 | 
            c2b[index] = (char)((i>=0x80)?(i-0x80):(i+0x80));  | 
 | 
        }  | 
 | 
        if (c2bNR != null) { | 
 | 
              | 
 | 
            int i = 0;  | 
 | 
            while (i < c2bNR.length) { | 
 | 
                char b = c2bNR[i++];  | 
 | 
                char c = c2bNR[i++];  | 
 | 
                int index = (c >> 8);  | 
 | 
                if (c2bIndex[index] == UNMAPPABLE_ENCODING) { | 
 | 
                    c2bIndex[index] = (char)off;  | 
 | 
                    off += 0x100;  | 
 | 
                }  | 
 | 
                index = c2bIndex[index] + (c & 0xff);  | 
 | 
                c2b[index] = b;  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
}  |