|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package com.sun.media.sound; |
|
|
|
import java.io.ByteArrayInputStream; |
|
import java.io.DataInputStream; |
|
import java.io.File; |
|
import java.io.IOException; |
|
import java.io.InputStream; |
|
import java.io.OutputStream; |
|
import java.io.RandomAccessFile; |
|
import java.util.Collection; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final class ModelByteBuffer { |
|
|
|
private ModelByteBuffer root = this; |
|
private File file; |
|
private long fileoffset; |
|
private byte[] buffer; |
|
private long offset; |
|
private final long len; |
|
|
|
private class RandomFileInputStream extends InputStream { |
|
|
|
private final RandomAccessFile raf; |
|
private long left; |
|
private long mark = 0; |
|
private long markleft = 0; |
|
|
|
RandomFileInputStream() throws IOException { |
|
raf = new RandomAccessFile(root.file, "r"); |
|
raf.seek(root.fileoffset + arrayOffset()); |
|
left = capacity(); |
|
} |
|
|
|
public int available() throws IOException { |
|
if (left > Integer.MAX_VALUE) |
|
return Integer.MAX_VALUE; |
|
return (int)left; |
|
} |
|
|
|
public synchronized void mark(int readlimit) { |
|
try { |
|
mark = raf.getFilePointer(); |
|
markleft = left; |
|
} catch (IOException e) { |
|
//e.printStackTrace(); |
|
} |
|
} |
|
|
|
public boolean markSupported() { |
|
return true; |
|
} |
|
|
|
public synchronized void reset() throws IOException { |
|
raf.seek(mark); |
|
left = markleft; |
|
} |
|
|
|
public long skip(long n) throws IOException { |
|
if( n < 0) |
|
return 0; |
|
if (n > left) |
|
n = left; |
|
long p = raf.getFilePointer(); |
|
raf.seek(p + n); |
|
left -= n; |
|
return n; |
|
} |
|
|
|
public int read(byte b[], int off, int len) throws IOException { |
|
if (len > left) |
|
len = (int)left; |
|
if (left == 0) |
|
return -1; |
|
len = raf.read(b, off, len); |
|
if (len == -1) |
|
return -1; |
|
left -= len; |
|
return len; |
|
} |
|
|
|
public int read(byte[] b) throws IOException { |
|
int len = b.length; |
|
if (len > left) |
|
len = (int)left; |
|
if (left == 0) |
|
return -1; |
|
len = raf.read(b, 0, len); |
|
if (len == -1) |
|
return -1; |
|
left -= len; |
|
return len; |
|
} |
|
|
|
public int read() throws IOException { |
|
if (left == 0) |
|
return -1; |
|
int b = raf.read(); |
|
if (b == -1) |
|
return -1; |
|
left--; |
|
return b; |
|
} |
|
|
|
public void close() throws IOException { |
|
raf.close(); |
|
} |
|
} |
|
|
|
private ModelByteBuffer(ModelByteBuffer parent, |
|
long beginIndex, long endIndex, boolean independent) { |
|
this.root = parent.root; |
|
this.offset = 0; |
|
long parent_len = parent.len; |
|
if (beginIndex < 0) |
|
beginIndex = 0; |
|
if (beginIndex > parent_len) |
|
beginIndex = parent_len; |
|
if (endIndex < 0) |
|
endIndex = 0; |
|
if (endIndex > parent_len) |
|
endIndex = parent_len; |
|
if (beginIndex > endIndex) |
|
beginIndex = endIndex; |
|
offset = beginIndex; |
|
len = endIndex - beginIndex; |
|
if (independent) { |
|
buffer = root.buffer; |
|
if (root.file != null) { |
|
file = root.file; |
|
fileoffset = root.fileoffset + arrayOffset(); |
|
offset = 0; |
|
} else |
|
offset = arrayOffset(); |
|
root = this; |
|
} |
|
} |
|
|
|
public ModelByteBuffer(byte[] buffer) { |
|
this.buffer = buffer; |
|
this.offset = 0; |
|
this.len = buffer.length; |
|
} |
|
|
|
public ModelByteBuffer(byte[] buffer, int offset, int len) { |
|
this.buffer = buffer; |
|
this.offset = offset; |
|
this.len = len; |
|
} |
|
|
|
public ModelByteBuffer(File file) { |
|
this.file = file; |
|
this.fileoffset = 0; |
|
this.len = file.length(); |
|
} |
|
|
|
public ModelByteBuffer(File file, long offset, long len) { |
|
this.file = file; |
|
this.fileoffset = offset; |
|
this.len = len; |
|
} |
|
|
|
public void writeTo(OutputStream out) throws IOException { |
|
if (root.file != null && root.buffer == null) { |
|
try (InputStream is = getInputStream()) { |
|
byte[] buff = new byte[1024]; |
|
int ret; |
|
while ((ret = is.read(buff)) != -1) { |
|
out.write(buff, 0, ret); |
|
} |
|
} |
|
} else |
|
out.write(array(), (int) arrayOffset(), (int) capacity()); |
|
} |
|
|
|
public InputStream getInputStream() { |
|
if (root.file != null && root.buffer == null) { |
|
try { |
|
return new RandomFileInputStream(); |
|
} catch (IOException e) { |
|
|
|
return null; |
|
} |
|
} |
|
return new ByteArrayInputStream(array(), |
|
(int)arrayOffset(), (int)capacity()); |
|
} |
|
|
|
public ModelByteBuffer subbuffer(long beginIndex) { |
|
return subbuffer(beginIndex, capacity()); |
|
} |
|
|
|
public ModelByteBuffer subbuffer(long beginIndex, long endIndex) { |
|
return subbuffer(beginIndex, endIndex, false); |
|
} |
|
|
|
public ModelByteBuffer subbuffer(long beginIndex, long endIndex, |
|
boolean independent) { |
|
return new ModelByteBuffer(this, beginIndex, endIndex, independent); |
|
} |
|
|
|
public byte[] array() { |
|
return root.buffer; |
|
} |
|
|
|
public long arrayOffset() { |
|
if (root != this) |
|
return root.arrayOffset() + offset; |
|
return offset; |
|
} |
|
|
|
public long capacity() { |
|
return len; |
|
} |
|
|
|
public ModelByteBuffer getRoot() { |
|
return root; |
|
} |
|
|
|
public File getFile() { |
|
return file; |
|
} |
|
|
|
public long getFilePointer() { |
|
return fileoffset; |
|
} |
|
|
|
public static void loadAll(Collection<ModelByteBuffer> col) |
|
throws IOException { |
|
File selfile = null; |
|
RandomAccessFile raf = null; |
|
try { |
|
for (ModelByteBuffer mbuff : col) { |
|
mbuff = mbuff.root; |
|
if (mbuff.file == null) |
|
continue; |
|
if (mbuff.buffer != null) |
|
continue; |
|
if (selfile == null || !selfile.equals(mbuff.file)) { |
|
if (raf != null) { |
|
raf.close(); |
|
raf = null; |
|
} |
|
selfile = mbuff.file; |
|
raf = new RandomAccessFile(mbuff.file, "r"); |
|
} |
|
raf.seek(mbuff.fileoffset); |
|
byte[] buffer = new byte[(int) mbuff.capacity()]; |
|
|
|
int read = 0; |
|
int avail = buffer.length; |
|
while (read != avail) { |
|
if (avail - read > 65536) { |
|
raf.readFully(buffer, read, 65536); |
|
read += 65536; |
|
} else { |
|
raf.readFully(buffer, read, avail - read); |
|
read = avail; |
|
} |
|
|
|
} |
|
|
|
mbuff.buffer = buffer; |
|
mbuff.offset = 0; |
|
} |
|
} finally { |
|
if (raf != null) |
|
raf.close(); |
|
} |
|
} |
|
|
|
public void load() throws IOException { |
|
if (root != this) { |
|
root.load(); |
|
return; |
|
} |
|
if (buffer != null) |
|
return; |
|
if (file == null) { |
|
throw new IllegalStateException( |
|
"No file associated with this ByteBuffer!"); |
|
} |
|
|
|
DataInputStream is = new DataInputStream(getInputStream()); |
|
buffer = new byte[(int) capacity()]; |
|
offset = 0; |
|
is.readFully(buffer); |
|
is.close(); |
|
|
|
} |
|
|
|
public void unload() { |
|
if (root != this) { |
|
root.unload(); |
|
return; |
|
} |
|
if (file == null) { |
|
throw new IllegalStateException( |
|
"No file associated with this ByteBuffer!"); |
|
} |
|
root.buffer = null; |
|
} |
|
} |