1 /* 2 * Copyright (c) 2000, 2004, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.nio.cs; 27 28 import java.nio.ByteBuffer; 29 import java.nio.CharBuffer; 30 import java.nio.charset.Charset; 31 import java.nio.charset.CharsetDecoder; 32 import java.nio.charset.CharsetEncoder; 33 import java.nio.charset.CoderResult; 34 import java.util.Arrays; 35 36 public class US_ASCII 37 extends Charset 38 implements HistoricallyNamedCharset 39 { 40 41 public US_ASCII() { 42 super("US-ASCII", StandardCharsets.aliases_US_ASCII); 43 } 44 45 public String historicalName() { 46 return "ASCII"; 47 } 48 49 public boolean contains(Charset cs) { 50 return (cs instanceof US_ASCII); 51 } 52 53 public CharsetDecoder newDecoder() { 54 return new Decoder(this); 55 } 56 57 public CharsetEncoder newEncoder() { 58 return new Encoder(this); 59 } 60 61 private static class Decoder extends CharsetDecoder 62 implements ArrayDecoder { 63 64 private Decoder(Charset cs) { 65 super(cs, 1.0f, 1.0f); 66 } 67 68 private CoderResult decodeArrayLoop(ByteBuffer src, 69 CharBuffer dst) 70 { 71 byte[] sa = src.array(); 72 int sp = src.arrayOffset() + src.position(); 73 int sl = src.arrayOffset() + src.limit(); 74 assert (sp <= sl); 75 sp = (sp <= sl ? sp : sl); 76 char[] da = dst.array(); 77 int dp = dst.arrayOffset() + dst.position(); 78 int dl = dst.arrayOffset() + dst.limit(); 79 assert (dp <= dl); 80 dp = (dp <= dl ? dp : dl); 81 82 try { 83 while (sp < sl) { 84 byte b = sa[sp]; 85 if (b >= 0) { 86 if (dp >= dl) 87 return CoderResult.OVERFLOW; 88 da[dp++] = (char)b; 89 sp++; 90 continue; 91 } 92 return CoderResult.malformedForLength(1); 93 } 94 return CoderResult.UNDERFLOW; 95 } finally { 96 src.position(sp - src.arrayOffset()); 97 dst.position(dp - dst.arrayOffset()); 98 } 99 } 100 101 private CoderResult decodeBufferLoop(ByteBuffer src, 102 CharBuffer dst) 103 { 104 int mark = src.position(); 105 try { 106 while (src.hasRemaining()) { 107 byte b = src.get(); 108 if (b >= 0) { 109 if (!dst.hasRemaining()) 110 return CoderResult.OVERFLOW; 111 dst.put((char)b); 112 mark++; 113 continue; 114 } 115 return CoderResult.malformedForLength(1); 116 } 117 return CoderResult.UNDERFLOW; 118 } finally { 119 src.position(mark); 120 } 121 } 122 123 protected CoderResult decodeLoop(ByteBuffer src, 124 CharBuffer dst) 125 { 126 if (src.hasArray() && dst.hasArray()) 127 return decodeArrayLoop(src, dst); 128 else 129 return decodeBufferLoop(src, dst); 130 } 131 132 private char repl = '\uFFFD'; 133 protected void implReplaceWith(String newReplacement) { 134 repl = newReplacement.charAt(0); 135 } 136 137 public int decode(byte[] src, int sp, int len, char[] dst) { 138 int dp = 0; 139 len = Math.min(len, dst.length); 140 while (dp < len) { 141 byte b = src[sp++]; 142 if (b >= 0) 143 dst[dp++] = (char)b; 144 else 145 dst[dp++] = repl; 146 } 147 return dp; 148 } 149 150 public boolean isASCIICompatible() { 151 return true; 152 } 153 } 154 155 private static class Encoder extends CharsetEncoder 156 implements ArrayEncoder { 157 158 private Encoder(Charset cs) { 159 super(cs, 1.0f, 1.0f); 160 } 161 162 public boolean canEncode(char c) { 163 return c < 0x80; 164 } 165 166 public boolean isLegalReplacement(byte[] repl) { 167 return (repl.length == 1 && repl[0] >= 0) || 168 super.isLegalReplacement(repl); 169 } 170 171 private final Surrogate.Parser sgp = new Surrogate.Parser(); 172 private CoderResult encodeArrayLoop(CharBuffer src, 173 ByteBuffer dst) 174 { 175 char[] sa = src.array(); 176 int sp = src.arrayOffset() + src.position(); 177 int sl = src.arrayOffset() + src.limit(); 178 assert (sp <= sl); 179 sp = (sp <= sl ? sp : sl); 180 byte[] da = dst.array(); 181 int dp = dst.arrayOffset() + dst.position(); 182 int dl = dst.arrayOffset() + dst.limit(); 183 assert (dp <= dl); 184 dp = (dp <= dl ? dp : dl); 185 186 try { 187 while (sp < sl) { 188 char c = sa[sp]; 189 if (c < 0x80) { 190 if (dp >= dl) 191 return CoderResult.OVERFLOW; 192 da[dp] = (byte)c; 193 sp++; dp++; 194 continue; 195 } 196 if (sgp.parse(c, sa, sp, sl) < 0) 197 return sgp.error(); 198 return sgp.unmappableResult(); 199 } 200 return CoderResult.UNDERFLOW; 201 } finally { 202 src.position(sp - src.arrayOffset()); 203 dst.position(dp - dst.arrayOffset()); 204 } 205 } 206 207 private CoderResult encodeBufferLoop(CharBuffer src, 208 ByteBuffer dst) 209 { 210 int mark = src.position(); 211 try { 212 while (src.hasRemaining()) { 213 char c = src.get(); 214 if (c < 0x80) { 215 if (!dst.hasRemaining()) 216 return CoderResult.OVERFLOW; 217 dst.put((byte)c); 218 mark++; 219 continue; 220 } 221 if (sgp.parse(c, src) < 0) 222 return sgp.error(); 223 return sgp.unmappableResult(); 224 } 225 return CoderResult.UNDERFLOW; 226 } finally { 227 src.position(mark); 228 } 229 } 230 231 protected CoderResult encodeLoop(CharBuffer src, 232 ByteBuffer dst) 233 { 234 if (src.hasArray() && dst.hasArray()) 235 return encodeArrayLoop(src, dst); 236 else 237 return encodeBufferLoop(src, dst); 238 } 239 240 private byte repl = (byte)'?'; 241 protected void implReplaceWith(byte[] newReplacement) { 242 repl = newReplacement[0]; 243 } 244 245 public int encode(char[] src, int sp, int len, byte[] dst) { 246 int dp = 0; 247 int sl = sp + Math.min(len, dst.length); 248 while (sp < sl) { 249 char c = src[sp++]; 250 if (c < 0x80) { 251 dst[dp++] = (byte)c; 252 continue; 253 } 254 if (Character.isHighSurrogate(c) && sp < sl && 255 Character.isLowSurrogate(src[sp])) { 256 if (len > dst.length) { 257 sl++; 258 len--; 259 } 260 sp++; 261 } 262 dst[dp++] = repl; 263 } 264 return dp; 265 } 266 267 public boolean isASCIICompatible() { 268 return true; 269 } 270 } 271 272 }