001/* 002 * SVG Salamander 003 * Copyright (c) 2004, Mark McKay 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or 007 * without modification, are permitted provided that the following 008 * conditions are met: 009 * 010 * - Redistributions of source code must retain the above 011 * copyright notice, this list of conditions and the following 012 * disclaimer. 013 * - Redistributions in binary form must reproduce the above 014 * copyright notice, this list of conditions and the following 015 * disclaimer in the documentation and/or other materials 016 * provided with the distribution. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 019 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 020 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 021 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 022 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 023 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 025 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 026 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 027 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 029 * OF THE POSSIBILITY OF SUCH DAMAGE. 030 * 031 * Mark McKay can be contacted at mark@kitfox.com. Salamander and other 032 * projects can be found at http://www.kitfox.com 033 */ 034 035package com.kitfox.svg.xml; 036 037import java.io.FilterInputStream; 038import java.io.IOException; 039import java.io.InputStream; 040 041/** 042 * 043 * @author kitfox 044 */ 045public class Base64InputStream extends FilterInputStream 046{ 047 int buf; //Cached bytes to read 048 int bufSize; //Number of bytes waiting to be read from buffer 049 boolean drain = false; //After set, read no more chunks 050 051 public Base64InputStream(InputStream in) 052 { 053 super(in); 054 } 055 056 public int read() throws IOException 057 { 058 if (drain && bufSize == 0) 059 { 060 return -1; 061 } 062 063 if (bufSize == 0) 064 { 065 //Read next chunk into 4 byte buffer 066 int chunk = in.read(); 067 if (chunk == -1) 068 { 069 drain = true; 070 return -1; 071 } 072 073 //get remaining 3 bytes 074 for (int i = 0; i < 3; ++i) 075 { 076 int value = in.read(); 077 if (value == -1) 078 { 079 throw new IOException("Early termination of base64 stream"); 080 } 081 chunk = (chunk << 8) | (value & 0xff); 082 } 083 084 //Check for special termination characters 085 if ((chunk & 0xffff) == (((byte)'=' << 8) | (byte)'=')) 086 { 087 bufSize = 1; 088 drain = true; 089 } 090 else if ((chunk & 0xff) == (byte)'=') 091 { 092 bufSize = 2; 093 drain = true; 094 } 095 else 096 { 097 bufSize = 3; 098 } 099 100 //Fill buffer with decoded characters 101 for (int i = 0; i < bufSize + 1; ++i) 102 { 103 buf = (buf << 6) | Base64Util.decodeByte((chunk >> 24) & 0xff); 104 chunk <<= 8; 105 } 106 } 107 108 //Return nth remaing bte & decrement counter 109 return (buf >> (--bufSize * 8)) & 0xff; 110 } 111}