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.*;
055
056/**
057 * This class provides a byte input facility from byte buffers. It is similar
058 * to the ByteArrayInputStream class, but adds the possibility to add data to
059 * the stream after the creation of the object.
060 *
061 * <P>Unlike the ByteArrayInputStream this class is not thread safe (i.e. no
062 * two threads can use the same object at the same time, but different objects
063 * may be used in different threads).
064 *
065 * <P>This class can modify the contents of the buffer given to the
066 * constructor, when the addByteArray() method is called.
067 *
068 * @see InputStream
069 * */
070public class ByteInputBuffer {
071
072    /** The byte array containing the data */
073    private byte buf[];
074
075    /** The index one greater than the last valid character in the input
076     *  stream buffer */
077    private int count;
078
079    /** The index of the next character to read from the input stream buffer
080     * */
081    private int pos;
082
083    /**
084     * Creates a new byte array input stream that reads data from the
085     * specified byte array. The byte array is not copied.
086     *
087     * @param buf the input buffer.
088     */
089    public ByteInputBuffer(byte buf[]){
090        this.buf = buf;
091        count = buf.length;
092    }
093
094    /**
095     * Creates a new byte array input stream that reads data from the
096     * specified byte array. Up to length characters are to be read
097     * from the byte array, starting at the indicated offset.
098     *
099     * <P>The byte array is not copied.
100     *
101     * @param buf the input buffer.
102     *
103     * @param offset the offset in the buffer of the first byte to
104     * read.
105     *
106     * @param length the maximum number of bytes to read from the
107     * buffer.
108     */
109    public ByteInputBuffer(byte buf[], int offset, int length) {
110        this.buf = buf;
111        pos = offset;
112        count = offset+length;
113    }
114
115    /**
116     * Sets the underlying buffer byte array to the given one, with the given
117     * offset and length. If 'buf' is null then the current byte buffer is
118     * assumed. If 'offset' is negative, then it will be assumed to be
119     * 'off+len', where 'off' and 'len' are the offset and length of the
120     * current byte buffer.
121     *
122     * <P>The byte array is not copied.
123     *
124     * @param buf the input buffer. If null it is the current input buffer.
125     *
126     * @param offset the offset in the buffer of the first byte to read. If
127     * negative it is assumed to be the byte just after the end of the current
128     * input buffer, only permitted if 'buf' is null.
129     *
130     * @param length the maximum number of bytes to read frmo the buffer.
131     */
132    public void setByteArray(byte buf[], int offset, int length) {
133        // In same buffer?
134        if (buf == null) {
135            if (length < 0 || count+length>this.buf.length) {
136                throw new IllegalArgumentException();
137            }
138            if (offset < 0) {
139                pos = count;
140                count += length;
141            } else {
142                count = offset+length;
143                pos = offset;
144            }
145        } else { // New input buffer
146            if (offset < 0 || length < 0 || offset+length > buf.length) {
147                throw new IllegalArgumentException();
148            }
149            this.buf = buf;
150            count = offset+length;
151            pos = offset;
152        }
153    }
154
155    /**
156     * Adds the specified data to the end of the byte array stream. This
157     * method modifies the byte array buffer. It can also discard the already
158     * read input.
159     *
160     * @param data The data to add. The data is copied.
161     *
162     * @param off The index, in data, of the first element to add to
163     * the stream.
164     *
165     * @param len The number of elements to add to the array.
166     *
167     *
168     * */
169    public synchronized void addByteArray(byte data[], int off, int len) {
170        // Check integrity
171        if (len < 0 || off < 0 || len+off > buf.length) {
172            throw new IllegalArgumentException();
173        }
174        // Copy new data
175        if (count+len <= buf.length) { // Enough place in 'buf'
176            System.arraycopy(data,off,buf,count,len);
177            count += len;
178        } else {
179            if (count-pos+len <= buf.length) {
180                // Enough place in 'buf' if we move input data
181                // Move buffer
182                System.arraycopy(buf,pos,buf,0,count-pos);
183            } else { // Not enough place in 'buf', use new buffer
184                byte [] oldbuf = buf;
185                buf = new byte[count-pos+len];
186                // Copy buffer
187                System.arraycopy(oldbuf,count,buf,0,count-pos);
188            }
189            count -= pos;
190            pos = 0;
191            // Copy new data
192            System.arraycopy(data,off,buf,count,len);
193            count += len;
194        }
195    }
196
197    /**
198     * Reads the next byte of data from this input stream. The value
199     * byte is returned as an int in the range 0 to 255. If no byte is
200     * available because the end of the stream has been reached, the
201     * EOFException exception is thrown.
202     *
203     * <P>This method is not synchronized, so it is not thread safe.
204     *
205     * @return The byte read in the range 0-255.
206     *
207     * @exception EOFException If the end of the stream is reached.
208     *
209     *
210     * */
211    public int readChecked() throws IOException {
212        if (pos < count) {
213            return (int)buf[pos++] & 0xFF;
214        } else {
215            throw new EOFException();
216        }
217    }
218
219    /**
220     * Reads the next byte of data from this input stream. The value byte is
221     * returned as an int in the range 0 to 255. If no byte is available
222     * because the end of the stream has been reached, -1 is returned.
223     *
224     * <P>This method is not synchronized, so it is not thread safe.
225     *
226     * @return The byte read in the range 0-255, or -1 if the end of stream
227     * has been reached.
228     *
229     *
230     * */
231    public int read() {
232        if (pos < count) {
233            return (int)buf[pos++] & 0xFF;
234        } else {
235            return -1;
236        }
237    }
238
239}