src/java.base/share/classes/sun/nio/cs/DoubleByte.java

Print this page

        

@@ -113,10 +113,11 @@
     {
         final char[][] b2c;
         final char[] b2cSB;
         final int b2Min;
         final int b2Max;
+        final boolean isASCIICompatible;
 
         // for SimpleEUC override
         protected CoderResult crMalformedOrUnderFlow(int b) {
             return CoderResult.UNDERFLOW;
         }

@@ -130,20 +131,27 @@
             return CoderResult.unmappableForLength(2);
         }
 
         public Decoder(Charset cs, float avgcpb, float maxcpb,
                        char[][] b2c, char[] b2cSB,
-                       int b2Min, int b2Max) {
+                       int b2Min, int b2Max,
+                       boolean isASCIICompatible) {
             super(cs, avgcpb, maxcpb);
             this.b2c = b2c;
             this.b2cSB = b2cSB;
             this.b2Min = b2Min;
             this.b2Max = b2Max;
+            this.isASCIICompatible = isASCIICompatible;
+        }
+
+        public Decoder(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max,
+                       boolean isASCIICompatible) {
+            this(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max, isASCIICompatible);
         }
 
         public Decoder(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
-            this(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max);
+            this(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max, false);
         }
 
         protected CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
             byte[] sa = src.array();
             int sp = src.arrayOffset() + src.position();

@@ -213,10 +221,11 @@
                 return decodeArrayLoop(src, dst);
             else
                 return decodeBufferLoop(src, dst);
         }
 
+        @Override
         public int decode(byte[] src, int sp, int len, char[] dst) {
             int dp = 0;
             int sl = sp + len;
             char repl = replacement().charAt(0);
             while (sp < sl) {

@@ -241,10 +250,15 @@
                 dst[dp++] = c;
             }
             return dp;
         }
 
+        @Override
+        public boolean isASCIICompatible() {
+            return isASCIICompatible;
+        }
+
         public void implReset() {
             super.implReset();
         }
 
         public CoderResult implFlush(CharBuffer out) {

@@ -272,12 +286,18 @@
         private static final int SO = 0x0e;
         private static final int SI = 0x0f;
         private int  currentState;
 
         public Decoder_EBCDIC(Charset cs,
+                              char[][] b2c, char[] b2cSB, int b2Min, int b2Max,
+                              boolean isASCIICompatible) {
+            super(cs, b2c, b2cSB, b2Min, b2Max, isASCIICompatible);
+        }
+
+        public Decoder_EBCDIC(Charset cs,
                        char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
-            super(cs, b2c, b2cSB, b2Min, b2Max);
+            super(cs, b2c, b2cSB, b2Min, b2Max, false);
         }
 
         public void implReset() {
             currentState = SBCS;
         }

@@ -401,10 +421,11 @@
             } finally {
                 src.position(mark);
             }
         }
 
+        @Override
         public int decode(byte[] src, int sp, int len, char[] dst) {
             int dp = 0;
             int sl = sp + len;
             currentState = SBCS;
             char repl = replacement().charAt(0);

@@ -449,12 +470,17 @@
         static final char[] b2cSB_UNMAPPABLE;
         static {
             b2cSB_UNMAPPABLE = new char[0x100];
             Arrays.fill(b2cSB_UNMAPPABLE, UNMAPPABLE_DECODING);
         }
+        public Decoder_DBCSONLY(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max,
+                                boolean isASCIICompatible) {
+            super(cs, 0.5f, 1.0f, b2c, b2cSB_UNMAPPABLE, b2Min, b2Max, isASCIICompatible);
+        }
+
         public Decoder_DBCSONLY(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
-            super(cs, 0.5f, 1.0f, b2c, b2cSB_UNMAPPABLE, b2Min, b2Max);
+            super(cs, 0.5f, 1.0f, b2c, b2cSB_UNMAPPABLE, b2Min, b2Max, false);
         }
     }
 
     // EUC_SIMPLE
     // The only thing we need to "override" is to check SS2/SS3 and

@@ -462,12 +488,13 @@
     public static class Decoder_EUC_SIM extends Decoder {
         private final int SS2 =  0x8E;
         private final int SS3 =  0x8F;
 
         public Decoder_EUC_SIM(Charset cs,
-                        char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
-            super(cs, b2c, b2cSB, b2Min, b2Max);
+                               char[][] b2c, char[] b2cSB, int b2Min, int b2Max,
+                               boolean isASCIICompatible) {
+            super(cs, b2c, b2cSB, b2Min, b2Max, isASCIICompatible);
         }
 
         // No support provided for G2/G3 for SimpleEUC
         protected CoderResult crMalformedOrUnderFlow(int b) {
             if (b == SS2 || b == SS3 )

@@ -479,10 +506,11 @@
             if (b1 == SS2 || b1 == SS3 )
                 return CoderResult.malformedForLength(1);
             return CoderResult.unmappableForLength(2);
         }
 
+        @Override
         public int decode(byte[] src, int sp, int len, char[] dst) {
             int dp = 0;
             int sl = sp + len;
             char repl = replacement().charAt(0);
             while (sp < sl) {

@@ -513,21 +541,29 @@
     {
         protected final int MAX_SINGLEBYTE = 0xff;
         private final char[] c2b;
         private final char[] c2bIndex;
         protected Surrogate.Parser sgp;
+        final boolean isASCIICompatible;
 
         public Encoder(Charset cs, char[] c2b, char[] c2bIndex) {
+            this(cs, c2b, c2bIndex, false);
+        }
+
+        public Encoder(Charset cs, char[] c2b, char[] c2bIndex, boolean isASCIICompatible) {
             super(cs, 2.0f, 2.0f);
             this.c2b = c2b;
             this.c2bIndex = c2bIndex;
+            this.isASCIICompatible = isASCIICompatible;
         }
 
-        public Encoder(Charset cs, float avg, float max, byte[] repl, char[] c2b, char[] c2bIndex) {
+        public Encoder(Charset cs, float avg, float max, byte[] repl, char[] c2b, char[] c2bIndex,
+                       boolean isASCIICompatible) {
             super(cs, avg, max, repl);
             this.c2b = c2b;
             this.c2bIndex = c2bIndex;
+            this.isASCIICompatible = isASCIICompatible;
         }
 
         public boolean canEncode(char c) {
             return encodeChar(c) != UNMAPPABLE_ENCODING;
         }

@@ -622,10 +658,11 @@
         protected byte[] repl = replacement();
         protected void implReplaceWith(byte[] newReplacement) {
             repl = newReplacement;
         }
 
+        @Override
         public int encode(char[] src, int sp, int len, byte[] dst) {
             int dp = 0;
             int sl = sp + len;
             int dl = dst.length;
             while (sp < sl) {

@@ -645,15 +682,73 @@
                     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;
+            int sl = sp + len;
+            while (sp < sl) {
+                char c = (char)(src[sp++] & 0xff);
+                int bb = encodeChar(c);
+                if (bb == UNMAPPABLE_ENCODING) {
+                    // no surrogate pair in latin1 string
+                    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 encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
+            int dp = 0;
+            int sl = sp + len;
+            while (sp < sl) {
+                char c = StringUTF16.getChar(src, sp++);
+                int bb = encodeChar(c);
+                if (bb == UNMAPPABLE_ENCODING) {
+                    if (Character.isHighSurrogate(c) && sp < sl &&
+                        Character.isLowSurrogate(StringUTF16.getChar(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 boolean isASCIICompatible() {
+            return isASCIICompatible;
+        }
+
         public int encodeChar(char ch) {
             return c2b[c2bIndex[ch >> 8] + (ch & 0xff)];
         }
 
         // init the c2b and c2bIndex tables from b2c.

@@ -739,35 +834,36 @@
             }
         }
     }
 
     public static class Encoder_DBCSONLY extends Encoder {
+
         public Encoder_DBCSONLY(Charset cs, byte[] repl,
-                         char[] c2b, char[] c2bIndex) {
-            super(cs, 2.0f, 2.0f, repl, c2b, c2bIndex);
+                                char[] c2b, char[] c2bIndex,
+                                boolean isASCIICompatible) {
+            super(cs, 2.0f, 2.0f, repl, c2b, c2bIndex, isASCIICompatible);
         }
 
         public int encodeChar(char ch) {
             int bb = super.encodeChar(ch);
             if (bb <= MAX_SINGLEBYTE)
                 return UNMAPPABLE_ENCODING;
             return bb;
         }
     }
 
-
-
     public static class Encoder_EBCDIC extends Encoder {
         static final int SBCS = 0;
         static final int DBCS = 1;
         static final byte SO = 0x0e;
         static final byte SI = 0x0f;
 
         protected int  currentState = SBCS;
 
-        public Encoder_EBCDIC(Charset cs, char[] c2b, char[] c2bIndex) {
-            super(cs, 4.0f, 5.0f, new byte[] {(byte)0x6f}, c2b, c2bIndex);
+        public Encoder_EBCDIC(Charset cs, char[] c2b, char[] c2bIndex,
+                              boolean isASCIICompatible) {
+            super(cs, 4.0f, 5.0f, new byte[] {(byte)0x6f}, c2b, c2bIndex, isASCIICompatible);
         }
 
         protected void implReset() {
             currentState = SBCS;
         }

@@ -876,10 +972,11 @@
             } finally {
                 src.position(mark);
             }
         }
 
+        @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++];

@@ -915,15 +1012,91 @@
                  currentState = SBCS;
                  dst[dp++] = SI;
             }
             return dp;
         }
+
+        @Override
+        public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
+            int dp = 0;
+            int sl = sp + len;
+            while (sp < sl) {
+                char c = (char)(src[sp++] & 0xff);
+                int bb = encodeChar(c);
+                if (bb == UNMAPPABLE_ENCODING) {
+                    // no surrogate pair in latin1 string
+                    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 encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
+            int dp = 0;
+            int sl = sp + len;
+            while (sp < sl) {
+                char c = StringUTF16.getChar(src, sp++);
+                int bb = encodeChar(c);
+                if (bb == UNMAPPABLE_ENCODING) {
+                    if (Character.isHighSurrogate(c) && sp < sl &&
+                        Character.isLowSurrogate(StringUTF16.getChar(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;
+        }
     }
 
     // EUC_SIMPLE
     public static class Encoder_EUC_SIM extends Encoder {
-        public Encoder_EUC_SIM(Charset cs, char[] c2b, char[] c2bIndex) {
-            super(cs, c2b, c2bIndex);
+        public Encoder_EUC_SIM(Charset cs, char[] c2b, char[] c2bIndex,
+                               boolean isASCIICompatible) {
+            super(cs, c2b, c2bIndex, isASCIICompatible);
         }
     }
 
 }