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