// 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 streamer;

import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * This class represents a slice in a buffer.
 */
public class ByteBuffer {

    public static final String SEQUENCE_NUMBER = "seq";

    public byte data[];
    public int offset = 0;
    public int length = 0;
    public int cursor = 0;

    private int refCount = 1;

    private Order order;

    /**
     * Create buffer of size no less than length. Buffer can be a bit larger than
     * length. Offset also can be set to non-zero value to leave some place for
     * future headers.
     */
    public ByteBuffer(int minLength) {
        // Get buffer of acceptable size from buffer pool
        data = BufferPool.allocateNewBuffer(minLength);
        offset = 0;
        length = minLength;
    }

    public ByteBuffer(byte data[]) {
        if (data == null)
            throw new NullPointerException("Data must be non-null.");

        this.data = data;
        offset = 0;
        length = data.length;
    }

    public ByteBuffer(byte[] data, int offset, int length) {
        if (data == null)
            throw new NullPointerException("Data must be non-null.");

        this.data = data;
        this.offset = offset;
        this.length = length;
    }

    /**
     * Create byte buffer of requested size with some space reserved for future
     * headers.
     */
    public ByteBuffer(int minLength, boolean reserveSpaceForHeader) {
        // Get buffer of acceptable size from buffer pool
        data = BufferPool.allocateNewBuffer(128 + minLength);
        offset = 128; // 100 bytes should be enough for headers
        length = minLength;
    }

    /**
     * Create empty buffer with given order only.
     */
    public ByteBuffer(Order order) {
        this.order = order;
    }

    public void setOrder(Order order) {
        this.order = order;
    }

    public Order getOrder() {
        return order;
    }

    @Override
    public String toString() {
        return toString(length);
    }

    /**
     * Return string representation of this byte buffer.
     *
     * @param maxLength
     *          number of bytes to show in string
     */
    public String toString(int maxLength) {
        return "ByteRange(){offset=" + offset + ", length=" + length + ", cursor=" + cursor + ", data=" + ((data == null) ? "null" : toHexString(maxLength))
                + ((metadata == null || metadata.size() == 0) ? "" : ", metadata=" + metadata) + "}";
    }

    /**
     * Return string representation of this byte buffer as hexadecimal numbers,
     * e.g. "[0x01, 0x02]".
     *
     * @param maxLength
     *          number of bytes to show in string
     */
    public String toHexString(int maxLength) {
        StringBuilder builder = new StringBuilder(maxLength * 6);
        builder.append('[');
        for (int i = 0; i < maxLength && i < length; i++) {
            if (i > 0)
                builder.append(", ");
            int b = data[offset + i] & 0xff;
            builder.append("0x" + ((b < 16) ? "0" : "") + Integer.toString(b, 16));
        }
        builder.append(']');
        return builder.toString();
    }

    /**
     * Return string representation of this byte buffer as hexadecimal numbers,
     * e.g. "01 02".
     *
     * @param maxLength
     *          number of bytes to show in string
     */
    public String toPlainHexString(int maxLength) {
        StringBuilder builder = new StringBuilder(maxLength * 3);
        for (int i = 0; i < maxLength && i < length; i++) {
            if (i > 0)
                builder.append(" ");
            int b = data[offset + i] & 0xff;
            builder.append(String.format("%02x", b));
        }
        return builder.toString();
    }

    /**
     * Return string representation of this byte buffer as dump, e.g.
     * "0000  01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 .................".
     *
     * @param maxLength
     *          number of bytes to show in string
     */
    public String dump() {
        StringBuilder builder = new StringBuilder(length * 4);
        int i = addBytesToBuilder(builder);
        int end = i - 1;
        if (end % 16 != 15) {
            int begin = end & ~0xf;
            for (int j = 0; j < (15 - (end % 16)); j++) {
                builder.append("   ");
            }
            builder.append(' ');
            builder.append(toASCIIString(begin, end));
            builder.append('\n');
        }
        return builder.toString();
    }

    protected int addBytesToBuilder(StringBuilder builder) {
        int i = 0;
        for (; i < length; i++) {
            if (i % 16 == 0) {
                builder.append(String.format("%04x", i));
            }

            builder.append(' ');
            int b = data[offset + i] & 0xff;
            builder.append(String.format("%02x", b));

            if (i % 16 == 15) {
                builder.append(' ');
                builder.append(toASCIIString(i - 15, i));
                builder.append('\n');
            }
        }
        return i;
    }

    private String toASCIIString(int start, int finish) {
        StringBuffer sb = new StringBuffer(16);
        for (int i = start; i <= finish; i++) {
            char ch = (char)data[offset + i];
            if (ch < ' ' || ch >= 0x7f) {
                sb.append('.');
            } else {
                sb.append(ch);
            }
        }
        return sb.toString();
    }

    /**
     * Return string representation of this byte buffer as hexadecimal numbers,
     * e.g. "01 02".
     */
    public String toPlainHexString() {
        return toPlainHexString(length);
    }

    public void extend(int newLength) {
        if (data.length < newLength)
            data = Arrays.copyOf(data, newLength);
    }

    public void ref() {
        refCount++;
    }

    public void unref() {
        refCount--;

        if (refCount == 0) {
            // Return buffer to buffer pool
            BufferPool.recycleBuffer(data);

            data = null;
        }

    }

    public boolean isSoleOwner() {
        return refCount == 1;
    }

    /**
     * Create shared lightweight copy of part of this buffer.
     */
    public ByteBuffer slice(int offset, int length, boolean copyMetadata) {
        ref();

        if (this.length < (offset + length))
            throw new RuntimeException("Length of region is larger that length of this buffer. Buffer length: " + this.length + ", offset: " + offset + ", new region length: "
                    + length + ".");

        ByteBuffer slice = new ByteBuffer(data, this.offset + offset, length);

        if (copyMetadata && metadata != null)
            slice.metadata = new HashMap<String, Object>(metadata);

        return slice;
    }

    private Map<String, Object> metadata = null;

    public Object putMetadata(String key, Object value) {
        if (metadata == null)
            metadata = new HashMap<String, Object>();
        return metadata.put(key, value);
    }

    public Object getMetadata(String key) {
        return (metadata != null) ? metadata.get(key) : null;
    }

    /**
     * Create new buffer, which holds data from both buffers. Expensive operation.
     *
     * @TODO if only one reference to this ByteBuffer exists, then extend this
     *       buffer instead of creating new buffer
     * @TODO support list of buffers to avoid expensive joins until absolute
     *       necessary
     */
    public ByteBuffer join(ByteBuffer buf) {
        // Extend byte array for new data
        int newLength = length + buf.length;
        byte newData[] = new byte[newLength];

        // Copy data from our buffer
        System.arraycopy(data, offset, newData, 0, length);

        // Copy data from other buffer
        System.arraycopy(buf.data, buf.offset, newData, length, buf.length);

        ByteBuffer newBuf = new ByteBuffer(newData);

        // Copy our (older) metadata to new buffer, because handler might store some
        // metadata in buffer, which is pushed back.
        if (metadata != null)
            newBuf.metadata = new HashMap<String, Object>(metadata);

        return newBuf;
    }

    /**
     * Copy used portion of buffer to new byte array. Expensive operation.
     */
    public byte[] toByteArray() {
        return Arrays.copyOfRange(data, offset, offset + length);
    }

    public short[] toShortArray() {
        if (length % 2 != 0)
            throw new ArrayIndexOutOfBoundsException("Length of byte array must be dividable by 2 without remainder. Array length: " + length + ", remainder: " + (length % 2)
                    + ".");

        short[] buf = new short[length / 2];

        for (int i = 0, j = offset; i < buf.length; i++, j += 2) {
            buf[i] = (short)((data[j + 0] & 0xFF) | ((data[j + 1] & 0xFF) << 8));
        }
        return buf;
    }

