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+ }
157+ }
0 commit comments