/**********************************************************\
| |
| hprose |
| |
| Official WebSite: http://www.hprose.com/ |
| http://www.hprose.org/ |
| |
\**********************************************************/
/**********************************************************\
* *
* HproseReader.java *
* *
* hprose reader class for Java. *
* *
* LastModified: Feb 8, 2014 *
* Author: Ma Bingyao <andot@hprose.com> *
* *
\**********************************************************/
package hprose.io;
import hprose.common.HproseException;
import hprose.common.UUID;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.AbstractCollection;
import java.util.AbstractList;
import java.util.AbstractMap;
import java.util.AbstractSequentialList;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.Stack;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
public final class HproseReader {
public final InputStream stream;
private final List ref = new ArrayList();
private final List classref = new ArrayList();
private final HashMap propertyref = new HashMap();
public HproseReader(InputStream stream) {
this.stream = stream;
}
public Object unserialize() throws IOException {
return unserialize(stream.read(), null);
}
public Object unserialize(Class type) throws IOException {
return unserialize(stream.read(), type);
}
private Object unserialize(int tag, Class type) throws IOException {
switch (tag) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return readDigit(tag, type);
case HproseTags.TagInteger:
return readInteger(type);
case HproseTags.TagLong:
return readLong(type);
case HproseTags.TagDouble:
return readDouble(type);
case HproseTags.TagNull:
return null;
case HproseTags.TagEmpty:
return readEmpty(type);
case HproseTags.TagTrue:
return readTrue(type);
case HproseTags.TagFalse:
return readFalse(type);
case HproseTags.TagNaN:
return readNaN(type);
case HproseTags.TagInfinity:
return readInfinity(type);
case HproseTags.TagDate:
return readDate(false, type);
case HproseTags.TagTime:
return readTime(false, type);
case HproseTags.TagBytes:
return readBytes(type);
case HproseTags.TagUTF8Char:
return readUTF8Char(type);
case HproseTags.TagString:
return readString(false, type);
case HproseTags.TagGuid:
return readUUID(false, type);
case HproseTags.TagList:
return readList(false, type);
case HproseTags.TagMap:
return readMap(false, type);
case HproseTags.TagClass:
readClass();
return unserialize(stream.read(), type);
case HproseTags.TagObject:
return readObject(false, type);
case HproseTags.TagRef:
return readRef(type);
case HproseTags.TagError:
throw new HproseException((String)readString());
case -1:
throw new HproseException("No byte found in stream");
}
throw new HproseException("Unexpected serialize tag '" +
(char) tag + "' in stream");
}
private Object readDigit(int tag, Class type) throws IOException {
if ((type == null) ||
Integer.class.equals(type) ||
Object.class.equals(type)) {
return HproseHelper.valueOf((int)(tag - '0'));
}
if (Byte.class.equals(type)) {
return HproseHelper.valueOf((byte)(tag - '0'));
}
if (Long.class.equals(type)) {
return HproseHelper.valueOf((long)(tag - '0'));
}
if (Short.class.equals(type)) {
return HproseHelper.valueOf((short)(tag - '0'));
}
if (Float.class.equals(type)) {
return HproseHelper.valueOf((float)(tag - '0'));
}
if (Double.class.equals(type)) {
return HproseHelper.valueOf((double)(tag - '0'));
}
if (BigInteger.class.equals(type)) {
return BigInteger.valueOf((long)(tag - '0'));
}
if (BigDecimal.class.equals(type)) {
return BigDecimal.valueOf((long)(tag - '0'));
}
if (String.class.equals(type)) {
return String.valueOf((char)tag);
}
if (Character.class.equals(type)) {
return HproseHelper.valueOf((char)tag);
}
if (Boolean.class.equals(type)) {
return HproseHelper.valueOf(tag != '0');
}
if (Calendar.class.equals(type)) {
Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
calendar.setTime(new Date((long)(tag - '0')));
return calendar;
}
if (Date.class.equals(type)) {
return new Date((long)(tag - '0'));
}
return castError("Integer", type);
}
private Object readInteger(Class type) throws IOException {
if ((type == null) ||
Integer.class.equals(type) ||
Object.class.equals(type)) {
return new Integer(readInt(HproseTags.TagSemicolon));
}
if (Byte.class.equals(type)) {
return new Byte(readByte(HproseTags.TagSemicolon));
}
if (Long.class.equals(type)) {
return new Long(readLong(HproseTags.TagSemicolon));
}
if (Short.class.equals(type)) {
return new Short(readShort(HproseTags.TagSemicolon));
}
if (Float.class.equals(type)) {
return Float.valueOf(readUntil(HproseTags.TagSemicolon));
}
if (Double.class.equals(type)) {
return Double.valueOf(readUntil(HproseTags.TagSemicolon));
}
if (BigInteger.class.equals(type)) {
return new BigInteger(readUntil(HproseTags.TagSemicolon));
}
if (BigDecimal.class.equals(type)) {
return new BigDecimal(readUntil(HproseTags.TagSemicolon));
}
if (String.class.equals(type)) {
return readUntil(HproseTags.TagSemicolon);
}
if (Character.class.equals(type)) {
return HproseHelper.valueOf((char) readInteger(false));
}
if (Boolean.class.equals(type)) {
return HproseHelper.valueOf(readInteger(false) != 0);
}
if (Calendar.class.equals(type)) {
Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
calendar.setTime(new Date(readLong(false)));
return calendar;
}
if (Date.class.equals(type)) {
return new Date(readLong(false));
}
return castError("Integer", type);
}
private Object readLong(Class type) throws IOException {
if ((type == null) ||
BigInteger.class.equals(type) ||
Object.class.equals(type)) {
return new BigInteger(readUntil(HproseTags.TagSemicolon));
}
if (Long.class.equals(type)) {
return new Long(readLong(HproseTags.TagSemicolon));
}
if (Integer.class.equals(type)) {
return new Integer(readInt(HproseTags.TagSemicolon));
}
if (Float.class.equals(type)) {
return Float.valueOf(readUntil(HproseTags.TagSemicolon));
}
if (Double.class.equals(type)) {
return Double.valueOf(readUntil(HproseTags.TagSemicolon));
}
if (BigDecimal.class.equals(type)) {
return new BigDecimal(readUntil(HproseTags.TagSemicolon));
}
if (Byte.class.equals(type)) {
return new Byte(readByte(HproseTags.TagSemicolon));
}
if (Short.class.equals(type)) {
return new Short(readShort(HproseTags.TagSemicolon));
}
if (String.class.equals(type)) {
return readUntil(HproseTags.TagSemicolon);
}
if (Boolean.class.equals(type)) {
return HproseHelper.valueOf(readLong(false) != 0);
}
if (Character.class.equals(type)) {
return HproseHelper.valueOf((char) readLong(false));
}
if (Calendar.class.equals(type)) {
Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
calendar.setTime(new Date(readLong(false)));
return calendar;
}
if (Date.class.equals(type)) {
return new Date(readLong(false));
}
return castError("Long", type);
}
private Object readDouble(Class type) throws IOException {
if ((type == null) ||
Double.class.equals(type) ||
Object.class.equals(type)) {
return Double.valueOf(readUntil(HproseTags.TagSemicolon));
}
if (Float.class.equals(type)) {
return Float.valueOf(readUntil(HproseTags.TagSemicolon));
}
if (BigDecimal.class.equals(type)) {
return new BigDecimal(readUntil(HproseTags.TagSemicolon));
}
if (String.class.equals(type)) {
return readUntil(HproseTags.TagSemicolon);
}
if (Integer.class.equals(type)) {
return HproseHelper.valueOf(Double.valueOf(readUntil(HproseTags.TagSemicolon)).intValue());
}
if (Long.class.equals(type)) {
return HproseHelper.valueOf(Double.valueOf(readUntil(HproseTags.TagSemicolon)).longValue());
}
if (BigInteger.class.equals(type)) {
return new BigInteger(readUntil(HproseTags.TagSemicolon));
}
if (Byte.class.equals(type)) {
return HproseHelper.valueOf(Double.valueOf(readUntil(HproseTags.TagSemicolon)).byteValue());
}
if (Short.class.equals(type)) {
return HproseHelper.valueOf(Double.valueOf(readUntil(HproseTags.TagSemicolon)).shortValue());
}
if (Boolean.class.equals(type)) {
return HproseHelper.valueOf(readDouble(false) != 0.0);
}
if (Character.class.equals(type)) {
return HproseHelper.valueOf((char) Double.valueOf(readUntil(HproseTags.TagSemicolon)).intValue());
}
if (Calendar.class.equals(type)) {
Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
calendar.setTime(new Date(Double.valueOf(readUntil(HproseTags.TagSemicolon)).longValue()));
return calendar;
}
if (Date.class.equals(type)) {
return new Date(Double.valueOf(readUntil(HproseTags.TagSemicolon)).longValue());
}
return castError("Double", type);
}
private Object readEmpty(Class type) throws IOException {
if (type == null ||
String.class.equals(type) ||
Object.class.equals(type)) {
return "";
}
if (StringBuffer.class.equals(type)) {
return new StringBuffer();
}
if (char[].class.equals(type)) {
return new char[0];
}
if (byte[].class.equals(type)) {
return new byte[0];
}
if (Boolean.class.equals(type)) {
return Boolean.FALSE;
}
if (Integer.class.equals(type)) {
return HproseHelper.valueOf(0);
}
if (Long.class.equals(type)) {
return HproseHelper.valueOf((long) 0);
}
if (Byte.class.equals(type)) {
return HproseHelper.valueOf((byte) 0);
}
if (Short.class.equals(type)) {
return HproseHelper.valueOf((short) 0);
}
if (Character.class.equals(type)) {
return HproseHelper.valueOf((char) 0);
}
if (Float.class.equals(type)) {
return new Float(0);
}
if (Double.class.equals(type)) {
return new Double(0);
}
if (BigInteger.class.equals(type)) {
return BigInteger.ZERO;
}
if (BigDecimal.class.equals(type)) {
return BigDecimal.valueOf(0);
}
return castError("Empty String", type);
}
private Object readTrue(Class type) throws IOException {
if (type == null ||
Boolean.class.equals(type) ||
Object.class.equals(type)) {
return Boolean.TRUE;
}
if (String.class.equals(type)) {
return "true";
}
if (Integer.class.equals(type)) {
return HproseHelper.valueOf(1);
}
if (Long.class.equals(type)) {
return HproseHelper.valueOf((long) 1);
}
if (Byte.class.equals(type)) {
return HproseHelper.valueOf((byte) 1);
}
if (Short.class.equals(type)) {
return HproseHelper.valueOf((short) 1);
}
if (Character.class.equals(type)) {
return HproseHelper.valueOf('T');
}
if (Float.class.equals(type)) {
return new Float(1);
}
if (Double.class.equals(type)) {
return new Double(1);
}
if (BigInteger.class.equals(type)) {
return BigInteger.ONE;
}
if (BigDecimal.class.equals(type)) {
return BigDecimal.valueOf(1);
}
return castError("Boolean", type);
}
private Object readFalse(Class type) throws IOException {
if (type == null ||
Boolean.class.equals(type) ||
Object.class.equals(type)) {
return Boolean.FALSE;
}
if (String.class.equals(type)) {
return "false";
}
if (Integer.class.equals(type)) {
return HproseHelper.valueOf(0);
}
if (Long.class.equals(type)) {
return HproseHelper.valueOf((long) 0);
}
if (Byte.class.equals(type)) {
return HproseHelper.valueOf((byte) 0);
}
if (Short.class.equals(type)) {
return HproseHelper.valueOf((short) 0);
}
if (Character.class.equals(type)) {
return HproseHelper.valueOf('F');
}
if (Float.class.equals(type)) {
return new Float(0);
}
if (Double.class.equals(type)) {
return new Double(0);
}
if (BigInteger.class.equals(type)) {
return BigInteger.ZERO;
}
if (BigDecimal.class.equals(type)) {
return BigDecimal.valueOf(0);
}
return castError("Boolean", type);
}
private Object readNaN(Class type) throws IOException {
if ((type == null) ||
Double.class.equals(type) ||
Object.class.equals(type)) {
return HproseHelper.valueOf(Double.NaN);
}
if (Float.class.equals(type)) {
return HproseHelper.valueOf(Float.NaN);
}
if (String.class.equals(type)) {
return "NaN";
}
return castError("NaN", type);
}
private Object readInfinity(Class type) throws IOException {
if ((type == null) ||
Double.class.equals(type) ||
Object.class.equals(type)) {
return HproseHelper.valueOf(readInfinity(false));
}
if (Float.class.equals(type)) {
return HproseHelper.valueOf((float) readInfinity(false));
}
if (String.class.equals(type)) {
return String.valueOf(readInfinity(false));
}
return castError("Infinity", type);
}
private Object readBytes(Class type) throws IOException {
if ((type == null) ||
byte[].class.equals(type) ||
Object.class.equals(type)) {
return readBytes(false);
}
if (String.class.equals(type)) {
return new String(readBytes(false));
}
return castError("byte[]", type);
}
private Object readUTF8Char(Class type) throws IOException {
char u = readUTF8Char(false);
if ((type == null) ||
Character.class.equals(type)) {
return HproseHelper.valueOf(u);
}
if (String.class.equals(type) ||
Object.class.equals(type)) {
return String.valueOf((char)u);
}
if (Integer.class.equals(type)) {
return HproseHelper.valueOf((int)u);
}
if (Byte.class.equals(type)) {
return HproseHelper.valueOf((byte)u);
}
if (Long.class.equals(type)) {
return HproseHelper.valueOf((long)u);
}
if (Short.class.equals(type)) {
return HproseHelper.valueOf((short)u);
}
if (Float.class.equals(type)) {
return HproseHelper.valueOf((float)u);
}
if (Double.class.equals(type)) {
return HproseHelper.valueOf((double)u);
}
if (BigInteger.class.equals(type)) {
return BigInteger.valueOf((long)u);
}
if (BigDecimal.class.equals(type)) {
return BigDecimal.valueOf((long)u);
}
if (char[].class.equals(type)) {
return new char[] { u };
}
if (Boolean.class.equals(type)) {
return HproseHelper.valueOf(u != 0 && u != '0' && u != 'F' && u != 'f');
}
if (Calendar.class.equals(type)) {
Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
calendar.setTime(new Date((long)u));
return calendar;
}
if (Date.class.equals(type)) {
return new Date((long)u);
}
return castError("Character", type);
}
public void checkTag(int expectTag, int tag) throws IOException {
if (tag != expectTag) {
throw new HproseException("Tag '" + (char) expectTag +
"' expected, but '" + (char) tag +
"' found in stream");
}
}
public void checkTag(int expectTag) throws IOException {
checkTag(expectTag, stream.read());
}
public int checkTags(String expectTags, int tag) throws IOException {
if (expectTags.indexOf(tag) == -1) {
throw new HproseException("Tag '" + expectTags +
"' expected, but '" + (char) tag +
"' found in stream");
}
return tag;
}
public int checkTags(String expectTags) throws IOException {
return checkTags(expectTags, stream.read());
}
public String readUntil(int tag) throws IOException {
StringBuffer sb = new StringBuffer();
int i = stream.read();
while ((i != tag) && (i != -1)) {
sb.append((char) i);
i = stream.read();
}
return sb.toString();
}
public byte readByte(int tag) throws IOException {
byte result = 0;
int i = stream.read();
if (i == tag) return result;
byte sign = 1;
if (i == '+') {
i = stream.read();
}
else if (i == '-') {
sign = -1;
i = stream.read();
}
while ((i != tag) && (i != -1)) {
result *= 10;
result += (i - '0') * sign;
i = stream.read();
}
return result;
}
public short readShort(int tag) throws IOException {
short result = 0;
int i = stream.read();
if (i == tag) return result;
short sign = 1;
if (i == '+') {
i = stream.read();
}
else if (i == '-') {
sign = -1;
i = stream.read();
}
while ((i != tag) && (i != -1)) {
result *= 10;
result += (i - '0') * sign;
i = stream.read();
}
return result;
}
public int readInt(int tag) throws IOException {
int result = 0;
int i = stream.read();
if (i == tag) return result;
int sign = 1;
if (i == '+') {
i = stream.read();
}
else if (i == '-') {
sign = -1;
i = stream.read();
}
while ((i != tag) && (i != -1)) {
result *= 10;
result += (i - '0') * sign;
i = stream.read();
}
return result;
}
public long readLong(int tag) throws IOException {
long result = 0;
int i = stream.read();
if (i == tag) return result;
long sign = 1;
if (i == '+') {
i = stream.read();
}
else if (i == '-') {
sign = -1;
i = stream.read();
}
while ((i != tag) && (i != -1)) {
result *= 10;
result += (i - '0') * sign;
i = stream.read();
}
return result;
}
public int readInteger() throws IOException {
return readInteger(true);
}
public int readInteger(boolean includeTag) throws IOException {
if (includeTag) {
int tag = stream.read();
if ((tag >= '0') && (tag <= '9')) {
return tag - '0';
}
checkTag(HproseTags.TagInteger, tag);
}
return readInt(HproseTags.TagSemicolon);
}
public BigInteger readBigInteger() throws IOException {
return readBigInteger(true);
}
public BigInteger readBigInteger(boolean includeTag) throws IOException {
if (includeTag) {
int tag = stream.read();
if ((tag >= '0') && (tag <= '9')) {
return BigInteger.valueOf((long)(tag - '0'));
}
checkTags((char) HproseTags.TagInteger + "" +
(char) HproseTags.TagLong, tag);
}
return new BigInteger(readUntil(HproseTags.TagSemicolon));
}
public long readLong() throws IOException {
return readLong(true);
}
public long readLong(boolean includeTag) throws IOException {
if (includeTag) {
int tag = stream.read();
if ((tag >= '0') && (tag <= '9')) {
return (long)(tag - '0');
}
checkTags((char) HproseTags.TagInteger + "" +
(char) HproseTags.TagLong, tag);
}
return readLong(HproseTags.TagSemicolon);
}
public double readDouble() throws IOException {
return readDouble(true);
}
public double readDouble(boolean includeTag) throws IOException {
if (includeTag) {
int tag = stream.read();
if ((tag >= '0') && (tag <= '9')) {
return (double)(tag - '0');
}
checkTags((char) HproseTags.TagInteger + "" +
(char) HproseTags.TagLong + "" +
(char) HproseTags.TagDouble + "" +
(char) HproseTags.TagNaN + "" +
(char) HproseTags.TagInfinity, tag);
if (tag == HproseTags.TagNaN) {
return Double.NaN;
}
if (tag == HproseTags.TagInfinity) {
return readInfinity(false);
}
}
return Double.parseDouble(readUntil(HproseTags.TagSemicolon));
}
public double readNaN() throws IOException {
checkTag(HproseTags.TagNaN);
return Double.NaN;
}
public double readInfinity() throws IOException {
return readInfinity(true);
}
public double readInfinity(boolean includeTag) throws IOException {
if (includeTag) {
checkTag(HproseTags.TagInfinity);
}
return ((stream.read() == HproseTags.TagNeg) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY);
}
public Object readNull() throws IOException {
checkTag(HproseTags.TagNull);
return null;
}
public Object readEmpty() throws IOException {
checkTag(HproseTags.TagEmpty);
return "";
}
public boolean readBoolean() throws IOException {
int tag = checkTags((char) HproseTags.TagTrue + "" + (char) HproseTags.TagFalse);
return (tag == HproseTags.TagTrue);
}
public Object readDate() throws IOException {
return readDate(true, null);
}
public Object readDate(boolean includeTag) throws IOException {
return readDate(includeTag, null);
}
public Object readDate(Class type) throws IOException {
return readDate(true, type);
}
public Object readDate(boolean includeTag, Class type) throws IOException {
int tag;
if (includeTag) {
tag = checkTags((char) HproseTags.TagDate + "" + (char) HproseTags.TagRef);
if (tag == HproseTags.TagRef) {
return readRef(type);
}
}
Calendar calendar;
int year = stream.read() - '0';
year = year * 10 + stream.read() - '0';
year = year * 10 + stream.read() - '0';
year = year * 10 + stream.read() - '0';
int month = stream.read() - '0';
month = month * 10 + stream.read() - '0';
int day = stream.read() - '0';
day = day * 10 + stream.read() - '0';
tag = stream.read();
if (tag == HproseTags.TagTime) {
int hour = stream.read() - '0';
hour = hour * 10 + stream.read() - '0';
int minute = stream.read() - '0';
minute = minute * 10 + stream.read() - '0';
int second = stream.read() - '0';
second = second * 10 + stream.read() - '0';
int millisecond = 0;
tag = stream.read();
if (tag == HproseTags.TagPoint) {
millisecond = stream.read() - '0';
millisecond = millisecond * 10 + stream.read() - '0';
millisecond = millisecond * 10 + stream.read() - '0';
tag = stream.read();
if (tag >= '0' && tag <= '9') {
stream.read();
stream.read();
tag = stream.read();
if (tag >= '0' && tag <= '9') {
stream.read();
stream.read();
tag = stream.read();
}
}
}
calendar = Calendar.getInstance(tag == HproseTags.TagUTC ? HproseHelper.UTC : TimeZone.getDefault());
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1);
calendar.set(Calendar.DATE, day);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
calendar.set(Calendar.MILLISECOND, millisecond);
}
else {
calendar = Calendar.getInstance(tag == HproseTags.TagUTC ? HproseHelper.UTC : TimeZone.getDefault());
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1);
calendar.set(Calendar.DATE, day);
}
Object o = changeCalendarType(calendar, type);
ref.add(o);
return o;
}
public Object readTime() throws IOException {
return readTime(true, null);
}
public Object readTime(boolean includeTag) throws IOException {
return readTime(includeTag, null);
}
public Object readTime(Class type) throws IOException {
return readTime(true, type);
}
public Object readTime(boolean includeTag, Class type) throws IOException {
int tag;
if (includeTag) {
tag = checkTags((char) HproseTags.TagTime + "" + (char) HproseTags.TagRef);
if (tag == HproseTags.TagRef) {
return readRef(type);
}
}
Calendar calendar;
int hour = stream.read() - '0';
hour = hour * 10 + stream.read() - '0';
int minute = stream.read() - '0';
minute = minute * 10 + stream.read() - '0';
int second = stream.read() - '0';
second = second * 10 + stream.read() - '0';
int millisecond = 0;
tag = stream.read();
if (tag == HproseTags.TagPoint) {
millisecond = stream.read() - '0';
millisecond = millisecond * 10 + stream.read() - '0';
millisecond = millisecond * 10 + stream.read() - '0';
tag = stream.read();
if (tag >= '0' && tag <= '9') {
stream.read();
stream.read();
tag = stream.read();
if (tag >= '0' && tag <= '9') {
stream.read();
stream.read();
tag = stream.read();
}
}
}
calendar = Calendar.getInstance(tag == HproseTags.TagUTC ? HproseHelper.UTC : TimeZone.getDefault());
calendar.set(Calendar.YEAR, 1970);
calendar.set(Calendar.MONTH, 0);
calendar.set(Calendar.DATE, 1);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
calendar.set(Calendar.MILLISECOND, millisecond);
Object o = changeCalendarType(calendar, type);
ref.add(o);
return o;
}
public Object readDateTime() throws IOException {
return readDateTime(null);
}
public Object readDateTime(Class type) throws IOException {
int tag = checkTags((char) HproseTags.TagDate + "" +
(char) HproseTags.TagTime + "" +
(char) HproseTags.TagRef);
if (tag == HproseTags.TagRef) {
return readRef(type);
}
if (tag == HproseTags.TagDate) {
return readDate(false, type);
}
return readTime(false, type);
}
private Object changeCalendarType(Calendar calendar, Class type) throws IOException {
if (type == null ||
Calendar.class.equals(type) ||
Object.class.equals(type)) {
return calendar;
}
if (Date.class.equals(type)) {
return calendar.getTime();
}
if (Long.class.equals(type)) {
return new Long(calendar.getTime().getTime());
}
if (String.class.equals(type)) {
return calendar.getTime().toString();
}
return castError(calendar, type);
}
public byte[] readBytes() throws IOException {
return readBytes(true);
}
public byte[] readBytes(boolean includeTag) throws IOException {
if (includeTag) {
int tag = checkTags((char) HproseTags.TagBytes + "" + (char) HproseTags.TagRef);
if (tag == HproseTags.TagRef) {
return (byte[]) readRef(byte[].class);
}
}
int len = readInt(HproseTags.TagQuote);
int off = 0;
byte[] b = new byte[len];
while (len > 0) {
int size = stream.read(b, off, len);
off += size;
len -= size;
}
checkTag(HproseTags.TagQuote);
ref.add(b);
return b;
}
public char readUTF8Char(boolean includeTag) throws IOException {
if (includeTag) {
checkTag(HproseTags.TagUTF8Char);
}
char u;
int c = stream.read();
switch (c >>> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7: {
// 0xxx xxxx
u = (char) c;
break;
}
case 12:
case 13: {
// 110x xxxx 10xx xxxx
int c2 = stream.read();
u = (char) (((c & 0x1f) << 6) |
(c2 & 0x3f));
break;
}
case 14: {
// 1110 xxxx 10xx xxxx 10xx xxxx
int c2 = stream.read();
int c3 = stream.read();
u = (char) (((c & 0x0f) << 12) |
((c2 & 0x3f) << 6) |
(c3 & 0x3f));
break;
}
default:
throw new HproseException("bad utf-8 encoding at " +
((c < 0) ? "end of stream" : "0x" + Integer.toHexString(c & 0xff)));
}
return u;
}
public Object readString() throws IOException {
return readString(true, null, true);
}
public Object readString(boolean includeTag) throws IOException {
return readString(includeTag, null, true);
}
public Object readString(Class type) throws IOException {
return readString(true, type, true);
}
public Object readString(boolean includeTag, Class type) throws IOException {
return readString(includeTag, type, true);
}
private Object readString(boolean includeTag, Class type, boolean includeRef) throws IOException {
if (includeTag) {
int tag = checkTags((char) HproseTags.TagString + "" +
(char) HproseTags.TagRef);
if (tag == HproseTags.TagRef) {
return readRef(type);
}
}
int count = readInt(HproseTags.TagQuote);
char[] buf = new char[count];
for (int i = 0; i < count; i++) {
int c = stream.read();
switch (c >>> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7: {
// 0xxx xxxx
buf[i] = (char) c;
break;
}
case 12:
case 13: {
// 110x xxxx 10xx xxxx
int c2 = stream.read();
buf[i] = (char) (((c & 0x1f) << 6) |
(c2 & 0x3f));
break;
}
case 14: {
// 1110 xxxx 10xx xxxx 10xx xxxx
int c2 = stream.read();
int c3 = stream.read();
buf[i] = (char) (((c & 0x0f) << 12) |
((c2 & 0x3f) << 6) |
(c3 & 0x3f));
break;
}
case 15: {
// 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
if ((c & 0xf) <= 4) {
int c2 = stream.read();
int c3 = stream.read();
int c4 = stream.read();
int s = ((c & 0x07) << 18) |
((c2 & 0x3f) << 12) |
((c3 & 0x3f) << 6) |
(c4 & 0x3f) - 0x10000;
if (0 <= s && s <= 0xfffff) {
buf[i++] = (char) (((s >>> 10) & 0x03ff) | 0xd800);
buf[i] = (char) ((s & 0x03ff) | 0xdc00);
break;
}
}
// no break here!! here need throw exception.
}
default:
throw new HproseException("bad utf-8 encoding at " +
((c < 0) ? "end of stream" : "0x" + Integer.toHexString(c & 0xff)));
}
}
checkTag(HproseTags.TagQuote);
Object o = changeStringType(buf, type);
if (includeRef) {
ref.add(o);
}
return o;
}
private Object changeStringType(char[] str, Class type) throws IOException {
if (char[].class.equals(type)) {
return str;
}
if (StringBuffer.class.equals(type)) {
return new StringBuffer(str.length).append(str);
}
String s = new String(str);
if ((type == null) ||
String.class.equals(type) ||
Object.class.equals(type)) {
return s;
}
if (BigDecimal.class.equals(type)) {
return new BigDecimal(s);
}
if (BigInteger.class.equals(type)) {
return new BigInteger(s);
}
if (Byte.class.equals(type)) {
return new Byte(Byte.parseByte(s));
}
if (Short.class.equals(type)) {
return new Short(Short.parseShort(s));
}
if (Integer.class.equals(type)) {
return new Integer(Integer.parseInt(s));
}
if (Long.class.equals(type)) {
return new Long(Long.parseLong(s));
}
if (Float.class.equals(type)) {
return new Float(Float.parseFloat(s));
}
if (Double.class.equals(type)) {
return new Double(Double.parseDouble(s));
}
if (Character.class.equals(type)) {
if (str.length == 1) {
return new Character(str[0]);
}
else {
return new Character((char) Integer.parseInt(s));
}
}
if (Boolean.class.equals(type)) {
if (str.length == 0) {
return Boolean.FALSE;
}
else if (str.length == 1) {
return HproseHelper.valueOf(str[0] != 0);
}
else {
return HproseHelper.valueOf(s.equalsIgnoreCase("true"));
}
}
if (byte[].class.equals(type)) {
try {
return s.getBytes("UTF-8");
}
catch (Exception e) {
return s.getBytes();
}
}
if (UUID.class.equals(type)) {
return UUID.fromString(s);
}
return castError(str, type);
}
public Object readUUID() throws IOException {
return readUUID(true, null);
}
public Object readUUID(boolean includeTag) throws IOException {
return readUUID(includeTag, null);
}
public Object readUUID(Class type) throws IOException {
return readUUID(true, type);
}
public Object readUUID(boolean includeTag, Class type) throws IOException {
if (includeTag) {
int tag = checkTags((char)HproseTags.TagGuid + "" +
(char)HproseTags.TagRef);
if (tag == HproseTags.TagRef) {
return readRef(type);
}
}
checkTag(HproseTags.TagOpenbrace);
char[] buf = new char[36];
for (int i = 0; i < 36; i++) {
buf[i] = (char) stream.read();
}
checkTag(HproseTags.TagClosebrace);
Object o = changeUUIDType(buf, type);
ref.add(o);
return o;
}
private Object changeUUIDType(char[] buf, Class type) throws IOException {
if (char[].class.equals(type)) {
return buf;
}
String s = new String(buf);
if (String.class.equals(type)) {
return s;
}
if (type == null ||
UUID.class.equals(type) ||
Object.class.equals(type)) {
return UUID.fromString(s);
}
if (StringBuffer.class.equals(type)) {
return new StringBuffer(s);
}
return castError(buf, type);
}
private short[] readShortArray(int count) throws IOException {
short[] a = new short[count];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = ((Short)unserialize(Short.class)).shortValue();
}
return a;
}
private int[] readIntegerArray(int count) throws IOException {
int[] a = new int[count];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = ((Integer)unserialize(Integer.class)).intValue();
}
return a;
}
private long[] readLongArray(int count) throws IOException {
long[] a = new long[count];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = ((Long)unserialize(Long.class)).longValue();
}
return a;
}
private boolean[] readBooleanArray(int count) throws IOException {
boolean[] a = new boolean[count];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = ((Boolean)unserialize(Boolean.class)).booleanValue();
}
return a;
}
private float[] readFloatArray(int count) throws IOException {
float[] a = new float[count];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = ((Float)unserialize(Float.class)).floatValue();
}
return a;
}
private double[] readDoubleArray(int count) throws IOException {
double[] a = new double[count];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = ((Double)unserialize(Double.class)).doubleValue();
}
return a;
}
private BigInteger[] readBigIntegerArray(int count) throws IOException {
BigInteger[] a = new BigInteger[count];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = (BigInteger)unserialize(BigInteger.class);
}
return a;
}
private String[] readStringArray(int count) throws IOException {
String[] a = new String[count];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = (String) unserialize(String.class);
}
return a;
}
private StringBuffer[] readStringBufferArray(int count) throws IOException {
StringBuffer[] a = new StringBuffer[count];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = (StringBuffer) unserialize(StringBuffer.class);
}
return a;
}
private BigDecimal[] readBigDecimalArray(int count) throws IOException {
BigDecimal[] a = new BigDecimal[count];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = (BigDecimal) unserialize(BigDecimal.class);
}
return a;
}
private byte[][] readBytesArray(int count) throws IOException {
byte[][] a = new byte[count][];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = (byte[]) unserialize(byte[].class);
}
return a;
}
private char[][] readCharsArray(int count) throws IOException {
char[][] a = new char[count][];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = (char[]) unserialize(char[].class);
}
return a;
}
private Calendar[] readCalendarArray(int count) throws IOException {
Calendar[] a = new Calendar[count];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = (Calendar) unserialize(Calendar.class);
}
return a;
}
private Date[] readDateArray(int count) throws IOException {
Date[] a = new Date[count];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = (Date) unserialize(Date.class);
}
return a;
}
public void readArray(Class[] types, Object[] a, int count) throws IOException {
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = unserialize(types[i]);
}
}
public Object[] readArray(int count) throws IOException {
Object[] a = new Object[count];
ref.add(a);
for (int i = 0; i < count; i++) {
a[i] = unserialize(Object.class);
}
return a;
}
private ArrayList readArrayList(int count) throws IOException {
ArrayList list = new ArrayList(count);
ref.add(list);
for (int i = 0; i < count; i++) {
list.add(unserialize(Object.class));
}
return list;
}
private LinkedList readLinkedList(int count) throws IOException {
LinkedList list = new LinkedList();
ref.add(list);
for (int i = 0; i < count; i++) {
list.add(unserialize(Object.class));
}
return list;
}
private Vector readVector(int count) throws IOException {
Vector list = new Vector(count);
ref.add(list);
for (int i = 0; i < count; i++) {
list.addElement(unserialize(Object.class));
}
return list;
}
private Stack readStack(int count) throws IOException {
Stack list = new Stack();
ref.add(list);
for (int i = 0; i < count; i++) {
list.addElement(unserialize(Object.class));
}
return list;
}
private HashSet readHashSet(int count) throws IOException {
HashSet set = new HashSet();
ref.add(set);
for (int i = 0; i < count; i++) {
set.add(unserialize(Object.class));
}
return set;
}
private TreeSet readTreeSet(int count) throws IOException {
TreeSet set = new TreeSet();
ref.add(set);
for (int i = 0; i < count; i++) {
set.add(unserialize(Object.class));
}
return set;
}
private Collection readCollection(int count, Class type) throws IOException {
Collection collection = (Collection) HproseHelper.newInstance(type);
ref.add(collection);
for (int i = 0; i < count; i++) {
collection.add(unserialize(Object.class));
}
return collection;
}
private Hashtable readListAsHashtable(int count) throws IOException {
Hashtable map = new Hashtable(count);
ref.add(map);
for (int i = 0; i < count; i++) {
Object key = HproseHelper.valueOf(i);
Object value = unserialize(Object.class);
map.put(key, value);
}
return map;
}
private Map readListAsMap(int count, Class type) throws IOException {
Map map = (Map) HproseHelper.newInstance(type);
ref.add(map);
for (int i = 0; i < count; i++) {
Object key = HproseHelper.valueOf(i);
Object value = unserialize(Object.class);
map.put(key, value);
}
return map;
}
public Object readList() throws IOException {
return readList(true, null);
}
public Object readList(boolean includeTag) throws IOException {
return readList(includeTag, null);
}
public Object readList(Class type) throws IOException {
return readList(true, type);
}
public Object readList(boolean includeTag, Class type) throws IOException {
if (includeTag) {
int tag = checkTags((char) HproseTags.TagList + "" +
(char) HproseTags.TagRef);
if (tag == HproseTags.TagRef) {
return readRef(type);
}
}
int count = readInt(HproseTags.TagOpenbrace);
Object list = null;
if ((type == null) ||
Object.class.equals(type) ||
Collection.class.equals(type) ||
AbstractCollection.class.equals(type) ||
List.class.equals(type) ||
AbstractList.class.equals(type) ||
ArrayList.class.equals(type)) {
list = readArrayList(count);
}
else if (AbstractSequentialList.class.equals(type) ||
LinkedList.class.equals(type)) {
list = readLinkedList(count);
}
else if (int[].class.equals(type)) {
list = readIntegerArray(count);
}
else if (short[].class.equals(type)) {
list = readShortArray(count);
}
else if (long[].class.equals(type)) {
list = readLongArray(count);
}
else if (String[].class.equals(type)) {
list = readStringArray(count);
}
else if (boolean[].class.equals(type)) {
list = readBooleanArray(count);
}
else if (double[].class.equals(type)) {
list = readDoubleArray(count);
}
else if (float[].class.equals(type)) {
list = readFloatArray(count);
}
else if (BigInteger[].class.equals(type)) {
list = readBigIntegerArray(count);
}
else if (BigDecimal[].class.equals(type)) {
list = readBigDecimalArray(count);
}
else if (StringBuffer[].class.equals(type)) {
list = readStringBufferArray(count);
}
else if (byte[][].class.equals(type)) {
list = readBytesArray(count);
}
else if (char[][].class.equals(type)) {
list = readCharsArray(count);
}
else if (Calendar[].class.equals(type)) {
list = readCalendarArray(count);
}
else if (Date[].class.equals(type)) {
list = readDateArray(count);
}
else if (Object[].class.equals(type)) {
list = readArray(count);
}
else if (Vector.class.equals(type)) {
list = readVector(count);
}
else if (Stack.class.equals(type)) {
list = readStack(count);
}
else if (Set.class.equals(type) ||
AbstractSet.class.equals(type) ||
HashSet.class.equals(type)) {
list = readHashSet(count);
}
else if (SortedSet.class.equals(type) ||
TreeSet.class.equals(type)) {
list = readTreeSet(count);
}
else if (Collection.class.isAssignableFrom(type)) {
list = readCollection(count, type);
}
else if (Hashtable.class.equals(type)) {
list = readListAsHashtable(count);
}
else if (Map.class.isAssignableFrom(type)) {
list = readListAsMap(count, type);
}
else {
castError("List", type);
}
checkTag(HproseTags.TagClosebrace);
return list;
}
private HashMap readHashMap(int count) throws IOException {
HashMap map = new HashMap(count);
ref.add(map);
for (int i = 0; i < count; i++) {
Object key = unserialize(Object.class);
Object value = unserialize(Object.class);
map.put(key, value);
}
return map;
}
private TreeMap readTreeMap(int count) throws IOException {
TreeMap map = new TreeMap();
ref.add(map);
for (int i = 0; i < count; i++) {
Object key = unserialize(Object.class);
Object value = unserialize(Object.class);
map.put(key, value);
}
return map;
}
private Hashtable readHashtable(int count) throws IOException {
Hashtable map = new Hashtable(count);
ref.add(map);
for (int i = 0; i < count; i++) {
Object key = unserialize(Object.class);
Object value = unserialize(Object.class);
map.put(key, value);
}
return map;
}
private Map readMap(int count, Class type) throws IOException {
Map map = (Map) HproseHelper.newInstance(type);
ref.add(map);
for (int i = 0; i < count; i++) {
Object key = unserialize(Object.class);
Object value = unserialize(Object.class);
map.put(key, value);
}
return map;
}
private Serializable readObject(int count, Class type) throws IOException {
Serializable obj = (Serializable)HproseHelper.newInstance(type);
ref.add(obj);
for (int i = 0; i < count; i++) {
String name = (String)(readString(String.class));
Object value = unserialize(obj.getPropertyType(name));
obj.setProperty(name, value);
}
return obj;
}
public Object readMap() throws IOException {
return readMap(true, null);
}
public Object readMap(boolean includeTag) throws IOException {
return readMap(includeTag, null);
}
public Object readMap(Class type) throws IOException {
return readMap(true, type);
}
public Object readMap(boolean includeTag, Class type) throws IOException {
if (includeTag) {
int tag = checkTags((char) HproseTags.TagMap + "" +
(char) HproseTags.TagRef);
if (tag == HproseTags.TagRef) {
return readRef(type);
}
}
int count = readInt(HproseTags.TagOpenbrace);
Object map = null;
if ((type == null) ||
Object.class.equals(type) ||
Map.class.equals(type) ||
AbstractMap.class.equals(type) ||
HashMap.class.equals(type)) {
map = readHashMap(count);
}
else if (SortedMap.class.equals(type) ||
TreeMap.class.equals(type)) {
map = readTreeMap(count);
}
else if (Hashtable.class.equals(type)) {
map = readHashtable(count);
}
else {
if (Map.class.isAssignableFrom(type)) {
map = readMap(count, type);
}
else {
map = readObject(count, type);
}
}
checkTag(HproseTags.TagClosebrace);
return map;
}
public Object readObject() throws IOException {
return readObject(true, null);
}
public Object readObject(boolean includeTag) throws IOException {
return readObject(includeTag, null);
}
public Object readObject(Class type) throws IOException {
return readObject(true, type);
}
public Object readObject(boolean includeTag, Class type) throws IOException {
if (includeTag) {
int tag = checkTags((char) HproseTags.TagObject + "" +
(char) HproseTags.TagClass + "" +
(char) HproseTags.TagRef);
if (tag == HproseTags.TagRef) {
return readRef(type);
}
if (tag == HproseTags.TagClass) {
readClass();
return readObject(type);
}
}
Object c = classref.get(readInt(HproseTags.TagOpenbrace));
String[] propertyNames = (String[]) propertyref.get(c);
int count = propertyNames.length;
Serializable obj = null;
if (Class.class.equals(c.getClass())) {
Class cls = (Class) c;
if ((type == null) || type.isAssignableFrom(cls)) {
obj = HproseHelper.newInstance(cls);
}
else {
obj = HproseHelper.newInstance(type);
}
}
else if (type != null) {
obj = HproseHelper.newInstance(type);
}
if (obj == null) {
HashMap map = new HashMap(count);
ref.add(map);
for (int i = 0; i < count; i++) {
map.put(propertyNames[i], unserialize(Object.class));
}
checkTag(HproseTags.TagClosebrace);
return map;
}
else {
ref.add(obj);
for (int i = 0; i < count; i++) {
Object value = unserialize(obj.getPropertyType(propertyNames[i]));
obj.setProperty(propertyNames[i], value);
}
checkTag(HproseTags.TagClosebrace);
return obj;
}
}
private void readClass() throws IOException {
String className = (String) readString(false, null, false);
int count = readInt(HproseTags.TagOpenbrace);
String[] propertyNames = new String[count];
for (int i = 0; i < count; i++) {
propertyNames[i] = (String) readString(true);
}
checkTag(HproseTags.TagClosebrace);
Class type = HproseHelper.getClass(className);
if (type == null) {
Object key = new Object();
classref.add(key);
propertyref.put(key, propertyNames);
}
else {
classref.add(type);
propertyref.put(type, propertyNames);
}
}
private Object readRef(Class type) throws IOException {
Object o = ref.get(readInt(HproseTags.TagSemicolon));
if (type == null || type.isInstance(o)) {
return o;
}
return castError(o, type);
}
private Object castError(String srctype, Class desttype) throws IOException {
throw new HproseException(srctype + " can't change to " + desttype.getName());
}
private Object castError(Object obj, Class type) throws IOException {
throw new HproseException(obj.getClass().getName() + " can't change to " + type.getName());
}
public ByteArrayOutputStream readRaw() throws IOException {
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
readRaw(ostream);
return ostream;
}
public void readRaw(OutputStream ostream) throws IOException {
readRaw(ostream, stream.read());
}
private void readRaw(OutputStream ostream, int tag) throws IOException {
ostream.write(tag);
switch (tag) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case HproseTags.TagNull:
case HproseTags.TagEmpty:
case HproseTags.TagTrue:
case HproseTags.TagFalse:
case HproseTags.TagNaN:
break;
case HproseTags.TagInfinity:
ostream.write(stream.read());
break;
case HproseTags.TagInteger:
case HproseTags.TagLong:
case HproseTags.TagDouble:
case HproseTags.TagRef:
readNumberRaw(ostream);
break;
case HproseTags.TagDate:
case HproseTags.TagTime:
readDateTimeRaw(ostream);
break;
case HproseTags.TagUTF8Char:
readUTF8CharRaw(ostream);
break;
case HproseTags.TagBytes:
readBytesRaw(ostream);
break;
case HproseTags.TagString:
readStringRaw(ostream);
break;
case HproseTags.TagGuid:
readGuidRaw(ostream);
break;
case HproseTags.TagList:
case HproseTags.TagMap:
case HproseTags.TagObject:
readComplexRaw(ostream);
break;
case HproseTags.TagClass:
readComplexRaw(ostream);
readRaw(ostream);
break;
case HproseTags.TagError:
readRaw(ostream);
break;
case -1:
throw new HproseException("No byte found in stream");
default:
throw new HproseException("Unexpected serialize tag '" +
(char) tag + "' in stream");
}
}
private void readNumberRaw(OutputStream ostream) throws IOException {
int tag;
do {
tag = stream.read();
ostream.write(tag);
} while (tag != HproseTags.TagSemicolon);
}
private void readDateTimeRaw(OutputStream ostream) throws IOException {
int tag;
do {
tag = stream.read();
ostream.write(tag);
} while (tag != HproseTags.TagSemicolon &&
tag != HproseTags.TagUTC);
}
private void readUTF8CharRaw(OutputStream ostream) throws IOException {
int tag = stream.read();
switch (tag >>> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7: {
// 0xxx xxxx
ostream.write(tag);
break;
}
case 12:
case 13: {
// 110x xxxx 10xx xxxx
ostream.write(tag);
ostream.write(stream.read());
break;
}
case 14: {
// 1110 xxxx 10xx xxxx 10xx xxxx
ostream.write(tag);
ostream.write(stream.read());
ostream.write(stream.read());
break;
}
default:
throw new HproseException("bad utf-8 encoding at " +
((tag < 0) ? "end of stream" :
"0x" + Integer.toHexString(tag & 0xff)));
}
}
private void readBytesRaw(OutputStream ostream) throws IOException {
int len = 0;
int tag = '0';
do {
len *= 10;
len += tag - '0';
tag = stream.read();
ostream.write(tag);
} while (tag != HproseTags.TagQuote);
int off = 0;
byte[] b = new byte[len];
while (len > 0) {
int size = stream.read(b, off, len);
off += size;
len -= size;
}
ostream.write(b);
ostream.write(stream.read());
}
private void readStringRaw(OutputStream ostream) throws IOException {
int count = 0;
int tag = '0';
do {
count *= 10;
count += tag - '0';
tag = stream.read();
ostream.write(tag);
} while (tag != HproseTags.TagQuote);
for (int i = 0; i < count; i++) {
tag = stream.read();
switch (tag >>> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7: {
// 0xxx xxxx
ostream.write(tag);
break;
}
case 12:
case 13: {
// 110x xxxx 10xx xxxx
ostream.write(tag);
ostream.write(stream.read());
break;
}
case 14: {
// 1110 xxxx 10xx xxxx 10xx xxxx
ostream.write(tag);
ostream.write(stream.read());
ostream.write(stream.read());
break;
}
case 15: {
// 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
if ((tag & 0xf) <= 4) {
ostream.write(tag);
ostream.write(stream.read());
ostream.write(stream.read());
ostream.write(stream.read());
break;
}
// no break here!! here need throw exception.
}
default:
throw new HproseException("bad utf-8 encoding at " +
((tag < 0) ? "end of stream" :
"0x" + Integer.toHexString(tag & 0xff)));
}
}
ostream.write(stream.read());
}
private void readGuidRaw(OutputStream ostream) throws IOException {
int len = 38;
int off = 0;
byte[] b = new byte[len];
while (len > 0) {
int size = stream.read(b, off, len);
off += size;
len -= size;
}
ostream.write(b);
}
private void readComplexRaw(OutputStream ostream) throws IOException {
int tag;
do {
tag = stream.read();
ostream.write(tag);
} while (tag != HproseTags.TagOpenbrace);
while ((tag = stream.read()) != HproseTags.TagClosebrace) {
readRaw(ostream, tag);
}
ostream.write(tag);
}
public void reset() {
ref.clear();
classref.clear();
propertyref.clear();
}
}