    /**
     * Return array of int's in little endian order.
     */
    public int[] toIntLEArray() {
        if (length % 4 != 0)
            throw new ArrayIndexOutOfBoundsException("Length of byte array must be dividable by 4 without remainder. Array length: " + length + ", remainder: " + (length % 4)
                    + ".");

        int[] buf = new int[length / 4];

        for (int i = 0, j = offset; i < buf.length; i++, j += 4) {
            buf[i] = (data[j + 0] & 0xFF) | ((data[j + 1] & 0xFF) << 8) | ((data[j + 2] & 0xFF) << 16) | ((data[j + 3] & 0xFF) << 24);
        }
        return buf;
    }

    /**
     * Return array of int's in little endian order, but use only 3 bytes per int
     * (3RGB).
     */
    public int[] toInt3LEArray() {
        if (length % 3 != 0)
            throw new ArrayIndexOutOfBoundsException("Length of byte array must be dividable by 3 without remainder. Array length: " + length + ", remainder: " + (length % 3)
                    + ".");

        int[] buf = new int[length / 3];

        for (int i = 0, j = offset; i < buf.length; i++, j += 3) {
            buf[i] = (data[j + 0] & 0xFF) | ((data[j + 1] & 0xFF) << 8) | ((data[j + 2] & 0xFF) << 16);
        }
        return buf;
    }

    /**
     * Helper method for test cases to convert array of byte arrays to array of
     * byte buffers.
     */
    public static ByteBuffer[] convertByteArraysToByteBuffers(byte[]... bas) {
        ByteBuffer bufs[] = new ByteBuffer[bas.length];

        int i = 0;
        for (byte[] ba : bas) {
            bufs[i++] = new ByteBuffer(ba);
        }
        return bufs;
    }

    /**
     * Read signed int in network order. Cursor is advanced by 4.
     */
    public int readSignedInt() {
        if (cursor + 4 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot read 4 bytes from this buffer: " + this + ".");

        int result = (((data[offset + cursor] & 0xff) << 24) + ((data[offset + cursor + 1] & 0xff) << 16) + ((data[offset + cursor + 2] & 0xff) << 8) + (data[offset + cursor + 3] & 0xff));
        cursor += 4;
        return result;
    }

    /**
     * Read signed int in little endian order. Cursor is advanced by 4.
     */
    public int readSignedIntLE() {
        if (cursor + 4 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot read 4 bytes from this buffer: " + this + ".");

        int result = (((data[offset + cursor + 3] & 0xff) << 24) + ((data[offset + cursor + 2] & 0xff) << 16) + ((data[offset + cursor + 1] & 0xff) << 8) + (data[offset + cursor] & 0xff));
        cursor += 4;
        return result;
    }

    /**
     * Read unsigned int in little endian order. Cursor is advanced by 4.
     */
    public long readUnsignedIntLE() {
        if (cursor + 4 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot read 4 bytes from this buffer: " + this + ".");

        long result = (((long)(data[offset + cursor + 3] & 0xff) << 24) + ((long)(data[offset + cursor + 2] & 0xff) << 16) + ((long)(data[offset + cursor + 1] & 0xff) << 8) + (data[offset
                + cursor + 0] & 0xff));
        cursor += 4;
        return result;
    }

    /**
     * Read unsigned int in network order. Cursor is advanced by 4.
     */
    public long readUnsignedInt() {
        if (cursor + 4 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot read 4 bytes from this buffer: " + this + ".");

        byte value1 = data[offset + cursor + 0];
        byte value2 = data[offset + cursor + 1];
        byte value3 = data[offset + cursor + 2];
        byte value4 = data[offset + cursor + 3];
        long result = calculateUnsignedInt(value1, value2, value3, value4);
        cursor += 4;
        return result;
    }

    protected static long calculateUnsignedInt(byte value1, byte value2, byte value3, byte value4) {
        return (((long)calculateUnsignedByte(value1)) << 24)
                + (((long)calculateUnsignedByte(value2)) << 16)
                + (((long)calculateUnsignedByte(value3)) << 8)
                + calculateUnsignedByte(value4);
    }

    /**
     * Read signed int in variable length format. Top most bit of each byte
     * indicates that next byte contains additional bits. Cursor is advanced by
     * 1-5 bytes.
     */
    public int readVariableSignedIntLE() {
        int result = 0;

        for (int shift = 0; shift < 32; shift += 7) {
            int b = readUnsignedByte();
            result |= (b & 0x7f) << shift;
            if ((b & 0x80) == 0)
                break;
        }

        return result;
    }

    /**
     * Read unsigned int in network order in variable length format. Cursor is
     * advanced by 1 to 4 bytes.
     *
     * Two most significant bits of first byte indicates length of field: 0x00 - 1
     * byte, 0x40 - 2 bytes, 0x80 - 3 bytes, 0xc0 - 4 bytes.
     *
     * @see http://msdn.microsoft.com/en-us/library/cc241614.aspx
     */
    public int readEncodedUnsignedInt() {
        int firstByte = readUnsignedByte();
        int result;
        switch (firstByte & 0xc0) {
        default:
        case 0x00:
            result = firstByte & 0x3f;
            break;
        case 0x40:
            result = (firstByte & 0x3f << 8) | readUnsignedByte();
            break;
        case 0x80:
            result = (((firstByte & 0x3f << 8) | readUnsignedByte()) << 8) | readUnsignedByte();
            break;
        case 0xc0:
            result = ((((firstByte & 0x3f << 8) | readUnsignedByte()) << 8) | readUnsignedByte() << 8) | readUnsignedByte();
            break;
        }

        return result;
    }

    /**
     * Read unsigned byte. Cursor is advanced by 1.
     */
    public int readUnsignedByte() {
        if (cursor + 1 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot read 1 byte from this buffer: " + this + ".");

        byte value = data[offset + cursor];
        int b = calculateUnsignedByte(value);
        cursor += 1;
        return b;
    }

    protected static int calculateUnsignedByte(byte value) {
        return value & 0xff;
    }

    /**
     * Read signed byte. Cursor is advanced by 1.
     */
    public byte readSignedByte() {
        if (cursor + 1 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot read 1 byte from this buffer: " + this + ".");

        byte b = data[offset + cursor];
        cursor += 1;
        return b;
    }

    /**
     * Read unsigned short in network order. Cursor is advanced by 2.
     */
    public int readUnsignedShort() {
        if (cursor + 2 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot read 2 bytes from this buffer: " + this + ".");

        byte value1 = data[offset + cursor];
        byte value2 = data[offset + cursor + 1];
        int result = calculateUnsignedShort(value1, value2);
        cursor += 2;
        return result;
    }

    protected static int calculateUnsignedShort(byte value1, byte value2) {
        return (calculateUnsignedByte(value1) << 8) | calculateUnsignedByte(value2);
    }

    /**
     * Read signed short in little endian order. Cursor is advanced by 2.
     */
    public short readSignedShortLE() {
        if (cursor + 2 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot read 2 bytes from this buffer: " + this + ".");

        short result = (short)(((data[offset + cursor + 1] & 0xff) << 8) | (data[offset + cursor] & 0xff));
        cursor += 2;
        return result;
    }

    /**
     * Read signed short in network order. Cursor is advanced by 2.
     */
    public short readSignedShort() {
        if (cursor + 2 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot read 2 bytes from this buffer: " + this + ".");

        byte value1 = data[offset + cursor + 0];
        byte value2 = data[offset + cursor + 1];
        short result = calculateSignedShort(value1, value2);
        cursor += 2;
        return result;
    }

    protected static short calculateSignedShort(byte value1, byte value2) {
        return (short)calculateUnsignedShort(value1, value2);
    }

    /**
     * Read unsigned short in network order in variable length format. Cursor is
     * advanced by 1 or 2 bytes.
     *
     * Most significant bit of first byte indicates length of field: 0 - 1 byte, 1
     * - 2 bytes.
     */
    public int readVariableUnsignedShort() {
        int firstByte = readUnsignedByte();

        int result;
        if ((firstByte & 0x80) == 0) {
            result = firstByte & 0x7f;
        } else {
            int secondByte = readUnsignedByte();
            result = (((firstByte & 0x7f) << 8) | secondByte);
        }

        return result;
    }

    /**
     * Read integer in BER format.
     *
     * Most significant bit of first byte indicates type of date in first byte: if
     * 0, then byte contains length (up to 7f), if 1, then byte contains number of
     * following bytes with value in network order. Value 0x80 means unlimited
     * length, which ends with two zero bytes (0x00 0x00) sequence.
     *
     * If -1 is returned by this method, then caller must seek two consecutive
     * zeroes in buffer and consume all that data from buffer, including these two
     * zeroes, but caller should not parse these two zeroes.
     *
     * @return length or -1, for unlimited length
     */
    public long readBerLength() {
        int firstByte = readUnsignedByte();

        long result;
        if ((firstByte & 0x80) == 0) {
            result = firstByte & 0x7f;
        } else {
            int intLength = firstByte & 0x7f;
            if (intLength != 0)
                result = readUnsignedVarInt(intLength);
            else
                return -1;
        }

        return result;
    }

    /**
     * Read integer in BER format.
     *
     * Most significant bit of first byte indicates type of date in first byte: if
     * 0, then byte contains length (up to 7f), if 1, then byte contains number of
     * following bytes with value in network order.
     */
    public void writeBerLength(long length) {
        if (length < 0)
            throw new RuntimeException("Length cannot be less than zero: " + length + ". Data: " + this + ".");

        if (length < 0x80) {
            writeByte((int)length);
        } else {
            if (length < 0xff) {
                writeByte(0x81);
                writeByte((int)length);
            } else if (length <= 0xffFF) {
                writeByte(0x82);
                writeShort((int)length);
            } else if (length <= 0xffFFff) {
                writeByte(0x83);
                writeByte((int)(length >> 16));
                writeShort((int)length);
            } else if (length <= 0xffFFffFFL) {
                writeByte(0x84);
                writeInt((int)length);
            } else if (length <= 0xffFFffFFffL) {
                writeByte(0x85);
                writeByte((int)(length >> 32));
                writeInt((int)length);
            } else if (length <= 0xffFFffFFffFFL) {
                writeByte(0x86);
                writeShort((int)(length >> 32));
                writeInt((int)length);
            } else if (length <= 0xffFFffFFffFFffL) {
                writeByte(0x87);
                writeByte((int)(length >> (32 + 16)));
                writeShort((int)(length >> 32));
                writeInt((int)length);
            } else {
                writeByte(0x88);
                writeInt((int)(length >> 32));
                writeInt((int)length);
            }
        }

    }

    /**
     * Read signed variable length integers in network order.
     *
     * @param len
     *          length of integer
     */
    public long readSignedVarInt(int len) {
        long value = 0;
        switch (len) {
        case 0:
            value = 0;
            break;
        case 1:
            value = readSignedByte();
            break;
        case 2:
            value = readSignedShort();
            break;
        case 3:
            value = (readSignedByte() << 16) | readUnsignedShort();
            break;
        case 4:
            value = readSignedInt();
            break;
        case 5:
            value = readSignedByte() | readUnsignedInt();
            break;
        case 6:
            value = readSignedShort() | readUnsignedInt();
            break;
        case 7:
            value = (readSignedByte() << 24) | readUnsignedShort() | readUnsignedInt();
            break;
        case 8:
            value = readSignedLong();
            break;
        default:
            throw new RuntimeException("Cannot read integers which are more than 8 bytes long. Length: " + len + ". Data: " + this + ".");
        }

        return value;
    }

    /**
     * Read unsigned variable length integers in network order. Values, which are
     * larger than 0x7FffFFffFFffFFff cannot be parsed by this method.
     */
    public long readUnsignedVarInt(int len) {
        long value = 0;
        switch (len) {
        case 0:
            value = 0;
            break;
        case 1:
            value = readUnsignedByte();
            break;
        case 2:
            value = readUnsignedShort();
            break;
        case 3:
            value = (readUnsignedByte() << 16) | readUnsignedShort();
            break;
        case 4:
            value = readUnsignedInt();
            break;
        case 5:
            value = readUnsignedByte() | readUnsignedInt();
            break;
        case 6:
            value = readUnsignedShort() | readUnsignedInt();
            break;
        case 7:
            value = (readUnsignedByte() << 16) | readUnsignedShort() | readUnsignedInt();
            break;
        case 8:
            value = readSignedLong();
            if (value < 0)
                throw new RuntimeException("Cannot read 64 bit integers which are larger than 0x7FffFFffFFffFFff, because of lack of unsigned long type in Java. Value: " + value
                        + ". Data: " + this + ".");
            break;
        default:
            throw new RuntimeException("Cannot read integers which are more than 8 bytes long. Length: " + len + ". Data: " + this + ".");
        }

        return value;
    }

    /**
     * Read unsigned short in little endian order. Cursor is advanced by 2.
     */
    public int readUnsignedShortLE() {
        if (cursor + 2 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot read 2 bytes from this buffer: " + this + ".");

        int result = (((data[offset + cursor + 1] & 0xff) << 8) | (data[offset + cursor] & 0xff));
        cursor += 2;
        return result;
    }

    /**
     * Read unsigned short in network order in variable length format. Cursor is
     * advanced by 1 or 2 bytes.
     *
     * Most significant bit of first byte indicates length of field: 0x00 - 1
     * byte, 0x80 - 2 bytes.
     *
     * @see http://msdn.microsoft.com/en-us/library/cc241612.aspx
     */
    public int readEncodedUnsignedShort() {
        int firstByte = readUnsignedByte();

        int result;
        if ((firstByte & 0x80) == 0)
            result = firstByte & 0x7f;
        else {
            int secondByte = readUnsignedByte();
            result = (((firstByte & 0x7f) << 8) | secondByte);
        }

        return result;
    }

    /**
     * Read signed short in network order in variable length format. Cursor is
     * advanced by 1 or 2 bytes.
     *
     * Most significant bit of first byte indicates length of field: 0x00 - 1
     * byte, 0x80 - 2 bytes. Second most significant bit indicates is value
     * positive or negative.
     *
     * @see http://msdn.microsoft.com/en-us/library/cc241613.aspx
     */
    public int readEncodedSignedShort() {
        int firstByte = readUnsignedByte();

        int result;
        if ((firstByte & 0x80) == 0)
            result = firstByte & 0x3f;
        else {
            int secondByte = readUnsignedByte();
            result = (((firstByte & 0x3f) << 8) | secondByte);
        }

        if ((firstByte & 0x40) > 0)
            return -result;
        else
            return result;
    }

    /**
     * Read signed long in little endian order. Cursor is advanced by 8 bytes.
     */
    public long readSignedLongLE() {
        return ((readSignedIntLE()) & 0xffFFffFFL) | (((long)readSignedIntLE()) << 32);
    }

    /**
     * Read signed long in network order. Cursor is advanced by 8 bytes.
     */
    public long readSignedLong() {
        return (((long)readSignedInt()) << 32) | ((readSignedInt()) & 0xffFFffFFL);
    }

    /**
     * Read string from buffer. Cursor is advanced by string length.
     */
    public String readString(int length, Charset charset) {
        if (cursor + length > this.length)
            throw new ArrayIndexOutOfBoundsException("Cannot read " + length + " bytes from this buffer: " + this + ".");

        String string = new String(data, offset + cursor, length, charset);
        cursor += length;
        return string;
    }

    /**
     * Read string with '\0' character at end.
     */
    public String readVariableString(Charset charset) {

        int start = cursor;

        // Find end of string
        while (readUnsignedByte() != 0) {
        }

        String string = new String(data, offset + start, cursor - start - 1, charset);

        return string;
    }

    /**
     * Read wide string with wide '\0' character at end.
     */
    public String readVariableWideString(Charset charset) {

        int start = cursor;

        // Find end of string
        while (readUnsignedShortLE() != 0) {
        }

        String string = new String(data, offset + start, cursor - start - 2, charset);

        return string;
    }

    /**
     * Get bytes as lightweight slice. Cursor is advanced by data length.
     */
    public ByteBuffer readBytes(int dataLength) {
        if (cursor + dataLength > length)
            throw new ArrayIndexOutOfBoundsException("Cannot read " + dataLength + " bytes from this buffer: " + this + ".");

        ByteBuffer slice = slice(cursor, dataLength, false);
        cursor += dataLength;
        return slice;
    }

    /**
     * Cursor is advanced by given number of bytes.
     */
    public void skipBytes(int numOfBytes) {
        if (cursor + numOfBytes > length)
            throw new ArrayIndexOutOfBoundsException("Cannot read " + numOfBytes + " bytes from this buffer: " + this + ".");

        cursor += numOfBytes;
    }

    /**
     * Write byte. Cursor is advanced by 1.
     */
    public void writeByte(int b) {
        if (cursor + 1 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot write 1 byte to this buffer: " + this + ".");

        data[offset + cursor] = (byte)b;
        cursor += 1;
    }

    /**
     * Write short in network order. Cursor is advanced by 2.
     */
    public void writeShort(int x) {
        if (cursor + 2 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot write 2 bytes to this buffer: " + this + ".");

        data[offset + cursor] = (byte)(x >> 8);
        data[offset + cursor + 1] = (byte)x;
        cursor += 2;
    }

    /**
     * Write short in little endian order. Cursor is advanced by 2.
     */
    public void writeShortLE(int x) {
        if (cursor + 2 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot write 2 bytes to this buffer: " + this + ".");

        data[offset + cursor + 1] = (byte)(x >> 8);
        data[offset + cursor] = (byte)x;
        cursor += 2;
    }

    /**
     * Write int in network order. Cursor is advanced by 4.
     */
    public void writeInt(int i) {
        if (cursor + 4 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot write 4 bytes to this buffer: " + this + ".");

        data[offset + cursor] = (byte)(i >> 24);
        data[offset + cursor + 1] = (byte)(i >> 16);
        data[offset + cursor + 2] = (byte)(i >> 8);
        data[offset + cursor + 3] = (byte)i;
        cursor += 4;
    }

    public void writeIntLE(int i) {
        if (cursor + 4 > length)
            throw new ArrayIndexOutOfBoundsException("Cannot write 4 bytes to this buffer: " + this + ".");

        data[offset + cursor] = (byte)i;
        data[offset + cursor + 1] = (byte)(i >> 8);
        data[offset + cursor + 2] = (byte)(i >> 16);
        data[offset + cursor + 3] = (byte)(i >> 24);
        cursor += 4;
    }

    /**
     * Write int in variable length format. Cursor is advanced by number of bytes
     * written (1-5).
     *
     * Topmost bit of each byte is set to 1 to indicate that next byte has data.
     */
    public void writeVariableIntLE(int i) {
        while (i != 0) {
            // Get lower bits of number
            int b = i & 0x7f;
            i >>= 7;

            if (i > 0)
                // Set topmost bit of byte to indicate that next byte(s) contains
                // remainder bits
                b |= 0x80;

            writeByte(b);
        }
    }

    /**
     * Write short in variable length format. Cursor is advanced by number of
     * bytes written (1-2).
     *
     * Topmost bit of first byte is set to 1 to indicate that next byte has data.
     */
    public void writeVariableShort(int length) {
        if (length > 0x7f | length < 0)
            writeShort(length | 0x8000);
        else
            writeByte(length);
    }

    /**
     * Prepend given data to this byte buffer.
     */
    public void prepend(ByteBuffer buf) {
        prepend(buf.data, buf.offset, buf.length);
    }

    /**
     * Prepend given data to this byte buffer.
     */
    public void prepend(byte[] data) {
        prepend(data, 0, data.length);
    }

    /**
     * Prepend given data to this byte buffer.
     */
    public void prepend(byte[] data, int offset, int length) {
        if (!isSoleOwner()) {
            throw new RuntimeException("Create full copy of this byte buffer data for modification. refCount: " + refCount + ".");
        }

        // If there is no enough space for header to prepend
        if (!(this.offset >= length)) {
            throw new RuntimeException("Reserve data to have enough space for header.");
        }

        // Copy header
        System.arraycopy(data, offset, this.data, this.offset - length, length);

        // Extend byte range to include header
        this.offset -= length;
        this.length += length;
        cursor += length;
    }

    /**
     * Write byte representation of given string, without string terminators (zero
     * or zeroes at end of string).
     */
    public void writeString(String str, Charset charset) {
        writeBytes(str.getBytes(charset));
    }

    /**
     * Write string of fixed size. When string is shorted, empty space is filled
     * with zeros. When string is larger, it is truncated.
     */
    public void writeFixedString(int length, String str, Charset charset) {
        byte[] bytes = str.getBytes(charset);
        writeBytes(bytes, 0, Math.min(bytes.length, length));

        for (int i = bytes.length; i < length; i++)
            writeByte(0);
    }

    public void writeBytes(ByteBuffer buf) {
        writeBytes(buf.data, buf.offset, buf.length);
    }

    public void writeBytes(byte[] bytes) {
        writeBytes(bytes, 0, bytes.length);
    }

    public void writeBytes(byte[] bytes, int offset, int length) {
        System.arraycopy(bytes, offset, data, this.offset + cursor, length);
        cursor += length;
    }

    /**
     * Reduce length of buffer to cursor position.
     */
    public void trimAtCursor() {
        length = cursor;
    }

    /**
     * Rewind cursor to beginning of the buffer.
     */
    public void rewindCursor() {
        cursor = 0;
    }

    /**
     * Read RGB color in LE order. Cursor is advanced by 3.
     *
     * @return color as int, with red in lowest octet.
     */
    public int readRGBColor() {
        return readUnsignedByte() | (readUnsignedByte() << 8) | (readUnsignedByte() << 16);
    }

    public void assertThatBufferIsFullyRead() {
        if (cursor != length)
            throw new RuntimeException("Data in buffer is not read fully. Buf: " + this + ".");
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;

        int end = offset + length;
        for (int i = offset; i < end; i++)
            result = 31 * result + data[i];

        result = prime * result + length;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;

        if (obj == null)
            return false;

        // Does not work in case of anonymous type(s)
        if (getClass() != obj.getClass())
            return false;

        ByteBuffer other = (ByteBuffer)obj;
        if (length != other.length)
            return false;

        for (int i = 0; i < length; i++)
            if (data[offset + i] != other.data[other.offset + i])
                return false;

        return true;
    }

    /**
     * Return length of data left after cursor.
     */
    public int remainderLength() {
        if (length >= cursor)
            return length - cursor;
        else
            throw new RuntimeException("Inconsistent state of buffer: cursor is after end of buffer: " + this + ".");
    }

    public Set<String> getMetadataKeys() {
        if (metadata != null)
            return metadata.keySet();
        else
            return new HashSet<String>(0);
    }

    /**
     * Return unsigned value of byte at given position relative to cursor. Cursor
     * is not advanced.
     */
    public int peekUnsignedByte(int i) {
        return data[offset + cursor + i] & 0xff;
    }

    /**
     * Trim few first bytes.
     */
    public void trimHeader(int length) {
        offset += length;
        this.length -= length;
        rewindCursor();
    }

}
