1/* 2 * Copyright (c) 2000, 2010, 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 26package sun.nio.cs; 27 28import java.nio.*; 29import java.nio.charset.*; 30 31/** 32 * Base class for different flavors of UTF-16 encoders 33 */ 34public abstract class UnicodeEncoder extends CharsetEncoder { 35 36 protected static final char BYTE_ORDER_MARK = '\uFEFF'; 37 protected static final char REVERSED_MARK = '\uFFFE'; 38 39 protected static final int BIG = 0; 40 protected static final int LITTLE = 1; 41 42 private int byteOrder; /* Byte order in use */ 43 private boolean usesMark; /* Write an initial BOM */ 44 private boolean needsMark; 45 46 protected UnicodeEncoder(Charset cs, int bo, boolean m) { 47 super(cs, 2.0f, 48 // Four bytes max if you need a BOM 49 m ? 4.0f : 2.0f, 50 // Replacement depends upon byte order 51 ((bo == BIG) 52 ? new byte[] { (byte)0xff, (byte)0xfd } 53 : new byte[] { (byte)0xfd, (byte)0xff })); 54 usesMark = needsMark = m; 55 byteOrder = bo; 56 } 57 58 private void put(char c, ByteBuffer dst) { 59 if (byteOrder == BIG) { 60 dst.put((byte)(c >> 8)); 61 dst.put((byte)(c & 0xff)); 62 } else { 63 dst.put((byte)(c & 0xff)); 64 dst.put((byte)(c >> 8)); 65 } 66 } 67 68 private final Surrogate.Parser sgp = new Surrogate.Parser(); 69 70 protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) { 71 int mark = src.position(); 72 73 if (needsMark && src.hasRemaining()) { 74 if (dst.remaining() < 2) 75 return CoderResult.OVERFLOW; 76 put(BYTE_ORDER_MARK, dst); 77 needsMark = false; 78 } 79 try { 80 while (src.hasRemaining()) { 81 char c = src.get(); 82 if (!Character.isSurrogate(c)) { 83 if (dst.remaining() < 2) 84 return CoderResult.OVERFLOW; 85 mark++; 86 put(c, dst); 87 continue; 88 } 89 int d = sgp.parse(c, src); 90 if (d < 0) 91 return sgp.error(); 92 if (dst.remaining() < 4) 93 return CoderResult.OVERFLOW; 94 mark += 2; 95 put(Character.highSurrogate(d), dst); 96 put(Character.lowSurrogate(d), dst); 97 } 98 return CoderResult.UNDERFLOW; 99 } finally { 100 src.position(mark); 101 } 102 } 103 104 protected void implReset() { 105 needsMark = usesMark; 106 } 107 108 public boolean canEncode(char c) { 109 return ! Character.isSurrogate(c); 110 } 111} 112