io.datty.msgpack.core.AbstractMessageReader.java Source code

Java tutorial

Introduction

Here is the source code for io.datty.msgpack.core.AbstractMessageReader.java

Source

/*
 * Copyright (C) 2016 Datty.io 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 io.datty.msgpack.core;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import org.msgpack.core.MessageFormat;
import org.msgpack.core.MessagePack.Code;

import io.datty.msgpack.support.MessageNumberOverflowException;
import io.datty.msgpack.support.MessageParseException;
import io.netty.buffer.ByteBuf;

/**
 * AbstractMessageReader
 * 
 * @author Alex Shvid
 *
 */

public abstract class AbstractMessageReader {

    public boolean hasNext(ByteBuf buffer) {
        return buffer.readableBytes() > 0;
    }

    public MessageFormat getNextFormat(ByteBuf buffer) {
        return MessageFormat.valueOf(buffer.getByte(buffer.readerIndex()));
    }

    public byte getNextCode(ByteBuf buffer) {
        return buffer.getByte(buffer.readerIndex());
    }

    public void skipBytes(int numberOfBytes, ByteBuf buffer) {
        buffer.skipBytes(numberOfBytes);
    }

    public byte readByte(ByteBuf buffer) {
        return buffer.readByte();
    }

    public short readUnsignedByte(ByteBuf buffer) {
        return (short) (buffer.readByte() & 0xFF);
    }

    public short readShort(ByteBuf buffer) {
        return buffer.readShort();
    }

    public int readUnsignedShort(ByteBuf buffer) {
        return buffer.readShort() & 0xFFFF;
    }

    public int readInt(ByteBuf buffer) {
        return buffer.readInt();
    }

    public long readUnsignedInt(ByteBuf buffer) {
        int u32 = buffer.readInt();
        if (u32 < 0) {
            long l64 = (long) (u32 & 0x7fffffff) + 0x80000000L;
            return l64;
        }
        return u32;
    }

    public long readLong(ByteBuf buffer) {
        return buffer.readLong();
    }

    public long readUnsignedLong(ByteBuf buffer) {
        long u64 = buffer.readLong();
        if (u64 < 0) {
            throw new MessageNumberOverflowException(u64);
        }
        return u64;
    }

    public int readLength8(ByteBuf buffer) {
        return readUnsignedByte(buffer);
    }

    public int readLength16(ByteBuf buffer) {
        return readUnsignedShort(buffer);
    }

    public int readLength32(ByteBuf buffer) {
        long u32 = readUnsignedInt(buffer);
        if (u32 > (long) Integer.MAX_VALUE) {
            throw new MessageNumberOverflowException(u32);
        }
        return (int) u32;
    }

    public float readFloat(ByteBuf buffer) {
        return Float.intBitsToFloat(buffer.readInt());
    }

    public double readDouble(ByteBuf buffer) {
        return Double.longBitsToDouble(buffer.readLong());
    }

    public void skipValue(ByteBuf buffer) {
        skipValue(1, buffer);
    }

