Skip to content

Commit 4f42427

Browse files
committed
Move MemorySegmentInputStream and make it public
1 parent ae94b50 commit 4f42427

File tree

2 files changed

+189
-158
lines changed

2 files changed

+189
-158
lines changed

Diff for: src/main/java/software/coley/lljzip/format/compression/ZipCompressions.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package software.coley.lljzip.format.compression;
22

33
import software.coley.lljzip.format.model.LocalFileHeader;
4+
import software.coley.lljzip.util.MemorySegmentInputStream;
45

6+
import javax.annotation.Nonnull;
57
import java.io.IOException;
68
import java.io.InputStream;
79
import java.lang.foreign.MemorySegment;
@@ -175,7 +177,8 @@ static String getName(int method) {
175177
* @throws IOException
176178
* When the decompression failed.
177179
*/
178-
static MemorySegment decompress(LocalFileHeader header) throws IOException {
180+
@Nonnull
181+
static MemorySegment decompress(@Nonnull LocalFileHeader header) throws IOException {
179182
int method = header.getCompressionMethod();
180183
return switch (method) {
181184
case STORED -> header.getFileData();
@@ -197,7 +200,8 @@ static MemorySegment decompress(LocalFileHeader header) throws IOException {
197200
* @throws IOException
198201
* When the decompression failed.
199202
*/
200-
static InputStream decompressStream(LocalFileHeader header) throws IOException {
203+
@Nonnull
204+
static InputStream decompressStream(@Nonnull LocalFileHeader header) throws IOException {
201205
int method = header.getCompressionMethod();
202206
InputStream in = new MemorySegmentInputStream(header.getFileData());
203207
return switch (method) {
Original file line numberDiff line numberDiff line change
@@ -1,157 +1,184 @@
1-
package software.coley.lljzip.format.compression;
2-
3-
import java.io.IOException;
4-
import java.io.InputStream;
5-
import java.io.OutputStream;
6-
import java.lang.foreign.MemorySegment;
7-
import java.lang.foreign.ValueLayout;
8-
9-
final class MemorySegmentInputStream extends InputStream {
10-
private final MemorySegment data;
11-
private long read;
12-
private long markedOffset = -1;
13-
private long markedLimit;
14-
private volatile boolean closed;
15-
16-
MemorySegmentInputStream(MemorySegment data) {
17-
this.data = data;
18-
}
19-
20-
private void checkMarkLimit() {
21-
if (markedOffset > -1) {
22-
// Discard if we passed the read limit for our mark
23-
long diff = read - markedOffset;
24-
if (diff > markedLimit) {
25-
markedOffset = -1;
26-
}
27-
}
28-
}
29-
30-
@Override
31-
public boolean markSupported() {
32-
return true;
33-
}
34-
35-
@Override
36-
public synchronized void mark(int limit) {
37-
// Record current position and read-limit
38-
markedOffset = read;
39-
markedLimit = limit;
40-
}
41-
42-
@Override
43-
public synchronized void reset() {
44-
// Revert read to marked position.
45-
read = markedOffset;
46-
}
47-
48-
@Override
49-
public int read() throws IOException {
50-
ensureOpen();
51-
MemorySegment data = this.data;
52-
if (read >= data.byteSize()) {
53-
return -1;
54-
}
55-
byte b = data.get(ValueLayout.JAVA_BYTE, read++);
56-
checkMarkLimit();
57-
return b & 0xff;
58-
}
59-
60-
@Override
61-
public int read(byte[] b, int off, int len) throws IOException {
62-
ensureOpen();
63-
MemorySegment data = this.data;
64-
long read = this.read;
65-
long length = data.byteSize();
66-
if (read >= length) {
67-
return -1;
68-
}
69-
long remaining = length - read;
70-
len = (int) Math.min(remaining, len);
71-
MemorySegment.copy(data, read, MemorySegment.ofArray(b), off, len);
72-
this.read += len;
73-
checkMarkLimit();
74-
return len;
75-
}
76-
77-
@Override
78-
public byte[] readNBytes(int len) throws IOException {
79-
ensureOpen();
80-
MemorySegment data = this.data;
81-
long read = this.read;
82-
long length = data.byteSize();
83-
if (read >= length) {
84-
return new byte[0];
85-
}
86-
long remaining = length - read;
87-
len = (int) Math.min(remaining, len);
88-
byte[] buf = new byte[len];
89-
MemorySegment.copy(data, read, MemorySegment.ofArray(buf), 0, len);
90-
this.read += len;
91-
checkMarkLimit();
92-
return buf;
93-
}
94-
95-
@Override
96-
public long skip(long n) throws IOException {
97-
ensureOpen();
98-
MemorySegment data = this.data;
99-
long read = this.read;
100-
long length = data.byteSize();
101-
if (read >= length) {
102-
return 0;
103-
}
104-
n = Math.min(n, length - read);
105-
this.read += n;
106-
checkMarkLimit();
107-
return n;
108-
}
109-
110-
@Override
111-
public int available() throws IOException {
112-
ensureOpen();
113-
MemorySegment data = this.data;
114-
long length = data.byteSize();
115-
long read = this.read;
116-
if (read >= length) {
117-
return 0;
118-
}
119-
long remaining = length - read;
120-
if (remaining > Integer.MAX_VALUE)
121-
return Integer.MAX_VALUE;
122-
return (int) remaining;
123-
}
124-
125-
@Override
126-
public void close() throws IOException {
127-
closed = true;
128-
}
129-
130-
@Override
131-
public long transferTo(OutputStream out) throws IOException {
132-
ensureOpen();
133-
MemorySegment data = this.data;
134-
long length = data.byteSize();
135-
long read = this.read;
136-
if (read >= length) {
137-
return 0L;
138-
}
139-
long remaining = length - read;
140-
byte[] buffer = new byte[(int) Math.min(16384, remaining)];
141-
MemorySegment bufferSegment = MemorySegment.ofArray(buffer);
142-
while (read < length) {
143-
int copyable = (int) Math.min(buffer.length, length - read);
144-
MemorySegment.copy(data, read, bufferSegment, 0, copyable);
145-
out.write(buffer, 0, copyable);
146-
read += copyable;
147-
}
148-
this.read = length;
149-
checkMarkLimit();
150-
return remaining;
151-
}
152-
153-
private void ensureOpen() throws IOException {
154-
if (closed)
155-
throw new IOException("Stream closed");
156-
}
1+
package software.coley.lljzip.util;
2+
3+
import javax.annotation.Nonnull;
4+
import java.io.IOException;
5+
import java.io.InputStream;
6+
import java.io.OutputStream;
7+
import java.lang.foreign.MemorySegment;
8+
import java.lang.foreign.ValueLayout;
9+
10+
/**
11+
* Input stream implementation backed by {@link MemorySegment}.
12+
*
13+
* @author xDark
14+
*/
15+
public class MemorySegmentInputStream extends InputStream {
16+
private final MemorySegment data;
17+
private long read;
18+
private long markedOffset = -1;
19+
private long markedLimit;
20+
private volatile boolean closed;
21+
22+
public MemorySegmentInputStream(@Nonnull MemorySegment data) {
23+
this.data = data;
24+
}
25+
26+
@Nonnull
27+
public MemorySegment getData() {
28+
return data;
29+
}
30+
31+
public long getRead() {
32+
return read;
33+
}
34+
35+
public long getMarkedOffset() {
36+
return markedOffset;
37+
}
38+
39+
public long getMarkedLimit() {
40+
return markedLimit;
41+
}
42+
43+
public boolean isClosed() {
44+
return closed;
45+
}
46+
47+
private void checkMarkLimit() {
48+
if (markedOffset > -1) {
49+
// Discard if we passed the read limit for our mark
50+
long diff = read - markedOffset;
51+
if (diff > markedLimit) {
52+
markedOffset = -1;
53+
}
54+
}
55+
}
56+
57+
@Override
58+
public boolean markSupported() {
59+
return true;
60+
}
61+
62+
@Override
63+
public synchronized void mark(int limit) {
64+
// Record current position and read-limit
65+
markedOffset = read;
66+
markedLimit = limit;
67+
}
68+
69+
@Override
70+
public synchronized void reset() {
71+
// Revert read to marked position.
72+
read = markedOffset;
73+
}
74+
75+
@Override
76+
public int read() throws IOException {
77+
ensureOpen();
78+
MemorySegment data = this.data;
79+
if (read >= data.byteSize()) {
80+
return -1;
81+
}
82+
byte b = data.get(ValueLayout.JAVA_BYTE, read++);
83+
checkMarkLimit();
84+
return b & 0xff;
85+
}
86+
87+
@Override
88+
public int read(@Nonnull byte[] b, int off, int len) throws IOException {
89+
ensureOpen();
90+
MemorySegment data = this.data;
91+
long read = this.read;
92+
long length = data.byteSize();
93+
if (read >= length) {
94+
return -1;
95+
}
96+
long remaining = length - read;
97+
len = (int) Math.min(remaining, len);
98+
MemorySegment.copy(data, read, MemorySegment.ofArray(b), off, len);
99+
this.read += len;
100+
checkMarkLimit();
101+
return len;
102+
}
103+
104+
@Override
105+
public byte[] readNBytes(int len) throws IOException {
106+
ensureOpen();
107+
MemorySegment data = this.data;
108+
long read = this.read;
109+
long length = data.byteSize();
110+
if (read >= length) {
111+
return new byte[0];
112+
}
113+
long remaining = length - read;
114+
len = (int) Math.min(remaining, len);
115+
byte[] buf = new byte[len];
116+
MemorySegment.copy(data, read, MemorySegment.ofArray(buf), 0, len);
117+
this.read += len;
118+
checkMarkLimit();
119+
return buf;
120+
}
121+
122+
@Override
123+
public long skip(long n) throws IOException {
124+
ensureOpen();
125+
MemorySegment data = this.data;
126+
long read = this.read;
127+
long length = data.byteSize();
128+
if (read >= length) {
129+
return 0;
130+
}
131+
n = Math.min(n, length - read);
132+
this.read += n;
133+
checkMarkLimit();
134+
return n;
135+
}
136+
137+
@Override
138+
public int available() throws IOException {
139+
ensureOpen();
140+
MemorySegment data = this.data;
141+
long length = data.byteSize();
142+
long read = this.read;
143+
if (read >= length) {
144+
return 0;
145+
}
146+
long remaining = length - read;
147+
if (remaining > Integer.MAX_VALUE)
148+
return Integer.MAX_VALUE;
149+
return (int) remaining;
150+
}
151+
152+
@Override
153+
public void close() {
154+
closed = true;
155+
}
156+
157+
@Override
158+
public long transferTo(OutputStream out) throws IOException {
159+
ensureOpen();
160+
MemorySegment data = this.data;
161+
long length = data.byteSize();
162+
long read = this.read;
163+
if (read >= length) {
164+
return 0L;
165+
}
166+
long remaining = length - read;
167+
byte[] buffer = new byte[(int) Math.min(16384, remaining)];
168+
MemorySegment bufferSegment = MemorySegment.ofArray(buffer);
169+
while (read < length) {
170+
int copyable = (int) Math.min(buffer.length, length - read);
171+
MemorySegment.copy(data, read, bufferSegment, 0, copyable);
172+
out.write(buffer, 0, copyable);
173+
read += copyable;
174+
}
175+
this.read = length;
176+
checkMarkLimit();
177+
return remaining;
178+
}
179+
180+
private void ensureOpen() throws IOException {
181+
if (closed)
182+
throw new IOException("Stream closed");
183+
}
157184
}

0 commit comments

Comments
 (0)