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