Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/debugtools/DDR_VM/src/com/ibm/j9ddr/libraries/SlidingImageInputStream.java
6005 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2014 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
package com.ibm.j9ddr.libraries;
24
25
//sliding image input stream to present a portion of a file as a complete file in itself
26
27
import java.io.File;
28
import java.io.IOException;
29
30
import javax.imageio.stream.FileImageInputStream;
31
import javax.imageio.stream.ImageInputStream;
32
import javax.imageio.stream.ImageInputStreamImpl;
33
34
public class SlidingImageInputStream extends ImageInputStreamImpl {
35
private final ImageInputStream stream;
36
private long length;
37
private long start;
38
private final static int BUFFER_SIZE = 4096;
39
private final byte[] buffer = new byte[BUFFER_SIZE];
40
private int bytesAvailable = 0;
41
private boolean EOF = false;
42
private int bufferPos = 0;
43
private long bytesRead = 0;
44
private boolean hasBufferRefreshed = false;
45
private long markBytesRead = 0;
46
private long markFilePos = 0;
47
private long bufferStartPos = 0;
48
49
public SlidingImageInputStream(File raf, long start, long length) throws IOException {
50
stream = new FileImageInputStream(raf);
51
init(start, length);
52
}
53
54
public SlidingImageInputStream(ImageInputStream iis, long start, long length) throws IOException {
55
stream = iis;
56
init(start, length);
57
}
58
59
private void init(long start, long length) throws IOException {
60
stream.seek(start);
61
checkBuffer();
62
this.length = length;
63
this.start = start;
64
markFilePos = stream.getStreamPosition();
65
}
66
67
@Override
68
public int read() throws IOException {
69
if(EOF) return -1; //end of file
70
if(bytesRead == length) {
71
EOF = true;
72
return -1;
73
}
74
checkBuffer();
75
bytesRead++;
76
return 0xFF & buffer[bufferPos++]; //return and increment buffer pointer
77
}
78
79
@Override
80
public int read(byte[] b, int off, int len) throws IOException {
81
if(EOF) return -1; //end of file already set
82
if(bytesRead == length) { //sliding window over the file is exhausted so treat as EOF
83
EOF = true;
84
return -1;
85
}
86
if((len + off) > b.length) { //check that destination array is big enough
87
String msg = String.format("The array is too small to copy %d bytes starting at offset %d", len, off);
88
throw new IndexOutOfBoundsException(msg);
89
}
90
if(len < (bytesAvailable - bufferPos)) { //this request can be satisfied entirely from the buffer
91
int tocopy = (int) Math.min(len, length - bytesRead); //see which is smaller, amount requested or amount left in window
92
System.arraycopy(buffer, bufferPos, b, off, tocopy);
93
bufferPos += tocopy;
94
bytesRead += tocopy;
95
return tocopy;
96
}
97
//this request needs to be satisfied from one or more buffer fills
98
int copiedBytes = 0;
99
while(!EOF && (copiedBytes < len) && (bytesRead < length)){
100
int tocopy = (int) Math.min(bytesAvailable - bufferPos, length - bytesRead); //see which is smaller, amount left in buffer or amount left in window
101
tocopy = Math.min(tocopy, len - copiedBytes); //then see which is smaller the proposed copy amount or the amount left to fulfill the request
102
System.arraycopy(buffer, bufferPos, b, copiedBytes, tocopy);
103
bufferPos += tocopy;
104
bytesRead += tocopy;
105
copiedBytes += tocopy;
106
checkBuffer();
107
}
108
return copiedBytes;
109
}
110
111
private void checkBuffer() throws IOException {
112
if(bytesAvailable == bufferPos) { //see if need to refill the buffer
113
bufferStartPos = bytesRead; //the start of this buffer is the number of bytes read
114
hasBufferRefreshed = true; //indicate that the buffer has been refreshed
115
bytesAvailable = stream.read(buffer);
116
if(bytesAvailable == -1) {
117
EOF = true;
118
}
119
bufferPos = 0;
120
}
121
}
122
123
@Override
124
public long length() {
125
return length;
126
}
127
128
@Override
129
public void mark() {
130
hasBufferRefreshed = false;
131
markBytesRead = bytesRead;
132
super.mark();
133
}
134
135
@Override
136
public void reset() throws IOException {
137
super.reset();
138
long resetCount = bytesRead - markBytesRead; //how many bytes to rewind by
139
bytesRead -= resetCount; //update the bytes read count with the rewind
140
if(hasBufferRefreshed) { //cannot reset back within the buffer so we will need to throw away the current contents
141
bufferPos = 0;
142
bytesAvailable = 0;
143
stream.seek(markFilePos - resetCount); //reset underlying stream position
144
} else {
145
bufferPos -= resetCount; //reset within the buffer
146
}
147
}
148
149
@Override
150
public void seek(long pos) throws IOException {
151
if((pos < bufferStartPos) || (pos >= (bufferStartPos + BUFFER_SIZE))) { //move outside of the current buffer
152
stream.seek(start + pos); //move the underlying stream
153
bufferPos = 0; //throw away the current buffer contents
154
bytesAvailable = 0;
155
bytesRead = pos;
156
checkBuffer(); //flag the invalidated buffer
157
super.seek(pos);
158
} else { //seek within current buffer
159
int diff = (int)(pos - bufferStartPos); //how far in ?
160
bytesRead = bufferStartPos + diff;
161
bufferPos = diff;
162
}
163
}
164
165
@Override
166
public long getStreamPosition() throws IOException {
167
return bytesRead;
168
}
169
170
171
172
}
173
174