|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.misc; |
|
|
|
import java.io.OutputStream; |
|
import java.io.ByteArrayOutputStream; |
|
import java.io.InputStream; |
|
import java.io.PushbackInputStream; |
|
import java.io.ByteArrayInputStream; |
|
import java.io.IOException; |
|
import java.nio.ByteBuffer; |
|
|
|
/** |
|
* This class defines the decoding half of character encoders. |
|
* A character decoder is an algorithim for transforming 8 bit |
|
* binary data that has been encoded into text by a character |
|
* encoder, back into original binary form. |
|
* |
|
* The character encoders, in general, have been structured |
|
* around a central theme that binary data can be encoded into |
|
* text that has the form: |
|
* |
|
* <pre> |
|
* [Buffer Prefix] |
|
* [Line Prefix][encoded data atoms][Line Suffix] |
|
* [Buffer Suffix] |
|
* </pre> |
|
* |
|
* Of course in the simplest encoding schemes, the buffer has no |
|
* distinct prefix of suffix, however all have some fixed relationship |
|
* between the text in an 'atom' and the binary data itself. |
|
* |
|
* In the CharacterEncoder and CharacterDecoder classes, one complete |
|
* chunk of data is referred to as a <i>buffer</i>. Encoded buffers |
|
* are all text, and decoded buffers (sometimes just referred to as |
|
* buffers) are binary octets. |
|
* |
|
* To create a custom decoder, you must, at a minimum, overide three |
|
* abstract methods in this class. |
|
* <DL> |
|
* <DD>bytesPerAtom which tells the decoder how many bytes to |
|
* expect from decodeAtom |
|
* <DD>decodeAtom which decodes the bytes sent to it as text. |
|
* <DD>bytesPerLine which tells the encoder the maximum number of |
|
* bytes per line. |
|
* </DL> |
|
* |
|
* In general, the character decoders return error in the form of a |
|
* CEFormatException. The syntax of the detail string is |
|
* <pre> |
|
* DecoderClassName: Error message. |
|
* </pre> |
|
* |
|
* Several useful decoders have already been written and are |
|
* referenced in the See Also list below. |
|
* |
|
* @author Chuck McManis |
|
* @see CEFormatException |
|
* @see CharacterEncoder |
|
* @see UCDecoder |
|
* @see UUDecoder |
|
* @see BASE64Decoder |
|
*/ |
|
|
|
public abstract class CharacterDecoder { |
|
|
|
|
|
abstract protected int bytesPerAtom(); |
|
|
|
|
|
abstract protected int bytesPerLine(); |
|
|
|
|
|
protected void decodeBufferPrefix(PushbackInputStream aStream, OutputStream bStream) throws IOException { } |
|
|
|
|
|
protected void decodeBufferSuffix(PushbackInputStream aStream, OutputStream bStream) throws IOException { } |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
protected int decodeLinePrefix(PushbackInputStream aStream, OutputStream bStream) throws IOException { |
|
return (bytesPerLine()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
protected void decodeLineSuffix(PushbackInputStream aStream, OutputStream bStream) throws IOException { } |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
protected void decodeAtom(PushbackInputStream aStream, OutputStream bStream, int l) throws IOException { |
|
throw new CEStreamExhausted(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
protected int readFully(InputStream in, byte buffer[], int offset, int len) |
|
throws java.io.IOException { |
|
for (int i = 0; i < len; i++) { |
|
int q = in.read(); |
|
if (q == -1) |
|
return ((i == 0) ? -1 : i); |
|
buffer[i+offset] = (byte)q; |
|
} |
|
return len; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void decodeBuffer(InputStream aStream, OutputStream bStream) throws IOException { |
|
int i; |
|
int totalBytes = 0; |
|
|
|
PushbackInputStream ps = new PushbackInputStream (aStream); |
|
decodeBufferPrefix(ps, bStream); |
|
while (true) { |
|
int length; |
|
|
|
try { |
|
length = decodeLinePrefix(ps, bStream); |
|
for (i = 0; (i+bytesPerAtom()) < length; i += bytesPerAtom()) { |
|
decodeAtom(ps, bStream, bytesPerAtom()); |
|
totalBytes += bytesPerAtom(); |
|
} |
|
if ((i + bytesPerAtom()) == length) { |
|
decodeAtom(ps, bStream, bytesPerAtom()); |
|
totalBytes += bytesPerAtom(); |
|
} else { |
|
decodeAtom(ps, bStream, length - i); |
|
totalBytes += (length - i); |
|
} |
|
decodeLineSuffix(ps, bStream); |
|
} catch (CEStreamExhausted e) { |
|
break; |
|
} |
|
} |
|
decodeBufferSuffix(ps, bStream); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public byte decodeBuffer(String inputString)[] throws IOException { |
|
byte inputBuffer[] = new byte[inputString.length()]; |
|
ByteArrayInputStream inStream; |
|
ByteArrayOutputStream outStream; |
|
|
|
inputString.getBytes(0, inputString.length(), inputBuffer, 0); |
|
inStream = new ByteArrayInputStream(inputBuffer); |
|
outStream = new ByteArrayOutputStream(); |
|
decodeBuffer(inStream, outStream); |
|
return (outStream.toByteArray()); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public byte decodeBuffer(InputStream in)[] throws IOException { |
|
ByteArrayOutputStream outStream = new ByteArrayOutputStream(); |
|
decodeBuffer(in, outStream); |
|
return (outStream.toByteArray()); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public ByteBuffer decodeBufferToByteBuffer(String inputString) |
|
throws IOException { |
|
return ByteBuffer.wrap(decodeBuffer(inputString)); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public ByteBuffer decodeBufferToByteBuffer(InputStream in) |
|
throws IOException { |
|
return ByteBuffer.wrap(decodeBuffer(in)); |
|
} |
|
} |