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