All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.redkalex.convert.pson.ProtobufReader Maven / Gradle / Ivy

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.redkalex.convert.pson;

import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import org.redkale.convert.*;
import org.redkale.util.*;

/**
 *
 * @author zhangjx
 */
public class ProtobufReader extends Reader {

    protected int position = -1;

    private byte[] content;

    protected int cachetag = Integer.MIN_VALUE;

    public static ObjectPool createPool(int max) {
        return new ObjectPool<>(max, (Object... params) -> new ProtobufReader(), null, (t) -> t.recycle());
    }

    public ProtobufReader() {
    }

    public ProtobufReader(byte[] bytes) {
        setBytes(bytes, 0, bytes.length);
    }

    public ProtobufReader(byte[] bytes, int start, int len) {
        setBytes(bytes, start, len);
    }

    public final void setBytes(byte[] bytes) {
        if (bytes == null) {
            this.position = 0;
        } else {
            setBytes(bytes, 0, bytes.length);
        }
    }

    public final void setBytes(byte[] bytes, int start, int len) {
        if (bytes == null) {
            this.position = 0;
        } else {
            this.content = bytes;
            this.position = start - 1;
        }
    }

    protected boolean recycle() {
        this.position = -1;
        this.content = null;
        return true;
    }

    public void close() {
        this.recycle();
    }

    /**
     * 跳过属性的值
     */
    @Override
    @SuppressWarnings("unchecked")
    public final void skipValue() {
        readTag();
    }

    @Override
    public final String readObjectB(final Class clazz) {
        return "";
    }

    @Override
    public final void readObjectE(final Class clazz) {

    }

