001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    
018    package org.apache.geronimo.crypto.encoders;
019    
020    
021    /**
022     * a buffering class to allow translation from one format to another to
023     * be done in discrete chunks.
024     */
025    public class BufferedDecoder
026    {
027        protected byte[]        buf;
028        protected int           bufOff;
029    
030        protected Translator    translator;
031    
032        /**
033         * @param translator the translator to use.
034         * @param bufSize amount of input to buffer for each chunk.
035         */
036        public BufferedDecoder(
037            Translator  translator,
038            int         bufSize)
039        {
040            this.translator = translator;
041    
042            if ((bufSize % translator.getEncodedBlockSize()) != 0)
043            {
044                throw new IllegalArgumentException("buffer size not multiple of input block size");
045            }
046    
047            buf = new byte[bufSize];
048            bufOff = 0;
049        }
050    
051        public int processByte(
052            byte        in,
053            byte[]      out,
054            int         outOff)
055        {
056            int         resultLen = 0;
057    
058            buf[bufOff++] = in;
059    
060            if (bufOff == buf.length)
061            {
062                resultLen = translator.decode(buf, 0, buf.length, out, outOff);
063                bufOff = 0;
064            }
065    
066            return resultLen;
067        }
068    
069        public int processBytes(
070            byte[]      in,
071            int         inOff,
072            int         len,
073            byte[]      out,
074            int         outOff)
075        {
076            if (len < 0)
077            {
078                throw new IllegalArgumentException("Can't have a negative input length!");
079            }
080    
081            int resultLen = 0;
082            int gapLen = buf.length - bufOff;
083    
084            if (len > gapLen)
085            {
086                System.arraycopy(in, inOff, buf, bufOff, gapLen);
087    
088                resultLen += translator.decode(buf, 0, buf.length, out, outOff);
089    
090                bufOff = 0;
091    
092                len -= gapLen;
093                inOff += gapLen;
094                outOff += resultLen;
095    
096                int chunkSize = len - (len % buf.length);
097    
098                resultLen += translator.decode(in, inOff, chunkSize, out, outOff);
099    
100                len -= chunkSize;
101                inOff += chunkSize;
102            }
103    
104            if (len != 0)
105            {
106                System.arraycopy(in, inOff, buf, bufOff, len);
107    
108                bufOff += len;
109            }
110    
111            return resultLen;
112        }
113    }