829N/A/*
6321N/A * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
829N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
829N/A *
829N/A * This code is free software; you can redistribute it and/or modify it
829N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
829N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
829N/A *
829N/A * This code is distributed in the hope that it will be useful, but WITHOUT
829N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
829N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
829N/A * version 2 for more details (a copy is included in the LICENSE file that
829N/A * accompanied this code).
829N/A *
829N/A * You should have received a copy of the GNU General Public License version
829N/A * 2 along with this work; if not, write to the Free Software Foundation,
829N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
829N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
829N/A */
829N/Apackage com.sun.media.sound;
829N/A
829N/Aimport java.io.ByteArrayInputStream;
829N/Aimport java.io.DataInputStream;
829N/Aimport java.io.File;
829N/Aimport java.io.IOException;
829N/Aimport java.io.InputStream;
829N/Aimport java.io.OutputStream;
829N/Aimport java.io.RandomAccessFile;
829N/Aimport java.util.Collection;
829N/A
829N/A/**
829N/A * This class is a pointer to a binary array either in memory or on disk.
829N/A *
829N/A * @author Karl Helgason
829N/A */
6321N/Apublic final class ModelByteBuffer {
829N/A
829N/A private ModelByteBuffer root = this;
829N/A private File file;
829N/A private long fileoffset;
829N/A private byte[] buffer;
829N/A private long offset;
829N/A private final long len;
829N/A
829N/A private class RandomFileInputStream extends InputStream {
829N/A
6321N/A private final RandomAccessFile raf;
829N/A private long left;
829N/A private long mark = 0;
829N/A private long markleft = 0;
829N/A
6321N/A RandomFileInputStream() throws IOException {
829N/A raf = new RandomAccessFile(root.file, "r");
829N/A raf.seek(root.fileoffset + arrayOffset());
829N/A left = capacity();
829N/A }
829N/A
829N/A public int available() throws IOException {
829N/A if (left > Integer.MAX_VALUE)
829N/A return Integer.MAX_VALUE;
829N/A return (int)left;
829N/A }
829N/A
829N/A public synchronized void mark(int readlimit) {
829N/A try {
829N/A mark = raf.getFilePointer();
829N/A markleft = left;
829N/A } catch (IOException e) {
829N/A //e.printStackTrace();
829N/A }
829N/A }
829N/A
829N/A public boolean markSupported() {
829N/A return true;
829N/A }
829N/A
829N/A public synchronized void reset() throws IOException {
829N/A raf.seek(mark);
829N/A left = markleft;
829N/A }
829N/A
829N/A public long skip(long n) throws IOException {
829N/A if( n < 0)
829N/A return 0;
829N/A if (n > left)
829N/A n = left;
829N/A long p = raf.getFilePointer();
829N/A raf.seek(p + n);
829N/A left -= n;
829N/A return n;
829N/A }
829N/A
829N/A public int read(byte b[], int off, int len) throws IOException {
829N/A if (len > left)
829N/A len = (int)left;
829N/A if (left == 0)
829N/A return -1;
829N/A len = raf.read(b, off, len);
829N/A if (len == -1)
829N/A return -1;
829N/A left -= len;
829N/A return len;
829N/A }
829N/A
829N/A public int read(byte[] b) throws IOException {
829N/A int len = b.length;
829N/A if (len > left)
829N/A len = (int)left;
829N/A if (left == 0)
829N/A return -1;
829N/A len = raf.read(b, 0, len);
829N/A if (len == -1)
829N/A return -1;
829N/A left -= len;
829N/A return len;
829N/A }
829N/A
829N/A public int read() throws IOException {
829N/A if (left == 0)
829N/A return -1;
829N/A int b = raf.read();
829N/A if (b == -1)
829N/A return -1;
829N/A left--;
829N/A return b;
829N/A }
829N/A
829N/A public void close() throws IOException {
829N/A raf.close();
829N/A }
829N/A }
829N/A
829N/A private ModelByteBuffer(ModelByteBuffer parent,
829N/A long beginIndex, long endIndex, boolean independent) {
829N/A this.root = parent.root;
829N/A this.offset = 0;
829N/A long parent_len = parent.len;
829N/A if (beginIndex < 0)
829N/A beginIndex = 0;
829N/A if (beginIndex > parent_len)
829N/A beginIndex = parent_len;
829N/A if (endIndex < 0)
829N/A endIndex = 0;
829N/A if (endIndex > parent_len)
829N/A endIndex = parent_len;
829N/A if (beginIndex > endIndex)
829N/A beginIndex = endIndex;
829N/A offset = beginIndex;
829N/A len = endIndex - beginIndex;
829N/A if (independent) {
829N/A buffer = root.buffer;
829N/A if (root.file != null) {
829N/A file = root.file;
829N/A fileoffset = root.fileoffset + arrayOffset();
829N/A offset = 0;
829N/A } else
829N/A offset = arrayOffset();
829N/A root = this;
829N/A }
829N/A }
829N/A
829N/A public ModelByteBuffer(byte[] buffer) {
829N/A this.buffer = buffer;
829N/A this.offset = 0;
829N/A this.len = buffer.length;
829N/A }
829N/A
829N/A public ModelByteBuffer(byte[] buffer, int offset, int len) {
829N/A this.buffer = buffer;
829N/A this.offset = offset;
829N/A this.len = len;
829N/A }
829N/A
829N/A public ModelByteBuffer(File file) {
829N/A this.file = file;
829N/A this.fileoffset = 0;
829N/A this.len = file.length();
829N/A }
829N/A
829N/A public ModelByteBuffer(File file, long offset, long len) {
829N/A this.file = file;
829N/A this.fileoffset = offset;
829N/A this.len = len;
829N/A }
829N/A
829N/A public void writeTo(OutputStream out) throws IOException {
829N/A if (root.file != null && root.buffer == null) {
829N/A InputStream is = getInputStream();
829N/A byte[] buff = new byte[1024];
829N/A int ret;
829N/A while ((ret = is.read(buff)) != -1)
829N/A out.write(buff, 0, ret);
829N/A } else
829N/A out.write(array(), (int) arrayOffset(), (int) capacity());
829N/A }
829N/A
829N/A public InputStream getInputStream() {
829N/A if (root.file != null && root.buffer == null) {
829N/A try {
829N/A return new RandomFileInputStream();
829N/A } catch (IOException e) {
829N/A //e.printStackTrace();
829N/A return null;
829N/A }
829N/A }
829N/A return new ByteArrayInputStream(array(),
829N/A (int)arrayOffset(), (int)capacity());
829N/A }
829N/A
829N/A public ModelByteBuffer subbuffer(long beginIndex) {
829N/A return subbuffer(beginIndex, capacity());
829N/A }
829N/A
829N/A public ModelByteBuffer subbuffer(long beginIndex, long endIndex) {
829N/A return subbuffer(beginIndex, endIndex, false);
829N/A }
829N/A
829N/A public ModelByteBuffer subbuffer(long beginIndex, long endIndex,
829N/A boolean independent) {
829N/A return new ModelByteBuffer(this, beginIndex, endIndex, independent);
829N/A }
829N/A
829N/A public byte[] array() {
829N/A return root.buffer;
829N/A }
829N/A
829N/A public long arrayOffset() {
829N/A if (root != this)
829N/A return root.arrayOffset() + offset;
829N/A return offset;
829N/A }
829N/A
829N/A public long capacity() {
829N/A return len;
829N/A }
829N/A
829N/A public ModelByteBuffer getRoot() {
829N/A return root;
829N/A }
829N/A
829N/A public File getFile() {
829N/A return file;
829N/A }
829N/A
829N/A public long getFilePointer() {
829N/A return fileoffset;
829N/A }
829N/A
829N/A public static void loadAll(Collection<ModelByteBuffer> col)
829N/A throws IOException {
829N/A File selfile = null;
829N/A RandomAccessFile raf = null;
829N/A try {
829N/A for (ModelByteBuffer mbuff : col) {
829N/A mbuff = mbuff.root;
829N/A if (mbuff.file == null)
829N/A continue;
829N/A if (mbuff.buffer != null)
829N/A continue;
829N/A if (selfile == null || !selfile.equals(mbuff.file)) {
829N/A if (raf != null) {
829N/A raf.close();
829N/A raf = null;
829N/A }
829N/A selfile = mbuff.file;
829N/A raf = new RandomAccessFile(mbuff.file, "r");
829N/A }
829N/A raf.seek(mbuff.fileoffset);
829N/A byte[] buffer = new byte[(int) mbuff.capacity()];
829N/A
829N/A int read = 0;
829N/A int avail = buffer.length;
829N/A while (read != avail) {
829N/A if (avail - read > 65536) {
829N/A raf.readFully(buffer, read, 65536);
829N/A read += 65536;
829N/A } else {
829N/A raf.readFully(buffer, read, avail - read);
829N/A read = avail;
829N/A }
829N/A
829N/A }
829N/A
829N/A mbuff.buffer = buffer;
829N/A mbuff.offset = 0;
829N/A }
829N/A } finally {
829N/A if (raf != null)
829N/A raf.close();
829N/A }
829N/A }
829N/A
829N/A public void load() throws IOException {
829N/A if (root != this) {
829N/A root.load();
829N/A return;
829N/A }
829N/A if (buffer != null)
829N/A return;
829N/A if (file == null) {
829N/A throw new IllegalStateException(
829N/A "No file associated with this ByteBuffer!");
829N/A }
829N/A
829N/A DataInputStream is = new DataInputStream(getInputStream());
829N/A buffer = new byte[(int) capacity()];
829N/A offset = 0;
829N/A is.readFully(buffer);
829N/A is.close();
829N/A
829N/A }
829N/A
829N/A public void unload() {
829N/A if (root != this) {
829N/A root.unload();
829N/A return;
829N/A }
829N/A if (file == null) {
829N/A throw new IllegalStateException(
829N/A "No file associated with this ByteBuffer!");
829N/A }
829N/A root.buffer = null;
829N/A }
829N/A}