    @Override
    public final int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valueDecoder) {
        return Reader.SIGN_NOLENGTH;
    }

    @Override
    public final void readMapE() {
    }

    /**
     * 判断下一个非空白字符是否为[
     *
     * @param member           DeMember
     * @param typevals         byte[]
     * @param componentDecoder Decodeable
     *
     * @return SIGN_NOLENGTH 或 SIGN_NULL
     */
    @Override
    public final int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder) {
        if (member == null || componentDecoder == null) return Reader.SIGN_NOLENBUTBYTES;
        Type type = componentDecoder.getType();
        if (!(type instanceof Class)) return Reader.SIGN_NOLENBUTBYTES;
        Class clazz = (Class) type;
        if (clazz.isPrimitive() || clazz == Boolean.class
            || clazz == Byte.class || clazz == Short.class
            || clazz == Character.class || clazz == Integer.class
            || clazz == Float.class || clazz == Long.class
            || clazz == Double.class) {
            return Reader.SIGN_NOLENBUTBYTES;
        }
        return Reader.SIGN_NOLENGTH;
    }

    @Override
    public final void readArrayE() {
    }

    /**
     * 判断下一个非空白字节是否:
     */
    @Override
    public final void readBlank() {
    }

    @Override
    public final int position() {
        return this.position;
    }

    @Override
    public final int readMemberContentLength(DeMember member, Decodeable decoder) {
        if (member == null && decoder == null) return -1; //为byte[]
        if (member != null && !(member.getDecoder() instanceof ProtobufArrayDecoder)) return -1;
        return readRawVarint32(); //readUInt32
    }

    @Override
    public final DeMember readFieldName(final DeMember[] members) {
        int tag = readTag();
        int pos = tag >>> 3;
        for (DeMember member : members) {
            if (member.getPosition() == pos) {
                return member;
            }
        }
        backTag(tag);
        return null;
    }

    //------------------------------------------------------------
    @Override
    public final boolean readBoolean() {
        return readRawVarint64() != 0;
    }

    @Override
    public final byte readByte() {
        return (byte) readInt();
    }

    @Override
    public final char readChar() {
        return (char) readInt();
    }

    @Override
    public final short readShort() {
        return (short) readInt();
    }

    @Override
    public final int readInt() { //readSInt32
        int n = readRawVarint32();
        return (n >>> 1) ^ -(n & 1);
    }

    @Override
    public final long readLong() { //readSInt64
        long n = readRawVarint64();
        return (n >>> 1) ^ -(n & 1);
    }

    @Override
    public final float readFloat() {
        return Float.intBitsToFloat(readRawLittleEndian32());
    }

    @Override
    public final double readDouble() {
        return Double.longBitsToDouble(readRawLittleEndian64());
    }

    @Override
    public final String readClassName() {
        return "";
    }

    @Override
    public final String readSmallString() {
        return readString();
    }

    @Override
    public final String readString() {
        return new String(readByteArray(), StandardCharsets.UTF_8);
    }

    protected final int readTag() {
        if (cachetag != Integer.MIN_VALUE) {
            int tag = cachetag;
            cachetag = Integer.MIN_VALUE;
            return tag;
        }
        return readRawVarint32();
    }

    protected final void backTag(int tag) {
        this.cachetag = tag;
    }

    protected byte currentByte() {
        return this.content[this.position];
    }

    /**
     * 判断对象是否存在下一个属性或者数组是否存在下一个元素
     *
     * @param startPosition 起始位置
     * @param contentLength 内容大小, 不确定的传-1
     *
     * @return 是否存在
     */
    @Override
    public boolean hasNext(int startPosition, int contentLength) {
        //("-------------: " + startPosition + ", " + contentLength + ", " + this.position);
        if (startPosition >= 0 && contentLength >= 0) {
            return (this.position) < (startPosition + contentLength);
        }
        return (this.position + 1) < this.content.length;
    }

    @Override
    public byte[] readByteArray() {
        final int size = readRawVarint32();
        byte[] bs = new byte[size];
        System.arraycopy(content, position + 1, bs, 0, size);
        position += size;
        return bs;
    }

    protected int readRawVarint32() {  //readUInt32
        fastpath:
        {
            int tempPos = this.position;
            if ((tempPos + 1) == content.length) break fastpath;

            int x;
            if ((x = content[++tempPos]) >= 0) {
                this.position = tempPos;
                return x;
            } else if (content.length - (tempPos + 1) < 9) {
                break fastpath;
            } else if ((x ^= (content[++tempPos] << 7)) < 0) {
                x ^= (~0 << 7);
            } else if ((x ^= (content[++tempPos] << 14)) >= 0) {
                x ^= (~0 << 7) ^ (~0 << 14);
            } else if ((x ^= (content[++tempPos] << 21)) < 0) {
                x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
            } else {
                int y = content[++tempPos];
                x ^= y << 28;
                x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
                if (y < 0
                    && content[++tempPos] < 0
                    && content[++tempPos] < 0
                    && content[++tempPos] < 0
                    && content[++tempPos] < 0
                    && content[++tempPos] < 0) {
                    break fastpath; // Will throw malformedVarint()
                }
            }
            this.position = tempPos;
            return x;
        }
        return (int) readRawVarint64SlowPath();
    }

    protected long readRawVarint64() {
        fastpath:
        {
            int tempPos = this.position;
            if ((tempPos + 1) == content.length) break fastpath;

            long x;
            int y;
            if ((y = content[++tempPos]) >= 0) {
                this.position = tempPos;
                return y;
            } else if (content.length - (tempPos + 1) < 9) {
                break fastpath;
            } else if ((y ^= (content[++tempPos] << 7)) < 0) {
                x = y ^ (~0 << 7);
            } else if ((y ^= (content[++tempPos] << 14)) >= 0) {
                x = y ^ ((~0 << 7) ^ (~0 << 14));
            } else if ((y ^= (content[++tempPos] << 21)) < 0) {
                x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
            } else if ((x = y ^ ((long) content[++tempPos] << 28)) >= 0L) {
                x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
            } else if ((x ^= ((long) content[++tempPos] << 35)) < 0L) {
                x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
            } else if ((x ^= ((long) content[++tempPos] << 42)) >= 0L) {
                x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
            } else if ((x ^= ((long) content[++tempPos] << 49)) < 0L) {
                x ^= (~0L << 7)
                    ^ (~0L << 14)
                    ^ (~0L << 21)
                    ^ (~0L << 28)
                    ^ (~0L << 35)
                    ^ (~0L << 42)
                    ^ (~0L << 49);
            } else {
                x ^= ((long) content[++tempPos] << 56);
                x ^= (~0L << 7)
                    ^ (~0L << 14)
                    ^ (~0L << 21)
                    ^ (~0L << 28)
                    ^ (~0L << 35)
                    ^ (~0L << 42)
                    ^ (~0L << 49)
                    ^ (~0L << 56);
                if (x < 0L) {
                    if (content[++tempPos] < 0L) {
                        break fastpath; // Will throw malformedVarint()
                    }
                }
            }
            this.position = tempPos;
            return x;
        }
        return readRawVarint64SlowPath();
    }

    protected long readRawVarint64SlowPath() {
        long result = 0;
        for (int shift = 0; shift < 64; shift += 7) {
            final byte b = content[++this.position];
            result |= (long) (b & 0x7F) << shift;
            if ((b & 0x80) == 0) return result;
        }
        throw new ConvertException("readRawVarint64SlowPath error");
    }

    protected int readRawLittleEndian32() {
        return ((content[++this.position] & 0xff)
            | ((content[++this.position] & 0xff) << 8)
            | ((content[++this.position] & 0xff) << 16)
            | ((content[++this.position] & 0xff) << 24));
    }

    protected long readRawLittleEndian64() {
        return ((content[++this.position] & 0xffL)
            | ((content[++this.position] & 0xffL) << 8)
            | ((content[++this.position] & 0xffL) << 16)
            | ((content[++this.position] & 0xffL) << 24)
            | ((content[++this.position] & 0xffL) << 32)
            | ((content[++this.position] & 0xffL) << 40)
            | ((content[++this.position] & 0xffL) << 48)
            | ((content[++this.position] & 0xffL) << 56));
    }

    @Override
    public ValueType readType() {
        throw new UnsupportedOperationException("Not supported yet."); 
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy