package net.sf.openrocket.android.thrustcurve;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
public abstract class Base64Decoder {
private static final String BASE64_CHARS =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
private static final char PAD_CHAR = '=';
private final static short[] _charToBits = new short[128];
static {
for (int i = 0; i < _charToBits.length; i++)
_charToBits[i] = -1;
for (int i = 0; i < BASE64_CHARS.length(); i++)
_charToBits[BASE64_CHARS.charAt(i)] = (byte) i;
_charToBits[PAD_CHAR] = 0;
}
/**
* Decode the specified Base64 string and write binary data
* to the given stream.
* @param str Base64 encoded string
* @param w output stream
*/
public static String decodeData(String str) throws IOException
{
StringReader r;
int c1;
if (str == null || str.length() < 1)
return null;
r = new StringReader(str);
StringWriter w = new StringWriter();
// spin through the input string
c1 = readToNonSpace(r);
while (c1 > 0)
{
int c2, c3, c4;
int p1, p2, p3, p4;
int pad, n;
pad = 0;
c2 = readToNonSpace(r);
c3 = readToNonSpace(r);
c4 = readToNonSpace(r);
if (c4 < 0)
throw new IllegalArgumentException("Encoded string ends prematurely.");
p1 = charToBits(c1);
p2 = charToBits(c2);
if (c3 == PAD_CHAR)
{
p3 = 0;
pad++;
}
else
p3 = charToBits(c3);
if (c4 == PAD_CHAR)
{
p4 = 0;
pad++;
}
else
p4 = charToBits(c4);
if (p1 < 0 || p2 < 0 || p3 < 0 || p4 < 0)
throw new IllegalArgumentException("Encoded string contains invalid characters.");
n = (p1 << 18) | (p2 << 12) | (p3 << 6) | p4;
w.write((byte) ((n & 0xFF0000) >> 16));
if (pad < 2)
w.write((byte) ((n & 0x00FF00) >> 8));
if (pad < 1)
w.write((byte) (n & 0x0000FF));
c1 = readToNonSpace(r);
if (c1 > 0 && pad > 0)
throw new IllegalArgumentException("Extra characters found after padding.");
}
return w.toString();
}
private static int readToNonSpace(Reader r)
throws IOException
{
int c;
c = r.read();
while (c >= 0 && Character.isWhitespace(c))
c = r.read();
return c;
}
private static int charToBits(int c)
{
// use it to look up the value
if (c < 0 || c >= _charToBits.length)
return -1;
else
return _charToBits[c];
}
}