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