
com.sun.xml.io.Base64Decoder Maven / Gradle / Ivy
/*
* @(#)Base64Decoder.java 1.2 98/05/31
*
* Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*/
package com.sun.xml.io;
import java.io.*;
/**
* Given Base64 encoded text data from a Reader
, this returns
* it as a byte stream.
*
* It is the caller's responsibility not to read more binary data from
* the stream than is actually there. In some cases, the stream itself
* can detect the end of that encoded data, and will accordingly report
* errors on attempts to read past the end of that data. However, that
* behaviour is dependant on the input data, and should not be relied on.
*
* @see Base64Encoder
*
* @author David Brownell
* @version 1.2
*/
public class Base64Decoder extends InputStream
{
private Reader in;
private boolean eof;
private char data [] = new char [4];
private byte buf [] = new byte [3];
private int off = 3;
private int len = 0;
/**
* Constructs a binary input stream from the Base64 encoded
* data in the input reader.
*/
public Base64Decoder (Reader in) {
this.in = in;
}
// @return false on EOF
private boolean fillbuf () throws IOException
{
int tmp;
for (tmp = 0; tmp < 4; tmp++) {
int c = in.read ();
if (c == -1) {
eof = true;
return false;
}
data [tmp] = (char) c;
// ignore line endings etc
if (Character.isWhitespace (data [tmp]))
tmp--;
}
off = 0;
buf [0] = (byte) (digit (data [0]) << 2);
tmp = digit (data [1]);
buf [0] |= (byte) (0x3 & (tmp >> 4));
if (data [2] == '=') {
buf [1] = buf [2] = 0;
eof = true;
len = 1;
return true;
}
buf [1] = (byte) (tmp << 4);
tmp = digit (data [2]);
buf [1] |= (byte) (0xf & (tmp >> 2));
buf [2] = (byte) (tmp << 6);
if (data [3] == '=') {
eof = true;
len = 2;
} else {
buf [2] |= (byte) digit (data [3]);
len = 3;
}
return true;
}
private int digit (char c) {
if (c >= 'A' && c <= 'Z')
return c - 'A';
if (c >= 'a' && c <= 'z')
return (c - 'a') + 26;
if (c >= '0' && c <= '9')
return (c - '0') + 52;
if (c == '+')
return 63;
if (c == '/')
return 64;
eof = true;
throw new IllegalArgumentException ("not a BASE64 digit: " + c);
}
/**
* Returns a single decoded byte.
*/
public int read () throws IOException
{
if (off >= len && !fillbuf ())
return -1;
return buf [off++];
}
/**
* Returns true only if the Base64 encoded input data is known to have
* to have terminated. That data terminates in three cases: when the
* underlying reader reports EOF, when illegal Base64 characters are
* encountered, and in some cases when EOF is encoded in the Base64
* data. That latter case happens only in cases where the input data
* length is not a multiple of three, and should not be relied on.
*/
public boolean isEOF ()
{
return eof;
}
/*
public static void main (String argv [])
{
try {
String value = "SGVsbG8sIHdvcmxkPz8K";
// String value = "SGVsbG8sIHdvcmxkIQo=";
// String value = "SGVsbG8sIHdvcmxkCg==";
// String value = "YWRtaW4=";
Reader r = new StringReader (value);
InputStream in = new Base64Decoder (r);
int c;
System.out.println (value);
while ((c = in.read ()) != -1) {
System.out.write (c);
}
System.out.println ("**");
System.out.flush ();
} catch (Throwable t) {
t.printStackTrace ();
}
}
*/
}