Skip to content

Commit 960c48b

Browse files
authored
Merge pull request #259 from scijava/more-handles-gabriel
Finalize Location / DataHandle API and add more Locations
2 parents 7cccfac + 6c7aab8 commit 960c48b

34 files changed

+2187
-437
lines changed
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
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 ByteBank} implementation backed by a {@link ByteArray}. Self-growing
38+
* up to a maximum capacity of {@link Integer#MAX_VALUE}
39+
*
40+
* @author Gabriel Einsdorf
41+
*/
42+
public class ByteArrayByteBank implements ByteBank {
43+
44+
private final ByteArray buffer;
45+
private long maxBufferedPos = -1;
46+
47+
/**
48+
* Creates a {@link ByteArrayByteBank}
49+
*/
50+
public ByteArrayByteBank() {
51+
buffer = new ByteArray();
52+
}
53+
54+
/**
55+
* Creates a {@link ByteArrayByteBank} with the specified initial capacity
56+
*
57+
* @param initialCapacity the initial capacity of this {@link ByteBank}
58+
*/
59+
public ByteArrayByteBank(final int initialCapacity) {
60+
buffer = new ByteArray(initialCapacity);
61+
}
62+
63+
/**
64+
* Creates a {@link ByteArrayByteBank} that wraps the specified
65+
* {@link ByteArray}.
66+
*
67+
* @param bytes the {@link ByteArray} to wrap
68+
*/
69+
public ByteArrayByteBank(final ByteArray bytes) {
70+
buffer = bytes;
71+
bytes.size();
72+
}
73+
74+
/**
75+
* Creates a {@link ByteArrayByteBank} that wraps the provided byte array
76+
*
77+
* @param bytes the bytes to wrap
78+
*/
79+
public ByteArrayByteBank(final byte[] bytes) {
80+
buffer = new ByteArray(bytes);
81+
maxBufferedPos = bytes.length;
82+
}
83+
84+
@Override
85+
public long getMaxBufferSize() {
86+
return Integer.MAX_VALUE;
87+
}
88+
89+
@Override
90+
public void setBytes(final long startpos, final byte[] bytes,
91+
final int offset, final int length)
92+
{
93+
// ensure we have space
94+
checkWritePos(startpos, startpos + length);
95+
final int neededCapacity = (int) (Math.max(maxBufferedPos, 0) + length);
96+
buffer.ensureCapacity(neededCapacity);
97+
98+
// copy the data
99+
System.arraycopy(bytes, offset, buffer.getArray(), (int) startpos, length);
100+
buffer.setSize(neededCapacity);
101+
updateMaxPos(startpos + length);
102+
}
103+
104+
@Override
105+
public void setByte(final long pos, final byte b) {
106+
checkWritePos(pos, pos);
107+
buffer.setValue((int) pos, b);
108+
updateMaxPos(pos);
109+
}
110+
111+
private void updateMaxPos(final long pos) {
112+
maxBufferedPos = pos > maxBufferedPos ? pos : maxBufferedPos;
113+
}
114+
115+
@Override
116+
public void clear() {
117+
buffer.clear();
118+
maxBufferedPos = 0;
119+
}
120+
121+
@Override
122+
public byte getByte(final long pos) {
123+
checkReadPos(pos, pos);
124+
// the buffer might contain bytes with negative value
125+
// we need to flip the sign to positive to satisfy the method contract
126+
return buffer.getValue((int) pos);
127+
}
128+
129+
@Override
130+
public int getBytes(final long startPos, final byte[] b, final int offset,
131+
final int length)
132+
{
133+
checkReadPos(startPos, startPos + length);
134+
final int readLength = (int) Math.min(getMaxPos() - startPos, length);
135+
System.arraycopy(buffer.getArray(), (int) startPos, b, offset, readLength);
136+
return readLength;
137+
}
138+
139+
@Override
140+
public long getMaxPos() {
141+
return maxBufferedPos;
142+
}
143+
}
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
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+
* A {@link ByteBank} is a self-growing buffer over arbitrary bytes.
36+
*
37+
* @author Gabriel Einsdorf
38+
*/
39+
public interface ByteBank {
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 array containing 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+
* Check if we can read from the specified range
88+
*
89+
* @param start the start position of the range
90+
* @param end the end position of the range
91+
*/
92+
default void checkReadPos(final long start, final long end) {
93+
basicRangeCheck(start, end);
94+
if (start > getMaxPos()) {
95+
throw new IndexOutOfBoundsException("Requested position: " + start +
96+
" is larger than the maximally buffered postion: " + getMaxPos());
97+
}
98+
}
99+
100+
/**
101+
* Check if we can write to the specified range
102+
*
103+
* @param start the start position of the range
104+
* @param end the end position of the range
105+
* @throws IndexOutOfBoundsException if
106+
*/
107+
default void checkWritePos(final long start, final long end) {
108+
if (start > getMaxPos() + 1) { // we can't have holes in the buffer
109+
throw new IndexOutOfBoundsException("Requested start position: " + start +
110+
" would leave a hole in the buffer, largest legal position is: " +
111+
getMaxPos() + 1);
112+
}
113+
if (end < start) {
114+
throw new IllegalArgumentException(
115+
"Invalid range, end is smaller than start!");
116+
}
117+
if (end > getMaxBufferSize()) {
118+
throw new IndexOutOfBoundsException("Requested postion " + end +
119+
" is larger than the maximal buffer size: " + getMaxPos());
120+
}
121+
}
122+
123+
/**
124+
* Ensures that the requested range satisfies basic sanity criteria.
125+
*
126+
* @param start the start of the range
127+
* @param end the end of the range
128+
*/
129+
default void basicRangeCheck(final long start, final long end) {
130+
if (start > getMaxPos()) {
131+
throw new IndexOutOfBoundsException("Requested postion " + start +
132+
" is larger than the maximal buffer size: " + getMaxPos());
133+
}
134+
if (end < start) {
135+
throw new IllegalArgumentException(
136+
"Invalid range, end is smaller than start!");
137+
}
138+
}
139+
140+
/**
141+
* Clears the buffer
142+
*/
143+
void clear();
144+
145+
/**
146+
* @return the position of the last byte in this ByteBank
147+
*/
148+
long getMaxPos();
149+
150+
/**
151+
* Sets the byte at the given position
152+
*
153+
* @param pos the position
154+
* @param b the value to set
155+
*/
156+
void setByte(long pos, byte b);
157+
158+
/**
159+
* @return the maximal size of the buffer
160+
*/
161+
long getMaxBufferSize();
162+
163+
/**
164+
* @return True iff the buffer is read-only.
165+
*/
166+
default boolean isReadOnly() {
167+
return false;
168+
}
169+
}

0 commit comments

Comments
 (0)