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

hprose.io.unserialize.Reader Maven / Gradle / Ivy

/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * HproseReader.java                                      *
 *                                                        *
 * hprose reader class for Java.                          *
 *                                                        *
 * LastModified: Nov 12, 2017                             *
 * Author: Ma Bingyao                   *
 *                                                        *
\**********************************************************/
package hprose.io.unserialize;

import hprose.common.HproseException;
import hprose.io.ByteBufferStream;
import hprose.io.HproseClassManager;
import hprose.io.HproseMode;
import static hprose.io.HproseTags.TagBytes;
import static hprose.io.HproseTags.TagClass;
import static hprose.io.HproseTags.TagDate;
import static hprose.io.HproseTags.TagDouble;
import static hprose.io.HproseTags.TagEmpty;
import static hprose.io.HproseTags.TagError;
import static hprose.io.HproseTags.TagFalse;
import static hprose.io.HproseTags.TagGuid;
import static hprose.io.HproseTags.TagInfinity;
import static hprose.io.HproseTags.TagInteger;
import static hprose.io.HproseTags.TagList;
import static hprose.io.HproseTags.TagLong;
import static hprose.io.HproseTags.TagMap;
import static hprose.io.HproseTags.TagNaN;
import static hprose.io.HproseTags.TagNull;
import static hprose.io.HproseTags.TagObject;
import static hprose.io.HproseTags.TagOpenbrace;
import static hprose.io.HproseTags.TagRef;
import static hprose.io.HproseTags.TagString;
import static hprose.io.HproseTags.TagTime;
import static hprose.io.HproseTags.TagTrue;
import static hprose.io.HproseTags.TagUTF8Char;
import hprose.io.convert.DefaultConverter;
import hprose.util.ClassUtil;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.UUID;

interface ReaderRefer {
    void set(Object obj);
    Object read(int index);
    void reset();
}

final class FakeReaderRefer implements ReaderRefer {
    public final void set(Object obj) {}
    public final Object read(int index) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public final void reset() {}
}

final class RealReaderRefer implements ReaderRefer {
    private final ArrayList ref = new ArrayList();
    public final void set(Object obj) { ref.add(obj); }
    public final Object read(int index) { return ref.get(index); }
    public final void reset() { ref.clear(); }
}

public class Reader {

    public final InputStream stream;
    final HproseMode mode;
    final ArrayList classref = new ArrayList();
    final IdentityHashMap membersref = new IdentityHashMap();
    final ReaderRefer refer;

    public Reader(InputStream stream) {
        this(stream, HproseMode.MemberMode, false);
    }

    public Reader(InputStream stream, boolean simple) {
        this(stream, HproseMode.MemberMode, simple);
    }

    public Reader(InputStream stream, HproseMode mode) {
        this(stream, mode, false);
    }

    public Reader(InputStream stream, HproseMode mode, boolean simple) {
        this.stream = stream;
        this.mode = mode;
        this.refer = simple ? new FakeReaderRefer() : new RealReaderRefer();
    }

    public Reader(ByteBuffer buffer) {
        this(buffer, HproseMode.MemberMode, false);
    }

    public Reader(ByteBuffer buffer, boolean simple) {
        this(buffer, HproseMode.MemberMode, simple);
    }

    public Reader(ByteBuffer buffer, HproseMode mode) {
        this(buffer, mode, false);
    }

    public Reader(ByteBuffer buffer, HproseMode mode, boolean simple) {
        this(new ByteBufferStream(buffer).getInputStream(), mode, simple);
    }

    public Reader(byte[] bytes) {
        this(bytes, HproseMode.MemberMode, false);
    }

    public Reader(byte[] bytes, boolean simple) {
        this(bytes, HproseMode.MemberMode, simple);
    }

    public Reader(byte[] bytes, HproseMode mode) {
        this(bytes, mode, false);
    }

    public Reader(byte[] bytes, HproseMode mode, boolean simple) {
        this(new ByteArrayInputStream(bytes), mode, simple);
    }

    public final HproseException unexpectedTag(int tag) {
        return unexpectedTag(tag, null);
    }

