Skip to content

Commit 763c105

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 4285032 commit 763c105

File tree

2 files changed

+253
-0
lines changed

2 files changed

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

0 commit comments

Comments
 (0)