Skip to content

Commit 622af57

Browse files
committed
Add IOBuffer interface + ByteArray implementation
Signed-off-by: Curtis Rueden <ctrueden@wisc.edu>
1 parent 00d3c55 commit 622af57

File tree

2 files changed

+267
-0
lines changed

2 files changed

+267
-0
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* #%L
3+
* SciJava Common shared library for SciJava software.
4+
* %%
5+
* Copyright (C) 2009 - 2017 Board of Regents of the University of
6+
* Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck
7+
* Institute of Molecular Cell Biology and Genetics.
8+
* %%
9+
* Redistribution and use in source and binary forms, with or without
10+
* modification, are permitted provided that the following conditions are met:
11+
*
12+
* 1. Redistributions of source code must retain the above copyright notice,
13+
* this list of conditions and the following disclaimer.
14+
* 2. Redistributions in binary form must reproduce the above copyright notice,
15+
* this list of conditions and the following disclaimer in the documentation
16+
* and/or other materials provided with the distribution.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
* POSSIBILITY OF SUCH DAMAGE.
29+
* #L%
30+
*/
31+
32+
package org.scijava.io;
33+
34+
import org.scijava.util.ByteArray;
35+
36+
/**
37+
* {@link IOBuffer} implementation backed by a {@link ByteArray}.
38+
*
39+
* @author Gabriel Einsdorf
40+
*/
41+
public class ByteArrayIOBuffer implements IOBuffer {
42+
43+
private ByteArray buffer;
44+
private long maxBufferedPos = -1;
45+
46+
public ByteArrayIOBuffer() {
47+
buffer = new ByteArray();
48+
}
49+
50+
@Override
51+
public int getMaxBufferSize() {
52+
return Integer.MAX_VALUE;
53+
}
54+
55+
@Override
56+
public void setBytes(long startpos, byte[] bytes, int offset, int length) {
57+
// ensure we have space
58+
checkWritePos(startpos, startpos + length);
59+
int neededCapacity = (int) (Math.max(maxBufferedPos, 0) + length);
60+
buffer.ensureCapacity(neededCapacity);
61+
62+
// copy the data
63+
System.arraycopy(bytes, offset, buffer.getArray(), (int) startpos, length);
64+
buffer.setSize(neededCapacity);
65+
updateMaxPos(startpos + length);
66+
}
67+
68+
@Override
69+
public void setByte(long pos, byte b) {
70+
checkWritePos(pos, pos);
71+
buffer.setValue((int) pos, b);
72+
updateMaxPos(pos);
73+
}
74+
75+
private void updateMaxPos(long pos) {
76+
maxBufferedPos = pos > maxBufferedPos ? pos : maxBufferedPos;
77+
}
78+
79+
@Override
80+
public void clear() {
81+
buffer.clear();
82+
maxBufferedPos = 0;
83+
}
84+
85+
@Override
86+
public byte getByte(long pos) {
87+
checkReadPos(pos, pos);
88+
// the buffer might contain bytes with negative value
89+
// we need to flip the sign to positive to satisfy the method contract
90+
return buffer.getValue((int) pos);
91+
}
92+
93+
@Override
94+
public int getBytes(long startPos, byte[] b, int offset, int length) {
95+
checkReadPos(startPos, startPos + length);
96+
System.arraycopy(buffer.getArray(), (int) startPos, b, offset, length);
97+
return length;
98+
}
99+
100+
@Override
101+
public long getMaxPos() {
102+
return maxBufferedPos;
103+
}
104+
105+
/**
106+
* Ensures that the requested range satisfies basic sanity criteria.
107+
*
108+
* @param start the start of the range
109+
* @param end the end of the range
110+
*/
111+
private void basicRangeCheck(long start, long end) {
112+
if (start > Integer.MAX_VALUE) {
113+
throw new IndexOutOfBoundsException("Requested postion " + start +
114+
" is larger than the maximal buffer size: " + Integer.MAX_VALUE);
115+
}
116+
if (end > Integer.MAX_VALUE) {
117+
throw new IndexOutOfBoundsException("Requested postion " + end +
118+
" is larger than the maximal buffer size: " + Integer.MAX_VALUE);
119+
}
120+
if (end < start) {
121+
throw new IllegalArgumentException(
122+
"Invalid range, end is smaller than start!");
123+
}
124+
}
125+
126+
/**
127+
* Check if we can write to the specified range
128+
*
129+
* @param start the start position of the range
130+
* @param end the end position of the range
131+
*/
132+
private void checkWritePos(long start, long end) {
133+
basicRangeCheck(start, end);
134+
if (start > maxBufferedPos + 1) { // we can't have holes in the buffer
135+
throw new IndexOutOfBoundsException("Requested start position: " + start +
136+
" would leave a hole in the buffer, largest legal position is: " +
137+
maxBufferedPos + 1);
138+
}
139+
}
140+
141+
/**
142+
* Check if we can read from the specified range
143+
*
144+
* @param start the start position of the range
145+
* @param end the end position of the range
146+
*/
147+
private void checkReadPos(long start, long end) {
148+
basicRangeCheck(start, end);
149+
if (start > maxBufferedPos) {
150+
throw new IndexOutOfBoundsException("Reuested position: " + start +
151+
" is larger than the maximally buffered postion: " + maxBufferedPos);
152+
}
153+
if (end > maxBufferedPos) {
154+
throw new IndexOutOfBoundsException("reuested position: " + end +
155+
" is larger than the maximally buffered postion: " + maxBufferedPos);
156+
}
157+
}
158+
159+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* #%L
3+
* SciJava Common shared library for SciJava software.
4+
* %%
5+
* Copyright (C) 2009 - 2017 Board of Regents of the University of
6+
* Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck
7+
* Institute of Molecular Cell Biology and Genetics.
8+
* %%
9+
* Redistribution and use in source and binary forms, with or without
10+
* modification, are permitted provided that the following conditions are met:
11+
*
12+
* 1. Redistributions of source code must retain the above copyright notice,
13+
* this list of conditions and the following disclaimer.
14+
* 2. Redistributions in binary form must reproduce the above copyright notice,
15+
* this list of conditions and the following disclaimer in the documentation
16+
* and/or other materials provided with the distribution.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
* POSSIBILITY OF SUCH DAMAGE.
29+
* #L%
30+
*/
31+
32+
package org.scijava.io;
33+
34+
/**
35+
* Self-growing buffer over arbitrary bytes.
36+
*
37+
* @author Gabriel Einsdorf
38+
*/
39+
public interface IOBuffer {
40+
41+
/**
42+
* @param pos the position to read from
43+
* @return the byte at the given position
44+
*/
45+
public byte getByte(long pos);
46+
47+
/**
48+
* @param startPos the position in the buffer to start reading from
49+
* @param bytes the byte array to read into
50+
* @return the number of bytes read
51+
*/
52+
default int getBytes(long startPos, byte[] bytes) {
53+
return getBytes(startPos, bytes, 0, bytes.length);
54+
}
55+
56+
/**
57+
* @param startPos the position in the buffer to start reading from
58+
* @param bytes the byte array to read into
59+
* @param offset the offset in the bytes array
60+
* @param length the number of elements to read into the bytes array
61+
* @return number of bytes read
62+
*/
63+
int getBytes(long startPos, byte[] bytes, int offset, int length);
64+
65+
/**
66+
* Sets the bytes starting form the given position to the values form the
67+
* provided array.
68+
*
69+
* @param startPos the position in the buffer to start writing from
70+
* @param bytes the byte array to write
71+
* @param offset the offset in the bytes array
72+
* @param length the number of bytes to read
73+
*/
74+
void setBytes(long startPos, byte[] bytes, int offset, int length);
75+
76+
/**
77+
* Appends the given bytes to the buffer
78+
*
79+
* @param bytes the bytes to append to the buffer
80+
* @param length the number of elements to append from the bytes array
81+
*/
82+
default void appendBytes(byte[] bytes, int length) {
83+
setBytes(getMaxPos() + 1, bytes, 0, length);
84+
}
85+
86+
/**
87+
* Clears the buffer
88+
*/
89+
public void clear();
90+
91+
/**
92+
* @return the largest bufferd position
93+
*/
94+
public long getMaxPos();
95+
96+
/**
97+
* Sets the byte at the given position
98+
*
99+
* @param pos the position
100+
* @param b the value to set
101+
*/
102+
void setByte(long pos, byte b);
103+
104+
/**
105+
* @return the max size of the buffer
106+
*/
107+
public int getMaxBufferSize();
108+
}

0 commit comments

Comments
 (0)