    public final HproseException unexpectedTag(int tag, String expectTags) {
        if (tag == -1) {
            return new HproseException("No byte found in stream");
        }
        else if (expectTags == null) {
            return new HproseException("Unexpected serialize tag '" +
                                       (char)tag + "' in stream");
        }
        else {
            return new HproseException("Tag '" + expectTags +
                                       "' expected, but '" + (char)tag +
                                       "' found in stream");
        }
    }

    public final void checkTag(int tag, int expectTag) throws HproseException {
        if (tag != expectTag) {
            throw unexpectedTag(tag, new String(new char[] {(char)expectTag}));
        }
    }

    public final void checkTag(int expectTag) throws IOException {
        checkTag(stream.read(), expectTag);
    }

    public final int checkTags(int tag, String expectTags) throws IOException {
        if (expectTags.indexOf(tag) == -1) {
            throw unexpectedTag(tag, expectTags);
        }
        return tag;
    }

    public final int checkTags(String expectTags) throws IOException {
        return checkTags(stream.read(), expectTags);
    }

    public final void skip(int tag) throws IOException {
        int c = stream.read();
        assert c == tag : "Tag '" + (char)tag +
                          "' expected, but '" + (char)c +
                          "' found in stream";
    }

    public final byte readByte(int tag) throws IOException {
        return (byte) ValueReader.readInt(this, tag);
    }

    public final short readShort(int tag) throws IOException {
        return (short) ValueReader.readInt(this, tag);
    }

    public final int readInt(int tag) throws IOException {
        return ValueReader.readInt(this, tag);
    }

    public final long readLong(int tag) throws IOException {
        return ValueReader.readLong(this, tag);
    }

    public final int readIntWithoutTag() throws IOException {
        return ValueReader.readInt(this);
    }

    public final BigInteger readBigIntegerWithoutTag() throws IOException {
        return ValueReader.readBigInteger(this);
    }

    public final long readLongWithoutTag() throws IOException {
        return ValueReader.readInt(this);
    }

    public final double readDoubleWithoutTag() throws IOException {
        return ValueReader.readDouble(this);
    }

    public final double readInfinityWithoutTag() throws IOException {
        return ValueReader.readInfinity(this);
    }

    public final Calendar readDateWithoutTag()throws IOException {
        return ReferenceReader.readDateTime(this).toCalendar();
    }

    public final Calendar readTimeWithoutTag()throws IOException {
        return ReferenceReader.readTime(this).toCalendar();
    }

    public final byte[] readBytesWithoutTag() throws IOException {
        return ReferenceReader.readBytes(this);
    }

    public final String readUTF8CharWithoutTag() throws IOException {
        return ValueReader.readUTF8Char(this);
    }

    public final String readStringWithoutTag() throws IOException {
        return ReferenceReader.readString(this);
    }

    public final char[] readCharsWithoutTag() throws IOException {
        return ReferenceReader.readChars(this);
    }

    public final UUID readUUIDWithoutTag() throws IOException {
        return ReferenceReader.readUUID(this);
    }

    public final ArrayList readListWithoutTag() throws IOException {
        return ReferenceReader.readArrayList(this);
    }

    public final HashMap readMapWithoutTag() throws IOException {
        return ReferenceReader.readHashMap(this);
    }

    public final Object readObjectWithoutTag(Type type) throws IOException {
        return ReferenceReader.readObject(this, type);
    }

    public final Object unserialize() throws IOException {
        return DefaultUnserializer.instance.read(this);
    }

    public final boolean readBoolean() throws IOException {
        return BooleanUnserializer.instance.read(this);
    }

    public final Boolean readBooleanObject() throws IOException {
        return BooleanObjectUnserializer.instance.read(this);
    }

    public final char readChar() throws IOException {
        return CharUnserializer.instance.read(this);
    }

    public final Character readCharObject() throws IOException {
        return CharObjectUnserializer.instance.read(this);
    }

    public final byte readByte() throws IOException {
        return ByteUnserializer.instance.read(this);
    }

    public final Byte readByteObject() throws IOException {
        return ByteObjectUnserializer.instance.read(this);
    }

    public final short readShort() throws IOException {
        return ShortUnserializer.instance.read(this);
    }

