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 /*
033 * Copyright (c) Andrey Kuznetsov. All Rights Reserved.
034 *
035 * http://uio.imagero.com
036 *
037 * Redistribution and use in source and binary forms, with or without
038 * modification, are permitted provided that the following conditions are met:
039 *
040 * o Redistributions of source code must retain the above copyright notice,
041 * this list of conditions and the following disclaimer.
042 *
043 * o Redistributions in binary form must reproduce the above copyright notice,
044 * this list of conditions and the following disclaimer in the documentation
045 * and/or other materials provided with the distribution.
046 *
047 * o Neither the name of Andrey Kuznetsov nor the names of
048 * its contributors may be used to endorse or promote products derived
049 * from this software without specific prior written permission.
050 *
051 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
052 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
053 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
054 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
055 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
056 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
057 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
058 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
059 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
060 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
061 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
062 */
063 package com.imagero.uio.bio;
064
065 import com.imagero.uio.Transformer;
066 import com.imagero.uio.RandomAccessIO;
067 import com.imagero.uio.RandomAccessInput;
068 import com.imagero.uio.RandomAccessOutput;
069 import com.imagero.uio.impl.AbstractRandomAccessIO;
070
071 import java.io.DataOutput;
072 import java.io.IOException;
073 import java.io.OutputStream;
074 import java.io.InputStream;
075
076 /**
077 * This class can be used to read from and write to byte array.
078 *
079 * @author Andrey Kuznetsov
080 */
081 public class FixedSizeByteBuffer {
082
083 byte[] buf;
084 int count;
085
086 boolean changed;
087 BufferIndex index;
088
089 public FixedSizeByteBuffer(byte buf[]) {
090 this.buf = buf;
091 }
092
093 public int read(BufferPosition position) {
094 if (availableForReading(position) > 0) {
095 int v = buf[position.pos++] & 0xFF;
096 return v;
097 }
098 return -1;
099 }
100
101 public long skip(long n, BufferPosition position) {
102 long p = Math.max(0, Math.min(count - position.pos, n));
103 position.pos += p;
104 return p;
105 }
106
107 public int availableForReading(BufferPosition position) {
108 return Math.max(0, count - position.pos);
109 }
110
111 public int availableForWriting(BufferPosition position) {
112 return Math.max(0, buf.length - position.pos);
113 }
114
115 public int read(byte[] dest, int offset, int length, BufferPosition position) {
116 final int available = availableForReading(position);
117 int toCopy = Math.max(0, Math.min(length, available));
118 if (toCopy > 0) {
119 System.arraycopy(buf, position.pos, dest, offset, toCopy);
120 position.pos += toCopy;
121 }
122 return toCopy;
123 }
124
125 public int read(short[] dest, int offset, int length, boolean bigEndian, BufferPosition position) {
126 final int available = availableForReading(position) >> 1;
127 int toCopy = Math.max(0, Math.min(length, available));
128 com.imagero.uio.Transformer.byteToShort(buf, position.pos, toCopy, dest, offset, bigEndian);
129 position.pos += toCopy << 1;
130 return toCopy;
131 }
132
133 public int read(char[] dest, int offset, int length, boolean bigEndian, BufferPosition position) {
134 final int available = availableForReading(position) >> 1;
135 int toCopy = Math.max(0, Math.min(length, available));
136 com.imagero.uio.Transformer.byteToChar(buf, position.pos, toCopy, dest, offset, bigEndian);
137 position.pos += toCopy << 1;
138 return toCopy;
139 }
140
141 public int read(int[] dest, int offset, int length, boolean bigEndian, BufferPosition position) {
142 final int available = availableForReading(position) >> 2;
143 int toCopy = Math.max(0, Math.min(length, available));
144 com.imagero.uio.Transformer.byteToInt(buf, position.pos, toCopy, dest, offset, bigEndian);
145 position.pos += toCopy << 2;
146 return toCopy;
147 }
148
149 public int read(float[] dest, int offset, int length, boolean bigEndian, BufferPosition position) {
150 final int available = availableForReading(position) >> 2;
151 int toCopy = Math.max(0, Math.min(length, available));
152 com.imagero.uio.Transformer.byteToFloat(buf, position.pos, toCopy, dest, offset, bigEndian);
153 position.pos += toCopy << 2;
154 return toCopy;
155 }
156
157 public int read(long[] dest, int offset, int length, boolean bigEndian, BufferPosition position) {
158 final int available = availableForReading(position) >> 3;
159 int toCopy = Math.max(0, Math.min(length, available));
160 com.imagero.uio.Transformer.byteToLong(buf, position.pos, toCopy, dest, offset, bigEndian);
161 position.pos += toCopy << 3;
162 return toCopy;
163 }
164
165 public int read(double[] dest, int offset, int length, boolean bigEndian, BufferPosition position) {
166 final int available = availableForReading(position) >> 3;
167 int toCopy = Math.max(0, Math.min(length, available));
168 com.imagero.uio.Transformer.byteToDouble(buf, position.pos, toCopy, dest, offset, bigEndian);
169 position.pos += toCopy << 3;
170 return toCopy;
171 }
172
173 /**
174 * write given byte to buffer.
175 *
176 * @param b int to write
177 */
178 public void write(int b, BufferPosition position) {
179 buf[position.pos++] = (byte) b;
180 count = Math.max(position.pos, count);
181 }
182
183 public int getCount() {
184 return count;
185 }
186
187 public int getPosition(BufferPosition position) {
188 return position.pos;
189 }
190
191 public void setCount(int count) {
192 this.count = Math.min(Math.max(count, 0), buf.length);
193 }
194
195 /**
196 * write buffer contents to OutputStream
197 * @param wholeBuffer if true then whole buffer is written, otherwise only getCount() bytes are written
198 */
199 public void writeBuffer(OutputStream out, boolean wholeBuffer) throws IOException {
200 if (wholeBuffer) {
201 out.write(buf);
202 } else {
203 out.write(buf, 0, count);
204 }
205 }
206
207 public void writeBuffer(DataOutput out, boolean wholeBuffer) throws IOException {
208 if (wholeBuffer) {
209 out.write(buf);
210 } else {
211 out.write(buf, 0, count);
212 }
213 }
214
215 /**
216 * write whole buffer contents to OutputStream (count is ignored)
217 */
218 public void writeBuffer(OutputStream out) throws IOException {
219 out.write(buf);
220 }
221
222 public void writeBuffer(DataOutput out) throws IOException {
223 out.write(buf);
224 }
225
226 public int write(byte src[], int offset, int length, BufferPosition position) {
227 int available = availableForWriting(position);
228 int toCopy = Math.max(0, Math.min(length, available));
229 if (toCopy > 0) {
230 System.arraycopy(src, offset, buf, position.pos, toCopy);
231 position.pos += toCopy;
232 count = Math.max(count, position.pos);
233 }
234 return toCopy;
235 }
236
237 public int write(short[] src, int offset, int length, boolean bigEndian, BufferPosition position) {
238 final int available = availableForWriting(position) >> 1;
239 int toCopy = Math.max(0, Math.min(length, available));
240 com.imagero.uio.Transformer.shortToByte(src, offset, toCopy, buf, position.pos, bigEndian);
241 position.pos += toCopy << 1;
242 count = Math.max(count, position.pos);
243 return toCopy;
244 }
245
246 public int write(char[] src, int offset, int length, boolean bigEndian, BufferPosition position) {
247 final int available = availableForWriting(position) >> 1;
248 int toCopy = Math.max(0, Math.min(length, available));
249 com.imagero.uio.Transformer.charToByte(src, offset, toCopy, buf, position.pos, bigEndian);
250 position.pos += toCopy << 1;
251 count = Math.max(count, position.pos);
252 return toCopy;
253 }
254
255 public int write(int[] src, int offset, int length, boolean bigEndian, BufferPosition position) {
256 final int available = availableForWriting(position) >> 2;
257 int toCopy = Math.max(0, Math.min(length, available));
258 com.imagero.uio.Transformer.intToByte(src, offset, toCopy, buf, position.pos, bigEndian);
259 position.pos += toCopy << 2;
260 count = Math.max(count, position.pos);
261 return toCopy;
262 }
263
264 public int write(float[] src, int offset, int length, boolean bigEndian, BufferPosition position) {
265 final int available = availableForWriting(position) >> 2;
266 int toCopy = Math.max(0, Math.min(length, available));
267 com.imagero.uio.Transformer.floatToByte(src, offset, toCopy, buf, position.pos, bigEndian);
268 position.pos += toCopy << 2;
269 count = Math.max(count, position.pos);
270 return toCopy;
271 }
272
273 public int write(long[] src, int offset, int length, boolean bigEndian, BufferPosition position) {
274 final int available = availableForWriting(position) >> 3;
275 int toCopy = Math.max(0, Math.min(length, available));
276 com.imagero.uio.Transformer.longToByte(src, offset, toCopy, buf, position.pos, bigEndian);
277 position.pos += toCopy << 3;
278 count = Math.max(count, position.pos);
279 return toCopy;
280 }
281
282 public int write(double[] src, int offset, int length, boolean bigEndian, BufferPosition position) {
283 final int available = availableForWriting(position) >> 3;
284 int toCopy = Math.max(0, Math.min(length, available));
285 com.imagero.uio.Transformer.doubleToByte(src, offset, toCopy, buf, position.pos, bigEndian);
286 position.pos += toCopy << 3;
287 count = Math.max(count, position.pos);
288 return toCopy;
289 }
290
291 public RandomAccessIO create() {
292 return new FSBRandomAccessIO(this);
293 }
294
295 public RandomAccessIO create(int offset, int length) {
296 return new FSBRandomAccessIO(this, offset, length);
297 }
298
299 static class FSBRandomAccessIO extends AbstractRandomAccessIO {
300
301 FixedSizeByteBuffer buffer;
302 BufferPosition position;
303
304 int offset;
305 int length;
306
307 public FSBRandomAccessIO(FixedSizeByteBuffer buffer) {
308 this(buffer, 0, buffer.buf.length);
309 }
310
311 public FSBRandomAccessIO(FixedSizeByteBuffer buffer, int offset) {
312 this(buffer, offset, buffer.buf.length - offset);
313 }
314
315 public FSBRandomAccessIO(FixedSizeByteBuffer buffer, int offset, int length) {
316 this.buffer = buffer;
317 this.offset = offset;
318 this.length = length;
319 }
320
321 public int read() throws IOException {
322 return buffer.read(position);
323 }
324
325 public void seek(long pos) {
326 position.pos = (int) Math.min(length, pos + offset);
327 }
328
329 public long length() throws IOException {
330 return length;
331 }
332
333 public long getFilePointer() throws IOException {
334 return position.pos - offset;
335 }
336
337 public void setLength(long newLength) throws IOException {
338 this.length = (int) Math.min(buffer.buf.length, newLength);
339 }
340
341 public void write(int b) throws IOException {
342 buffer.write(b, position);
343 }
344
345 public void write(byte b[], int off, int len) throws IOException {
346 buffer.write(b, off, len, position);
347 }
348
349 public InputStream createInputStream(long offset) {
350 return new FSBInputStream((int) offset, buffer);
351 }
352
353 public OutputStream createOutputStream(long offset) {
354 return new FSBOutputStream((int) offset, buffer) ;
355 }
356
357 public RandomAccessIO createIOChild(long offset, int byteOrder, boolean syncPointer) throws IOException {
358 FSBRandomAccessIO rio = new FSBRandomAccessIO(buffer, (int) offset);
359 if(syncPointer) {
360 rio.position = position;
361 }
362 rio.setByteOrder(byteOrder);
363 return rio;
364 }
365
366 public RandomAccessInput createInputChild(long offset, int byteOrder, boolean syncPointer) throws IOException {
367 return createIOChild(offset, byteOrder, syncPointer);
368 }
369
370 public RandomAccessOutput createOutputChild(long offset, int byteOrder, boolean syncPointer) throws IOException {
371 return createIOChild(offset, byteOrder, syncPointer);
372 }
373 }
374
375 static class FSBInputStream extends InputStream {
376 FixedSizeByteBuffer buffer;
377 BufferPosition position;
378 int mark;
379
380 public FSBInputStream(FixedSizeByteBuffer buffer) {
381 this.buffer = buffer;
382 position = new BufferPosition(buffer.buf.length);
383 }
384
385 public FSBInputStream(int offset, FixedSizeByteBuffer buffer) {
386 this.buffer = buffer;
387 position = new BufferPosition(Integer.MAX_VALUE);
388 position.pos = offset;
389 }
390
391 public int read() {
392 return buffer.read(position);
393 }
394
395 public int read(byte b[]) throws IOException {
396 return buffer.read(b, 0, b.length, position);
397 }
398
399 public int read(byte b[], int off, int len) {
400 return buffer.read(b, off, len, position);
401 }
402
403 public long skip(long n) {
404 return buffer.skip(n, position);
405 }
406
407 public int available() {
408 return buffer.availableForReading(position);
409 }
410
411 public synchronized void mark(int readlimit) {
412 this.mark = position.pos;
413 }
414
415 public synchronized void reset() throws IOException {
416 position.pos = mark;
417 }
418
419 public boolean markSupported() {
420 return true;
421 }
422 }
423
424 static class FSBOutputStream extends OutputStream {
425 FixedSizeByteBuffer buffer;
426 BufferPosition position;
427
428 public FSBOutputStream(FixedSizeByteBuffer buffer) {
429 this(0, buffer);
430 }
431
432 public FSBOutputStream(int offset, FixedSizeByteBuffer buffer) {
433 this.buffer = buffer;
434 position = new BufferPosition(Integer.MAX_VALUE);
435 position.pos = offset;
436 }
437
438 public void write(int b) throws IOException {
439 buffer.write(b, position);
440 }
441
442 public void write(byte b[]) throws IOException {
443 buffer.write(b, 0, b.length, position);
444 }
445
446 public void write(byte b[], int off, int len) throws IOException {
447 buffer.write(b, off, len, position);
448 }
449
450 public void close() throws IOException {
451 buffer = null;
452 }
453 }
454 }