001    /*
002     * Copyright (c) Andrey Kuznetsov. All Rights Reserved.
003     *
004     * http://uio.imagero.com
005     *
006     * Redistribution and use in source and binary forms, with or without
007     * modification, are permitted provided that the following conditions are met:
008     *
009     *  o Redistributions of source code must retain the above copyright notice,
010     *    this list of conditions and the following disclaimer.
011     *
012     *  o Redistributions in binary form must reproduce the above copyright notice,
013     *    this list of conditions and the following disclaimer in the documentation
014     *    and/or other materials provided with the distribution.
015     *
016     *  o Neither the name of Andrey Kuznetsov nor the names of
017     *    its contributors may be used to endorse or promote products derived
018     *    from this software without specific prior written permission.
019     *
020     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
021     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
022     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
023     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
027     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
028     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
029     * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
030     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031     */
032    package com.imagero.uio.bio;
033    
034    import com.imagero.uio.RandomAccessIO;
035    import com.imagero.uio.RandomAccessInput;
036    import com.imagero.uio.RandomAccessOutput;
037    import com.imagero.uio.io.UnexpectedEOFException;
038    import com.imagero.uio.impl.AbstractRandomAccessIO;
039    
040    import java.io.IOException;
041    import java.io.InputStream;
042    import java.io.OutputStream;
043    
044    /**
045     * ByteArrayRandomAccessIO is like ByteArrayOutputStream and ByteArrayInputStream together.
046     * It implements also DataInput/DataOutput and other advanced interfaces.
047     * @author Andrey Kuznetsov
048     */
049    public class ByteArrayRandomAccessIO extends AbstractRandomAccessIO implements RandomAccessIO {
050    
051        VariableSizeByteBuffer buffer;
052        BufferPosition position;
053        int _offset;
054    
055        public ByteArrayRandomAccessIO(int initialSize) {
056            this(new VariableSizeByteBuffer(initialSize));
057        }
058    
059        public ByteArrayRandomAccessIO(int offset, VariableSizeByteBuffer buffer) {
060            this._offset = offset;
061            this.buffer = buffer;
062            position = new BufferPosition(Integer.MAX_VALUE);
063        }
064    
065        public ByteArrayRandomAccessIO(byte [] data) {
066            this(new VariableSizeByteBuffer(data));
067        }
068    
069        public ByteArrayRandomAccessIO(VariableSizeByteBuffer buffer) {
070            this.buffer = buffer;
071            position = new BufferPosition(Integer.MAX_VALUE);
072        }
073    
074        public int read() throws IOException {
075            return buffer.read(position);
076        }
077    
078        public long skip(long n) throws IOException {
079            return buffer.skip(n, position);
080        }
081    
082        public int read(byte[] b, int off, int len) throws IOException {
083            return buffer.read(b, 0, b.length, position);
084        }
085    
086        public int getByteOrder() {
087            return byteOrder;
088        }
089    
090        public void setByteOrder(int byteOrder) {
091            switch (byteOrder) {
092                case BIG_ENDIAN:
093                case LITTLE_ENDIAN:
094                    this.byteOrder = byteOrder;
095                    break;
096                default:
097                    throw new IllegalArgumentException();
098            }
099        }
100    
101        public long getFilePointer() throws IOException {
102            return position.pos - _offset;
103        }
104    
105        public long length() throws IOException {
106            return buffer.getCount() - _offset;
107        }
108    
109        public void seek(long offset) throws IOException {
110            if (offset + _offset > Integer.MAX_VALUE) {
111                throw new IOException("Offset too big: 0x" + Long.toHexString(offset));
112            }
113            buffer.seek((int) offset + _offset, position);
114        }
115    
116    
117        public void close() throws IOException {
118        }
119    
120        public void readFully(byte b[], int offset, int length) throws IOException {
121            int sum = 0;
122            while (length > 0) {
123                int read = buffer.read(b, offset, length, position);
124                if (read <= 0) {
125                    throw new UnexpectedEOFException(sum);
126                }
127                sum += read;
128                length -= read;
129                offset += read;
130            }
131        }
132    
133        public int skipBytes(int n) throws IOException {
134            return (int) buffer.skip(n, position);
135        }
136    
137        public void setLength(long newLength) throws IOException {
138            if (newLength > Integer.MAX_VALUE) {
139                throw new IOException();
140            }
141            buffer.setCount((int) newLength);
142        }
143    
144        public void write(int b) throws IOException {
145            buffer.write(b, position);
146        }
147    
148        public void write(byte b[], int offset, int length) throws IOException {
149            buffer.write(b, offset, length, position);
150        }
151    
152        public int read(short[] dest, int offset, int length, int byteOrder) throws IOException {
153            return buffer.read(dest, offset, length, byteOrder == BIG_ENDIAN, position);
154        }
155    
156        public int read(char[] dest, int offset, int length, int byteOrder) throws IOException {
157            return buffer.read(dest, offset, length, byteOrder == BIG_ENDIAN, position);
158        }
159    
160        public int read(int[] dest, int offset, int length, int byteOrder) throws IOException {
161            return buffer.read(dest, offset, length, byteOrder == BIG_ENDIAN, position);
162        }
163    
164        public int read(long[] dest, int offset, int length, int byteOrder) throws IOException {
165            return buffer.read(dest, offset, length, byteOrder == BIG_ENDIAN, position);
166        }
167    
168        public int read(float[] dest, int offset, int length, int byteOrder) throws IOException {
169            return buffer.read(dest, offset, length, byteOrder == BIG_ENDIAN, position);
170        }
171    
172        public int read(double[] dest, int offset, int length, int byteOrder) throws IOException {
173            return buffer.read(dest, offset, length, byteOrder == BIG_ENDIAN, position);
174        }
175    
176        public void write(short[] data, int offset, int length, int byteOrder) throws IOException {
177            buffer.write(data, offset, length, byteOrder == BIG_ENDIAN, position);
178        }
179    
180        public void write(char[] data, int offset, int length, int byteOrder) throws IOException {
181            buffer.write(data, offset, length, byteOrder == BIG_ENDIAN, position);
182        }
183    
184        public void write(int[] data, int offset, int length, int byteOrder) throws IOException {
185            buffer.write(data, offset, length, byteOrder == BIG_ENDIAN, position);
186        }
187    
188        public void write(float[] data, int offset, int length, int byteOrder) throws IOException {
189            buffer.write(data, offset, length, byteOrder == BIG_ENDIAN, position);
190        }
191    
192        public void write(long[] data, int offset, int length, int byteOrder) throws IOException {
193            buffer.write(data, offset, length, byteOrder == BIG_ENDIAN, position);
194        }
195    
196        public void write(double[] data, int offset, int length, int byteOrder) throws IOException {
197            buffer.write(data, offset, length, byteOrder == BIG_ENDIAN, position);
198        }
199    
200        public RandomAccessIO createIOChild(long offset, int byteOrder, boolean syncPointer) {
201            ByteArrayRandomAccessIO io = new ByteArrayRandomAccessIO((int) offset, buffer);
202            if(syncPointer) {
203                io.buffer = buffer;
204            }
205            io.setByteOrder(byteOrder);
206            return io;
207        }
208    
209        public RandomAccessInput createInputChild(long offset, int byteOrder, boolean syncPointer) {
210            return createIOChild(offset, byteOrder, syncPointer);
211        }
212    
213        public RandomAccessOutput createOutputChild(long offset, int byteOrder, boolean syncPointer) {
214            return createIOChild(offset, byteOrder, syncPointer);
215        }
216    
217        public byte [] toByteArray() throws IOException {
218            byte [] b = new byte[(int)length()];
219            int pos = position.pos;
220            buffer.seek(0, position);
221            buffer.read(b, 0, b.length, position);
222            buffer.seek(pos, position);
223            return b;
224        }
225    
226        public void flush() throws IOException {
227        }
228    
229        public InputStream createInputStream(long offset) {
230            return buffer.getInputStream((int) offset);
231        }
232    
233        public OutputStream createOutputStream(long offset) {
234            return buffer.getOutputStream((int) offset);
235        }
236    }