001 /*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005
006 package com.kitfox.svg.xml;
007
008 import java.io.FilterInputStream;
009 import java.io.IOException;
010 import java.io.InputStream;
011
012 /**
013 *
014 * @author kitfox
015 */
016 public class Base64InputStream extends FilterInputStream
017 {
018 int buf; //Cached bytes to read
019 int bufSize; //Number of bytes waiting to be read from buffer
020 boolean drain = false; //After set, read no more chunks
021
022 public Base64InputStream(InputStream in)
023 {
024 super(in);
025 }
026
027 public int read() throws IOException
028 {
029 if (drain && bufSize == 0)
030 {
031 return -1;
032 }
033
034 if (bufSize == 0)
035 {
036 //Read next chunk into 4 byte buffer
037 int chunk = in.read();
038 if (chunk == -1)
039 {
040 drain = true;
041 return -1;
042 }
043
044 //get remaining 3 bytes
045 for (int i = 0; i < 3; ++i)
046 {
047 int value = in.read();
048 if (value == -1)
049 {
050 throw new IOException("Early termination of base64 stream");
051 }
052 chunk = (chunk << 8) | (value & 0xff);
053 }
054
055 //Check for special termination characters
056 if ((chunk & 0xffff) == (((byte)'=' << 8) | (byte)'='))
057 {
058 bufSize = 1;
059 drain = true;
060 }
061 else if ((chunk & 0xff) == (byte)'=')
062 {
063 bufSize = 2;
064 drain = true;
065 }
066 else
067 {
068 bufSize = 3;
069 }
070
071 //Fill buffer with decoded characters
072 for (int i = 0; i < bufSize + 1; ++i)
073 {
074 buf = (buf << 6) | Base64Util.decodeByte((chunk >> 24) & 0xff);
075 chunk <<= 8;
076 }
077 }
078
079 //Return nth remaing bte & decrement counter
080 return (buf >> (--bufSize * 8)) & 0xff;
081 }
082 }