fujaba/NetworkParser

View on GitHub
src/main/java/de/uniks/networkparser/buffer/ByteBuffer.java

Summary

Maintainability
F
4 days
Test Coverage
package de.uniks.networkparser.buffer;

import java.nio.charset.Charset;

import de.uniks.networkparser.converter.ByteConverter;
import de.uniks.networkparser.converter.ByteConverterHTTP;
import de.uniks.networkparser.converter.ByteConverterString;
import de.uniks.networkparser.interfaces.Converter;

public class ByteBuffer extends BufferedBuffer {
    /** The buffer. */
    protected byte[] buffer;

    @Override
    public char charAt(int index) {
        if (index < 0 || buffer == null || index >= buffer.length) {
            return 0;
        }
        return (char) buffer[index];
    }

    @Override
    public byte byteAt(int index) {
        if (index < 0 || buffer == null || index >= buffer.length) {
            return 0;
        }
        return buffer[index];
    }

    @Override
    public CharacterBuffer subSequence(int start, int end) {
        int len = end - start;
        if (len < 0 || buffer == null) {
            return new CharacterBuffer();
        }
        byte[] sub = new byte[len];
        if (start < buffer.length && len <= buffer.length) {
            for (int i = 0; i < len; i++) {
                sub[i] = buffer[start + i];
            }
        }
        return new CharacterBuffer().with(sub);
    }

    public ByteBuffer withBufferLength(int length) {
        super.withLength(length);
        if (length >= 0) {
            this.buffer = new byte[length];
        }
        return this;
    }

    @Override
    public char getChar() {
        int no = getByte();
        if (no >= 0) {
            return (char) no;
        }
        char result = (char) (no << 8 + (char) getByte());
        return result;
    }

    @Override
    public byte getByte() {
        if (buffer == null || position >= buffer.length - 1) {
            return 0;
        }
        return this.buffer[++position];
    }

    /**
     * Get a Byte Field
     * 
     * @param parameter Null for full, Number Length, or new Byte Array
     * @return a ByteArray
     */
    public byte[] getBytes(Object... parameter) {
        if (buffer == null || position >= buffer.length - 1) {
            return new byte[0];
        }

        int len = length;
        byte[] result = null;
        if (parameter != null && parameter.length > 0) {
            if (parameter[0] instanceof Integer) {
                len = (Integer) parameter[0];
            } else if (parameter[0] instanceof Byte[] || parameter[0] instanceof byte[]) {
                result = (byte[]) parameter[0];
                len = result.length;
            }
        }
        if (result == null) {
            result = new byte[len];
        }
        for (int i = 0; i < len; i++) {
            result[i] = this.buffer[++position];
        }
        return result;
    }

    public byte[] getValue(int start, int len) {
        this.withPosition(start);
        if (len < 0) {
            len = 0;
        }
        byte[] array = new byte[len];
        for (int i = 0; i < len; i++) {
            array[i] = getByte();
        }
        return array;
    }

    public byte[] array() {
        return buffer;
    }

    public boolean add(Object... values) {
        if (values == null) {
            return true;
        }
        for (Object item : values) {
            insert(item, true);
        }
        return true;
    }

    public boolean insert(Object item, boolean bufferAdEnd) {
        if (item instanceof Byte) {
            return addBytes(item, 1, bufferAdEnd);
        }
        if (item instanceof Character) {
            return addBytes((Character) item, 1, bufferAdEnd);
        }
        if (item instanceof String) {
            String str = (String) item;
            byte[] array = str.getBytes();
            return addBytes(array, array.length, bufferAdEnd);
        }
        if (item instanceof CharSequence) {
            CharSequence str = (CharSequence) item;
            resize(str.length(), bufferAdEnd);
            for (int i = 0; i < str.length(); i++) {
                addBytes((Character) str.charAt(i), 1, bufferAdEnd);
            }
            return true;
        }
        if (item instanceof byte[]) {
            byte[] array = (byte[]) item;
            return addBytes(array, array.length, bufferAdEnd);
        }
        if (item instanceof Byte[]) {
            Byte[] array = (Byte[]) item;
            return addBytes(array, array.length, bufferAdEnd);
        }
        if (item instanceof Integer) {
            return addBytes(item, 4, bufferAdEnd);
        }
        if (item instanceof Short) {
            return addBytes(item, 2, bufferAdEnd);
        }
        if (item instanceof Long) {
            return addBytes(item, 8, bufferAdEnd);
        }
        if (item instanceof Boolean) {
            return addBytes(item, 1, bufferAdEnd);
        }
        return false;
    }