    public final Short readShortObject() throws IOException {
        return ShortObjectUnserializer.instance.read(this);
    }

    public final int readInt() throws IOException {
        return IntUnserializer.instance.read(this);
    }

    public final Integer readIntObject() throws IOException {
        return IntObjectUnserializer.instance.read(this);
    }

    public final long readLong() throws IOException {
        return LongUnserializer.instance.read(this);
    }

    public final Long readLongObject() throws IOException {
        return LongObjectUnserializer.instance.read(this);
    }

    public final float readFloat() throws IOException {
        return FloatUnserializer.instance.read(this);
    }

    public final Float readFloatObject() throws IOException {
        return FloatObjectUnserializer.instance.read(this);
    }

    public final double readDouble() throws IOException {
        return DoubleUnserializer.instance.read(this);
    }

    public final Double readDoubleObject() throws IOException {
        return DoubleObjectUnserializer.instance.read(this);
    }

    @SuppressWarnings({"unchecked"})
    public final > T readEnum(Class type) throws IOException {
        return (T) EnumUnserializer.instance.read(this, type);
    }

    public final String readString() throws IOException {
        return StringUnserializer.instance.read(this);
    }

    public final BigInteger readBigInteger() throws IOException {
        return BigIntegerUnserializer.instance.read(this);
    }

    public final Date readDate() throws IOException {
        return DateUnserializer.instance.read(this);
    }

    public final Time readTime() throws IOException {
        return TimeUnserializer.instance.read(this);
    }

    public final java.util.Date readDateTime() throws IOException {
        return DateTimeUnserializer.instance.read(this);
    }

    public final Timestamp readTimestamp() throws IOException {
        return TimestampUnserializer.instance.read(this);
    }

    public final Calendar readCalendar() throws IOException {
        return CalendarUnserializer.instance.read(this);
    }

    public final BigDecimal readBigDecimal() throws IOException {
        return BigDecimalUnserializer.instance.read(this);
    }

    public final StringBuilder readStringBuilder() throws IOException {
        return StringBuilderUnserializer.instance.read(this);
    }

    public final StringBuffer readStringBuffer() throws IOException {
        return StringBufferUnserializer.instance.read(this);
    }

    public final UUID readUUID() throws IOException  {
        return UUIDUnserializer.instance.read(this);
    }

    public final void readArray(Type[] types, Object[] a, int count) throws IOException {
        ReferenceReader.readArray(this, types, a, count);
    }

    public final Object[] readArray(int count) throws IOException {
        return ReferenceReader.readArray(this, count);
    }

    public final Object[] readObjectArray() throws IOException {
        return ObjectArrayUnserializer.instance.read(this);
    }

    public final boolean[] readBooleanArray() throws IOException {
        return BooleanArrayUnserializer.instance.read(this);
    }

    public final char[] readCharArray() throws IOException {
        return CharArrayUnserializer.instance.read(this);
    }

    public final byte[] readByteArray() throws IOException {
        return ByteArrayUnserializer.instance.read(this);
    }

    public final short[] readShortArray() throws IOException {
        return ShortArrayUnserializer.instance.read(this);
    }

    public final int[] readIntArray() throws IOException {
        return IntArrayUnserializer.instance.read(this);
    }

    public final long[] readLongArray() throws IOException {
        return LongArrayUnserializer.instance.read(this);
    }

    public final float[] readFloatArray() throws IOException {
        return FloatArrayUnserializer.instance.read(this);
    }

    public final double[] readDoubleArray() throws IOException {
        return DoubleArrayUnserializer.instance.read(this);
    }

    public final String[] readStringArray() throws IOException {
        return StringArrayUnserializer.instance.read(this);
    }

    public final BigInteger[] readBigIntegerArray() throws IOException {
        return BigIntegerArrayUnserializer.instance.read(this);
    }

    public final Date[] readDateArray() throws IOException {
        return DateArrayUnserializer.instance.read(this);
    }

    public final Time[] readTimeArray() throws IOException {
        return TimeArrayUnserializer.instance.read(this);
    }

    public final Timestamp[] readTimestampArray() throws IOException {
        return TimestampArrayUnserializer.instance.read(this);
    }

    public final java.util.Date[] readDateTimeArray() throws IOException {
        return DateTimeArrayUnserializer.instance.read(this);
    }

    public final Calendar[] readCalendarArray() throws IOException {
        return CalendarArrayUnserializer.instance.read(this);
    }

    public final BigDecimal[] readBigDecimalArray() throws IOException {
        return BigDecimalArrayUnserializer.instance.read(this);
    }

    public final StringBuilder[] readStringBuilderArray() throws IOException {
        return StringBuilderArrayUnserializer.instance.read(this);
    }

    public final StringBuffer[] readStringBufferArray() throws IOException {
        return StringBufferArrayUnserializer.instance.read(this);
    }

    public final UUID[] readUUIDArray() throws IOException {
        return UUIDArrayUnserializer.instance.read(this);
    }

    public final char[][] readCharsArray() throws IOException {
        return CharsArrayUnserializer.instance.read(this);
    }

    public final byte[][] readBytesArray() throws IOException {
        return BytesArrayUnserializer.instance.read(this);
    }

    public final Object unserialize(Type type) throws IOException {
        if (type == null) {
            return DefaultUnserializer.instance.read(this);
        }
        Class cls = ClassUtil.toClass(type);
        return UnserializerFactory.get(cls).read(this, stream.read(), type);
    }

    @SuppressWarnings({"unchecked"})
    public final  T unserialize(Class type) throws IOException {
        return (T) unserialize((Type) type);
    }

    public final Object readRef() throws IOException {
        return refer.read(ValueReader.readInt(this));
    }

    @SuppressWarnings({"unchecked"})
    public final  T readRef(Type type) throws IOException {
        return (T) DefaultConverter.instance.convertTo(readRef(), type);
    }

    public void setRef(Object obj) {
        refer.set(obj);
    }

    public void readClass() throws IOException {
        String className = ValueReader.readString(this);
        int count = ValueReader.readCount(this);
        String[] memberNames = new String[count];
        StringUnserializer unserialize = StringUnserializer.instance;
        for (int i = 0; i < count; ++i) {
            memberNames[i] = unserialize.read(this, stream.read(), String.class);
        }
        stream.read();
        Class cls = HproseClassManager.getClass(className);
        Object key = (cls == null || void.class.equals(cls)) ? new Object() : cls;
        classref.add(key);
        membersref.put(key, memberNames);
    }

    public Object readClassRef() throws IOException {
        return classref.get(ValueReader.readInt(this, TagOpenbrace));
    }

    public String[] getMemberNames(Object cr) {
        return membersref.get(cr);
    }

    public String[] readMemberNames() throws IOException {
        return getMemberNames(readClassRef());
    }

    public final String tagToString(int tag) throws IOException {
        switch (tag) {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            case TagInteger: return "Integer";
            case TagLong: return "BigInteger";
            case TagDouble: return "Double";
            case TagNull: return "Null";
            case TagEmpty: return "Empty String";
            case TagTrue: return "Boolean True";
            case TagFalse: return "Boolean False";
            case TagNaN: return "NaN";
            case TagInfinity: return "Infinity";
            case TagDate: return "DateTime";
            case TagTime: return "DateTime";
            case TagBytes: return "Byte[]";
            case TagUTF8Char: return "Char";
            case TagString: return "String";
            case TagGuid: return "Guid";
            case TagList: return "IList";
            case TagMap: return "IDictionary";
            case TagClass: return "Class";
            case TagObject: return "Object";
            case TagRef: return "Object Reference";
            case TagError: throw new HproseException(readString());
            default: throw unexpectedTag(tag);
        }
    }

    public final ByteBufferStream readRaw() throws IOException {
    	ByteBufferStream rawstream = new ByteBufferStream();
    	readRaw(rawstream.getOutputStream());
        rawstream.flip();
    	return rawstream;
    }

    public final void readRaw(OutputStream ostream) throws IOException {
        RawReader.readRaw(stream, ostream, stream.read());
    }

    public final void reset() {
        refer.reset();
        classref.clear();
        membersref.clear();
    }
}