Package org.apache.mina.codec

Source Code of org.apache.mina.codec.IoBuffer$Pointer

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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 org.apache.mina.codec;

import java.io.IOException;
import java.io.InputStream;
import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.InvalidMarkException;
import java.nio.ReadOnlyBufferException;

/**
* A proxy class used to manage ByteBuffers as if they were just a big
* ByteBuffer. We can add as many buffers as needed when accumulating data. From
* the user point of view, the methods are the very same as ByteBuffer provides.
*
* <p>
* IoBuffer instances are *not* thread safe.
*
* <p>
* The IoBuffer uses a singly linked list to handle the multiple Buffers. Thus
* sequential access is very efficient and random access is not. It fits well
* with the common usage patterns of IoBuffer.
*
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public final class IoBuffer {
    private static final int BYTE_MASK = 0xff;

    private static final long BYTE_MASK_L = 0xffL;

    /**
     * @see ByteBuffer#allocate(int)
     */
    public static IoBuffer allocate(int capacity) {
        return wrap(ByteBuffer.allocate(capacity));
    }

    /**
     * @see ByteBuffer#allocateDirect(int)
     */
    public static IoBuffer allocateDirect(int capacity) {
        return wrap(ByteBuffer.allocateDirect(capacity));
    }

    /**
     * Build a new instance of {@link IoBuffer}
     *
     * @return a new instance of {@link IoBuffer}
     */
    public static IoBuffer newInstance() {
        return new IoBuffer();
    }

    /**
     * @see ByteBuffer#wrap(byte[])
     */
    public static IoBuffer wrap(byte[]... arrays) {
        IoBuffer ioBuffer = new IoBuffer();
        for (byte[] array : arrays) {
            ioBuffer.add(ByteBuffer.wrap(array));
        }
        return ioBuffer;
    }

    /**
     * @see ByteBuffer#wrap(byte[], int, int)
     */
    public static IoBuffer wrap(byte[] array, int offset, int length) {
        return wrap(ByteBuffer.wrap(array, offset, length));
    }

    /**
     * Wraps ByteBuffers into a new IoBuffer
     *
     * @param buffers
     *            the ByteBuffers to wrap
     * @return the new {@link IoBuffer}
     */
    public static IoBuffer wrap(ByteBuffer... buffers) {
        IoBuffer ioBuffer = new IoBuffer();
        for (ByteBuffer b : buffers) {
            ioBuffer.add(b);
        }
        return ioBuffer;
    }

    private ByteOrder bo = ByteOrder.BIG_ENDIAN;

    private int capacity = 0;

    private boolean direct = true;

    private BufferNode head, tail;

    /** The maximal position in the IoBuffer */
    private Pointer limit = new Pointer();

    /** The current position in the buffer */
    private Pointer mark = new Pointer();

    /** The marked position, for the next reset() */
    private Pointer position = new Pointer();

    /** If the buffer is readonly */
    private boolean readonly = false;

    private IoBuffer() {
        limit(0);
        position(0);
        mark = null;
    }

    /**
     * Add one or more ByteBuffer to the current IoBuffer
     *
     * @param buffers
     *            the ByteBuffers to add
     * @return the current {@link IoBuffer}
     */
    public IoBuffer add(ByteBuffer... buffers) {
        for (ByteBuffer buffer : buffers) {
            enqueue(buffer.slice());
        }
        return this;
    }

    /**
     * @see ByteBuffer#array()
     */
    public byte[] array() {
        if (capacity == 0) {
            return new byte[0];
        }
        if (head.hasNext()) {
            throw new UnsupportedOperationException();
        }
        return head.getBuffer().array();
    }

    /**
     * @see ByteBuffer#arrayOffset()
     */
    public int arrayOffset() {
        if (capacity == 0) {
            return 0;
        }
        if (head.hasNext()) {
            throw new UnsupportedOperationException();
        }
        return head.getBuffer().arrayOffset();
    }

    /**
     * Provides an input stream which is actually reading the {@link IoBuffer}
     * instance.
     * <p>
     * Further reads on the returned InputStream move the reading head of the
     * {@link IoBuffer} instance used for it's creation
     *
     * @return an input stream
     */
    public InputStream asInputStream() {
        return new InputStream() {

            @Override
            public int read() throws IOException {
                return hasRemaining() ? get() & BYTE_MASK : -1;
            }

            @Override
            public int read(byte[] b, int off, int len) throws IOException {
                if (!hasRemaining()) {
                    return -1;
                }

                int toRead = Math.min(remaining(), len);
                get(b, off, toRead);
                return toRead;
            }
        };
    }

    /**
     * @see ByteBuffer#asReadOnlyBuffer()
     */
    public IoBuffer asReadOnlyBuffer() {
        IoBuffer buffer = duplicate();
        buffer.readonly = true;
        return buffer;
    }

    /**
     * @see ByteBuffer#capacity()
     */
    public int capacity() {
        return capacity;
    }

    /**
     * @see ByteBuffer#clear()
     */
    public IoBuffer clear() {
        position = getPointerByPosition(0);
        limit = getPointerByPosition(capacity);
        mark = null;
        return this;
    }

    /**
     * @see ByteBuffer#compact()
     */
    public IoBuffer compact() {
        for (int i = 0; i < remaining(); i++) {
            put(i, get(i + position.getPosition()));
        }
        position(limit() - position());
        limit(capacity);
        mark = null;
        return this;
    }

    /**
     * Returns a copy of the current {@link IoBuffer}, with an independent copy
     * of the position, limit and mark.
     *
     * @return the copied {@link IoBuffer}
     */
    public IoBuffer duplicate() {
        IoBuffer buffer = new IoBuffer();

        for (BufferNode node = head; node != null; node = node.getNext()) {
            ByteBuffer byteBuffer = node.getBuffer().duplicate();
            byteBuffer.rewind();
            buffer.enqueue(byteBuffer);
        }
        buffer.position(position());
        buffer.limit(limit());
        buffer.mark = mark != null ? getPointerByPosition(mark.getPosition()) : null;

        buffer.readonly = readonly;
        return buffer;
    }

    private void enqueue(ByteBuffer buffer) {

        if (buffer.isReadOnly()) {
            readonly = true;
        }

        if (!buffer.isDirect()) {
            direct = false;
        }
        if (buffer.remaining() > 0) {
            BufferNode newnode = new BufferNode(buffer, capacity);
            capacity += buffer.capacity();

            if (head == null) {
                head = newnode;
                position = getPointerByPosition(0);
            } else {
                tail.setNext(newnode);
            }
            tail = newnode;

            limit = getPointerByPosition(capacity);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object ob) {
        if (this == ob) {
            return true;
        }
        if (!(ob instanceof IoBuffer)) {
            return false;
        }
        IoBuffer that = (IoBuffer) ob;
        if (this.remaining() != that.remaining()) {
            return false;
        }
        int p = this.position();
        int q = that.position();
        while (this.hasRemaining() && that.hasRemaining()) {
            if (this.get() != that.get()) {
                this.position(p);
                that.position(q);
                return false;
            }

        }
        this.position(p);
        that.position(q);
        return true;
    }

    /**
     * Extends the current IoBuffer capacity.
     *
     * @param size
     *            the number of bytes to extend the current IoBuffer
     * @return the current {@link IoBuffer}
     */
    public IoBuffer extend(int size) {
        ByteBuffer extension = isDirect() ? ByteBuffer.allocateDirect(size) : ByteBuffer.allocate(size);
        add(extension);
        return this;
    }

    /**
     * @see ByteBuffer#flip()
     */
    public IoBuffer flip() {
        limit = position;
        position = getPointerByPosition(0);
        return this;
    }

    /**
     * @see ByteBuffer#get()
     */
    public byte get() {
        if (!hasRemaining()) {
            throw new BufferUnderflowException();
        }

        return get(position);
    }

    /**
     * @see ByteBuffer#get(byte[])
     */
    public IoBuffer get(byte[] dst) {
        get(dst, 0, dst.length);
        return this;
    }

    /**
     * @see ByteBuffer#get(byte[], int,int)
     */
    public IoBuffer get(byte[] dst, int offset, int length) {
        if (remaining() < length) {
            throw new BufferUnderflowException();
        }
        int remainsToCopy = length;
        int currentOffset = offset;

        while (remainsToCopy > 0) {
            position.updatePos();
            position.getNode().getBuffer().position(position.getPositionInNode());
            ByteBuffer currentBuffer = position.getNode().getBuffer();
            int blocksize = Math.min(remainsToCopy, currentBuffer.remaining());
            position.getNode().getBuffer().get(dst, currentOffset, blocksize);

            currentOffset += blocksize;
            remainsToCopy -= blocksize;

            position.incrementPosition(blocksize);

            position.getNode().getBuffer().position(0);
        }
        return this;
    }

    /**
     * @see ByteBuffer#get(int)
     */
    public byte get(int index) {
        if (index >= limit.getPosition()) {
            throw new IndexOutOfBoundsException();
        }
        return get(getPointerByPosition(index));
    }

    private byte get(Pointer pos) {
        pos.updatePos();
        byte b = pos.getNode().getBuffer().get(pos.getPositionInNode());
        pos.incrPosition();
        return b;
    }

    /**
     * @see ByteBuffer#getChar()
     */
    public char getChar() {
        return getChar(position);
    }

    /**
     * @see ByteBuffer#getChar(int)
     */
    public char getChar(int index) {
        return getChar(getPointerByPosition(index));
    }

    private char getChar(Pointer position) {
        return (char) getShort(position);
    }

    /**
     * @see ByteBuffer#getDouble()
     */
    public double getDouble() {
        return Double.longBitsToDouble(getLong());
    }

    /**
     * @see ByteBuffer#getDouble(int)
     */
    public double getDouble(int index) {
        return getDouble(getPointerByPosition(index));
    }

    private double getDouble(Pointer pos) {
        return Double.longBitsToDouble(getLong(pos));
    }

    /**
     * @see ByteBuffer#getFloat()
     */
    public float getFloat() {
        return getFloat(position);
    }

    /**
     * @see ByteBuffer#getFloat(int)
     */
    public float getFloat(int index) {
        return getFloat(getPointerByPosition(index));
    }

    private float getFloat(Pointer pos) {
        return Float.intBitsToFloat(getInt(pos));
    }

    /**
     * @see ByteBuffer#getInt()
     */
    public int getInt() {
        return getInt(position);
    }

    /**
     * @see ByteBuffer#getInt(int)
     */
    public int getInt(int index) {
        return getInt(getPointerByPosition(index));
    }

    private int getInt(Pointer pos) {
        if (pos.getPosition() > capacity - Integer.SIZE / Byte.SIZE) {
            throw new BufferUnderflowException();
        }

        int out = 0;
        for (int i = 0; i < Integer.SIZE; i += Byte.SIZE) {
            out |= (get(pos) & BYTE_MASK) << (bo == ByteOrder.BIG_ENDIAN ? (Integer.SIZE - Byte.SIZE) - i : i);
        }
        return out;
    }

    /**
     * @see ByteBuffer#getLong()
     */
    public long getLong() {
        return getLong(position);
    }

    /**
     * @see ByteBuffer#getLong(int)
     */
    public long getLong(int index) {
        return getLong(getPointerByPosition(index));
    }

    private long getLong(Pointer pos) {
        if (pos.getPosition() > capacity - Long.SIZE / Byte.SIZE) {
            throw new BufferUnderflowException();
        }

        long out = 0;
        for (int i = 0; i < Long.SIZE; i += Byte.SIZE) {
            out |= (get(pos) & BYTE_MASK_L) << (bo == ByteOrder.BIG_ENDIAN ? (Long.SIZE - Byte.SIZE) - i : i);
        }
        return out;
    }

    private Pointer getPointerByPosition(int pos) {
        return new Pointer(pos);
    }

    /**
     * @see ByteBuffer#getShort()
     */
    public short getShort() {
        return getShort(position);
    }

    /**
     * @see ByteBuffer#getShort(int)
     */
    public long getShort(int index) {
        return getShort(getPointerByPosition(index));
    }

    private short getShort(Pointer pos) {
        if (pos.getPosition() > capacity - Short.SIZE / Byte.SIZE) {
            throw new BufferUnderflowException();
        }
        if (bo == ByteOrder.BIG_ENDIAN) {
            return (short) ((get(pos) & BYTE_MASK) << Byte.SIZE | (get(pos) & BYTE_MASK));
        } else {
            return (short) ((get(pos) & BYTE_MASK) | (get(pos) & BYTE_MASK) << Byte.SIZE);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        int hash = 0;
        Pointer oldPos = position.duplicate();
        while (hasRemaining()) {
            hash *= 31; // NOSONAR, standard way of hashing
            hash += get();
        }
        position = oldPos;
        return hash;
    }

    /**
     * @see ByteBuffer#hasRemaining()
     */
    public boolean hasRemaining() {
        return remaining() > 0;
    }

    /**
     * @see ByteBuffer#isDirect()
     */
    public boolean isDirect() {
        return direct;
    }

    /**
     * @see ByteBuffer#isReadOnly()
     */
    public boolean isReadOnly() {
        return readonly;
    }

    /**
     * @see ByteBuffer#limit()
     */
    public int limit() {
        return limit.getPosition();
    }

    /**
     * @see ByteBuffer#limit(int)
     */
    public void limit(int newLimit) {
        this.limit = getPointerByPosition(newLimit);
    }

    /**
     * @see ByteBuffer#mark()
     */
    public void mark() {
        this.mark = position.duplicate();
    }

    /**
     * Returns the byte order used by this IoBuffer when converting bytes
     * from/to other primitive types.
     * <p>
     * The default byte order of byte buffer is always
     * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}
     *
     * @return the byte order used by this IoBuffer when converting bytes
     *         from/to other primitive types.
     *
     * @see ByteBuffer#order()
     */
    public ByteOrder order() {
        return bo;
    }

    /**
     * Sets the byte order of this IoBuffer.
     *
     * @param bo
     *            the byte order to set. If {@code null} then the order will be
     *            {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN}.
     * @return this IoBuffer.
     * @see ByteBuffer#order(ByteOrder)
     */
    public IoBuffer order(ByteOrder bo) {
        this.bo = bo != null ? bo : ByteOrder.LITTLE_ENDIAN;

        return this;
    }

    /**
     * @see ByteBuffer#position()
     */
    public int position() {
        return position.getPosition();
    }

    /**
     * @see ByteBuffer#position(int)
     */
    public void position(int newPosition) {
        if (newPosition > limit() || newPosition < 0) {
            throw new IllegalArgumentException();
        }

        if (mark != null && mark.getPosition() > newPosition) {
            mark = null;
        }

        this.position.setPosition(newPosition);
    }

    /**
     * @see ByteBuffer#put(byte)
     */
    public IoBuffer put(byte b) {
        if (readonly) {
            throw new ReadOnlyBufferException();
        }
        if (position.getPosition() >= limit.getPosition()) {
            throw new BufferUnderflowException();
        }

        put(position, b);
        return this;
    }

    /**
     * @see ByteBuffer#put(byte[])
     */
    public IoBuffer put(byte[] src) {
        put(src, 0, src.length);
        return this;
    }

    /**
     * @see ByteBuffer#put(ByteBuffer)
     */
    public IoBuffer put(ByteBuffer src) {

        if (remaining() < src.remaining()) {
            throw new BufferOverflowException();
        }
        if (isReadOnly()) {
            throw new ReadOnlyBufferException();
        }

        while (src.hasRemaining()) {
            put(src.get());
        }

        return this;
    }

    /**
     * @see ByteBuffer#put(ByteBuffer)
     */
    public IoBuffer put(IoBuffer src) {
        if (src == this) { // NOSONAR, checking the instance
            throw new IllegalArgumentException();
        }

        if (remaining() < src.remaining()) {
            throw new BufferOverflowException();
        }
        if (isReadOnly()) {
            throw new ReadOnlyBufferException();
        }

        while (src.hasRemaining()) {
            put(src.get());
        }

        return this;
    }

    /**
     * @see ByteBuffer#put(byte[], int, int)
     */
    public IoBuffer put(byte[] src, int offset, int length) {
        if (readonly) {
            throw new ReadOnlyBufferException();
        }
        if (remaining() < length) {
            throw new BufferUnderflowException();
        }

        int remainsToCopy = length;
        int currentOffset = offset;
        position.getNode().getBuffer().position(position.getPositionInNode());
        while (remainsToCopy > 0) {
            position.updatePos();

            ByteBuffer currentBuffer = position.getNode().getBuffer();
            int blocksize = Math.min(remainsToCopy, currentBuffer.remaining());
            position.getNode().getBuffer().put(src, currentOffset, blocksize);

            currentOffset += blocksize;
            remainsToCopy -= blocksize;

            position.incrementPosition(blocksize);
        }
        position.getNode().getBuffer().position(0);
        return this;
    }

    /**
     * @see ByteBuffer#put(int, byte)
     */
    public IoBuffer put(int index, byte value) {
        if (index >= limit.getPosition()) {
            throw new IndexOutOfBoundsException();
        }
        Pointer p = getPointerByPosition(index);
        put(p, value);
        return this;
    }

    private IoBuffer put(Pointer pos, byte b) {
        pos.updatePos();
        pos.getNode().getBuffer().put(pos.getPositionInNode(), b);
        pos.incrPosition();
        return this;
    }

    /**
     * @see ByteBuffer#putChar(char)
     */
    public IoBuffer putChar(char value) {
        return putChar(position, value);
    }

    /**
     * @see ByteBuffer#putChar(int, char)
     */
    public IoBuffer putChar(int index, char value) {
        return putChar(getPointerByPosition(index), value);
    }

    private IoBuffer putChar(Pointer index, char value) {
        return putShort(index, (short) value);
    }

    /**
     * @see ByteBuffer#putDouble(double)
     */
    public IoBuffer putDouble(double value) {
        return putDouble(position, value);
    }

    /**
     * @see ByteBuffer#putDouble(int, double)
     */
    public IoBuffer putDouble(int index, double value) {
        return putDouble(getPointerByPosition(index), value);
    }

    private IoBuffer putDouble(Pointer pos, double value) {
        return putLong(pos, Double.doubleToLongBits(value));
    }

    /**
     * @see ByteBuffer#putFloat(float)
     */
    public IoBuffer putFloat(float value) {
        return putFloat(position, value);
    }

    /**
     * @see ByteBuffer#putFloat(int, float)
     */
    public IoBuffer putFloat(int index, float value) {
        return putFloat(getPointerByPosition(index), value);
    }

    private IoBuffer putFloat(Pointer pointer, float value) {
        return putInt(pointer, Float.floatToIntBits(value));
    }

    /**
     * @see ByteBuffer#putInt(int)
     */
    public IoBuffer putInt(int value) {
        return putInt(position, value);
    }

    /**
     * @see ByteBuffer#putInt(int, int)
     */
    public IoBuffer putInt(int index, int value) {
        return putInt(getPointerByPosition(index), value);
    }

    private IoBuffer putInt(Pointer pointer, int value) {
        if (position.getPosition() > pointer.getPosition()
                || pointer.getPosition() > limit.getPosition() - Integer.SIZE / Byte.SIZE) {
            throw new BufferUnderflowException();
        }
        for (int i = 0; i < Integer.SIZE; i += Byte.SIZE) {
            put(pointer, (byte) (value >> (bo == ByteOrder.BIG_ENDIAN ? (Integer.SIZE - Byte.SIZE) - i : i)));
        }
        return this;
    }

    /**
     * @see ByteBuffer#putLong(int, long)
     */
    public IoBuffer putLong(int index, long value) {
        return putLong(getPointerByPosition(index), value);
    }

    /**
     * @see ByteBuffer#putLong(long)
     */
    public IoBuffer putLong(long value) {
        return putLong(position, value);
    }

    private IoBuffer putLong(Pointer pointer, long value) {
        if (position.getPosition() > pointer.getPosition()
                || pointer.getPosition() > limit.getPosition() - Long.SIZE / Byte.SIZE) {
            throw new BufferUnderflowException();
        }
        for (int i = 0; i < Long.SIZE; i += Byte.SIZE) {
            put(pointer, (byte) (value >> (bo == ByteOrder.BIG_ENDIAN ? (Long.SIZE - Byte.SIZE) - i : i)));
        }

        return this;
    }

    /**
     * @see ByteBuffer#putShort(int, short)
     */
    public IoBuffer putShort(int index, short value) {
        return putShort(getPointerByPosition(index), value);
    }

    private IoBuffer putShort(Pointer pointer, short value) {
        if (position.getPosition() > pointer.getPosition()
                || pointer.getPosition() > limit.getPosition() - Short.SIZE / Byte.SIZE) {
            throw new BufferUnderflowException();
        }
        for (int i = 0; i < Short.SIZE; i += Byte.SIZE) {
            put(pointer, (byte) (value >> (bo == ByteOrder.BIG_ENDIAN ? Byte.SIZE - i : i)));
        }
        return this;
    }

    /**
     * @see ByteBuffer#putShort(short)
     */
    public IoBuffer putShort(short value) {
        return putShort(position, value);
    }

    /**
     * @see ByteBuffer#remaining()
     */
    public int remaining() {
        return limit() - position();
    }

    /**
     * @see ByteBuffer#reset()
     */
    public IoBuffer reset() {
        if (mark == null) {
            throw new InvalidMarkException();
        }
        position = mark.duplicate();
        return this;
    }

    /**
     * @see ByteBuffer#rewind()
     */
    public IoBuffer rewind() {
        position(0);
        mark = getPointerByPosition(-1);
        return this;
    }

    /**
     * @see ByteBuffer#slice()
     */
    public IoBuffer slice() {
        position.updatePos();
        IoBuffer out = new IoBuffer();
        out.order(order());

        position.getNode().getBuffer().position(position.getPositionInNode());
        if (hasRemaining()) {
            tail.getBuffer().limit(limit.getPositionInNode());
            for (BufferNode node = position.getNode(); node != limit.getNode(); node = node.getNext()) {
                if (node != head) { // NOSONAR, check if instances are the same.
                    node.getBuffer().position(0);
                }
                out.add(node.getBuffer());
            }
            if (tail != head) { // NOSONAR, check if instances are the same.
                tail.getBuffer().position(0);
            }
            out.add(tail.getBuffer().slice());
            tail.getBuffer().limit(tail.getBuffer().capacity());
        }
        position.getNode().getBuffer().position(0);

        return out;
    }

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

    private static final class BufferNode {
        private final ByteBuffer buffer;

        private BufferNode next;

        private final int offset;

        public BufferNode(ByteBuffer buffer, int offset) {
            this.buffer = buffer;
            this.offset = offset;
        }

        public ByteBuffer getBuffer() {
            return buffer;
        }

        public BufferNode getNext() {
            return next;
        }

        public boolean hasNext() {
            return next != null;
        }

        public void setNext(BufferNode next) {
            this.next = next;
        }

        @Override
        public String toString() {
            return "BufferNode [offset=" + offset + ", buffer=" + buffer + "]";
        }
    }

    private final class Pointer {

        private BufferNode node;

        private int positionInBuffer;

        public Pointer(int position) {
            this();

            setPosition(position);
        }

        public Pointer() {
        }

        public Pointer duplicate() {
            return new Pointer(getPosition());
        }

        public BufferNode getNode() {
            return node;
        }

        public int getPosition() {
            return positionInBuffer + (node == null ? 0 : node.offset);
        }

        public int getPositionInNode() {
            updatePos();
            return positionInBuffer;
        }

        public void incrPosition() {
            incrementPosition(1);
        }

        public void setPosition(int newPosition) {
            if ((node == null) || (newPosition < node.offset)) {
                node = head;
            }

            positionInBuffer = node == null ? 0 : newPosition - node.offset;
        }

        public void incrementPosition(int positionIncrement) {
            positionInBuffer += positionIncrement;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(getClass().getName());
            sb.append("[pos=");
            sb.append(getPosition());
            sb.append(", node=");
            sb.append(getNode());
            sb.append("]");
            return sb.toString();
        }

        public void updatePos() {
            while (node != null && positionInBuffer >= node.getBuffer().capacity() && node.hasNext()) {
                positionInBuffer -= node.getBuffer().capacity();
                node = node.getNext();
            }
        }
    }
}
TOP

Related Classes of org.apache.mina.codec.IoBuffer$Pointer

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.