Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/misc/CharacterEncoder.java
38829 views
/*1* Copyright (c) 1995, 2005, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.misc;2627import java.io.InputStream;28import java.io.ByteArrayInputStream;29import java.io.OutputStream;30import java.io.ByteArrayOutputStream;31import java.io.PrintStream;32import java.io.IOException;33import java.nio.ByteBuffer;343536/**37* This class defines the encoding half of character encoders.38* A character encoder is an algorithim for transforming 8 bit binary39* data into text (generally 7 bit ASCII or 8 bit ISO-Latin-1 text)40* for transmition over text channels such as e-mail and network news.41*42* The character encoders have been structured around a central theme43* that, in general, the encoded text has the form:44*45* <pre>46* [Buffer Prefix]47* [Line Prefix][encoded data atoms][Line Suffix]48* [Buffer Suffix]49* </pre>50*51* In the CharacterEncoder and CharacterDecoder classes, one complete52* chunk of data is referred to as a <i>buffer</i>. Encoded buffers53* are all text, and decoded buffers (sometimes just referred to as54* buffers) are binary octets.55*56* To create a custom encoder, you must, at a minimum, overide three57* abstract methods in this class.58* <DL>59* <DD>bytesPerAtom which tells the encoder how many bytes to60* send to encodeAtom61* <DD>encodeAtom which encodes the bytes sent to it as text.62* <DD>bytesPerLine which tells the encoder the maximum number of63* bytes per line.64* </DL>65*66* Several useful encoders have already been written and are67* referenced in the See Also list below.68*69* @author Chuck McManis70* @see CharacterDecoder;71* @see UCEncoder72* @see UUEncoder73* @see BASE64Encoder74*/75public abstract class CharacterEncoder {7677/** Stream that understands "printing" */78protected PrintStream pStream;7980/** Return the number of bytes per atom of encoding */81abstract protected int bytesPerAtom();8283/** Return the number of bytes that can be encoded per line */84abstract protected int bytesPerLine();8586/**87* Encode the prefix for the entire buffer. By default is simply88* opens the PrintStream for use by the other functions.89*/90protected void encodeBufferPrefix(OutputStream aStream) throws IOException {91pStream = new PrintStream(aStream);92}9394/**95* Encode the suffix for the entire buffer.96*/97protected void encodeBufferSuffix(OutputStream aStream) throws IOException {98}99100/**101* Encode the prefix that starts every output line.102*/103protected void encodeLinePrefix(OutputStream aStream, int aLength)104throws IOException {105}106107/**108* Encode the suffix that ends every output line. By default109* this method just prints a <newline> into the output stream.110*/111protected void encodeLineSuffix(OutputStream aStream) throws IOException {112pStream.println();113}114115/** Encode one "atom" of information into characters. */116abstract protected void encodeAtom(OutputStream aStream, byte someBytes[],117int anOffset, int aLength) throws IOException;118119/**120* This method works around the bizarre semantics of BufferedInputStream's121* read method.122*/123protected int readFully(InputStream in, byte buffer[])124throws java.io.IOException {125for (int i = 0; i < buffer.length; i++) {126int q = in.read();127if (q == -1)128return i;129buffer[i] = (byte)q;130}131return buffer.length;132}133134/**135* Encode bytes from the input stream, and write them as text characters136* to the output stream. This method will run until it exhausts the137* input stream, but does not print the line suffix for a final138* line that is shorter than bytesPerLine().139*/140public void encode(InputStream inStream, OutputStream outStream)141throws IOException {142int j;143int numBytes;144byte tmpbuffer[] = new byte[bytesPerLine()];145146encodeBufferPrefix(outStream);147148while (true) {149numBytes = readFully(inStream, tmpbuffer);150if (numBytes == 0) {151break;152}153encodeLinePrefix(outStream, numBytes);154for (j = 0; j < numBytes; j += bytesPerAtom()) {155156if ((j + bytesPerAtom()) <= numBytes) {157encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());158} else {159encodeAtom(outStream, tmpbuffer, j, (numBytes)- j);160}161}162if (numBytes < bytesPerLine()) {163break;164} else {165encodeLineSuffix(outStream);166}167}168encodeBufferSuffix(outStream);169}170171/**172* Encode the buffer in <i>aBuffer</i> and write the encoded173* result to the OutputStream <i>aStream</i>.174*/175public void encode(byte aBuffer[], OutputStream aStream)176throws IOException {177ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);178encode(inStream, aStream);179}180181/**182* A 'streamless' version of encode that simply takes a buffer of183* bytes and returns a string containing the encoded buffer.184*/185public String encode(byte aBuffer[]) {186ByteArrayOutputStream outStream = new ByteArrayOutputStream();187ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);188String retVal = null;189try {190encode(inStream, outStream);191// explicit ascii->unicode conversion192retVal = outStream.toString("8859_1");193} catch (Exception IOException) {194// This should never happen.195throw new Error("CharacterEncoder.encode internal error");196}197return (retVal);198}199200/**201* Return a byte array from the remaining bytes in this ByteBuffer.202* <P>203* The ByteBuffer's position will be advanced to ByteBuffer's limit.204* <P>205* To avoid an extra copy, the implementation will attempt to return the206* byte array backing the ByteBuffer. If this is not possible, a207* new byte array will be created.208*/209private byte [] getBytes(ByteBuffer bb) {210/*211* This should never return a BufferOverflowException, as we're212* careful to allocate just the right amount.213*/214byte [] buf = null;215216/*217* If it has a usable backing byte buffer, use it. Use only218* if the array exactly represents the current ByteBuffer.219*/220if (bb.hasArray()) {221byte [] tmp = bb.array();222if ((tmp.length == bb.capacity()) &&223(tmp.length == bb.remaining())) {224buf = tmp;225bb.position(bb.limit());226}227}228229if (buf == null) {230/*231* This class doesn't have a concept of encode(buf, len, off),232* so if we have a partial buffer, we must reallocate233* space.234*/235buf = new byte[bb.remaining()];236237/*238* position() automatically updated239*/240bb.get(buf);241}242243return buf;244}245246/**247* Encode the <i>aBuffer</i> ByteBuffer and write the encoded248* result to the OutputStream <i>aStream</i>.249* <P>250* The ByteBuffer's position will be advanced to ByteBuffer's limit.251*/252public void encode(ByteBuffer aBuffer, OutputStream aStream)253throws IOException {254byte [] buf = getBytes(aBuffer);255encode(buf, aStream);256}257258/**259* A 'streamless' version of encode that simply takes a ByteBuffer260* and returns a string containing the encoded buffer.261* <P>262* The ByteBuffer's position will be advanced to ByteBuffer's limit.263*/264public String encode(ByteBuffer aBuffer) {265byte [] buf = getBytes(aBuffer);266return encode(buf);267}268269/**270* Encode bytes from the input stream, and write them as text characters271* to the output stream. This method will run until it exhausts the272* input stream. It differs from encode in that it will add the273* line at the end of a final line that is shorter than bytesPerLine().274*/275public void encodeBuffer(InputStream inStream, OutputStream outStream)276throws IOException {277int j;278int numBytes;279byte tmpbuffer[] = new byte[bytesPerLine()];280281encodeBufferPrefix(outStream);282283while (true) {284numBytes = readFully(inStream, tmpbuffer);285if (numBytes == 0) {286break;287}288encodeLinePrefix(outStream, numBytes);289for (j = 0; j < numBytes; j += bytesPerAtom()) {290if ((j + bytesPerAtom()) <= numBytes) {291encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());292} else {293encodeAtom(outStream, tmpbuffer, j, (numBytes)- j);294}295}296encodeLineSuffix(outStream);297if (numBytes < bytesPerLine()) {298break;299}300}301encodeBufferSuffix(outStream);302}303304/**305* Encode the buffer in <i>aBuffer</i> and write the encoded306* result to the OutputStream <i>aStream</i>.307*/308public void encodeBuffer(byte aBuffer[], OutputStream aStream)309throws IOException {310ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);311encodeBuffer(inStream, aStream);312}313314/**315* A 'streamless' version of encode that simply takes a buffer of316* bytes and returns a string containing the encoded buffer.317*/318public String encodeBuffer(byte aBuffer[]) {319ByteArrayOutputStream outStream = new ByteArrayOutputStream();320ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);321try {322encodeBuffer(inStream, outStream);323} catch (Exception IOException) {324// This should never happen.325throw new Error("CharacterEncoder.encodeBuffer internal error");326}327return (outStream.toString());328}329330/**331* Encode the <i>aBuffer</i> ByteBuffer and write the encoded332* result to the OutputStream <i>aStream</i>.333* <P>334* The ByteBuffer's position will be advanced to ByteBuffer's limit.335*/336public void encodeBuffer(ByteBuffer aBuffer, OutputStream aStream)337throws IOException {338byte [] buf = getBytes(aBuffer);339encodeBuffer(buf, aStream);340}341342/**343* A 'streamless' version of encode that simply takes a ByteBuffer344* and returns a string containing the encoded buffer.345* <P>346* The ByteBuffer's position will be advanced to ByteBuffer's limit.347*/348public String encodeBuffer(ByteBuffer aBuffer) {349byte [] buf = getBytes(aBuffer);350return encodeBuffer(buf);351}352353}354355356