    public void skipValue(int count, ByteBuf buffer) {
        while (count > 0) {
            byte b = readByte(buffer);
            MessageFormat f = MessageFormat.valueOf(b);
            switch (f) {
            case POSFIXINT:
            case NEGFIXINT:
            case BOOLEAN:
            case NIL:
                break;
            case FIXMAP: {
                int mapLen = b & 0x0f;
                count += mapLen * 2;
                break;
            }
            case FIXARRAY: {
                int arrayLen = b & 0x0f;
                count += arrayLen;
                break;
            }
            case FIXSTR: {
                int strLen = b & 0x1f;
                skipBytes(strLen, buffer);
                break;
            }
            case INT8:
            case UINT8:
                skipBytes(1, buffer);
                break;
            case INT16:
            case UINT16:
                skipBytes(2, buffer);
                break;
            case INT32:
            case UINT32:
            case FLOAT32:
                skipBytes(4, buffer);
                break;
            case INT64:
            case UINT64:
            case FLOAT64:
                skipBytes(8, buffer);
                break;
            case BIN8:
            case STR8:
                skipBytes(readLength8(buffer), buffer);
                break;
            case BIN16:
            case STR16:
                skipBytes(readLength16(buffer), buffer);
                break;
            case BIN32:
            case STR32:
                skipBytes(readLength32(buffer), buffer);
                break;
            case FIXEXT1:
                skipBytes(2, buffer);
                break;
            case FIXEXT2:
                skipBytes(3, buffer);
                break;
            case FIXEXT4:
                skipBytes(5, buffer);
                break;
            case FIXEXT8:
                skipBytes(9, buffer);
                break;
            case FIXEXT16:
                skipBytes(17, buffer);
                break;
            case EXT8:
                skipBytes(readLength8(buffer) + 1, buffer);
                break;
            case EXT16:
                skipBytes(readLength16(buffer) + 1, buffer);
                break;
            case EXT32:
                skipBytes(readLength32(buffer) + 1, buffer);
                break;
            case ARRAY16:
                count += readLength16(buffer);
                break;
            case ARRAY32:
                count += readLength32(buffer);
                break;
            case MAP16:
                count += readLength16(buffer) * 2;
                break;
            case MAP32:
                count += readLength32(buffer) * 2;
                break;
            case NEVER_USED:
                throw new MessageParseException("never used message format");
            }

            count--;
        }
    }

    public <T> T readNull(ByteBuf buffer) {
        byte b = readByte(buffer);
        if (b == Code.NIL) {
            return null;
        }
        throw new MessageParseException("unexpected null code " + b);
    }

    public boolean readBoolean(ByteBuf buffer) {
        byte b = readByte(buffer);
        if (b == Code.NIL) {
            return false;
        } else if (b == Code.FALSE) {
            return false;
        } else if (b == Code.TRUE) {
            return true;
        }
        throw new MessageParseException("unexpected boolean code " + b);
    }

    public int readVInt(ByteBuf buffer) {
        byte b = readByte(buffer);
        if (Code.isFixInt(b)) {
            return (int) b;
        }
        switch (b) {
        case Code.NIL:
            return 0;
        case Code.UINT8:
            return readUnsignedByte(buffer);
        case Code.UINT16:
            return readUnsignedShort(buffer);
        case Code.UINT32:
            long u32 = readUnsignedInt(buffer);
            if (u32 > (long) Integer.MAX_VALUE) {
                throw new MessageNumberOverflowException(u32);
            }
            return (int) u32;
        case Code.UINT64:
            long u64 = readUnsignedLong(buffer);
            if (u64 > (long) Integer.MAX_VALUE) {
                throw new MessageNumberOverflowException(u64);
            }
            return (int) u64;
        case Code.INT8:
            return readByte(buffer);
        case Code.INT16:
            return readShort(buffer);
        case Code.INT32:
            return readInt(buffer);
        case Code.INT64:
            long i64 = readLong(buffer);
            if (i64 < (long) Integer.MIN_VALUE || i64 > (long) Integer.MAX_VALUE) {
                throw new MessageNumberOverflowException(i64);
            }
            return (int) i64;
        }
        throw new MessageParseException("unexpected int code " + b);
    }

    public long readVLong(ByteBuf buffer) {
        byte b = readByte(buffer);
        if (Code.isFixInt(b)) {
            return (long) b;
        }
        switch (b) {
        case Code.NIL:
            return 0L;
        case Code.UINT8:
            return readUnsignedByte(buffer);
        case Code.UINT16:
            return readUnsignedShort(buffer);
        case Code.UINT32:
            return readUnsignedInt(buffer);
        case Code.UINT64:
            return readUnsignedLong(buffer);
        case Code.INT8:
            return readByte(buffer);
        case Code.INT16:
            return readShort(buffer);
        case Code.INT32:
            return readInt(buffer);
        case Code.INT64:
            return readLong(buffer);
        }
        throw new MessageParseException("unexpected long code " + b);
    }

    public double readVDouble(ByteBuf buffer) {
        byte b = readByte(buffer);
        switch (b) {
        case Code.NIL:
            return 0.0;
        case Code.FLOAT32:
            return (double) readFloat(buffer);
        case Code.FLOAT64:
            return readDouble(buffer);
        }
        throw new MessageParseException("unexpected double code " + b);
    }

    public int readArrayHeader(ByteBuf buffer) {
        byte b = readByte(buffer);
        if (Code.isFixedArray(b)) {
            return b & 0x0f;
        }
        switch (b) {
        case Code.ARRAY16:
            return readLength16(buffer);
        case Code.ARRAY32:
            return readLength32(buffer);
        }
        throw new MessageParseException("unexpected array code " + b);
    }

    public int readMapHeader(ByteBuf buffer) {
        byte b = readByte(buffer);
        if (Code.isFixedMap(b)) {
            return b & 0x0f;
        }
        switch (b) {
        case Code.MAP16:
            return readLength16(buffer);
        case Code.MAP32:
            return readLength32(buffer);
        }
        throw new MessageParseException("unexpected map code " + b);
    }

    private int readBinaryHeader(byte b, ByteBuf buffer) {
        if (Code.isFixedRaw(b)) { // FixRaw
            return b & 0x1f;
        }
        switch (b) {
        case Code.BIN8:
            return readLength8(buffer);
        case Code.BIN16:
            return readLength16(buffer);
        case Code.BIN32:
            return readLength32(buffer);
        default:
            throw new MessageParseException("unexpected binary header code " + b);
        }
    }

    public int readBinaryHeader(ByteBuf buffer) {
        return readBinaryHeader(readByte(buffer), buffer);
    }

    public ByteBuf readBytes(ByteBuf buffer, boolean copy) {
        return readBytes(readByte(buffer), buffer, copy);
    }

    public ByteBuf readBytes(byte b, ByteBuf buffer, boolean copy) {
        int length = readBinaryHeader(b, buffer);
        if (length > buffer.readableBytes()) {
            throw new MessageParseException(
                    "insufficient buffer length: " + buffer.readableBytes() + ", required length: " + length);
        }
        if (copy) {
            ByteBuf dst = buffer.alloc().buffer(length);
            buffer.readBytes(dst, length);
            return dst;
        } else {
            ByteBuf slice = buffer.slice(buffer.readerIndex(), length);
            buffer.readerIndex(buffer.readerIndex() + length);
            return slice;
        }
    }

    private int readStringHeader(byte b, ByteBuf buffer) {
        if (Code.isFixedRaw(b)) { // FixRaw
            return b & 0x1f;
        }
        switch (b) {
        case Code.STR8: // str 8
            return readLength8(buffer);
        case Code.STR16: // str 16
            return readLength16(buffer);
        case Code.STR32: // str 32
            return readLength32(buffer);
        default:
            throw new MessageParseException("unexpected string header code " + b);
        }
    }

    public int readStringHeader(ByteBuf buffer) {
        return readStringHeader(readByte(buffer), buffer);
    }

    public String readString(ByteBuf buffer) {
        return readString(buffer, StandardCharsets.UTF_8);
    }

    public String readString(byte b, ByteBuf buffer) {
        return readString(b, buffer, StandardCharsets.UTF_8);
    }

    public String readString(ByteBuf buffer, Charset charset) {
        return readString(buffer, readStringHeader(buffer), charset);
    }

    public String readString(byte b, ByteBuf buffer, Charset charset) {
        return readString(buffer, readStringHeader(b, buffer), charset);
    }

    public String readAsciiString(ByteBuf source) {
        return readString(source, readBinaryHeader(source), StandardCharsets.US_ASCII);
    }

    public String readAsciiString(byte b, ByteBuf source) {
        return readString(source, readBinaryHeader(b, source), StandardCharsets.US_ASCII);
    }

    public String readString(ByteBuf buffer, int length, Charset charset) {
        if (length > buffer.readableBytes()) {
            throw new MessageParseException(
                    "insufficient buffer length: " + buffer.readableBytes() + ", required length: " + length);
        }
        if (buffer.hasArray()) {
            int start = buffer.readerIndex();
            int baseOffset = buffer.arrayOffset() + start;
            String str = new String(buffer.array(), baseOffset, length, charset);
            buffer.readerIndex(start + length);
            return str;
        } else {
            byte[] bytes = new byte[length];
            buffer.readBytes(bytes);
            return new String(bytes, charset);
        }
    }

}