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 }