Skip to content

Commit db2661e

Browse files
committed
Add StreamHandle
This basic version does not fully support random access, which will be provided by subclasses to be added in future commits.
1 parent 6c094f7 commit db2661e

File tree

2 files changed

+257
-0
lines changed

2 files changed

+257
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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.handle;
33+
34+
import org.scijava.io.location.Location;
35+
36+
/**
37+
* Abstract base class for {@link StreamHandle} implementations.
38+
*
39+
* @author Curtis Rueden
40+
* @author Melissa Linkert
41+
*/
42+
public abstract class AbstractStreamHandle<L extends Location> extends
43+
AbstractDataHandle<L> implements StreamHandle<L>
44+
{
45+
46+
// -- Fields --
47+
48+
/** Current position within the stream(s). */
49+
private long offset;
50+
51+
// -- StreamHandle methods --
52+
53+
@Override
54+
public void setOffset(final long offset) {
55+
this.offset = offset;
56+
}
57+
58+
// -- DataHandle methods --
59+
60+
@Override
61+
public long offset() {
62+
return offset;
63+
}
64+
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
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.handle;
33+
34+
import java.io.EOFException;
35+
import java.io.IOException;
36+
import java.io.InputStream;
37+
import java.io.OutputStream;
38+
39+
import org.scijava.io.location.Location;
40+
41+
/**
42+
* A {@link DataHandle} backed by an {@link InputStream} and/or
43+
* {@link OutputStream}.
44+
*
45+
* @author Curtis Rueden
46+
* @author Melissa Linkert
47+
* @author Gabriel Einsdorf
48+
*/
49+
public interface StreamHandle<L extends Location> extends DataHandle<L> {
50+
51+
// -- StreamHandle methods --
52+
53+
/**
54+
* Gets an input stream for reading data, positioned at the current offset.
55+
*
56+
* @return the appropriate input stream, or null if the handle is write-only.
57+
* @throws IOException
58+
*/
59+
InputStream in() throws IOException;
60+
61+
/**
62+
* Gets an output stream for writing data, positioned at the current offset.
63+
*
64+
* @return the appropriate output stream, or null if the handle is read-only.
65+
*/
66+
OutputStream out() throws IOException;
67+
68+
/**
69+
* Sets the offset of the handle to the given position.
70+
* <p>
71+
* This method is intended to be called only in conjunction with reading from
72+
* the input stream, or writing to the output stream. Otherwise, the contents
73+
* may get out of sync.
74+
* </p>
75+
*/
76+
void setOffset(long offset);
77+
78+
/**
79+
* Increments the handle's offset by the given amount.
80+
* <p>
81+
* This method is intended to be called only in conjunction with reading from
82+
* the input stream, or writing to the output stream. Otherwise, the contents
83+
* may get out of sync.
84+
* </p>
85+
*/
86+
default void advance(final long bytes) throws IOException {
87+
setOffset(offset() + bytes);
88+
}
89+
90+
// -- DataHandle methods --
91+
92+
@Override
93+
default void seek(final long pos) throws IOException {
94+
if (pos == offset()) return;
95+
if (pos > offset()) {
96+
jump(pos - offset());
97+
}
98+
else {
99+
throw new UnsupportedOperationException(
100+
"Can't seek backwards through this StreamHandle");
101+
}
102+
}
103+
104+
/**
105+
* Resets the stream to its start.
106+
*
107+
* @throws IOException If something goes wrong with the reset
108+
*/
109+
void resetStream() throws IOException;
110+
111+
default void jump(final long n) throws IOException, EOFException {
112+
long remain = n;
113+
while (remain > 0) {
114+
final long r = in().skip(remain);
115+
if (r < 0) throw new EOFException();
116+
remain -= r;
117+
}
118+
}
119+
120+
@Override
121+
default void ensureReadable(final long count) throws IOException {
122+
if (in() == null) throw new IOException("This handle is write-only.");
123+
DataHandle.super.ensureReadable(count);
124+
}
125+
126+
@Override
127+
default boolean ensureWritable(final long count) throws IOException {
128+
if (out() == null) throw new IOException("This handle is read-only.");
129+
return DataHandle.super.ensureWritable(count);
130+
}
131+
132+
@Override
133+
default int read() throws IOException {
134+
ensureReadable(0);
135+
final int v = in().read();
136+
if (v >= 0) advance(1);
137+
return v;
138+
}
139+
140+
@Override
141+
default byte readByte() throws IOException {
142+
int ch = this.read();
143+
if (ch < 0) throw new EOFException();
144+
return (byte) (ch);
145+
}
146+
147+
@Override
148+
default int read(final byte[] b, final int off, final int len)
149+
throws IOException
150+
{
151+
final int n = in().read(b, off, len);
152+
if (n >= 0) advance(n);
153+
return n;
154+
}
155+
156+
// -- DataOutput methods --
157+
158+
@Override
159+
default void write(final int v) throws IOException {
160+
ensureWritable(1);
161+
out().write(v);
162+
advance(1);
163+
}
164+
165+
@Override
166+
default void writeByte(int v) throws IOException {
167+
write(v);
168+
}
169+
170+
@Override
171+
default void write(final byte[] b, final int off, final int len)
172+
throws IOException
173+
{
174+
ensureWritable(len);
175+
out().write(b, off, len);
176+
advance(len);
177+
}
178+
179+
// -- Closeable methods --
180+
181+
@Override
182+
default void close() throws IOException {
183+
// TODO: Double check this logic.
184+
try (final InputStream in = in()) {
185+
if (in != null) in.close();
186+
}
187+
try (final OutputStream out = out()) {
188+
if (out != null) out.close();
189+
}
190+
}
191+
192+
}

0 commit comments

Comments
 (0)