    private boolean resize(int len, boolean bufferAtEnd) {
        int bufferLen = 0;
        if (this.buffer != null) {
            bufferLen = this.buffer.length;
        }
        /* Add ad end of Array */
        if (position < 0) {
            /* New Size with Buffer */
            int newSize;
            if (bufferAtEnd) {
                newSize = (length + len) + (length + len) / 2 + 5;
            } else {
                newSize = length + len;
            }
            if (newSize < 0) {
                newSize = 0;
            }
            byte[] oldBuffer = this.buffer;
            this.buffer = new byte[newSize];
            int oldSize = 0;
            if (oldBuffer != null) {
                oldSize = oldBuffer.length;
                if (length > 0) {
                    System.arraycopy(oldBuffer, oldBuffer.length - length, this.buffer, newSize - length, length);
                }
            }
            position += newSize - oldSize;
            return true;
        } else if (position + len > bufferLen) {
            /* New Size with Buffer */
            if (bufferLen > 0) {
                int newSize;
                if (bufferAtEnd) {
                    newSize = (length + len) + (length + len) / 2 + 5;
                } else {
                    newSize = length + len;
                }
                byte[] oldBuffer = this.buffer;
                this.buffer = new byte[newSize];
                System.arraycopy(oldBuffer, 0, this.buffer, 0, position);
            } else {
                this.buffer = new byte[len];
            }
            return true;
        }
        return false;
    }

    public boolean addBytes(Object value, int len, boolean bufferAtEnd) {
        boolean addEnd = false;
        if (this.position == this.length) {
            addEnd = true;
        }
        resize(len, bufferAtEnd);
        /* one Byte */
        if (value instanceof Byte) {
            this.buffer[position] = (Byte) value;
        } else {
            if (value instanceof byte[]) {
                byte[] source = (byte[]) value;
                if (this.buffer != null && this.buffer.length >= position + len) {
                    for (int i = 0; i < len; i++) {
                        this.buffer[position + i] = source[i];
                    }
                }
            } else if (value instanceof Byte[]) {
                Byte[] source = (Byte[]) value;
                if (this.buffer != null && this.buffer.length >= position + len) {
                    for (int i = 0; i < len; i++) {
                        this.buffer[position + i] = source[i];
                    }
                }
            } else if (value instanceof Character) {
                char charItem = (Character) value;
                if (len == 1) {
                    this.buffer[position] = (byte) (charItem);
                } else {
                    this.buffer[position] = (byte) (charItem >>> 8);
                    this.buffer[position + 1] = (byte) charItem;
                }
                /* two Bytes */
            } else if (value instanceof Short) {
                short item = (Short) value;
                this.buffer[position] = (byte) (item >>> 8);
                this.buffer[position + 1] = (byte) item;
                /* four Bytes */
            } else if (value instanceof Integer) { /* value instanceof Float */
                Integer item = (Integer) value;
                this.buffer[position] = (byte) (item >>> 24);
                this.buffer[position + 1] = (byte) (item >>> 16);
                this.buffer[position + 2] = (byte) (item >>> 8);
                this.buffer[position + 3] = (byte) (item & 0xff);
            } else if (value instanceof Long) { /* value instanceof Double */
                Long item = (Long) value;
                this.buffer[position] = (byte) (item >>> 56);
                this.buffer[position + 1] = (byte) (item >>> 48);
                this.buffer[position + 2] = (byte) (item >>> 40);
                this.buffer[position + 3] = (byte) (item >>> 32);
                this.buffer[position + 4] = (byte) (item >>> 24);
                this.buffer[position + 5] = (byte) (item >>> 16);
                this.buffer[position + 6] = (byte) (item >>> 8);
                this.buffer[position + 7] = (byte) (item & 0xff);
            } else if (value instanceof Boolean) { /* value instanceof Float */
                Boolean item = (Boolean) value;
                if (item) {
                    this.buffer[position] = 1;
                } else {
                    this.buffer[position] = 0;
                }
            }
        }
        this.length += len;
        if (addEnd) {
            this.position = this.length;
        }
        return true;
    }

