001/*
002 * $RCSfile: ByteInputBuffer.java,v $
003 * $Revision: 1.1 $
004 * $Date: 2005/02/11 05:02:05 $
005 * $State: Exp $
006 *
007 * Class:                   ByteInputBuffer
008 *
009 * Description:             Provides buffering for byte based input, similar
010 *                          to the standard class ByteArrayInputStream
011 *
012 *                          the old jj2000.j2k.io.ByteArrayInput class by
013 *                          Diego SANTA CRUZ, Apr-26-1999
014 *
015 *
016 * COPYRIGHT:
017 *
018 * This software module was originally developed by Raphaël Grosbois and
019 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
020 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
021 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
022 * Centre France S.A) in the course of development of the JPEG2000
023 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
024 * software module is an implementation of a part of the JPEG 2000
025 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
026 * Systems AB and Canon Research Centre France S.A (collectively JJ2000
027 * Partners) agree not to assert against ISO/IEC and users of the JPEG
028 * 2000 Standard (Users) any of their rights under the copyright, not
029 * including other intellectual property rights, for this software module
030 * with respect to the usage by ISO/IEC and Users of this software module
031 * or modifications thereof for use in hardware or software products
032 * claiming conformance to the JPEG 2000 Standard. Those intending to use
033 * this software module in hardware or software products are advised that
034 * their use may infringe existing patents. The original developers of
035 * this software module, JJ2000 Partners and ISO/IEC assume no liability
036 * for use of this software module or modifications thereof. No license
037 * or right to this software module is granted for non JPEG 2000 Standard
038 * conforming products. JJ2000 Partners have full right to use this
039 * software module for his/her own purpose, assign or donate this
040 * software module to any third party and to inhibit third parties from
041 * using this software module for non JPEG 2000 Standard conforming
042 * products. This copyright notice must be included in all copies or
043 * derivative works of this software module.
044 *
045 * Copyright (c) 1999/2000 JJ2000 Partners.
046 *
047 *
048 *
049 */
050
051
052package jj2000.j2k.entropy.decoder;
053
054import java.io.EOFException;
055import java.io.IOException;
056import java.io.InputStream;
057
058/**
059 * This class provides a byte input facility from byte buffers. It is similar
060 * to the ByteArrayInputStream class, but adds the possibility to add data to
061 * the stream after the creation of the object.
062 *
063 * <P>Unlike the ByteArrayInputStream this class is not thread safe (i.e. no
064 * two threads can use the same object at the same time, but different objects
065 * may be used in different threads).
066 *
067 * <P>This class can modify the contents of the buffer given to the
068 * constructor, when the addByteArray() method is called.
069 *
070 * @see InputStream
071 * */
072public class ByteInputBuffer {
073
074    /** The byte array containing the data */
075    private byte buf[];
076
077    /** The index one greater than the last valid character in the input
078     *  stream buffer */
079    private int count;
080
081    /** The index of the next character to read from the input stream buffer
082     * */
083    private int pos;
084
085    /**
086     * Creates a new byte array input stream that reads data from the
087     * specified byte array. The byte array is not copied.
088     *
089     * @param buf the input buffer.
090     */
091    public ByteInputBuffer(byte buf[]){
092        this.buf = buf;
093        count = buf.length;
094    }
095
096    /**
097     * Creates a new byte array input stream that reads data from the
098     * specified byte array. Up to length characters are to be read
099     * from the byte array, starting at the indicated offset.
100     *
101     * <P>The byte array is not copied.
102     *
103     * @param buf the input buffer.
104     *
105     * @param offset the offset in the buffer of the first byte to
106     * read.
107     *
108     * @param length the maximum number of bytes to read from the
109     * buffer.
110     */
111    public ByteInputBuffer(byte buf[], int offset, int length) {
112        this.buf = buf;
113        pos = offset;
114        count = offset+length;
115    }
116
117    /**
118     * Sets the underlying buffer byte array to the given one, with the given
119     * offset and length. If 'buf' is null then the current byte buffer is
120     * assumed. If 'offset' is negative, then it will be assumed to be
121     * 'off+len', where 'off' and 'len' are the offset and length of the
122     * current byte buffer.
123     *
124     * <P>The byte array is not copied.
125     *
126     * @param buf the input buffer. If null it is the current input buffer.
127     *
128     * @param offset the offset in the buffer of the first byte to read. If
129     * negative it is assumed to be the byte just after the end of the current
130     * input buffer, only permitted if 'buf' is null.
131     *
132     * @param length the maximum number of bytes to read frmo the buffer.
133     */
134    public void setByteArray(byte buf[], int offset, int length) {
135        // In same buffer?
136        if (buf == null) {
137            if (length < 0 || count+length>this.buf.length) {
138                throw new IllegalArgumentException();
139            }
140            if (offset < 0) {
141                pos = count;
142                count += length;
143            } else {
144                count = offset+length;
145                pos = offset;
146            }
147        } else { // New input buffer
148            if (offset < 0 || length < 0 || offset+length > buf.length) {
149                throw new IllegalArgumentException();
150            }
151            this.buf = buf;
152            count = offset+length;
153            pos = offset;
154        }
155    }
156
157    /**
158     * Adds the specified data to the end of the byte array stream. This
159     * method modifies the byte array buffer. It can also discard the already
160     * read input.
161     *
162     * @param data The data to add. The data is copied.
163     *
164     * @param off The index, in data, of the first element to add to
165     * the stream.
166     *
167     * @param len The number of elements to add to the array.
168     *
169     *
170     * */
171    public synchronized void addByteArray(byte data[], int off, int len) {
172        // Check integrity
173        if (len < 0 || off < 0 || len+off > buf.length) {
174            throw new IllegalArgumentException();
175        }
176        // Copy new data
177        if (count+len <= buf.length) { // Enough place in 'buf'
178            System.arraycopy(data,off,buf,count,len);
179            count += len;
180        } else {
181            if (count-pos+len <= buf.length) {
182                // Enough place in 'buf' if we move input data
183                // Move buffer
184                System.arraycopy(buf,pos,buf,0,count-pos);
185            } else { // Not enough place in 'buf', use new buffer
186                byte [] oldbuf = buf;
187                buf = new byte[count-pos+len];
188                // Copy buffer
189                System.arraycopy(oldbuf,count,buf,0,count-pos);
190            }
191            count -= pos;
192            pos = 0;
193            // Copy new data
194            System.arraycopy(data,off,buf,count,len);
195            count += len;
196        }
197    }
198
199    /**
200     * Reads the next byte of data from this input stream. The value
201     * byte is returned as an int in the range 0 to 255. If no byte is
202     * available because the end of the stream has been reached, the
203     * EOFException exception is thrown.
204     *
205     * <P>This method is not synchronized, so it is not thread safe.
206     *
207     * @return The byte read in the range 0-255.
208     *
209     * @exception EOFException If the end of the stream is reached.
210     *
211     *
212     * */
213    public int readChecked() throws IOException {
214        if (pos < count) {
215            return (int)buf[pos++] & 0xFF;
216        } else {
217            throw new EOFException();
218        }
219    }
220
221    /**
222     * Reads the next byte of data from this input stream. The value byte is
223     * returned as an int in the range 0 to 255. If no byte is available
224     * because the end of the stream has been reached, -1 is returned.
225     *
226     * <P>This method is not synchronized, so it is not thread safe.
227     *
228     * @return The byte read in the range 0-255, or -1 if the end of stream
229     * has been reached.
230     *
231     *
232     * */
233    public int read() {
234        if (pos < count) {
235            return (int)buf[pos++] & 0xFF;
236        } else {
237            return -1;
238        }
239    }
240
241}