151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1995, 2005, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.misc; 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.InputStream; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.ByteArrayInputStream; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.OutputStream; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.ByteArrayOutputStream; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.PrintStream; 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException; 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.ByteBuffer; 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This class defines the encoding half of character encoders. 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A character encoder is an algorithim for transforming 8 bit binary 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * data into text (generally 7 bit ASCII or 8 bit ISO-Latin-1 text) 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * for transmition over text channels such as e-mail and network news. 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The character encoders have been structured around a central theme 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * that, in general, the encoded text has the form: 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre> 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * [Buffer Prefix] 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * [Line Prefix][encoded data atoms][Line Suffix] 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * [Buffer Suffix] 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre> 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * In the CharacterEncoder and CharacterDecoder classes, one complete 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * chunk of data is referred to as a <i>buffer</i>. Encoded buffers 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are all text, and decoded buffers (sometimes just referred to as 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * buffers) are binary octets. 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * To create a custom encoder, you must, at a minimum, overide three 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * abstract methods in this class. 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <DL> 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <DD>bytesPerAtom which tells the encoder how many bytes to 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * send to encodeAtom 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <DD>encodeAtom which encodes the bytes sent to it as text. 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <DD>bytesPerLine which tells the encoder the maximum number of 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * bytes per line. 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </DL> 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Several useful encoders have already been written and are 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * referenced in the See Also list below. 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Chuck McManis 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see CharacterDecoder; 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see UCEncoder 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see UUEncoder 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see BASE64Encoder 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic abstract class CharacterEncoder { 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Stream that understands "printing" */ 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected PrintStream pStream; 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Return the number of bytes per atom of encoding */ 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski abstract protected int bytesPerAtom(); 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Return the number of bytes that can be encoded per line */ 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski abstract protected int bytesPerLine(); 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Encode the prefix for the entire buffer. By default is simply 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * opens the PrintStream for use by the other functions. 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected void encodeBufferPrefix(OutputStream aStream) throws IOException { 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pStream = new PrintStream(aStream); 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Encode the suffix for the entire buffer. 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected void encodeBufferSuffix(OutputStream aStream) throws IOException { 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Encode the prefix that starts every output line. 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected void encodeLinePrefix(OutputStream aStream, int aLength) 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException { 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Encode the suffix that ends every output line. By default 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this method just prints a <newline> into the output stream. 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected void encodeLineSuffix(OutputStream aStream) throws IOException { 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pStream.println(); 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Encode one "atom" of information into characters. */ 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski abstract protected void encodeAtom(OutputStream aStream, byte someBytes[], 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int anOffset, int aLength) throws IOException; 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This method works around the bizarre semantics of BufferedInputStream's 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * read method. 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected int readFully(InputStream in, byte buffer[]) 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws java.io.IOException { 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < buffer.length; i++) { 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int q = in.read(); 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (q == -1) 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return i; 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer[i] = (byte)q; 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.length; 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Encode bytes from the input stream, and write them as text characters 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to the output stream. This method will run until it exhausts the 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * input stream, but does not print the line suffix for a final 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * line that is shorter than bytesPerLine(). 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void encode(InputStream inStream, OutputStream outStream) 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException { 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int j; 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int numBytes; 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte tmpbuffer[] = new byte[bytesPerLine()]; 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeBufferPrefix(outStream); 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (true) { 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski numBytes = readFully(inStream, tmpbuffer); 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (numBytes == 0) { 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeLinePrefix(outStream, numBytes); 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (j = 0; j < numBytes; j += bytesPerAtom()) { 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((j + bytesPerAtom()) <= numBytes) { 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeAtom(outStream, tmpbuffer, j, bytesPerAtom()); 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeAtom(outStream, tmpbuffer, j, (numBytes)- j); 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (numBytes < bytesPerLine()) { 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeLineSuffix(outStream); 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeBufferSuffix(outStream); 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Encode the buffer in <i>aBuffer</i> and write the encoded 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * result to the OutputStream <i>aStream</i>. 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void encode(byte aBuffer[], OutputStream aStream) 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException { 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer); 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encode(inStream, aStream); 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A 'streamless' version of encode that simply takes a buffer of 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * bytes and returns a string containing the encoded buffer. 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String encode(byte aBuffer[]) { 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer); 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String retVal = null; 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encode(inStream, outStream); 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // explicit ascii->unicode conversion 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retVal = outStream.toString("8859_1"); 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (Exception IOException) { 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // This should never happen. 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new Error("CharacterEncoder.encode internal error"); 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (retVal); 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return a byte array from the remaining bytes in this ByteBuffer. 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P> 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The ByteBuffer's position will be advanced to ByteBuffer's limit. 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P> 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * To avoid an extra copy, the implementation will attempt to return the 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * byte array backing the ByteBuffer. If this is not possible, a 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * new byte array will be created. 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private byte [] getBytes(ByteBuffer bb) { 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This should never return a BufferOverflowException, as we're 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * careful to allocate just the right amount. 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte [] buf = null; 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If it has a usable backing byte buffer, use it. Use only 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if the array exactly represents the current ByteBuffer. 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (bb.hasArray()) { 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte [] tmp = bb.array(); 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((tmp.length == bb.capacity()) && 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (tmp.length == bb.remaining())) { 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf = tmp; 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bb.position(bb.limit()); 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buf == null) { 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This class doesn't have a concept of encode(buf, len, off), 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * so if we have a partial buffer, we must reallocate 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * space. 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf = new byte[bb.remaining()]; 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * position() automatically updated 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bb.get(buf); 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buf; 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Encode the <i>aBuffer</i> ByteBuffer and write the encoded 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * result to the OutputStream <i>aStream</i>. 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P> 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The ByteBuffer's position will be advanced to ByteBuffer's limit. 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void encode(ByteBuffer aBuffer, OutputStream aStream) 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException { 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte [] buf = getBytes(aBuffer); 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encode(buf, aStream); 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A 'streamless' version of encode that simply takes a ByteBuffer 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and returns a string containing the encoded buffer. 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P> 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The ByteBuffer's position will be advanced to ByteBuffer's limit. 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String encode(ByteBuffer aBuffer) { 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte [] buf = getBytes(aBuffer); 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return encode(buf); 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Encode bytes from the input stream, and write them as text characters 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to the output stream. This method will run until it exhausts the 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * input stream. It differs from encode in that it will add the 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * line at the end of a final line that is shorter than bytesPerLine(). 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void encodeBuffer(InputStream inStream, OutputStream outStream) 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException { 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int j; 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int numBytes; 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte tmpbuffer[] = new byte[bytesPerLine()]; 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeBufferPrefix(outStream); 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (true) { 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski numBytes = readFully(inStream, tmpbuffer); 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (numBytes == 0) { 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeLinePrefix(outStream, numBytes); 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (j = 0; j < numBytes; j += bytesPerAtom()) { 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((j + bytesPerAtom()) <= numBytes) { 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeAtom(outStream, tmpbuffer, j, bytesPerAtom()); 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeAtom(outStream, tmpbuffer, j, (numBytes)- j); 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeLineSuffix(outStream); 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (numBytes < bytesPerLine()) { 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeBufferSuffix(outStream); 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Encode the buffer in <i>aBuffer</i> and write the encoded 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * result to the OutputStream <i>aStream</i>. 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void encodeBuffer(byte aBuffer[], OutputStream aStream) 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException { 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer); 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeBuffer(inStream, aStream); 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A 'streamless' version of encode that simply takes a buffer of 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * bytes and returns a string containing the encoded buffer. 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String encodeBuffer(byte aBuffer[]) { 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer); 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeBuffer(inStream, outStream); 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (Exception IOException) { 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // This should never happen. 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new Error("CharacterEncoder.encodeBuffer internal error"); 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (outStream.toString()); 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Encode the <i>aBuffer</i> ByteBuffer and write the encoded 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * result to the OutputStream <i>aStream</i>. 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P> 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The ByteBuffer's position will be advanced to ByteBuffer's limit. 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void encodeBuffer(ByteBuffer aBuffer, OutputStream aStream) 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException { 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte [] buf = getBytes(aBuffer); 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodeBuffer(buf, aStream); 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A 'streamless' version of encode that simply takes a ByteBuffer 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and returns a string containing the encoded buffer. 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P> 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The ByteBuffer's position will be advanced to ByteBuffer's limit. 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String encodeBuffer(ByteBuffer aBuffer) { 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte [] buf = getBytes(aBuffer); 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return encodeBuffer(buf); 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 355