org.jcodec.common.io.Buffer.java Source code

Java tutorial

Introduction

Here is the source code for org.jcodec.common.io.Buffer.java

Source

package org.jcodec.common.io;

import static java.lang.Math.min;

import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.util.Arrays;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

/**
 * This class is part of JCodec ( www.jcodec.org ) This software is distributed
 * under FreeBSD License
 * 
 * Multipurpose byte buffer
 * 
 * @author The JCodec project
 * 
 */
public class Buffer {
    public byte[] buffer;
    public int pos;
    public int limit;
    private DataInput dinp;
    private DataOutput dout;

    public Buffer(byte[] buffer) {
        this.buffer = buffer;
        this.limit = buffer.length;
    }

    public Buffer(byte[] buffer, int pos, int limit) {
        this.buffer = buffer;
        this.pos = pos;
        this.limit = limit;
    }

    public Buffer(int size) {
        this(new byte[size]);
    }

    public final int next() {
        return pos < limit ? buffer[pos++] & 0xff : -1;
    }

    public final int nextIgnore() {
        return pos < limit ? buffer[pos++] & 0xff : 0;
    }

    public final int search(byte... param) {
        for (int i = pos; i < limit - param.length + 1; i++) {
            if (buffer[i] == param[0]) {
                int j = 1;
                for (; j < param.length; j++)
                    if (buffer[i + j] != param[j])
                        break;
                if (j == param.length)
                    return i - pos;
            }
        }
        return -1;
    }

    public Buffer read(int nl) {
        Buffer ret = new Buffer(buffer, pos, min(limit, pos + nl));
        pos += nl;
        return ret;
    }

    public final int get(int i) {
        return pos + i < limit ? buffer[pos + i] & 0xff : -1;
    }

    public final int nextIntLE() {
        if (pos < limit - 3) {
            return ((buffer[pos++] & 0xff) << 24) | ((buffer[pos++] & 0xff) << 16) | ((buffer[pos++] & 0xff) << 8)
                    | (buffer[pos++] & 0xff);
        } else {
            return (nextIgnore() << 24) | (nextIgnore() << 16) | (nextIgnore() << 8) | nextIgnore();
        }
    }

    public static Buffer fetchFrom(InputStream is, int size) throws IOException {
        byte[] buffer = new byte[size];
        return new Buffer(buffer, 0, read(buffer, 0, size, is));
    }

    public static Buffer fetchFrom(RandomAccessFile file, int size) throws IOException {
        byte[] buffer = new byte[size];
        return new Buffer(buffer, 0, read(buffer, 0, size, file));
    }

    public static Buffer fetchFrom(File file) throws IOException {
        long len = file.length();
        InputStream is = null;
        try {
            is = new FileInputStream(file);
            return fetchFrom(is, (int) len);
        } finally {
            IOUtils.closeQuietly(is);
        }
    }

    private static int read(byte[] buffer, int pos, int size, InputStream is) throws IOException {
        int read, total = 0;

        while (size > 0 && (read = is.read(buffer, pos, size)) != -1) {
            pos += read;
            size -= read;
            total += read;
        }

        return total;
    }

    private static int read(byte[] buffer, int pos, int size, RandomAccessFile is) throws IOException {
        int read, total = 0;

        while (size > 0 && (read = is.read(buffer, pos, size)) != -1) {
            pos += read;
            size -= read;
            total += read;
        }

        return total;
    }

    public final void skip(int i) {
        pos = min(pos + i, limit);
    }

    public int remaining() {
        return limit - pos;
    }

    public static Buffer combine(Iterable<Buffer> picture) {
        int size = 0;
        for (Buffer byteBuffer : picture) {
            size += byteBuffer.remaining();
        }
        Buffer result = new Buffer(size);
        for (Buffer byteBuffer : picture) {
            result.write(byteBuffer);
        }
        return result.flip();
    }

