⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractbuffer.java

📁 nio的framework,不需要关注NIO编程的细节,只需要根据几个简单的API就可以使用NIO了.
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * 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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -