/* * Copyright 1999-2011 Alibaba Group. * * 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 com.alibaba.dubbo.common.serialize.support.dubbo; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.UTFDataFormatException; import com.alibaba.dubbo.common.serialize.DataInput; /** * Default DataInput impl. * Not thread-safe. * * @author qian.lei */ public class GenericDataInput implements DataInput, GenericDataFlags { private static final String EMPTY_STRING = ""; private static final byte[] EMPTY_BYTES = {}; private final InputStream mInput; private final byte[] mBuffer; private int mRead = 0; private int mPosition = 0; public GenericDataInput(InputStream is) { this(is, 1024); } public GenericDataInput(InputStream is, int buffSize) { mInput = is; mBuffer = new byte[buffSize]; } public boolean readBool() throws IOException { byte b = read0(); switch( b ) { case VARINT_0: return false; case VARINT_1: return true; default: throw new IOException("Tag error, expect BYTE_TRUE|BYTE_FALSE, but get " + b); } } public byte readByte() throws IOException { byte b = read0(); switch( b ) { case VARINT8: return read0(); case VARINT_0: return 0; case VARINT_1: return 1; case VARINT_2: return 2; case VARINT_3: return 3; case VARINT_4: return 4; case VARINT_5: return 5; case VARINT_6: return 6; case VARINT_7: return 7; case VARINT_8: return 8; case VARINT_9: return 9; case VARINT_A: return 10; case VARINT_B: return 11; case VARINT_C: return 12; case VARINT_D: return 13; case VARINT_E: return 14; case VARINT_F: return 15; case VARINT_10: return 16; case VARINT_11: return 17; case VARINT_12: return 18; case VARINT_13: return 19; case VARINT_14: return 20; case VARINT_15: return 21; case VARINT_16: return 22; case VARINT_17: return 23; case VARINT_18: return 24; case VARINT_19: return 25; case VARINT_1A: return 26; case VARINT_1B: return 27; case VARINT_1C: return 28; case VARINT_1D: return 29; case VARINT_1E: return 30; case VARINT_1F: return 31; default: throw new IOException("Tag error, expect VARINT, but get " + b); } } public short readShort() throws IOException { return (short)readVarint32(); } public int readInt() throws IOException { return readVarint32(); } public long readLong() throws IOException { return readVarint64(); } public float readFloat() throws IOException { return Float.intBitsToFloat(readVarint32()); } public double readDouble() throws IOException { return Double.longBitsToDouble(readVarint64()); } public String readUTF() throws IOException { byte b = read0(); switch( b ) { case OBJECT_BYTES: int len = readUInt(); StringBuilder sb = new StringBuilder(); for(int i=0;i<len;i++) { byte b1 = read0(); if( (b1 & 0x80) == 0 ) { sb.append((char)b1); } else if( (b1 & 0xE0) == 0xC0 ) { byte b2 = read0(); sb.append((char)(((b1 & 0x1F) << 6) | (b2 & 0x3F))); } else if( (b1 & 0xF0) == 0xE0 ) { byte b2 = read0(), b3 = read0(); sb.append((char)(((b1 & 0x0F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F))); } else throw new UTFDataFormatException("Bad utf-8 encoding at " + b1); } return sb.toString(); case OBJECT_NULL: return null; case OBJECT_DUMMY: return EMPTY_STRING; default: throw new IOException("Tag error, expect BYTES|BYTES_NULL|BYTES_EMPTY, but get " + b); } } public byte[] readBytes() throws IOException { byte b = read0(); switch( b ) { case OBJECT_BYTES: return read0(readUInt()); case OBJECT_NULL: return null; case OBJECT_DUMMY: return EMPTY_BYTES; default: throw new IOException("Tag error, expect BYTES|BYTES_NULL|BYTES_EMPTY, but get " + b); } } public int readUInt() throws IOException { byte tmp = read0(); if( tmp < 0 ) return tmp & 0x7f; int ret = tmp & 0x7f; if( ( tmp = read0() ) < 0 ) { ret |= ( tmp & 0x7f ) << 7; } else { ret |= tmp << 7; if( ( tmp = read0() ) < 0 ) { ret |= ( tmp & 0x7f ) << 14; } else { ret |= tmp << 14; if( ( tmp = read0() ) < 0 ) { ret |= ( tmp & 0x7f ) << 21; } else { ret |= tmp << 21; ret |= ( read0() & 0x7f ) << 28; } } } return ret; } protected byte read0() throws IOException { if( mPosition == mRead ) fillBuffer(); return mBuffer[mPosition++]; } protected byte[] read0(int len) throws IOException { int rem = mRead - mPosition; byte[] ret = new byte[len]; if( len <= rem ) { System.arraycopy(mBuffer, mPosition, ret, 0, len); mPosition += len; } else { System.arraycopy(mBuffer, mPosition, ret, 0, rem); mPosition = mRead; len -= rem; int read, pos = rem; while( len > 0 ) { read = mInput.read(ret, pos, len); if( read == -1 ) throw new EOFException(); pos += read; len -= read; } } return ret; } private int readVarint32() throws IOException { byte b = read0(); switch( b ) { case VARINT8: return read0(); case VARINT16: { byte b1 = read0(), b2 = read0(); return (short)( ( b1 & 0xff ) | ( ( b2 & 0xff ) << 8 ) ); } case VARINT24: { byte b1 = read0(), b2 = read0(), b3 = read0(); int ret = ( b1 & 0xff ) | ( ( b2 & 0xff ) << 8 ) | ( ( b3 & 0xff ) << 16 ); if( b3 < 0 ) return ret | 0xff000000; return ret; } case VARINT32: { byte b1 = read0(), b2 = read0(), b3 = read0(), b4 = read0(); return ( ( b1 & 0xff ) | ( ( b2 & 0xff ) << 8 ) | ( ( b3 & 0xff ) << 16 ) | ( ( b4 & 0xff ) << 24 ) ); } case VARINT_NF: return -15; case VARINT_NE: return -14; case VARINT_ND: return -13; case VARINT_NC: return -12; case VARINT_NB: return -11; case VARINT_NA: return -10; case VARINT_N9: return -9; case VARINT_N8: return -8; case VARINT_N7: return -7; case VARINT_N6: return -6; case VARINT_N5: return -5; case VARINT_N4: return -4; case VARINT_N3: return -3; case VARINT_N2: return -2; case VARINT_N1: return -1; case VARINT_0: return 0; case VARINT_1: return 1; case VARINT_2: return 2; case VARINT_3: return 3; case VARINT_4: return 4; case VARINT_5: return 5; case VARINT_6: return 6; case VARINT_7: return 7; case VARINT_8: return 8; case VARINT_9: return 9; case VARINT_A: return 10; case VARINT_B: return 11; case VARINT_C: return 12; case VARINT_D: return 13; case VARINT_E: return 14; case VARINT_F: return 15; case VARINT_10: return 16; case VARINT_11: return 17; case VARINT_12: return 18; case VARINT_13: return 19; case VARINT_14: return 20; case VARINT_15: return 21; case VARINT_16: return 22; case VARINT_17: return 23; case VARINT_18: return 24; case VARINT_19: return 25; case VARINT_1A: return 26; case VARINT_1B: return 27; case VARINT_1C: return 28; case VARINT_1D: return 29; case VARINT_1E: return 30; case VARINT_1F: return 31; default: throw new IOException("Tag error, expect VARINT, but get " + b); } } private long readVarint64() throws IOException { byte b = read0(); switch( b ) { case VARINT8: return read0(); case VARINT16: { byte b1 = read0(), b2 = read0(); return (short)( ( b1 & 0xff ) | ( ( b2 & 0xff ) << 8 ) ); } case VARINT24: { byte b1 = read0(), b2 = read0(), b3 = read0(); int ret = ( b1 & 0xff ) | ( ( b2 & 0xff ) << 8 ) | ( ( b3 & 0xff ) << 16 ); if( b3 < 0 ) return ret | 0xff000000; return ret; } case VARINT32: { byte b1 = read0(), b2 = read0(), b3 = read0(), b4 = read0(); return ( ( b1 & 0xff ) | ( ( b2 & 0xff ) << 8 ) | ( ( b3 & 0xff ) << 16 ) | ( ( b4 & 0xff ) << 24 ) ); } case VARINT40: { byte b1 = read0(), b2 = read0(), b3 = read0(), b4 = read0(), b5 = read0(); long ret = ( (long)b1 & 0xff ) | ( ( (long)b2 & 0xff ) << 8 ) | ( ( (long)b3 & 0xff ) << 16 ) | ( ( (long)b4 & 0xff ) << 24 ) | ( ( (long)b5 & 0xff ) << 32 ); if( b5 < 0 ) return ret | 0xffffff0000000000l; return ret; } case VARINT48: { byte b1 = read0(), b2 = read0(), b3 = read0(), b4 = read0(), b5 = read0(), b6 = read0(); long ret = ( (long)b1 & 0xff ) | ( ( (long)b2 & 0xff ) << 8 ) | ( ( (long)b3 & 0xff ) << 16 ) | ( ( (long)b4 & 0xff ) << 24 ) | ( ( (long)b5 & 0xff ) << 32 ) | ( ( (long)b6 & 0xff ) << 40 ); if( b6 < 0 ) return ret | 0xffff000000000000l; return ret; } case VARINT56: { byte b1 = read0(), b2 = read0(), b3 = read0(), b4 = read0(), b5 = read0(), b6 = read0(), b7 = read0(); long ret = ( (long)b1 & 0xff ) | ( ( (long)b2 & 0xff ) << 8 ) | ( ( (long)b3 & 0xff ) << 16 ) | ( ( (long)b4 & 0xff ) << 24 ) | ( ( (long)b5 & 0xff ) << 32 ) | ( ( (long)b6 & 0xff ) << 40 ) | ( ( (long)b7 & 0xff ) << 48 ); if( b7 < 0 ) return ret | 0xff00000000000000l; return ret; } case VARINT64: { byte b1 = read0(), b2 = read0(), b3 = read0(), b4 = read0(); byte b5 = read0(), b6 = read0(), b7 = read0(), b8 = read0(); return ( ( (long)b1 & 0xff ) | ( ( (long)b2 & 0xff ) << 8 ) | ( ( (long)b3 & 0xff ) << 16 ) | ( ( (long)b4 & 0xff ) << 24 ) | ( ( (long)b5 & 0xff ) << 32 ) | ( ( (long)b6 & 0xff ) << 40 ) | ( ( (long)b7 & 0xff ) << 48 ) | ( ( (long)b8 & 0xff ) << 56 ) ); } case VARINT_NF: return -15; case VARINT_NE: return -14; case VARINT_ND: return -13; case VARINT_NC: return -12; case VARINT_NB: return -11; case VARINT_NA: return -10; case VARINT_N9: return -9; case VARINT_N8: return -8; case VARINT_N7: return -7; case VARINT_N6: return -6; case VARINT_N5: return -5; case VARINT_N4: return -4; case VARINT_N3: return -3; case VARINT_N2: return -2; case VARINT_N1: return -1; case VARINT_0: return 0; case VARINT_1: return 1; case VARINT_2: return 2; case VARINT_3: return 3; case VARINT_4: return 4; case VARINT_5: return 5; case VARINT_6: return 6; case VARINT_7: return 7; case VARINT_8: return 8; case VARINT_9: return 9; case VARINT_A: return 10; case VARINT_B: return 11; case VARINT_C: return 12; case VARINT_D: return 13; case VARINT_E: return 14; case VARINT_F: return 15; case VARINT_10: return 16; case VARINT_11: return 17; case VARINT_12: return 18; case VARINT_13: return 19; case VARINT_14: return 20; case VARINT_15: return 21; case VARINT_16: return 22; case VARINT_17: return 23; case VARINT_18: return 24; case VARINT_19: return 25; case VARINT_1A: return 26; case VARINT_1B: return 27; case VARINT_1C: return 28; case VARINT_1D: return 29; case VARINT_1E: return 30; case VARINT_1F: return 31; default: throw new IOException("Tag error, expect VARINT, but get " + b); } } private void fillBuffer() throws IOException { mPosition = 0; mRead = mInput.read(mBuffer); if( mRead == -1 ) { mRead = 0; throw new EOFException(); } } }