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