Package net.sf.cindy.buffer

Source Code of net.sf.cindy.buffer.AbstractBuffer

/*
* Copyright 2004-2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.cindy.buffer;

import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.InvalidMarkException;
import java.nio.ReadOnlyBufferException;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;

import net.sf.cindy.Buffer;
import net.sf.cindy.util.Charset;
import net.sf.cindy.util.Configuration;

/**
* Abstract buffer.
*
* @author <a href="chenrui@gmail.com">Roger Chen</a>
* @version $id$
*/
public abstract class AbstractBuffer implements Buffer {

    protected static final int WRITE_PACKET_SIZE = Configuration
            .getWritePacketSize();

    private boolean readonly;
    private boolean bigEndian = true;
    private boolean permanent;
    private boolean released;

    private int mark = -1;
    private int position = 0;
    private int limit;
    private int capacity;

    private final int offset;

    protected AbstractBuffer(int offset, int capacity) {
        this.offset = offset;
        this.capacity = capacity;

        limit(capacity);
    }

    public boolean isPermanent() {
        return permanent;
    }

    public void setPermanent(boolean b) {
        checkReleased();
        this.permanent = b;
    }

    public boolean isReleased() {
        return released;
    }

    public synchronized void release() {
        if (!(permanent || released)) {
            try {
                _release();
            } finally {
                released = true;
            }
        }
    }

    protected abstract void _release();

    public boolean isReadonly() {
        return readonly;
    }

    protected Buffer setReadonly(boolean readonly) {
        this.readonly = readonly;
        return this;
    }

    public boolean isBigEndian() {
        return bigEndian;
    }

    public Buffer setBigEndian(boolean bigEndian) {
        this.bigEndian = bigEndian;
        return this;
    }

    public Buffer skip(int size) {
        if (size != 0)
            position(position + size);
        return this;
    }

    public int capacity() {
        return capacity;
    }

    protected Buffer capacity(int newCapacity) {
        if (newCapacity < 0)
            throw new IllegalArgumentException();
        capacity = newCapacity;
        return limit(Math.min(limit, capacity));
    }

    public int limit() {
        return limit;
    }

    public Buffer limit(int newLimit) {
        if ((newLimit > capacity) || (newLimit < 0))
            throw new IllegalArgumentException();
        limit = newLimit;
        return position(Math.min(position, limit));
    }

    public int position() {
        return position;
    }

    public Buffer position(int newPosition) {
        if ((newPosition > limit) || (newPosition < 0))
            throw new IllegalArgumentException();
        position = newPosition;
        if (mark > position)
            mark = -1;
        return this;
    }

    public Buffer mark() {
        return mark(position);
    }

    protected Buffer mark(int mark) {
        if (mark < 0)
            this.mark = -1;
        else {
            if (mark > position)
                throw new IndexOutOfBoundsException();
            this.mark = mark;
        }
        return this;
    }

    protected int getMark() {
        return mark;
    }

    protected final int getIndex(int i, int len) {
        checkReleased();
        if ((len < 0) || (i < 0) || (len > limit - i))
            throw new IndexOutOfBoundsException();
        return i + offset;
    }

    protected final int getIndex(int len) {
        checkReleased();
        if (limit - position < len)
            throw new BufferUnderflowException();
        int p = position + offset;
        position += len;
        return p;
    }

    protected final int putIndex(int i, int len) {
        checkReleased();
        checkReadonly();
        if ((len < 0) || (i < 0) || (len > limit - i))
            throw new IndexOutOfBoundsException();
        return i + offset;
    }

    protected final int putIndex(int len) {
        checkReleased();
        checkReadonly();
        if (limit - position < len)
            throw new BufferOverflowException();
        int p = position + offset;
        position += len;
        return p;
    }

    protected final static void checkBounds(int off, int len, int size) {
        // all less than 0
        if ((off | len | (off + len) | (size - (off + len))) < 0)
            throw new IndexOutOfBoundsException();
    }

    protected final void checkReadonly() {
        if (isReadonly())
            throw new ReadOnlyBufferException();
    }

    protected final void checkReleased() {
        if (isReleased())
            throw new ReleasedBufferException();
    }

    public Buffer reset() {
        if (mark < 0)
            throw new InvalidMarkException();
        position = mark;
        return this;
    }

