jdk/src/share/classes/sun/nio/cs/SingleByte.java
changeset 1713 f8b8bfa64fc1
child 2294 4259115772f7
equal deleted inserted replaced
1712:8664f15a755b 1713:f8b8bfa64fc1
       
     1 /*
       
     2  * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package sun.nio.cs;
       
    27 
       
    28 import java.nio.Buffer;
       
    29 import java.nio.ByteBuffer;
       
    30 import java.nio.CharBuffer;
       
    31 import java.nio.charset.Charset;
       
    32 import java.nio.charset.CharsetDecoder;
       
    33 import java.nio.charset.CharsetEncoder;
       
    34 import java.nio.charset.CoderResult;
       
    35 import static sun.nio.cs.CharsetMapping.*;
       
    36 
       
    37 public class SingleByte
       
    38 {
       
    39     private static final CoderResult withResult(CoderResult cr,
       
    40                                                 Buffer src, int sp,
       
    41                                                 Buffer dst, int dp)
       
    42     {
       
    43         src.position(sp - src.arrayOffset());
       
    44         dst.position(dp - dst.arrayOffset());
       
    45         return cr;
       
    46     }
       
    47 
       
    48     public static class Decoder extends CharsetDecoder {
       
    49         private final char[] b2c;
       
    50 
       
    51         public Decoder(Charset cs, char[] b2c) {
       
    52             super(cs, 1.0f, 1.0f);
       
    53             this.b2c = b2c;
       
    54         }
       
    55 
       
    56         private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
       
    57             byte[] sa = src.array();
       
    58             int sp = src.arrayOffset() + src.position();
       
    59             int sl = src.arrayOffset() + src.limit();
       
    60 
       
    61             char[] da = dst.array();
       
    62             int dp = dst.arrayOffset() + dst.position();
       
    63             int dl = dst.arrayOffset() + dst.limit();
       
    64 
       
    65             CoderResult cr = CoderResult.UNDERFLOW;
       
    66             if ((dl - dp) < (sl - sp)) {
       
    67                 sl = sp + (dl - dp);
       
    68                 cr = CoderResult.OVERFLOW;
       
    69             }
       
    70 
       
    71             while (sp < sl) {
       
    72                 char c = decode(sa[sp]);
       
    73                 if (c == UNMAPPABLE_DECODING) {
       
    74                     return withResult(CoderResult.unmappableForLength(1),
       
    75                                src, sp, dst, dp);
       
    76                 }
       
    77                 da[dp++] = c;
       
    78                 sp++;
       
    79             }
       
    80             return withResult(cr, src, sp, dst, dp);
       
    81         }
       
    82 
       
    83         private CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) {
       
    84             int mark = src.position();
       
    85             try {
       
    86                 while (src.hasRemaining()) {
       
    87                     char c = decode(src.get());
       
    88                     if (c == UNMAPPABLE_DECODING)
       
    89                         return CoderResult.unmappableForLength(1);
       
    90                     if (!dst.hasRemaining())
       
    91                         return CoderResult.OVERFLOW;
       
    92                     dst.put(c);
       
    93                     mark++;
       
    94                 }
       
    95                 return CoderResult.UNDERFLOW;
       
    96             } finally {
       
    97                 src.position(mark);
       
    98             }
       
    99         }
       
   100 
       
   101         protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
       
   102             if (src.hasArray() && dst.hasArray())
       
   103                 return decodeArrayLoop(src, dst);
       
   104             else
       
   105                 return decodeBufferLoop(src, dst);
       
   106         }
       
   107 
       
   108         private final char decode(int b) {
       
   109             return b2c[b + 128];
       
   110         }
       
   111     }
       
   112 
       
   113     public static class Encoder extends CharsetEncoder {
       
   114         private Surrogate.Parser sgp;
       
   115         private final char[] c2b;
       
   116         private final char[] c2bIndex;
       
   117 
       
   118         public Encoder(Charset cs, char[] c2b, char[] c2bIndex) {
       
   119             super(cs, 1.0f, 1.0f);
       
   120             this.c2b = c2b;
       
   121             this.c2bIndex = c2bIndex;
       
   122         }
       
   123 
       
   124         public boolean canEncode(char c) {
       
   125             return encode(c) != UNMAPPABLE_ENCODING;
       
   126         }
       
   127 
       
   128         private CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) {
       
   129             char[] sa = src.array();
       
   130             int sp = src.arrayOffset() + src.position();
       
   131             int sl = src.arrayOffset() + src.limit();
       
   132 
       
   133             byte[] da = dst.array();
       
   134             int dp = dst.arrayOffset() + dst.position();
       
   135             int dl = dst.arrayOffset() + dst.limit();
       
   136 
       
   137             CoderResult cr = CoderResult.UNDERFLOW;
       
   138             if ((dl - dp) < (sl - sp)) {
       
   139                 sl = sp + (dl - dp);
       
   140                 cr = CoderResult.OVERFLOW;
       
   141             }
       
   142 
       
   143             while (sp < sl) {
       
   144                 char c = sa[sp];
       
   145                 int b = encode(c);
       
   146                 if (b == UNMAPPABLE_ENCODING) {
       
   147                     if (Surrogate.is(c)) {
       
   148                         if (sgp == null)
       
   149                             sgp = new Surrogate.Parser();
       
   150                         if (sgp.parse(c, sa, sp, sl) < 0)
       
   151                             return withResult(sgp.error(), src, sp, dst, dp);
       
   152                         return withResult(sgp.unmappableResult(), src, sp, dst, dp);
       
   153                     }
       
   154                     return withResult(CoderResult.unmappableForLength(1),
       
   155                                src, sp, dst, dp);
       
   156                 }
       
   157                 da[dp++] = (byte)b;
       
   158                 sp++;
       
   159             }
       
   160             return withResult(cr, src, sp, dst, dp);
       
   161         }
       
   162 
       
   163         private CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) {
       
   164             int mark = src.position();
       
   165             try {
       
   166                 while (src.hasRemaining()) {
       
   167                     char c = src.get();
       
   168                     int b = encode(c);
       
   169                     if (b == UNMAPPABLE_ENCODING) {
       
   170                         if (Surrogate.is(c)) {
       
   171                             if (sgp == null)
       
   172                                 sgp = new Surrogate.Parser();
       
   173                             if (sgp.parse(c, src) < 0)
       
   174                                 return sgp.error();
       
   175                             return sgp.unmappableResult();
       
   176                         }
       
   177                         return CoderResult.unmappableForLength(1);
       
   178                     }
       
   179                     if (!dst.hasRemaining())
       
   180                         return CoderResult.OVERFLOW;
       
   181                     dst.put((byte)b);
       
   182                     mark++;
       
   183                 }
       
   184                 return CoderResult.UNDERFLOW;
       
   185             } finally {
       
   186                 src.position(mark);
       
   187             }
       
   188         }
       
   189 
       
   190         protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
       
   191             if (src.hasArray() && dst.hasArray())
       
   192                 return encodeArrayLoop(src, dst);
       
   193             else
       
   194                 return encodeBufferLoop(src, dst);
       
   195         }
       
   196 
       
   197         private final int encode(char ch) {
       
   198             char index = c2bIndex[ch >> 8];
       
   199             if (index == UNMAPPABLE_ENCODING)
       
   200                 return UNMAPPABLE_ENCODING;
       
   201             return c2b[index + (ch & 0xff)];
       
   202         }
       
   203     }
       
   204 
       
   205     // init the c2b and c2bIndex tables from b2c.
       
   206     public static void initC2B(char[] b2c, char[] c2bNR,
       
   207                                char[] c2b, char[] c2bIndex) {
       
   208         for (int i = 0; i < c2bIndex.length; i++)
       
   209             c2bIndex[i] = UNMAPPABLE_ENCODING;
       
   210         for (int i = 0; i < c2b.length; i++)
       
   211             c2b[i] = UNMAPPABLE_ENCODING;
       
   212         int off = 0;
       
   213         for (int i = 0; i < b2c.length; i++) {
       
   214             char c = b2c[i];
       
   215             if (c == UNMAPPABLE_DECODING)
       
   216                 continue;
       
   217             int index = (c >> 8);
       
   218             if (c2bIndex[index] == UNMAPPABLE_ENCODING) {
       
   219                 c2bIndex[index] = (char)off;
       
   220                 off += 0x100;
       
   221             }
       
   222             index = c2bIndex[index] + (c & 0xff);
       
   223             c2b[index] = (char)((i>=0x80)?(i-0x80):(i+0x80));
       
   224         }
       
   225         if (c2bNR != null) {
       
   226             // c-->b nr entries
       
   227             int i = 0;
       
   228             while (i < c2bNR.length) {
       
   229                 char b = c2bNR[i++];
       
   230                 char c = c2bNR[i++];
       
   231                 int index = (c >> 8);
       
   232                 if (c2bIndex[index] == UNMAPPABLE_ENCODING) {
       
   233                     c2bIndex[index] = (char)off;
       
   234                     off += 0x100;
       
   235                 }
       
   236                 index = c2bIndex[index] + (c & 0xff);
       
   237                 c2b[index] = b;
       
   238             }
       
   239         }
       
   240     }
       
   241 }