    public boolean put(byte value) {
        if (this.buffer != null && position + 1 <= buffer.length) {
            this.buffer[position++] = value;
            return true;
        }
        return false;
    }

    public boolean put(short value) {
        if (this.buffer != null && position + 2 <= buffer.length) {
            this.buffer[position++] = (byte) (value >>> 8);
            this.buffer[position++] = (byte) value;
            return true;
        }
        return false;
    }

    public boolean put(int value) {
        if (this.buffer != null && position + 4 <= buffer.length) {
            this.buffer[position++] = (byte) (value >>> 24);
            this.buffer[position++] = (byte) (value >>> 16);
            this.buffer[position++] = (byte) (value >>> 8);
            this.buffer[position++] = (byte) value;
            return true;
        }
        return false;
    }

    public boolean put(long value) {
        if (this.buffer != null && position + 8 <= buffer.length) {
            this.buffer[position++] = (byte) (value >>> 56);
            this.buffer[position++] = (byte) (value >>> 48);
            this.buffer[position++] = (byte) (value >>> 40);
            this.buffer[position++] = (byte) (value >>> 32);
            this.buffer[position++] = (byte) (value >>> 24);
            this.buffer[position++] = (byte) (value >>> 16);
            this.buffer[position++] = (byte) (value >>> 8);
            this.buffer[position++] = (byte) value;
            return true;
        }
        return false;
    }

    public boolean put(char value) {
        if (this.buffer != null && position + 2 <= buffer.length) {
            this.buffer[position++] = (byte) (value >>> 8);
            this.buffer[position++] = (byte) value;
            return true;
        }
        return false;
    }

    public boolean put(float value) {
        int bits = Float.floatToIntBits(value);
        if (this.buffer != null && position + 4 <= buffer.length) {
            this.buffer[position++] = (byte) (bits & 0xff);
            this.buffer[position++] = (byte) ((bits >> 8) & 0xff);
            this.buffer[position++] = (byte) ((bits >> 16) & 0xff);
            this.buffer[position++] = (byte) ((bits >> 24) & 0xff);
            return true;
        }
        return false;
    }

    public boolean put(double value) {
        long bits = Double.doubleToLongBits(value);
        if (this.buffer != null && position + 8 <= buffer.length) {
            this.buffer[position++] = (byte) ((bits >> 56) & 0xff);
            this.buffer[position++] = (byte) ((bits >> 48) & 0xff);
            this.buffer[position++] = (byte) ((bits >> 40) & 0xff);
            this.buffer[position++] = (byte) ((bits >> 32) & 0xff);
            this.buffer[position++] = (byte) ((bits >> 24) & 0xff);
            this.buffer[position++] = (byte) ((bits >> 16) & 0xff);
            this.buffer[position++] = (byte) ((bits >> 8) & 0xff);
            this.buffer[position++] = (byte) ((bits >> 0) & 0xff);
            return true;
        }
        return false;
    }

    public boolean put(byte[] value) {
        if (value != null) {
            for (int i = 0; i < value.length; i++) {
                put(value[i]);
            }
            return true;
        }
        return false;
    }

    public void put(byte[] value, int offset, int length) {
        if (value == null || offset < 0 || offset > value.length) {
            return;
        }
        for (int i = 0; i < length; i++) {
            put(value[offset + i]);
        }
    }

    public ByteBuffer flip(boolean preFirst) {
        if (preFirst) {
            this.position = -1;
            return this;
        }
        this.position = 0;
        return this;
    }

    public ByteBuffer getNewBuffer(int capacity) {
        return new ByteBuffer().withBufferLength(capacity);
    }

    public static ByteBuffer allocate(int len) {
        if (len < 1) {
            return null;
        }
        ByteBuffer bytesBuffer = new ByteBuffer();
        bytesBuffer.withBufferLength(len);
        return bytesBuffer;
    }

    public ByteBuffer getNewBuffer(byte[] array) {
        return new ByteBuffer().with(array);
    }

    public ByteBuffer with(CharSequence... string) {
        if (string != null && string.length > 0 && string[0] instanceof String) {
            this.buffer = ((String) string[0]).getBytes(Charset.forName(ENCODING));
            this.position = 0;
            this.length = buffer.length;
        }
        return this;
    }

    public ByteBuffer with(byte[] array) {
        this.buffer = array;
        this.position = 0;
        if (array != null) {
            this.length = array.length;
        } else {
            this.length = 0;
        }
        return this;
    }

    public ByteBuffer with(byte value) {
        if (this.buffer == null) {
            this.buffer = new byte[] { value };
            this.length = 1;
            this.position = 0;
        } else if (this.length < this.buffer.length) {
            this.buffer[length++] = value;
        }
        return this;
    }

    @Override
    public String toString() {
        return toString(new ByteConverterString());
    }

    @Override
    public ByteBuffer getNewList(boolean keyValue) {
        return new ByteBuffer();
    }

    @Override
    public int size() {
        return length();
    }

    public String string() {
        return new String(buffer);
    }

    public String toString(Converter converter) {
        if (converter == null) {
            converter = new ByteConverterHTTP();
        }
        if (converter instanceof ByteConverter) {
            return ((ByteConverter) converter).toString(this.toBytes());
        }
        return String.valueOf(buffer);
    }

    public ByteBuffer with(byte[] array, int len) {
        this.position = 0;
        if (array == null) {
            return this;
        }
        if (len < 0 || len > array.length) {
            len = array.length;
        }
        if (this.buffer == null) {
            this.buffer = array;
            this.length = len;
        } else {
            /* Resize */
            byte[] oldBuffer = this.buffer;
            this.buffer = new byte[this.length * 2 + len];
            System.arraycopy(oldBuffer, 0, this.buffer, 0, this.length);
            System.arraycopy(array, 0, this.buffer, this.length, len);
            this.length += len;
        }
        return this;
    }

    public ByteBuffer with(char[] values, int start, int len) {
        if (values == null || start + length > values.length) {
            return this;
        }
        if (this.length < 0) {
            this.length = this.buffer.length;
        }
        int newLen = length + this.length;
        if (buffer == null || newLen + this.start > buffer.length) {
            byte[] oldValue = this.buffer;
            this.buffer = new byte[(newLen * 2 + 2)];
            if (oldValue != null) {
                System.arraycopy(oldValue, start, this.buffer, 0, this.length);
            }
            this.start = 0;
            this.position = 0;
        }
        System.arraycopy(values, start, this.buffer, this.length, length);
        this.length = newLen;
        return this;
    }

    private int bits = 0;
    private int nextBitMask = 0x100; /* triggers readOctet first time */

    /**
     * Public API - reads a bit/boolean argument.
     * 
     * @return boolean
     */

    public boolean getBit() {
        if (nextBitMask > 0x80) {
            bits = getByte();
            nextBitMask = 0x01;
        }
        boolean result = (bits & nextBitMask) != 0;
        nextBitMask = nextBitMask << 1;
        return result;
    }

    /**
     * Convenience method - reads a short string from a DataInput Stream.
     * 
     * @return a new String
     */
    public String getShortstr() {
        final int contentLength = (int) (getByte() & 0xff);
        byte[] b = getBytes(new byte[contentLength]);
        return new String(b);
    }

    public boolean set(int pos, byte value) {
        if (pos >= 0 && pos <= this.length && this.buffer != null) {
            this.buffer[pos] = value;
            return true;
        }
        return false;
    }

}