    public Buffer clear() {
        position = 0;
        limit = capacity;
        mark = -1;
        return this;
    }

    public Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }

    public Buffer rewind() {
        position = 0;
        mark = -1;
        return this;
    }

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

    public boolean hasRemaining() {
        return position < limit;
    }

    public int indexOf(byte[] b) {
        if (b.length == 0)
            return position;

        int startIndex = getIndex(0);
        int endIndex = startIndex + remaining() - b.length;
        byte first = b[0];

        Label: for (int i = startIndex; i <= endIndex; i++) {
            // look for the first character
            if (_get(i) == first) {
                for (int j = 1; j < b.length; j++) {
                    if (_get(i + j) != b[j])
                        continue Label;
                }
                return i - startIndex + position;
            }
        }
        return -1;
    }

    public int write(WritableByteChannel channel) throws IOException {
        int writeCount = 0;
        ByteBuffer buffer = asByteBuffer();
        if (buffer.remaining() > WRITE_PACKET_SIZE)
            buffer.limit(buffer.position() + WRITE_PACKET_SIZE);
        try {
            writeCount = channel.write(buffer);
        } finally {
            skip(writeCount);
        }
        return writeCount;
    }

    public int read(ReadableByteChannel channel) throws IOException {
        int readCount = 0;
        try {
            readCount = channel.read(asByteBuffer());
        } finally {
            if (readCount > 0)
                skip(readCount);
        }
        return readCount;
    }

    public Buffer asReadOnlyBuffer() {
        return ((AbstractBuffer) duplicate()).setReadonly(true);
    }

    public boolean equals(Object obj) {
        if (!(obj instanceof Buffer))
            return false;
        Buffer buffer = (Buffer) obj;
        if (this.remaining() != buffer.remaining())
            return false;
        int start = getIndex(0);
        int end = start + remaining();
        for (int i = start, j = buffer.position(); i < end; i++, j++) {
            if (_get(i) != buffer.get(j))
                return false;
        }
        return true;
    }

    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append(getClass().getName());
        sb.append("[pos=").append(position);
        sb.append(" lim=").append(limit);
        sb.append(" cap=").append(capacity);
        sb.append("]");
        return sb.toString();
    }

    public String dump() {
        ByteBuffer content = (ByteBuffer) asByteBuffer().clear();
        String separator = System.getProperty("line.separator");

        int cols = 16;
        int rows = (int) Math.ceil((double) capacity / cols);
        StringBuffer sb = new StringBuffer(rows * cols * 6);
        byte[] row = new byte[cols];

        sb.append(toString()).append(separator);

        int pos = 0;
        for (int i = 0; i < rows; i++) {
            // dump position
            if (pos != 0)
                sb.append(separator);
            String posHex = Integer.toHexString(pos);
            for (int j = 8 - posHex.length(); j > 0; j--) {
                sb.append(0);
            }
            sb.append(posHex).append("h:");

            // dump hex content
            if (content.remaining() < cols)
                row = new byte[content.remaining()];
            content.get(row);

            for (int j = 0; j < cols; j++) {
                if (pos == position || pos == limit)
                    sb.append("'");
                else
                    sb.append(" ");
                pos++;
                if (j < row.length) {
                    String hex = Integer.toHexString(row[j] & 0xff);
                    if (hex.length() < 2)
                        sb.append(0);
                    sb.append(hex.toUpperCase());
                } else
                    sb.append("  ");
            }
            sb.append(" ; ");

            // dump content
            String s = Charset.SYSTEM.decode(row);
            for (int j = 0; j < s.length(); j++) {
                char c = s.charAt(j);
                sb.append(Character.isISOControl(c) ? '.' : c);
            }
        }
        return sb.toString();
    }

    /**
     * Put byte without check.
     *
     * @param index
     *            index
     * @param b
     *            byte
     */
    protected abstract void _put(int index, byte b);

    /**
     * Get byte without check.
     *
     * @param index
     *            index
     * @return byte
     */
    protected abstract byte _get(int index);

    public byte get() {
        return _get(getIndex(1));
    }

    public byte get(int index) {
        return _get(getIndex(index, 1));
    }

    public Buffer get(byte[] dst) {
        return get(dst, 0, dst.length);
    }

    public Buffer get(int index, byte[] dst) {
        return get(index, dst, 0, dst.length);
    }

    public Buffer get(byte[] dst, int offset, int length) {
        return get(ByteBuffer.wrap(dst, offset, length));
    }

    public Buffer get(int index, byte[] dst, int offset, int length) {
        return get(index, ByteBuffer.wrap(dst, offset, length));
    }

    public Buffer get(ByteBuffer dst) {
        return get(dst, dst.remaining());
    }

    public Buffer get(int index, ByteBuffer dst) {
        return get(index, dst, dst.remaining());
    }

    public Buffer get(ByteBuffer dst, int length) {
        checkBounds(0, length, dst.remaining());
        getIndex(length);
        ByteBuffer buffer = asByteBuffer();
        buffer.limit(buffer.position());
        buffer.position(buffer.position() - length);
        dst.put(buffer);
        return this;
    }

    public Buffer get(int index, ByteBuffer dst, int length) {
        checkBounds(0, length, dst.remaining());
        getIndex(index, length);
        ByteBuffer buffer = asByteBuffer();
        buffer.position(index);
        buffer.limit(index + length);
        dst.put(buffer);
        return this;
    }

    public Buffer get(Buffer dst) {
        return get(dst, dst.remaining());
    }

    public Buffer get(int index, Buffer dst) {
        return get(index, dst, dst.remaining());
    }

    public Buffer get(Buffer dst, int length) {
        checkBounds(0, length, dst.remaining());
        getIndex(length);
        ByteBuffer buffer = asByteBuffer();
        buffer.limit(buffer.position());
        buffer.position(buffer.position() - length);
        dst.put(buffer);
        return this;
    }

    public Buffer get(int index, Buffer dst, int length) {
        checkBounds(0, length, dst.remaining());
        getIndex(index, length);
        ByteBuffer buffer = asByteBuffer();
        buffer.position(index);
        buffer.limit(index + length);
        dst.put(buffer);
        return this;
    }

    public Buffer put(byte b) {
        _put(putIndex(1), b);
        return this;
    }

    public Buffer put(int index, byte b) {
        _put(putIndex(index, 1), b);
        return this;
    }

    public Buffer put(byte[] src) {
        return put(src, 0, src.length);
    }

    public Buffer put(int index, byte[] src) {
        return put(index, src, 0, src.length);
    }

    public Buffer put(byte[] src, int offset, int length) {
        return put(ByteBuffer.wrap(src, offset, length));
    }

    public Buffer put(int index, byte[] src, int offset, int length) {
        return put(index, ByteBuffer.wrap(src, offset, length));
    }

    public Buffer put(ByteBuffer src) {
        return put(src, src.remaining());
    }

    public Buffer put(int index, ByteBuffer src) {
        return put(index, src, src.remaining());
    }

    public Buffer put(ByteBuffer src, int length) {
        checkBounds(0, length, src.remaining());
        int pos = putIndex(length);
        for (int i = 0; i < length; i++) {
            _put(pos + i, src.get());
        }
        return this;
    }

    public Buffer put(int index, ByteBuffer src, int length) {
        checkBounds(0, length, src.remaining());
        int pos = putIndex(index, length);
        for (int i = 0; i < length; i++) {
            _put(pos + i, src.get());
        }
        return this;
    }

    public Buffer put(Buffer src) {
        return put(src, src.remaining());
    }

    public Buffer put(int index, Buffer src) {
        return put(index, src, src.remaining());
    }

    public Buffer put(Buffer src, int length) {
        checkBounds(0, length, src.remaining());
        int pos = putIndex(length);
        for (int i = 0; i < length; i++) {
            _put(pos + i, src.get());
        }
        return this;
    }

    public Buffer put(int index, Buffer src, int length) {
        checkBounds(0, length, src.remaining());
        int pos = putIndex(index, length);
        for (int i = 0; i < length; i++) {
            _put(pos + i, src.get());
        }
        return this;
    }

    public char getChar() {
        return (char) getShort();
    }

    public char getChar(int index) {
        return (char) getShort(index);
    }

    public Buffer putChar(char c) {
        return putShort((short) c);
    }

    public Buffer putChar(int index, char c) {
        return putShort(index, (short) c);
    }

    public short getShort() {
        return Bits.decodeShort(this, getIndex(2));
    }

    public short getShort(int index) {
        return Bits.decodeShort(this, getIndex(index, 2));
    }

    public Buffer putShort(short s) {
        return Bits.encodeShort(this, putIndex(2), s);
    }

    public Buffer putShort(int index, short s) {
        return Bits.encodeShort(this, putIndex(index, 2), s);
    }

    public int getInt() {
        return Bits.decodeInt(this, getIndex(4));
    }

    public int getInt(int index) {
        return Bits.decodeInt(this, getIndex(index, 4));
    }

    public Buffer putInt(int i) {
        return Bits.encodeInt(this, putIndex(4), i);
    }

    public Buffer putInt(int index, int i) {
        return Bits.encodeInt(this, putIndex(index, 4), i);
    }

    public long getLong() {
        return Bits.decodeLong(this, getIndex(8));
    }

    public long getLong(int index) {
        return Bits.decodeLong(this, getIndex(index, 8));
    }

    public Buffer putLong(long l) {
        return Bits.encodeLong(this, putIndex(8), l);
    }

    public Buffer putLong(int index, long l) {
        return Bits.encodeLong(this, putIndex(index, 8), l);
    }

    public float getFloat() {
        return Float.intBitsToFloat(getInt());
    }

    public float getFloat(int index) {
        return Float.intBitsToFloat(getInt(index));
    }

    public Buffer putFloat(float f) {
        return putInt(Float.floatToRawIntBits(f));
    }

    public Buffer putFloat(int index, float f) {
        return putInt(index, Float.floatToRawIntBits(f));
    }

    public double getDouble() {
        return Double.longBitsToDouble(getLong());
    }

    public double getDouble(int index) {
        return Double.longBitsToDouble(getLong(index));
    }

    public Buffer putDouble(double d) {
        return putLong(Double.doubleToRawLongBits(d));
    }

    public Buffer putDouble(int index, double d) {
        return putLong(index, Double.doubleToRawLongBits(d));
    }

    public short getUnsignedByte() {
        return (short) (get() & 0xff);
    }

    public short getUnsignedByte(int index) {
        return (short) (get(index) & 0xff);
    }

    public Buffer putUnsignedByte(short s) {
        if (s < 0 || s > 0xff)
            throw new IllegalArgumentException();
        return put((byte) s);
    }

    public Buffer putUnsignedByte(int index, short s) {
        if (s < 0 || s > 0xff)
            throw new IllegalArgumentException();
        return put(index, (byte) s);
    }

    public int getUnsignedShort() {
        return getShort() & 0xffff;
    }

    public int getUnsignedShort(int index) {
        return getShort(index) & 0xffff;
    }

    public Buffer putUnsignedShort(int i) {
        if (i < 0 || i > 0xffff)
            throw new IllegalArgumentException();
        return putShort((short) i);
    }

    public Buffer putUnsignedShort(int index, int i) {
        if (i < 0 || i > 0xffff)
            throw new IllegalArgumentException();
        return putShort(index, (short) i);
    }

    public long getUnsignedInt() {
        return getInt() & 0xffffffffL;
    }

    public long getUnsignedInt(int index) {
        return getInt(index) & 0xffffffffL;
    }

    public Buffer putUnsignedInt(long l) {
        if (l < 0 || l > 0xffffffff)
            throw new IllegalArgumentException();
        return putInt((int) l);
    }

    public Buffer putUnsignedInt(int index, long l) {
        if (l < 0 || l > 0xffffffff)
            throw new IllegalArgumentException();
        return putInt(index, (int) l);
    }

    public String getString(Charset charset, int bufferLen) {
        getIndex(bufferLen);
        ByteBuffer buffer = asByteBuffer();
        buffer.limit(buffer.position());
        buffer.position(buffer.limit() - bufferLen);
        return charset.decode(buffer);
    }

    public String getString(int index, Charset charset, int bufferLen) {
        getIndex(index, bufferLen);
        ByteBuffer buffer = asByteBuffer();
        buffer.position(index);
        buffer.limit(index + bufferLen);
        return charset.decode(buffer);
    }

    public Buffer putString(String s, Charset charset) {
        return put(charset.encode(s));
    }

    public Buffer putString(int index, String s, Charset charset) {
        return put(index, charset.encode(s));
    }

}
TOP

Related Classes of net.sf.cindy.buffer.AbstractBuffer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.