| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
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;  | 
 | 
    }  | 
 | 
}  |