    public void write(Buffer other) {
        if (other.remaining() > remaining())
            throw new IndexOutOfBoundsException("No space left in buffer");
        System.arraycopy(other.buffer, other.pos, buffer, pos, other.remaining());
        pos += other.remaining();
    }

    public void extendFrom(InputStream is, int bufSize) throws IOException {
        int pos = remaining();
        extend(pos + bufSize);
        limit = pos + read(buffer, pos, bufSize, is);
    }

    private void extend(int bufSize) {
        if (bufSize <= remaining())
            return;
        byte[] newBuf = new byte[bufSize];
        System.arraycopy(buffer, pos, newBuf, 0, remaining());
        buffer = newBuf;
        pos = 0;
        limit = bufSize;
    }

    public Buffer from(int i) {
        if (remaining() < i)
            throw new IndexOutOfBoundsException("buffer overrun");
        return new Buffer(buffer, pos + i, limit);
    }

    public Buffer fork() {
        return from(0);
    }

    public void extendWith(Buffer other) {
        if (other == null)
            return;
        int pos = remaining();
        extend(pos + other.remaining());
        System.arraycopy(other.buffer, other.pos, buffer, pos, other.remaining());
    }

    public InputStream is() {
        return new InputStream() {
            public int read() throws IOException {
                return next();
            }
        };
    }

    public OutputStream os() {
        return new OutputStream() {

            public void write(byte[] b, int off, int len) throws IOException {
                System.arraycopy(b, off, buffer, pos, len);
                pos += len;
            }

            public void write(int b) throws IOException {
                buffer[pos++] = (byte) b;
            }
        };
    }

    public int searchFrom(int from, byte... params) {
        int found = from(from).search(params);
        return found == -1 ? -1 : from + found;
    }

    public int searchFrom(int from, int... params) {
        return searchFrom(from, toIntArray(params));
    }

    public void print(PrintStream out) {
        for (int i = pos; i < limit; i++) {
            out.print(buffer[i] & 0xff);
            out.print(i < limit - 1 ? ", " : "");
        }
    }

    public DataInput dinp() {
        if (dinp == null)
            dinp = new DataInputStream(is());
        return dinp;
    }

    public DataOutput dout() {
        if (dout == null)
            dout = new DataOutputStream(os());
        return dout;
    }

    public byte[] toArray() {
        byte[] result = new byte[limit - pos];
        System.arraycopy(buffer, pos, result, 0, result.length);
        return result;
    }

    public void toArray(byte[] result, int off, int len) {
        System.arraycopy(buffer, pos, result, off, len);
    }

    public void writeTo(RandomAccessFile file) throws IOException {
        file.write(buffer, pos, limit - pos);
    }

    public void writeTo(OutputStream file) throws IOException {
        file.write(buffer, pos, limit - pos);
    }

    public void writeTo(File file) throws IOException {
        FileUtils.writeByteArrayToFile(file, toArray());
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Buffer))
            return false;
        return Arrays.equals(toArray(), ((Buffer) obj).toArray());
    }

    public static Buffer combine(Buffer... buffers) {
        return combine(Arrays.asList(buffers));
    }

    public boolean startsWith(Buffer other) {
        int i, j;
        for (i = other.pos, j = pos; i < other.limit && j < limit; i++, j++)
            if (other.buffer[i] != buffer[i])
                return false;
        return i == other.limit;
    }

    public void write(byte b) {
        buffer[pos++] = b;
    }

    public void write(int i) {
        buffer[pos++] = (byte) i;
    }

    public int search(int... ints) {
        return search(toIntArray(ints));
    }

    private byte[] toIntArray(int... ints) {
        byte[] bytes = new byte[ints.length];
        for (int i = 0; i < ints.length; i++)
            bytes[i] = (byte) ints[i];
        return bytes;
    }

    public Buffer flip() {
        return new Buffer(buffer, 0, pos);
    }
}