JSONReaderJSONB.java
package com.alibaba.fastjson2;
import com.alibaba.fastjson2.reader.*;
import com.alibaba.fastjson2.util.*;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.*;
import java.util.*;
import static com.alibaba.fastjson2.JSONB.*;
import static com.alibaba.fastjson2.JSONB.Constants.*;
import static com.alibaba.fastjson2.JSONFactory.*;
import static com.alibaba.fastjson2.JSONReaderUTF8.*;
import static com.alibaba.fastjson2.util.DateUtils.*;
import static com.alibaba.fastjson2.util.IOUtils.*;
import static com.alibaba.fastjson2.util.JDKUtils.*;
import static com.alibaba.fastjson2.util.TypeUtils.toBigDecimal;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
final class JSONReaderJSONB
extends JSONReader {
static final long BASE = UNSAFE.arrayBaseOffset(byte[].class);
static final byte[] SHANGHAI_ZONE_ID_NAME_BYTES = JSONB.toBytes(SHANGHAI_ZONE_ID_NAME);
static Charset GB18030;
static final byte[] FIXED_TYPE_SIZE;
static {
byte[] bytes = new byte[256];
for (int i = BC_INT32_NUM_MIN; i < BC_INT32_NUM_MAX; i++) {
bytes[i & 0xFF] = 1;
}
for (int i = BC_INT32_BYTE_MIN; i < BC_INT32_BYTE_MAX; i++) {
bytes[i & 0xFF] = 2;
}
for (int i = BC_INT32_SHORT_MIN; i < BC_INT32_SHORT_MAX; i++) {
bytes[i & 0xFF] = 3;
}
for (int i = BC_INT64_NUM_MIN; i < BC_INT64_NUM_MAX; i++) {
bytes[i & 0xFF] = 1;
}
for (int i = BC_INT64_BYTE_MIN; i < BC_INT64_BYTE_MAX; i++) {
bytes[i & 0xFF] = 2;
}
for (int i = BC_INT64_SHORT_MIN; i < BC_INT64_SHORT_MAX; i++) {
bytes[i & 0xFF] = 3;
}
for (int i = BC_STR_ASCII_FIX_MIN; i < BC_STR_ASCII_FIX_MAX; i++) {
bytes[i & 0xFF] = (byte) (i - BC_STR_ASCII_FIX_MIN + 1);
}
bytes[BC_ARRAY_FIX_0 & 0xFF] = 1;
bytes[BC_STR_ASCII_FIX_0 & 0xFF] = 1;
bytes[BC_NULL & 0xFF] = 1;
bytes[BC_FALSE & 0xFF] = 1;
bytes[BC_TRUE & 0xFF] = 1;
bytes[BC_INT8 & 0xFF] = 2;
bytes[BC_INT16 & 0xFF] = 3;
bytes[BC_INT32 & 0xFF] = 5;
bytes[BC_TIMESTAMP_SECONDS & 0xFF] = 5;
bytes[BC_FLOAT & 0xFF] = 5;
bytes[BC_INT64_INT & 0xFF] = 5;
bytes[BC_INT64 & 0xFF] = 9;
bytes[BC_TIMESTAMP_MILLIS & 0xFF] = 9;
bytes[BC_DOUBLE & 0xFF] = 9;
bytes[BC_STR_ASCII & 0xFF] = -1;
bytes[BC_STR_UTF8 & 0xFF] = -1;
bytes[BC_STR_UTF16 & 0xFF] = -1;
bytes[BC_STR_UTF16LE & 0xFF] = -1;
bytes[BC_STR_UTF16BE & 0xFF] = -1;
FIXED_TYPE_SIZE = bytes;
}
final byte[] bytes;
final int length;
final int end;
byte type;
int strlen;
byte strtype;
int strBegin;
byte[] valueBytes;
char[] charBuf;
final CacheItem cacheItem;
final SymbolTable symbolTable;
long symbol0Hash;
int symbol0Begin;
int symbol0Length;
byte symbol0StrType;
long[] symbols;
JSONReaderJSONB(Context ctx, InputStream is) {
super(ctx, true, false);
int cacheIndex = System.identityHashCode(Thread.currentThread()) & (CACHE_ITEMS.length - 1);
cacheItem = CACHE_ITEMS[cacheIndex];
byte[] bytes = BYTES_UPDATER.getAndSet(cacheItem, null);
int bufferSize = ctx.bufferSize;
if (bytes == null) {
bytes = new byte[bufferSize];
}
int off = 0;
try {
for (; ; ) {
int n = is.read(bytes, off, bytes.length - off);
if (n == -1) {
break;
}
off += n;
if (off == bytes.length) {
bytes = Arrays.copyOf(bytes, bytes.length + bufferSize);
}
}
} catch (IOException ioe) {
throw new JSONException("read error", ioe);
}
this.bytes = bytes;
this.offset = 0;
this.length = off;
this.end = length;
this.symbolTable = ctx.symbolTable;
}
JSONReaderJSONB(Context ctx, byte[] bytes, int off, int length) {
super(ctx, true, false);
this.bytes = bytes;
this.offset = off;
this.length = length;
this.end = off + length;
this.symbolTable = ctx.symbolTable;
this.cacheItem = CACHE_ITEMS[System.identityHashCode(Thread.currentThread()) & (CACHE_ITEMS.length - 1)];
}
@Override
public String getString() {
final byte strtype = this.strtype;
final int strlen = this.strlen;
if (strtype == BC_NULL) {
return null;
}
if (strlen < 0) {
return symbolTable.getName(-strlen);
}
Charset charset;
if (strtype == BC_STR_ASCII) {
charset = ISO_8859_1;
} else if (strtype >= BC_STR_ASCII_FIX_MIN && strtype <= BC_STR_ASCII_FIX_MAX) {
if (STRING_CREATOR_JDK8 != null) {
return latin1StringJDK8(bytes, strBegin, strlen);
} else if (STRING_CREATOR_JDK11 != null) {
byte[] chars = new byte[strlen];
System.arraycopy(bytes, strBegin, chars, 0, strlen);
return STRING_CREATOR_JDK11.apply(chars, LATIN1);
}
charset = ISO_8859_1;
} else if (strtype == BC_STR_UTF8) {
charset = StandardCharsets.UTF_8;
} else if (strtype == BC_STR_UTF16) {
charset = StandardCharsets.UTF_16;
} else if (strtype == BC_STR_UTF16LE) {
charset = StandardCharsets.UTF_16LE;
} else if (strtype == BC_STR_UTF16BE) {
charset = StandardCharsets.UTF_16BE;
// } else if (strtype == BC_SYMBOL) {
// int symbol = strlen;
// int index = symbol * 2;
// return symbols[index];
} else {
throw notSupportType(strtype);
}
return new String(bytes, strBegin, strlen, charset);
}
public int readLength() {
byte[] bytes = this.bytes;
int offset = this.offset, end = this.end;
int type = bytes[offset++];
if (isInt32Num(type)) {
// noop
} else if (isInt32Byte(type)) {
type = getIntByte(bytes, offset++, type);
} else if (isInt32Short(type) && offset + 1 < end) {
type = getInt3(bytes, offset, type);
offset += 2;
} else if (type == BC_INT32 && offset + 3 < end) {
type = getIntBE(bytes, offset);
offset += 4;
if (type > 1024 * 1024 * 256) {
throw new JSONException("input length overflow");
}
} else {
throw notSupportType((byte) type);
}
this.offset = offset;
return type;
}
private static int getIntByte(byte[] bytes, int offset, int type) {
return ((type - BC_INT32_BYTE_ZERO) << 8) + (bytes[offset] & 0xFF);
}
private static int getInt3(byte[] bytes, int offset, int type) {
return ((type - BC_INT32_SHORT_ZERO) << 16) + (getShortBE(bytes, offset) & 0xFFFF);
}
private static int getLongByte(byte[] bytes, int offset, int type) {
return ((type - BC_INT64_BYTE_ZERO) << 8) + (bytes[offset] & 0xFF);
}
private static int getLong3(byte[] bytes, int offset, int type) {
return (((type - BC_INT64_SHORT_ZERO) << 16) + (getShortBE(bytes, offset) & 0xFFFF));
}
@Override
public boolean isArray() {
byte type;
return offset < end
&& (type = bytes[offset]) >= BC_ARRAY_FIX_MIN
&& type <= BC_ARRAY;
}
@Override
public boolean isObject() {
return offset < end && bytes[offset] == BC_OBJECT;
}
@Override
public boolean isNumber() {
byte type = bytes[offset];
return type >= BC_DOUBLE_NUM_0 && type <= BC_INT32;
}
@Override
public boolean isString() {
return offset < end
&& (type = bytes[offset]) >= BC_STR_ASCII_FIX_MIN;
}
@Override
public boolean nextIfMatch(char ch) {
throw new JSONException("UnsupportedOperation");
}
@Override
public boolean nextIfArrayStart() {
throw new JSONException("UnsupportedOperation");
}
@Override
public boolean nextIfComma() {
throw new JSONException("UnsupportedOperation");
}
@Override
public boolean nextIfArrayEnd() {
throw new JSONException("UnsupportedOperation");
}
@Override
public boolean nextIfObjectStart() {
int offset = this.offset;
if (bytes[offset] != BC_OBJECT) {
return false;
}
this.offset = offset + 1;
return true;
}
@Override
public boolean nextIfObjectEnd() {
int offset = this.offset;
if (bytes[offset] != BC_OBJECT_END) {
return false;
}
this.offset = offset + 1;
return true;
}
@Override
public boolean nextIfNullOrEmptyString() {
int offset = this.offset;
byte bc = bytes[offset];
if (bc != BC_NULL && bc != BC_STR_ASCII_FIX_MIN) {
return false;
}
this.offset = offset + 1;
return true;
}
@Override
public <T> T read(Type type) {
boolean fieldBased = (context.features & Feature.FieldBased.mask) != 0;
ObjectReader objectReader = context.provider.getObjectReader(type, fieldBased);
return (T) objectReader.readJSONBObject(this, null, null, 0);
}
@Override
public <T> T read(Class<T> type) {
boolean fieldBased = (context.features & Feature.FieldBased.mask) != 0;
ObjectReader objectReader = context.provider.getObjectReader(type, fieldBased);
return (T) objectReader.readJSONBObject(this, null, null, 0);
}
@Override
public Map<String, Object> readObject() {
final int end = this.end;
final byte[] bytes = this.bytes;
final long features = context.features;
type = bytes[offset++];
if (type == BC_NULL) {
return null;
}
if (type >= BC_OBJECT) {
Map map;
if ((features & Feature.UseNativeObject.mask) != 0) {
if (JVM_VERSION == 8 && bytes[offset] != BC_OBJECT_END) {
map = new HashMap(10);
} else {
map = new HashMap();
}
} else {
if (JVM_VERSION == 8 && bytes[offset] != BC_OBJECT_END) {
map = new JSONObject(10);
} else {
map = new JSONObject();
}
}
for (int i = 0; ; ++i) {
type = bytes[offset];
if (type == BC_OBJECT_END) {
offset++;
break;
}
Object name;
if (isString()) {
name = readFieldName();
} else {
name = readAny();
}
if (offset < bytes.length && bytes[offset] == BC_REFERENCE) {
String reference = readReference();
if ("..".equals(reference)) {
map.put(name, map);
} else {
addResolveTask(map, name, JSONPath.of(reference));
}
continue;
}
byte valueType = bytes[offset];
Object value;
if (valueType >= BC_STR_ASCII_FIX_MIN && valueType <= BC_STR_GB18030) {
value = readString();
} else if (isInt32Num(valueType)) {
offset++;
value = (int) valueType;
} else if (valueType == BC_TRUE) {
offset++;
value = Boolean.TRUE;
} else if (valueType == BC_FALSE) {
offset++;
value = Boolean.FALSE;
} else if (valueType == BC_OBJECT) {
value = readObject();
} else if (valueType == BC_INT64) {
value = IOUtils.getLongBE(bytes, check7(offset + 1, end));
offset += 9;
} else if (valueType >= BC_ARRAY_FIX_MIN && valueType <= BC_ARRAY) {
offset++;
int len;
if (valueType == BC_ARRAY) {
byte itemType = bytes[offset];
if (isInt32Num(itemType)) {
offset++;
len = itemType;
} else {
len = readLength();
}
} else {
len = valueType - BC_ARRAY_FIX_MIN;
}
if (len == 0) {
if ((features & Feature.UseNativeObject.mask) != 0) {
value = new ArrayList<>();
} else {
if (context.arraySupplier != null) {
value = context.arraySupplier.get();
} else {
value = new JSONArray();
}
}
} else {
List list;
if ((features & Feature.UseNativeObject.mask) != 0) {
list = new ArrayList(len);
} else {
list = new JSONArray(len);
}
for (int j = 0; j < len; ++j) {
if (isReference()) {
String reference = readReference();
if ("..".equals(reference)) {
list.add(list);
} else {
list.add(null);
addResolveTask(list, j, JSONPath.of(reference));
}
continue;
}
byte itemType = bytes[offset];
Object item;
if (itemType >= BC_STR_ASCII_FIX_MIN && itemType <= BC_STR_GB18030) {
item = readString();
} else if (itemType == BC_OBJECT) {
item = readObject();
} else {
item = readAny();
}
list.add(item);
}
value = list;
}
//
} else if (isInt32Byte(valueType)) {
value = getIntByte(bytes, offset + 1, valueType);
offset += 2;
} else if (isInt32Short(valueType) && offset + 1 < end) {
int int32Value = getInt3(bytes, offset + 1, valueType);
offset += 3;
value = int32Value;
} else if (valueType == BC_INT32 && offset + 3 < end) {
int int32Value = getIntBE(bytes, offset + 1);
offset += 5;
value = int32Value;
} else {
value = readAny();
}
if (value == null && (features & Feature.IgnoreNullPropertyValue.mask) != 0) {
continue;
}
map.put(name, value);
}
return map;
}
if (type == BC_TYPED_ANY) {
ObjectReader objectReader = checkAutoType(Map.class, 0, 0);
return (Map) objectReader.readObject(this, null, null, 0);
}
throw notSupportType(type);
}
@Override
public void read(final Map map, long features) {
if (bytes[offset] != BC_OBJECT) {
throw new JSONException("object not support input " + error(type));
}
offset++;
long contextFeatures = features | context.getFeatures();
while (true) {
byte type = bytes[offset];
if (type == BC_OBJECT_END) {
offset++;
break;
}
Object name;
if (type >= BC_STR_ASCII_FIX_MIN) {
name = readFieldName();
} else {
name = readAny();
}
if (isReference()) {
String reference = readReference();
if ("..".equals(reference)) {
map.put(name, map);
} else {
addResolveTask(map, name, JSONPath.of(reference));
map.put(name, null);
}
continue;
}
byte valueType = bytes[offset];
Object value;
if (valueType >= BC_STR_ASCII_FIX_MIN && valueType <= BC_STR_GB18030) {
value = readString();
} else if (isInt32Num(valueType)) {
offset++;
value = (int) valueType;
} else if (valueType == BC_TRUE) {
offset++;
value = Boolean.TRUE;
} else if (valueType == BC_FALSE) {
offset++;
value = Boolean.FALSE;
} else if (valueType == BC_OBJECT) {
value = readObject();
} else {
value = readAny();
}
if (value == null && (contextFeatures & Feature.IgnoreNullPropertyValue.mask) != 0) {
continue;
}
map.put(name, value);
}
}
@Override
public Object readAny() {
int end = this.end;
byte[] bytes = this.bytes;
if (offset >= bytes.length) {
throw new JSONException("readAny overflow : " + offset + "/" + bytes.length);
}
type = bytes[offset++];
switch (type) {
case BC_NULL:
return null;
case BC_TRUE:
return true;
case BC_FALSE:
return false;
case BC_INT8:
return bytes[offset++];
case BC_INT16:
return (short) ((bytes[offset++] << 8)
+ (bytes[offset++] & 0xFF));
case BC_INT32: {
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
return int32Value;
}
case BC_INT64_INT: {
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
return (long) int32Value;
}
case BC_INT64: {
long int64Value = getLongBE(bytes, check7(offset, end));
offset += 8;
return int64Value;
}
case BC_BIGINT: {
int len = readInt32Value();
byte[] buf = new byte[len];
System.arraycopy(bytes, offset, buf, 0, len);
offset += len;
return new BigInteger(buf);
}
case BC_FLOAT: {
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
return Float.intBitsToFloat(int32Value);
}
case BC_FLOAT_INT: {
return (float) readInt32Value();
}
case BC_DOUBLE: {
long int64Value = getLongBE(bytes, check7(offset, end));
offset += 8;
return Double.longBitsToDouble(int64Value);
}
case BC_DOUBLE_LONG: {
return (double) readInt64Value();
}
case BC_STR_UTF8: {
int strlen = readLength();
if (STRING_CREATOR_JDK11 != null && !JDKUtils.BIG_ENDIAN) {
if (valueBytes == null) {
valueBytes = BYTES_UPDATER.getAndSet(cacheItem, null);
if (valueBytes == null) {
valueBytes = new byte[8192];
}
}
int minCapacity = strlen << 1;
if (minCapacity > valueBytes.length) {
valueBytes = new byte[minCapacity];
}
int utf16_len = IOUtils.decodeUTF8(bytes, offset, strlen, valueBytes);
if (utf16_len != -1) {
byte[] value = new byte[utf16_len];
System.arraycopy(valueBytes, 0, value, 0, utf16_len);
String str = STRING_CREATOR_JDK11.apply(value, UTF16);
offset += strlen;
return str;
}
}
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_8);
offset += strlen;
return str;
}
case BC_STR_UTF16: {
int strlen = readLength();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_16);
offset += strlen;
return str;
}
case BC_STR_UTF16LE: {
int strlen = readLength();
String str;
if (STRING_CREATOR_JDK11 != null && !JDKUtils.BIG_ENDIAN) {
byte[] chars = new byte[strlen];
System.arraycopy(bytes, offset, chars, 0, strlen);
str = STRING_CREATOR_JDK11.apply(chars, strlen == 0 ? LATIN1 : UTF16);
} else {
str = new String(bytes, offset, strlen, StandardCharsets.UTF_16LE);
}
offset += strlen;
return str;
}
case BC_STR_UTF16BE: {
int strlen = readLength();
String str;
if (STRING_CREATOR_JDK11 != null && JDKUtils.BIG_ENDIAN) {
byte[] chars = new byte[strlen];
System.arraycopy(bytes, offset, chars, 0, strlen);
str = STRING_CREATOR_JDK11.apply(chars, strlen == 0 ? LATIN1 : UTF16);
} else {
str = new String(bytes, offset, strlen, StandardCharsets.UTF_16BE);
}
offset += strlen;
return str;
}
case BC_STR_GB18030: {
if (GB18030 == null) {
GB18030 = Charset.forName("GB18030");
}
int strlen = readLength();
String str = new String(bytes, offset, strlen, GB18030);
offset += strlen;
return str;
}
case BC_DECIMAL: {
int scale = readInt32Value();
BigInteger unscaledValue = readBigInteger();
BigDecimal decimal;
if (scale == 0) {
decimal = new BigDecimal(unscaledValue);
} else {
decimal = new BigDecimal(unscaledValue, scale);
}
return decimal;
}
case BC_DECIMAL_LONG: {
return BigDecimal.valueOf(
readInt64Value()
);
}
case BC_BINARY: {
int len = readLength();
byte[] binary = Arrays.copyOfRange(this.bytes, offset, offset + len);
offset += len;
return binary;
}
case BC_TIMESTAMP_MINUTES: {
long minutes = getIntBE(bytes, check3(offset, end));
offset += 4;
return new Date(minutes * 60L * 1000L);
}
case BC_TIMESTAMP_SECONDS: {
long seconds = getIntBE(bytes, check3(offset, end));
offset += 4;
return new Date(seconds * 1000);
}
case BC_LOCAL_DATE: {
int year = (bytes[offset++] << 8) + (bytes[offset++] & 0xFF);
byte month = bytes[offset++];
byte dayOfMonth = bytes[offset++];
return LocalDate.of(year, month, dayOfMonth);
}
case BC_LOCAL_TIME: {
byte hour = bytes[offset++];
byte minute = bytes[offset++];
byte second = bytes[offset++];
int nano = readInt32Value();
return LocalTime.of(hour, minute, second, nano);
}
case BC_LOCAL_DATETIME: {
int year = (bytes[offset++] << 8) + (bytes[offset++] & 0xFF);
byte month = bytes[offset++];
byte dayOfMonth = bytes[offset++];
byte hour = bytes[offset++];
byte minute = bytes[offset++];
byte second = bytes[offset++];
int nano = readInt32Value();
return LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nano);
}
case BC_TIMESTAMP_WITH_TIMEZONE: {
return readTimestampWithTimeZone();
}
case BC_TIMESTAMP: {
long epochSeconds = readInt64Value();
int nano = readInt32Value();
return Instant.ofEpochSecond(epochSeconds, nano);
}
case BC_TIMESTAMP_MILLIS: {
long millis = IOUtils.getLongBE(bytes, check7(offset, end));
offset += 8;
return new Date(millis);
}
case BC_BIGINT_LONG: {
return BigInteger.valueOf(
readInt64Value()
);
}
case BC_TYPED_ANY: {
long typeHash = readTypeHashCode();
if (context.autoTypeBeforeHandler != null) {
Class<?> filterClass = context.autoTypeBeforeHandler.apply(typeHash, null, context.features);
if (filterClass == null) {
String typeName = getString();
filterClass = context.autoTypeBeforeHandler.apply(typeName, null, context.features);
}
if (filterClass != null) {
ObjectReader autoTypeObjectReader = context.getObjectReader(filterClass);
return autoTypeObjectReader.readJSONBObject(this, null, null, 0);
}
}
boolean supportAutoType = (context.features & Feature.SupportAutoType.mask) != 0;
if (!supportAutoType) {
if (isObject()) {
return readObject();
}
if (isArray()) {
return readArray();
}
throw new JSONException("autoType not support , offset " + offset + "/" + bytes.length);
}
ObjectReader autoTypeObjectReader = context.getObjectReaderAutoType(typeHash);
if (autoTypeObjectReader == null) {
String typeName = getString();
autoTypeObjectReader = context.getObjectReaderAutoType(typeName, null);
if (autoTypeObjectReader == null) {
throw new JSONException("autoType not support : " + typeName + ", offset " + offset + "/" + bytes.length);
}
}
return autoTypeObjectReader.readJSONBObject(this, null, null, 0);
}
case BC_DOUBLE_NUM_0:
return 0D;
case BC_DOUBLE_NUM_1:
return 1D;
case BC_CHAR:
int intValue = readInt32Value();
return (char) intValue;
case BC_OBJECT: {
Map map = null;
boolean supportAutoType = (context.features & Feature.SupportAutoType.mask) != 0;
for (int i = 0; ; ++i) {
byte type = bytes[offset];
if (type == BC_OBJECT_END) {
offset++;
break;
}
Object name;
if (supportAutoType && i == 0 && type >= BC_STR_ASCII_FIX_MIN) {
long hash = readFieldNameHashCode();
if (hash == ObjectReader.HASH_TYPE) {
long typeHash = readValueHashCode();
ObjectReader autoTypeObjectReader = context.getObjectReaderAutoType(typeHash);
if (autoTypeObjectReader == null) {
String typeName = getString();
autoTypeObjectReader = context.getObjectReaderAutoType(typeName, null);
if (autoTypeObjectReader == null) {
throw new JSONException("autoType not support : " + typeName + ", offset " + offset + "/" + bytes.length);
}
}
typeRedirect = true;
return autoTypeObjectReader.readJSONBObject(this, null, null, 0);
}
name = getFieldName();
} else {
if (type >= BC_STR_ASCII_FIX_MIN) {
name = readFieldName();
} else {
name = readAny();
}
}
if (map == null) {
if ((context.features & Feature.UseNativeObject.mask) != 0) {
map = new HashMap();
} else {
map = new JSONObject();
}
}
if (isReference()) {
String reference = readReference();
if ("..".equals(reference)) {
map.put(name, map);
} else {
addResolveTask(map, name, JSONPath.of(reference));
map.put(name, null);
}
continue;
}
byte valueType = bytes[offset];
Object value;
if (valueType >= BC_STR_ASCII_FIX_MIN && valueType <= BC_STR_GB18030) {
value = readString();
} else if (isInt32Num(valueType)) {
offset++;
value = (int) valueType;
} else if (valueType == BC_TRUE) {
offset++;
value = Boolean.TRUE;
} else if (valueType == BC_FALSE) {
offset++;
value = Boolean.FALSE;
} else if (valueType == BC_OBJECT) {
value = readObject();
} else {
value = readAny();
}
if (value == null && (context.features & Feature.IgnoreNullPropertyValue.mask) != 0) {
continue;
}
map.put(name, value);
}
if (map == null) {
if ((context.features & Feature.UseNativeObject.mask) != 0) {
map = new HashMap();
} else {
map = new JSONObject();
}
}
return map;
}
default:
final byte type = this.type;
if (isInt32Num(type)) {
return (int) type;
}
if (isInt32Byte(type)) {
return getIntByte(bytes, offset++, type);
}
if (isInt32Short(type) && offset + 1 < end) {
int int3 = getInt3(bytes, offset, type);
offset += 2;
return int3;
}
if (isInt64Num(type)) {
return (long) INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
}
if (isInt64Byte(type)) {
return (long) getLongByte(bytes, offset++, type);
}
if (isInt64Short(type) && offset + 1 < end) {
long value = getLong3(bytes, offset, type);
offset += 2;
return value;
}
if (type >= BC_ARRAY_FIX_MIN && type <= BC_ARRAY) {
int len = type == BC_ARRAY
? readLength()
: type - BC_ARRAY_FIX_MIN;
if (len == 0) {
if ((context.features & Feature.UseNativeObject.mask) != 0) {
return new ArrayList<>();
} else {
if (context.arraySupplier != null) {
return context.arraySupplier.get();
}
return new JSONArray();
}
}
List list;
if ((context.features & Feature.UseNativeObject.mask) != 0) {
list = new ArrayList(len);
} else {
list = new JSONArray(len);
}
for (int i = 0; i < len; ++i) {
if (isReference()) {
String reference = readReference();
if ("..".equals(reference)) {
list.add(list);
} else {
list.add(null);
addResolveTask(list, i, JSONPath.of(reference));
}
continue;
}
Object item = readAny();
list.add(item);
}
return list;
}
if (type >= BC_STR_ASCII_FIX_MIN && type <= BC_STR_ASCII) {
strlen = type == BC_STR_ASCII
? readLength()
: type - BC_STR_ASCII_FIX_MIN;
if (strlen < 0) {
return symbolTable.getName(-strlen);
}
if (STRING_CREATOR_JDK8 != null) {
String str = latin1StringJDK8(bytes, offset, strlen);
offset += strlen;
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
// empty string to null
if (str.isEmpty() && (context.features & Feature.EmptyStringAsNull.mask) != 0) {
str = null;
}
return str;
} else if (STRING_CREATOR_JDK11 != null) {
byte[] chars = new byte[strlen];
System.arraycopy(bytes, offset, chars, 0, strlen);
offset += strlen;
String str = STRING_CREATOR_JDK11.apply(chars, LATIN1);
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
// empty string to null
if (str.isEmpty() && (context.features & Feature.EmptyStringAsNull.mask) != 0) {
str = null;
}
return str;
}
String str = new String(bytes, offset, strlen, ISO_8859_1);
offset += strlen;
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
// empty string to null
if (str.isEmpty() && (context.features & Feature.EmptyStringAsNull.mask) != 0) {
str = null;
}
return str;
}
if (type == BC_SYMBOL) {
strlen = readLength();
if (strlen >= 0) {
throw new JSONException("not support symbol : " + strlen);
}
return symbolTable.getName(-strlen);
}
throw new JSONException("not support type : " + error(type));
}
}
private ZonedDateTime readTimestampWithTimeZone() {
byte[] bytes = this.bytes;
int year = (bytes[offset++] << 8) + (bytes[offset++] & 0xFF);
byte month = bytes[offset++];
byte dayOfMonth = bytes[offset++];
byte hour = bytes[offset++];
byte minute = bytes[offset++];
byte second = bytes[offset++];
int nano = readInt32Value();
// SHANGHAI_ZONE_ID_NAME_BYTES
ZoneId zoneId;
{
boolean shanghai;
byte[] shanghaiZoneIdNameBytes = SHANGHAI_ZONE_ID_NAME_BYTES;
if (offset + shanghaiZoneIdNameBytes.length < bytes.length) {
shanghai = true;
for (int i = 0; i < shanghaiZoneIdNameBytes.length; ++i) {
if (bytes[offset + i] != shanghaiZoneIdNameBytes[i]) {
shanghai = false;
break;
}
}
} else {
shanghai = false;
}
if (shanghai) {
offset += shanghaiZoneIdNameBytes.length;
zoneId = SHANGHAI_ZONE_ID;
} else {
String zoneIdStr = readString();
zoneId = DateUtils.getZoneId(zoneIdStr, SHANGHAI_ZONE_ID);
}
}
LocalDateTime ldt = LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nano);
return ZonedDateTime.of(ldt, zoneId);
}
@Override
public byte getType() {
return bytes[offset];
}
@Override
public List readArray() {
int entryCnt = startArray();
JSONArray array = new JSONArray(entryCnt);
for (int i = 0; i < entryCnt; i++) {
byte valueType = bytes[offset];
Object value;
if (valueType >= BC_STR_ASCII_FIX_MIN && valueType <= BC_STR_GB18030) {
value = readString();
} else if (isInt32Num(valueType)) {
offset++;
value = (int) valueType;
} else if (valueType == BC_TRUE) {
offset++;
value = Boolean.TRUE;
} else if (valueType == BC_FALSE) {
offset++;
value = Boolean.FALSE;
} else if (valueType == BC_OBJECT) {
value = readObject();
} else if (valueType == BC_INT64) {
offset++;
value = getLongBE(bytes, check7(offset, end));
offset += 8;
} else if (valueType >= BC_ARRAY_FIX_MIN && valueType <= BC_ARRAY) {
offset++;
int len = valueType == BC_ARRAY
? readLength()
: valueType - BC_ARRAY_FIX_MIN;
if (len == 0) {
if ((context.features & Feature.UseNativeObject.mask) != 0) {
value = new ArrayList<>();
} else {
if (context.arraySupplier != null) {
value = context.arraySupplier.get();
} else {
value = new JSONArray();
}
}
} else {
List list;
if ((context.features & Feature.UseNativeObject.mask) != 0) {
list = new ArrayList(len);
} else {
list = new JSONArray(len);
}
for (int j = 0; j < len; ++j) {
if (isReference()) {
String reference = readReference();
if ("..".equals(reference)) {
list.add(list);
} else {
list.add(null);
addResolveTask(list, j, JSONPath.of(reference));
}
continue;
}
byte itemType = bytes[offset];
Object item;
if (itemType >= BC_STR_ASCII_FIX_MIN && itemType <= BC_STR_GB18030) {
item = readString();
} else if (itemType == BC_OBJECT) {
item = readObject();
} else {
item = readAny();
}
list.add(item);
}
value = list;
}
//
} else if (isInt32Byte(valueType)) {
value = getIntByte(bytes, offset + 1, valueType);
offset += 2;
} else if (isInt64Short(valueType) && offset + 2 < end) {
int int3 = getLong3(bytes, offset + 1, valueType);
offset += 3;
value = int3;
} else if (valueType == BC_INT32) {
value = getIntBE(bytes, check3(offset + 1, end));
offset += 5;
} else if (valueType == BC_REFERENCE) {
String reference = readReference();
if ("..".equals(reference)) {
value = array;
} else {
addResolveTask(array, i, JSONPath.of(reference));
continue;
}
} else {
value = readAny();
}
array.add(value);
}
return array;
}
@Override
public List readArray(Type itemType) {
if (nextIfNull()) {
return null;
}
if (bytes[offset] == BC_TYPED_ANY) {
Object obj = readAny();
if (obj instanceof List) {
return (List) obj;
}
if (obj instanceof Collection) {
return new JSONArray((Collection) obj);
}
throw new JSONException("not support class " + obj.getClass());
}
int entryCnt = startArray();
JSONArray array = new JSONArray(entryCnt);
for (int i = 0; i < entryCnt; i++) {
array.add(read(itemType));
}
return array;
}
@Override
public List readList(Type[] types) {
if (nextIfNull()) {
return null;
}
int entryCnt = startArray();
JSONArray array = new JSONArray(entryCnt);
for (int i = 0; i < entryCnt; i++) {
Type itemType = types[i];
array.add(read(itemType));
}
return array;
}
@Override
public byte[] readHex() {
String str = readString();
byte[] bytes = new byte[str.length() / 2];
for (int i = 0; i < bytes.length; ++i) {
char c0 = str.charAt(i * 2);
char c1 = str.charAt(i * 2 + 1);
int b0 = c0 - (c0 <= 57 ? 48 : 55);
int b1 = c1 - (c1 <= 57 ? 48 : 55);
bytes[i] = (byte) ((b0 << 4) | b1);
}
return bytes;
}
@Override
public boolean isReference() {
return offset < bytes.length && bytes[offset] == BC_REFERENCE;
}
@Override
public String readReference() {
if (bytes[offset] != BC_REFERENCE) {
return null;
}
offset++;
if (isString()) {
return readString();
}
throw new JSONException("reference not support input " + error(type));
}
public boolean readReference(Collection list, int i) {
if (bytes[offset] != BC_REFERENCE) {
return false;
}
offset++;
String path = readString();
if ("..".equals(path)) {
list.add(list);
} else {
addResolveTask(list, i, JSONPath.of(path));
}
return true;
}
Object readAnyObject() {
if (bytes[offset] != BC_TYPED_ANY) {
return readAny();
}
Context context = this.context;
offset++;
final long typeHash = readTypeHashCode();
ObjectReader autoTypeObjectReader = null;
AutoTypeBeforeHandler autoTypeBeforeHandler = context.autoTypeBeforeHandler;
if (autoTypeBeforeHandler != null) {
Class<?> objectClass = autoTypeBeforeHandler.apply(typeHash, Object.class, 0L);
if (objectClass == null) {
objectClass = autoTypeBeforeHandler.apply(getString(), Object.class, 0L);
}
if (objectClass != null) {
autoTypeObjectReader = context.getObjectReader(objectClass);
}
}
final long features = context.features;
if (autoTypeObjectReader == null) {
if ((features & Feature.SupportAutoType.mask) == 0) {
if ((features & Feature.ErrorOnNotSupportAutoType.mask) == 0) {
return null;
}
autoTypeError();
}
autoTypeObjectReader = context.provider.getObjectReader(typeHash);
}
if (autoTypeObjectReader != null) {
Class objectClass = autoTypeObjectReader.getObjectClass();
if (objectClass != null) {
ClassLoader classLoader = objectClass.getClassLoader();
if (classLoader != null) {
ClassLoader tcl = Thread.currentThread().getContextClassLoader();
if (classLoader != tcl) {
autoTypeObjectReader = getObjectReaderContext(autoTypeObjectReader, objectClass, tcl);
}
}
}
}
if (autoTypeObjectReader == null) {
autoTypeObjectReader = context.provider.getObjectReader(getString(), Object.class, features);
if (autoTypeObjectReader == null) {
if ((features & Feature.ErrorOnNotSupportAutoType.mask) == 0) {
return null;
}
autoTypeError();
}
}
this.type = bytes[offset];
return autoTypeObjectReader.readJSONBObject(this, Object.class, null, context.features);
}
@Override
public ObjectReader checkAutoType(Class expectClass, long expectClassHash, long features) {
ObjectReader autoTypeObjectReader = null;
if (bytes[offset] == BC_TYPED_ANY) {
offset++;
Context context = this.context;
final long typeHash = readTypeHashCode();
if (expectClassHash == typeHash) {
ObjectReader objectReader = context.getObjectReader(expectClass);
Class objectClass = objectReader.getObjectClass();
if (objectClass != null && objectClass == expectClass) {
context.provider.registerIfAbsent(typeHash, objectReader);
return objectReader;
}
}
AutoTypeBeforeHandler autoTypeBeforeHandler = context.autoTypeBeforeHandler;
if (autoTypeBeforeHandler != null) {
ObjectReader objectReader = checkAutoTypeWithHandler(expectClass, features, autoTypeBeforeHandler, typeHash);
if (objectReader != null) {
return objectReader;
}
}
final long features2 = context.features | features;
if ((features2 & Feature.SupportAutoType.mask) == 0) {
if ((features2 & Feature.ErrorOnNotSupportAutoType.mask) == 0) {
return null;
}
autoTypeError();
}
autoTypeObjectReader = context.provider.getObjectReader(typeHash);
if (autoTypeObjectReader != null) {
Class objectClass = autoTypeObjectReader.getObjectClass();
if (objectClass != null) {
ClassLoader classLoader = objectClass.getClassLoader();
if (classLoader != null) {
ClassLoader tcl = Thread.currentThread().getContextClassLoader();
if (classLoader != tcl) {
autoTypeObjectReader = getObjectReaderContext(autoTypeObjectReader, objectClass, tcl);
}
}
}
}
if (autoTypeObjectReader == null) {
autoTypeObjectReader = context.provider.getObjectReader(getString(), expectClass, features2);
if (autoTypeObjectReader == null) {
if ((features2 & Feature.ErrorOnNotSupportAutoType.mask) == 0) {
return null;
}
autoTypeError();
}
}
this.type = bytes[offset];
}
return autoTypeObjectReader;
}
ObjectReader checkAutoTypeWithHandler(
Class expectClass,
long features,
AutoTypeBeforeHandler autoTypeBeforeHandler,
long typeHash
) {
Class<?> objectClass = autoTypeBeforeHandler.apply(typeHash, expectClass, features);
if (objectClass == null) {
objectClass = autoTypeBeforeHandler.apply(getString(), expectClass, features);
}
if (objectClass != null) {
return context.getObjectReader(objectClass);
}
return null;
}
void autoTypeError() {
throw new JSONException("autoType not support : " + getString());
}
private ObjectReader getObjectReaderContext(
ObjectReader autoTypeObjectReader,
Class objectClass,
ClassLoader contextClassLoader
) {
String typeName = getString();
Class contextClass = TypeUtils.getMapping(typeName);
if (contextClass == null) {
try {
contextClass
= (contextClassLoader != null ? contextClassLoader : JSON.class.getClassLoader())
.loadClass(typeName);
} catch (ClassNotFoundException ignored) {
}
}
if (contextClass != null && !objectClass.equals(contextClass)) {
autoTypeObjectReader = getObjectReader(contextClass);
}
return autoTypeObjectReader;
}
@Override
public int startArray() {
final byte type = this.type = bytes[offset++];
if (type == BC_NULL) {
return -1;
}
if (type >= BC_ARRAY_FIX_MIN && type <= BC_ARRAY_FIX_MAX) {
ch = (char) -type;
return type - BC_ARRAY_FIX_MIN;
}
if (type == BC_BINARY) {
return readInt32Value();
}
if (type != BC_ARRAY) {
throw new JSONException("array not support input " + error(type));
}
return readInt32Value();
}
public String error(byte type) {
StringBuilder buf = new StringBuilder();
buf.append(typeName(type));
if (isString()) {
int mark = offset;
offset--;
String str = null;
try {
str = readString();
} catch (Throwable ignored) {
}
if (str != null) {
buf.append(' ');
buf.append(str);
}
offset = mark;
}
buf.append(", offset ");
buf.append(offset);
buf.append('/');
buf.append(bytes.length);
return buf.toString();
}
@Override
public void next() {
offset++;
}
@Override
public long readFieldNameHashCode() {
byte[] bytes = this.bytes;
byte strtype = this.strtype = bytes[offset++];
boolean typeSymbol = strtype == BC_SYMBOL;
if (typeSymbol) {
strtype = this.strtype = bytes[offset];
if (isInt32(strtype)) {
int symbol;
if (strtype <= BC_INT32_NUM_MAX) {
offset++;
symbol = strtype;
} else {
symbol = readInt32Value();
}
if (symbol < 0) {
return symbolTable.getHashCode(-symbol);
}
if (symbol == 0) {
this.strtype = symbol0StrType;
this.strlen = symbol0Length;
this.strBegin = symbol0Begin;
if (symbol0Hash == 0) {
symbol0Hash = getNameHashCode();
}
return symbol0Hash;
}
int index = symbol * 2;
long strInfo = symbols[index + 1];
this.strtype = (byte) strInfo;
this.strlen = ((int) strInfo) >> 8;
this.strBegin = (int) (strInfo >> 32);
long nameHashCode = symbols[index];
if (nameHashCode == 0) {
nameHashCode = getNameHashCode();
symbols[index] = nameHashCode;
}
return nameHashCode;
}
offset++;
}
final int strlen;
if (strtype >= BC_STR_ASCII_FIX_MIN && strtype <= BC_STR_ASCII_FIX_MAX) {
strlen = strtype - BC_STR_ASCII_FIX_MIN;
} else if (strtype == BC_STR_ASCII || strtype == BC_STR_UTF8) {
strlen = readLength();
} else {
throw readFieldNameHashCodeError();
}
this.strlen = strlen;
strBegin = offset;
long hashCode;
if (strlen < 0) {
hashCode = symbolTable.getHashCode(-strlen);
} else {
long nameValue = 0;
if (strlen <= 8 && offset + strlen <= bytes.length) {
long offsetBase = this.offset + BASE;
switch (strlen) {
case 1:
nameValue = bytes[offset];
break;
case 2:
nameValue = UNSAFE.getShort(bytes, offsetBase) & 0xFFFFL;
break;
case 3:
nameValue = (bytes[offset + 2] << 16)
+ (UNSAFE.getShort(bytes, offsetBase) & 0xFFFFL);
break;
case 4:
nameValue = UNSAFE.getInt(bytes, offsetBase);
break;
case 5:
nameValue = (((long) bytes[offset + 4]) << 32)
+ (UNSAFE.getInt(bytes, offsetBase) & 0xFFFFFFFFL);
break;
case 6:
nameValue = ((long) UNSAFE.getShort(bytes, offsetBase + 4) << 32)
+ (UNSAFE.getInt(bytes, offsetBase) & 0xFFFFFFFFL);
break;
case 7:
nameValue = (((long) bytes[offset + 6]) << 48)
+ (((long) bytes[offset + 5] & 0xFFL) << 40)
+ (((long) bytes[offset + 4] & 0xFFL) << 32)
+ (UNSAFE.getInt(bytes, offsetBase) & 0xFFFFFFFFL);
break;
default:
nameValue = UNSAFE.getLong(bytes, offsetBase);
break;
}
}
if (nameValue != 0) {
offset += strlen;
hashCode = nameValue;
} else {
hashCode = Fnv.MAGIC_HASH_CODE;
for (int i = 0; i < strlen; ++i) {
hashCode ^= bytes[offset++];
hashCode *= Fnv.MAGIC_PRIME;
}
}
}
if (typeSymbol) {
int symbol;
if (isInt32Num(symbol = bytes[offset])) {
offset++;
} else {
symbol = readInt32Value();
}
if (symbol == 0) {
symbol0Begin = strBegin;
symbol0Length = strlen;
symbol0StrType = strtype;
symbol0Hash = hashCode;
} else {
int symbolIndex = symbol << 1;
int minCapacity = symbolIndex + 2;
if (symbols == null) {
symbols = new long[Math.max(minCapacity, 32)];
} else if (symbols.length < minCapacity) {
symbols = Arrays.copyOf(symbols, minCapacity + 16);
}
symbols[symbolIndex] = hashCode;
symbols[symbolIndex + 1] = ((long) strBegin << 32) + ((long) strlen << 8) + strtype;
}
}
return hashCode;
}
JSONException readFieldNameHashCodeError() {
StringBuilder message = new StringBuilder()
.append("fieldName not support input type ")
.append(typeName(strtype));
if (strtype == BC_REFERENCE) {
message.append(" ")
.append(readString());
}
message.append(", offset ")
.append(offset);
return new JSONException(message.toString());
}
@Override
public boolean isInt() {
int type = bytes[offset];
return (type >= BC_BIGINT_LONG && type <= BC_INT32)
|| type == BC_TIMESTAMP_SECONDS
|| type == BC_TIMESTAMP_MINUTES
|| type == BC_TIMESTAMP_MILLIS;
}
@Override
public boolean isNull() {
return bytes[offset] == BC_NULL;
}
@Override
public Date readNullOrNewDate() {
throw new JSONException("UnsupportedOperation");
}
@Override
public boolean nextIfNull() {
if (bytes[offset] == BC_NULL) {
offset++;
return true;
}
return false;
}
@Override
public void readNull() {
type = bytes[offset++];
if (type != BC_NULL) {
throw new JSONException("null not match, " + type);
}
}
@Override
public boolean readIfNull() {
if (bytes[offset] == BC_NULL) {
offset++;
return true;
}
return false;
}
@Override
public long readTypeHashCode() {
final byte[] bytes = this.bytes;
int offset = this.offset;
byte strtype = this.strtype = bytes[offset];
int type, typelen;
long hashCode;
// strlen > 8
if (strtype == BC_STR_ASCII && (type = bytes[++offset]) > 8 && type <= BC_INT32_BYTE_MAX) {
if (type <= BC_INT32_NUM_MAX) {
offset++;
typelen = type;
} else {
typelen = ((type - BC_INT32_BYTE_ZERO) << 8) + (bytes[offset + 1] & 0xFF);
offset += 2;
}
int strBegin = offset;
hashCode = Fnv.MAGIC_HASH_CODE;
for (int i = 0; i < typelen; ++i) {
hashCode ^= bytes[offset++];
hashCode *= Fnv.MAGIC_PRIME;
}
int symbol;
if ((symbol = bytes[offset]) >= 0 && symbol <= BC_INT32_NUM_MAX) {
offset++;
if (symbol == 0) {
symbol0Begin = strBegin;
symbol0Length = typelen;
symbol0StrType = strtype;
symbol0Hash = hashCode;
} else {
int minCapacity = symbol * 2 + 2;
if (symbols == null) {
symbols = new long[Math.max(minCapacity, 32)];
} else if (symbols.length < minCapacity) {
symbols = Arrays.copyOf(symbols, minCapacity + 16);
}
symbols[symbol * 2 + 1] = ((long) strBegin << 32) + ((long) typelen << 8) + strtype;
}
this.strBegin = strBegin;
this.strlen = typelen;
this.offset = offset;
return hashCode;
}
}
return readTypeHashCode0();
}
public long readTypeHashCode0() {
final byte[] bytes = this.bytes;
byte strtype = this.strtype = bytes[offset];
if (strtype == BC_SYMBOL) {
offset++;
strtype = this.strtype = bytes[offset];
if (isInt32(strtype)) {
int symbol;
if (strtype <= BC_INT32_NUM_MAX) {
offset++;
symbol = strtype;
} else {
symbol = readInt32Value();
}
if (symbol < 0) {
return symbolTable.getHashCode(-symbol);
}
if (symbol == 0) {
this.strtype = symbol0StrType;
strlen = symbol0Length;
strBegin = symbol0Begin;
if (symbol0Hash == 0) {
symbol0Hash = getNameHashCode();
}
return symbol0Hash;
}
int index = symbol * 2;
long strInfo = symbols[index + 1];
this.strtype = (byte) strInfo;
strlen = ((int) strInfo) >> 8;
strBegin = (int) (strInfo >> 32);
long nameHashCode = symbols[index];
if (nameHashCode == 0) {
nameHashCode = getNameHashCode();
symbols[index] = nameHashCode;
}
return nameHashCode;
}
}
if (isInt32(strtype)) {
int typeIndex;
if (strtype <= BC_INT32_NUM_MAX) {
offset++;
typeIndex = strtype;
} else if (strtype <= BC_INT32_BYTE_MAX) {
offset++;
typeIndex = ((strtype - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
} else {
typeIndex = readInt32Value();
}
long refTypeHash;
if (typeIndex == 0) {
this.strtype = symbol0StrType;
strlen = symbol0Length;
strBegin = symbol0Begin;
if (symbol0Hash == 0) {
symbol0Hash = Fnv.hashCode64(getString());
}
refTypeHash = symbol0Hash;
} else if (typeIndex < 0) {
strlen = strtype;
refTypeHash = symbolTable.getHashCode(-typeIndex);
} else {
refTypeHash = symbols[typeIndex * 2];
if (refTypeHash == 0) {
long strInfo = symbols[typeIndex * 2 + 1];
this.strtype = (byte) strInfo;
strlen = ((int) strInfo) >> 8;
strBegin = (int) (strInfo >> 32);
refTypeHash = Fnv.hashCode64(getString());
}
}
if (refTypeHash == -1) {
throw typeRefNotFound(typeIndex);
}
return refTypeHash;
}
offset++;
strBegin = offset;
if (strtype >= BC_STR_ASCII_FIX_MIN && strtype <= BC_STR_ASCII_FIX_MAX) {
strlen = strtype - BC_STR_ASCII_FIX_MIN;
} else if (strtype == BC_STR_ASCII
|| strtype == BC_STR_UTF8
|| strtype == BC_STR_UTF16
|| strtype == BC_STR_UTF16LE
|| strtype == BC_STR_UTF16BE
) {
byte type = bytes[offset];
if (isInt32Num(type)) {
offset++;
strlen = type;
} else if (isInt32Byte(type)) { // type >= BC_INT32_BYTE_MIN && type <= BC_INT32_BYTE_MAX
offset++;
strlen = getIntByte(bytes, offset++, type);
} else {
strlen = readLength();
}
strBegin = offset;
} else {
throw readStringError();
}
long hashCode;
if (strlen < 0) {
hashCode = symbolTable.getHashCode(-strlen);
} else if (strtype == BC_STR_UTF8) {
hashCode = Fnv.MAGIC_HASH_CODE;
int end = offset + strlen;
while (offset < end) {
int c = bytes[offset];
if (c >= 0) {
offset++;
} else {
c &= 0xFF;
switch (c >> 4) {
case 12:
case 13: {
/* 110x xxxx 10xx xxxx*/
c = char2_utf8(c, bytes[offset + 1], offset);
offset += 2;
break;
}
case 14: {
c = char2_utf8(c, bytes[offset + 1], bytes[offset + 2], offset);
offset += 3;
break;
}
default:
/* 10xx xxxx, 1111 xxxx */
throw new JSONException("malformed input around byte " + offset);
}
}
hashCode ^= c;
hashCode *= Fnv.MAGIC_PRIME;
}
} else if (strtype == BC_STR_UTF16 || strtype == BC_STR_UTF16BE) {
hashCode = Fnv.MAGIC_HASH_CODE;
for (int i = 0; i < strlen; i += 2) {
byte c0 = bytes[offset + i];
byte c1 = bytes[offset + i + 1];
char ch = (char) ((c1 & 0xff) | ((c0 & 0xff) << 8));
hashCode ^= ch;
hashCode *= Fnv.MAGIC_PRIME;
}
} else if (strtype == BC_STR_UTF16LE) {
hashCode = Fnv.MAGIC_HASH_CODE;
for (int i = 0; i < strlen; i += 2) {
byte c0 = bytes[offset + i];
byte c1 = bytes[offset + i + 1];
char ch = (char) ((c0 & 0xff) | ((c1 & 0xff) << 8));
hashCode ^= ch;
hashCode *= Fnv.MAGIC_PRIME;
}
} else {
long nameValue = 0;
if (strlen <= 8) {
for (int i = 0, start = offset; i < strlen; offset++, i++) {
byte c = bytes[offset];
if (c < 0 || (c == 0 && bytes[start] == 0)) {
nameValue = 0;
offset = start;
break;
}
switch (i) {
case 0:
nameValue = c;
break;
case 1:
nameValue = ((c) << 8) + (nameValue & 0xFFL);
break;
case 2:
nameValue = ((c) << 16) + (nameValue & 0xFFFFL);
break;
case 3:
nameValue = ((c) << 24) + (nameValue & 0xFFFFFFL);
break;
case 4:
nameValue = (((long) c) << 32) + (nameValue & 0xFFFFFFFFL);
break;
case 5:
nameValue = (((long) c) << 40L) + (nameValue & 0xFFFFFFFFFFL);
break;
case 6:
nameValue = (((long) c) << 48L) + (nameValue & 0xFFFFFFFFFFFFL);
break;
case 7:
nameValue = (((long) c) << 56L) + (nameValue & 0xFFFFFFFFFFFFFFL);
break;
default:
break;
}
}
}
if (nameValue != 0) {
hashCode = nameValue;
} else {
hashCode = Fnv.MAGIC_HASH_CODE;
for (int i = 0; i < strlen; ++i) {
byte c = bytes[offset++];
hashCode ^= c;
hashCode *= Fnv.MAGIC_PRIME;
}
}
}
int symbol;
if (isInt32Num((type = bytes[offset]))) {
symbol = type;
offset++;
} else {
symbol = readInt32Value();
}
if (symbol == 0) {
symbol0Begin = strBegin;
symbol0Length = strlen;
symbol0StrType = strtype;
symbol0Hash = hashCode;
} else {
int minCapacity = symbol * 2 + 2;
if (symbols == null) {
symbols = new long[Math.max(minCapacity, 32)];
} else if (symbols.length < minCapacity) {
symbols = Arrays.copyOf(symbols, minCapacity + 16);
}
long strInfo = ((long) strBegin << 32) + ((long) strlen << 8) + strtype;
symbols[symbol * 2 + 1] = strInfo;
}
return hashCode;
}
@Override
public long readValueHashCode() {
final byte[] bytes = this.bytes;
final byte strtype = this.strtype = bytes[offset++];
strBegin = offset;
if (strtype >= BC_STR_ASCII_FIX_MIN && strtype <= BC_STR_ASCII_FIX_MAX) {
strlen = strtype - BC_STR_ASCII_FIX_MIN;
} else if (strtype == BC_STR_ASCII
|| strtype == BC_STR_UTF8
|| strtype == BC_STR_UTF16
|| strtype == BC_STR_UTF16LE
|| strtype == BC_STR_UTF16BE
) {
strlen = readLength();
strBegin = offset;
} else if (strtype == BC_SYMBOL) {
strlen = readLength();
strBegin = offset;
} else {
throw readStringError();
}
long hashCode;
if (strlen < 0) {
hashCode = symbolTable.getHashCode(-strlen);
} else if (strtype == BC_STR_UTF8) {
hashCode = Fnv.MAGIC_HASH_CODE;
int end = offset + strlen;
while (offset < end) {
int c = bytes[offset];
if (c >= 0) {
offset++;
} else {
c &= 0xFF;
switch (c >> 4) {
case 12:
case 13: {
/* 110x xxxx 10xx xxxx*/
c = char2_utf8(c, bytes[offset + 1], offset);
offset += 2;
break;
}
case 14: {
c = char2_utf8(c, bytes[offset + 1], bytes[offset + 2], offset);
offset += 3;
break;
}
default:
/* 10xx xxxx, 1111 xxxx */
throw new JSONException("malformed input around byte " + offset);
}
}
hashCode ^= c;
hashCode *= Fnv.MAGIC_PRIME;
}
} else if (strtype == BC_STR_UTF16) {
final int offset = this.offset;
hashCode = Fnv.MAGIC_HASH_CODE;
if (bytes[offset] == (byte) 0xFE
&& bytes[offset + 1] == (byte) 0xFF
) {
if (strlen <= 16) {
long nameValue = 0;
for (int i = 2; i < strlen; i += 2) {
byte c0 = bytes[offset + i];
byte c1 = bytes[offset + i + 1];
char ch = (char) ((c1 & 0xff) | ((c0 & 0xff) << 8));
if (ch > 0x7F || (i == 0 && ch == 0)) {
nameValue = 0;
break;
}
byte c = (byte) ch;
switch ((i - 2) >> 1) {
case 0:
nameValue = c;
break;
case 1:
nameValue = ((c) << 8) + (nameValue & 0xFFL);
break;
case 2:
nameValue = ((c) << 16) + (nameValue & 0xFFFFL);
break;
case 3:
nameValue = ((c) << 24) + (nameValue & 0xFFFFFFL);
break;
case 4:
nameValue = (((long) c) << 32) + (nameValue & 0xFFFFFFFFL);
break;
case 5:
nameValue = (((long) c) << 40L) + (nameValue & 0xFFFFFFFFFFL);
break;
case 6:
nameValue = (((long) c) << 48L) + (nameValue & 0xFFFFFFFFFFFFL);
break;
case 7:
nameValue = (((long) c) << 56L) + (nameValue & 0xFFFFFFFFFFFFFFL);
break;
default:
break;
}
}
if (nameValue != 0) {
return nameValue;
}
}
for (int i = 2; i < strlen; i += 2) {
byte c0 = bytes[offset + i];
byte c1 = bytes[offset + i + 1];
char ch = (char) ((c1 & 0xff) | ((c0 & 0xff) << 8));
hashCode ^= ch;
hashCode *= Fnv.MAGIC_PRIME;
}
} else if (bytes[offset] == (byte) 0xFF
&& bytes[offset + 1] == (byte) 0xFE
) {
for (int i = 2; i < strlen; i += 2) {
byte c1 = bytes[offset + i];
byte c0 = bytes[offset + i + 1];
char ch = (char) ((c1 & 0xff) | ((c0 & 0xff) << 8));
hashCode ^= ch;
hashCode *= Fnv.MAGIC_PRIME;
}
} else {
for (int i = 0; i < strlen; i += 2) {
byte c0 = bytes[offset + i];
byte c1 = bytes[offset + i + 1];
char ch = (char) ((c0 & 0xff) | ((c1 & 0xff) << 8));
hashCode ^= ch;
hashCode *= Fnv.MAGIC_PRIME;
}
}
} else if (strtype == BC_STR_UTF16BE) {
final int offset = this.offset;
if (strlen <= 16) {
long nameValue = 0;
for (int i = 0; i < strlen; i += 2) {
byte c0 = bytes[offset + i];
byte c1 = bytes[offset + i + 1];
char ch = (char) ((c1 & 0xff) | ((c0 & 0xff) << 8));
if (ch > 0x7F || (i == 0 && ch == 0)) {
nameValue = 0;
break;
}
byte c = (byte) ch;
switch (i >> 1) {
case 0:
nameValue = c;
break;
case 1:
nameValue = ((c) << 8) + (nameValue & 0xFFL);
break;
case 2:
nameValue = ((c) << 16) + (nameValue & 0xFFFFL);
break;
case 3:
nameValue = ((c) << 24) + (nameValue & 0xFFFFFFL);
break;
case 4:
nameValue = (((long) c) << 32) + (nameValue & 0xFFFFFFFFL);
break;
case 5:
nameValue = (((long) c) << 40L) + (nameValue & 0xFFFFFFFFFFL);
break;
case 6:
nameValue = (((long) c) << 48L) + (nameValue & 0xFFFFFFFFFFFFL);
break;
case 7:
nameValue = (((long) c) << 56L) + (nameValue & 0xFFFFFFFFFFFFFFL);
break;
default:
break;
}
}
if (nameValue != 0) {
return nameValue;
}
}
hashCode = Fnv.MAGIC_HASH_CODE;
for (int i = 0; i < strlen; i += 2) {
byte c0 = bytes[offset + i];
byte c1 = bytes[offset + i + 1];
char ch = (char) ((c1 & 0xff) | ((c0 & 0xff) << 8));
hashCode ^= ch;
hashCode *= Fnv.MAGIC_PRIME;
}
} else if (strtype == BC_STR_UTF16LE) {
final int offset = this.offset;
if (strlen <= 16) {
long nameValue = 0;
for (int i = 0; i < strlen; i += 2) {
byte c0 = bytes[offset + i];
byte c1 = bytes[offset + i + 1];
char ch = (char) ((c0 & 0xff) | ((c1 & 0xff) << 8));
if (ch > 0x7F || (i == 0 && ch == 0)) {
nameValue = 0;
break;
}
byte c = (byte) ch;
switch (i >> 1) {
case 0:
nameValue = c;
break;
case 1:
nameValue = ((c) << 8) + (nameValue & 0xFFL);
break;
case 2:
nameValue = ((c) << 16) + (nameValue & 0xFFFFL);
break;
case 3:
nameValue = ((c) << 24) + (nameValue & 0xFFFFFFL);
break;
case 4:
nameValue = (((long) c) << 32) + (nameValue & 0xFFFFFFFFL);
break;
case 5:
nameValue = (((long) c) << 40L) + (nameValue & 0xFFFFFFFFFFL);
break;
case 6:
nameValue = (((long) c) << 48L) + (nameValue & 0xFFFFFFFFFFFFL);
break;
case 7:
nameValue = (((long) c) << 56L) + (nameValue & 0xFFFFFFFFFFFFFFL);
break;
default:
break;
}
}
if (nameValue != 0) {
return nameValue;
}
}
hashCode = Fnv.MAGIC_HASH_CODE;
for (int i = 0; i < strlen; i += 2) {
byte c0 = bytes[offset + i];
byte c1 = bytes[offset + i + 1];
char ch = (char) ((c0 & 0xff) | ((c1 & 0xff) << 8));
hashCode ^= ch;
hashCode *= Fnv.MAGIC_PRIME;
}
} else {
if (strlen <= 8) {
long nameValue = 0;
for (int i = 0, start = offset; i < strlen; offset++, i++) {
byte c = bytes[offset];
if (c < 0 || (c == 0 && bytes[start] == 0)) {
nameValue = 0;
offset = start;
break;
}
switch (i) {
case 0:
nameValue = c;
break;
case 1:
nameValue = ((c) << 8) + (nameValue & 0xFFL);
break;
case 2:
nameValue = ((c) << 16) + (nameValue & 0xFFFFL);
break;
case 3:
nameValue = ((c) << 24) + (nameValue & 0xFFFFFFL);
break;
case 4:
nameValue = (((long) c) << 32) + (nameValue & 0xFFFFFFFFL);
break;
case 5:
nameValue = (((long) c) << 40L) + (nameValue & 0xFFFFFFFFFFL);
break;
case 6:
nameValue = (((long) c) << 48L) + (nameValue & 0xFFFFFFFFFFFFL);
break;
case 7:
nameValue = (((long) c) << 56L) + (nameValue & 0xFFFFFFFFFFFFFFL);
break;
default:
break;
}
}
if (nameValue != 0) {
return nameValue;
}
}
hashCode = Fnv.MAGIC_HASH_CODE;
for (int i = 0; i < strlen; ++i) {
byte c = bytes[offset++];
hashCode ^= c;
hashCode *= Fnv.MAGIC_PRIME;
}
}
return hashCode;
}
long getNameHashCode() {
int offset = strBegin;
long nameValue = 0;
for (int i = 0; i < strlen; offset++) {
byte c = bytes[offset];
if (c < 0 || i >= 8 || (i == 0 && bytes[strBegin] == 0)) {
offset = strBegin;
nameValue = 0;
break;
}
switch (i) {
case 0:
nameValue = c;
break;
case 1:
nameValue = ((c) << 8) + (nameValue & 0xFFL);
break;
case 2:
nameValue = ((c) << 16) + (nameValue & 0xFFFFL);
break;
case 3:
nameValue = ((c) << 24) + (nameValue & 0xFFFFFFL);
break;
case 4:
nameValue = (((long) c) << 32) + (nameValue & 0xFFFFFFFFL);
break;
case 5:
nameValue = (((long) c) << 40L) + (nameValue & 0xFFFFFFFFFFL);
break;
case 6:
nameValue = (((long) c) << 48L) + (nameValue & 0xFFFFFFFFFFFFL);
break;
case 7:
nameValue = (((long) c) << 56L) + (nameValue & 0xFFFFFFFFFFFFFFL);
break;
default:
break;
}
i++;
}
if (nameValue != 0) {
return nameValue;
}
long hashCode = Fnv.MAGIC_HASH_CODE;
for (int i = 0; i < strlen; ++i) {
byte c = bytes[offset++];
hashCode ^= c;
hashCode *= Fnv.MAGIC_PRIME;
}
return hashCode;
}
@Override
public long getNameHashCodeLCase() {
int offset = strBegin;
long nameValue = 0;
for (int i = 0; i < strlen; offset++) {
byte c = bytes[offset];
if (c < 0 || i >= 8 || (i == 0 && bytes[strBegin] == 0)) {
offset = strBegin;
nameValue = 0;
break;
}
if (c == '_' || c == '-' || c == ' ') {
byte c1 = bytes[offset + 1];
if (c1 != c) {
continue;
}
}
if (c >= 'A' && c <= 'Z') {
c += 32;
}
switch (i) {
case 0:
nameValue = c;
break;
case 1:
nameValue = ((c) << 8) + (nameValue & 0xFFL);
break;
case 2:
nameValue = ((c) << 16) + (nameValue & 0xFFFFL);
break;
case 3:
nameValue = ((c) << 24) + (nameValue & 0xFFFFFFL);
break;
case 4:
nameValue = (((long) c) << 32) + (nameValue & 0xFFFFFFFFL);
break;
case 5:
nameValue = (((long) c) << 40L) + (nameValue & 0xFFFFFFFFFFL);
break;
case 6:
nameValue = (((long) c) << 48L) + (nameValue & 0xFFFFFFFFFFFFL);
break;
case 7:
nameValue = (((long) c) << 56L) + (nameValue & 0xFFFFFFFFFFFFFFL);
break;
default:
break;
}
i++;
}
if (nameValue != 0) {
return nameValue;
}
long hashCode = Fnv.MAGIC_HASH_CODE;
for (int i = 0; i < strlen; ++i) {
byte c = bytes[offset++];
if (c >= 'A' && c <= 'Z') {
c = (byte) (c + 32);
}
if (c == '_' || c == '-' || c == ' ') {
continue;
}
hashCode ^= c;
hashCode *= Fnv.MAGIC_PRIME;
}
return hashCode;
}
@Override
public void skipValue() {
byte type = bytes[offset++];
switch (type) {
case BC_NULL:
case BC_ARRAY_FIX_0:
case BC_STR_ASCII_FIX_0:
case BC_FALSE:
case BC_TRUE:
case BC_DOUBLE_NUM_0:
case BC_DOUBLE_NUM_1:
return;
case BC_INT8:
offset++;
return;
case BC_INT16:
offset += 2;
return;
case BC_INT32:
case BC_TIMESTAMP_SECONDS:
case BC_TIMESTAMP_MINUTES:
case BC_FLOAT:
case BC_INT64_INT:
case BC_LOCAL_DATE:
offset += 4;
return;
case BC_FLOAT_INT:
readInt32Value(); // skip
return;
case BC_INT64:
case BC_TIMESTAMP_MILLIS:
case BC_DOUBLE:
offset += 8;
return;
case BC_DOUBLE_LONG:
case BC_DECIMAL_LONG:
readInt64Value();
return;
case BC_DECIMAL:
// TODO skip big decimal
readInt32Value();
readBigInteger();
return;
case BC_LOCAL_TIME:
offset += 3;
readInt32Value(); // skip
return;
case BC_LOCAL_DATETIME:
offset += 7;
readInt32Value(); // skip
return;
case BC_TIMESTAMP_WITH_TIMEZONE:
offset += 7;
readInt32Value(); // nano
readString(); // skip
return;
case BC_BINARY:
int byteslen = readInt32Value();
offset += byteslen;
return;
case BC_STR_ASCII:
case BC_STR_UTF8:
case BC_STR_UTF16:
case BC_STR_UTF16LE:
case BC_STR_UTF16BE:
int strlen = readInt32Value();
offset += strlen;
return;
case BC_TYPED_ANY: {
readTypeHashCode();
skipValue();
return;
}
case BC_OBJECT: {
while (true) {
byte b = bytes[offset];
if (b == BC_OBJECT_END) {
offset++;
break;
}
int size = FIXED_TYPE_SIZE[b & 0xFF];
if (size > 0) {
offset += size;
} else if (size == -1) {
offset++;
int len = readInt32Value();
offset += len;
} else {
skipName();
}
b = bytes[offset];
size = FIXED_TYPE_SIZE[b & 0xFF];
if (size > 0) {
offset += size;
} else if (size == -1) {
offset++;
int len = readInt32Value();
offset += len;
} else {
skipValue();
}
}
return;
}
case BC_REFERENCE: {
if (isString()) {
skipName();
return;
}
throw notSupportType(type);
}
default:
// [-16, 47]
if (isInt32Num(type) || isInt64Num(type)) {
return;
}
if (isInt32Byte(type) || isInt64Byte(type)) {
offset++;
return;
}
if (isInt32Short(type) || isInt64Short(type)) {
offset += 2;
return;
}
if (type >= BC_STR_ASCII_FIX_MIN && type <= BC_STR_ASCII_FIX_MAX) {
offset += (type - BC_STR_ASCII_FIX_MIN);
return;
}
if (type >= BC_ARRAY_FIX_MIN && type <= BC_ARRAY) {
int itemCnt;
if (type == BC_ARRAY) {
itemCnt = readInt32Value();
} else {
itemCnt = type - BC_ARRAY_FIX_MIN;
}
for (int i = 0; i < itemCnt; ++i) {
int size = FIXED_TYPE_SIZE[bytes[offset] & 0xFF];
if (size > 0) {
offset += size;
} else if (size == -1) {
offset++;
int len = readInt32Value();
offset += len;
} else {
skipValue();
}
}
return;
}
throw notSupportType(type);
}
}
@Override
public boolean skipName() {
byte strtype = this.strtype = bytes[offset++];
if (strtype >= BC_STR_ASCII_FIX_MIN && strtype <= BC_STR_ASCII_FIX_MAX) {
offset += (strtype - BC_STR_ASCII_FIX_MIN);
return true;
}
if (strtype == BC_STR_ASCII
|| strtype == BC_STR_UTF8
|| strtype == BC_STR_UTF16
|| strtype == BC_STR_UTF16LE
|| strtype == BC_STR_UTF16BE
) {
strlen = readLength();
offset += strlen;
return true;
}
if (strtype == BC_SYMBOL) {
int type = bytes[offset];
if (type >= BC_INT32_NUM_MIN && type <= BC_INT32) {
readInt32Value();
return true;
}
readString();
readInt32Value();
return true;
}
throw notSupportType(strtype);
}
static JSONException notSupportType(byte type) {
return new JSONException("name not support input : " + typeName(type));
}
JSONException notSupportString() {
throw new JSONException("readString not support type " + typeName(strtype) + ", offset " + offset + "/" + bytes.length);
}
JSONException readInt32ValueError(byte type) {
throw new JSONException("readInt32Value not support " + typeName(type) + ", offset " + offset + "/" + bytes.length);
}
JSONException readInt64ValueError(byte type) {
throw new JSONException("readInt64Value not support " + typeName(type) + ", offset " + offset + "/" + bytes.length);
}
JSONException readStringError() {
throw new JSONException("string value not support input " + typeName(type) + " offset " + offset + "/" + bytes.length);
}
static JSONException typeRefNotFound(int typeIndex) {
throw new JSONException("type ref not found : " + typeIndex);
}
@Override
public String readFieldName() {
final byte[] bytes = this.bytes;
byte strtype = this.strtype = bytes[offset++];
if (strtype == BC_NULL) {
return null;
}
boolean typeSymbol = strtype == BC_SYMBOL;
if (typeSymbol) {
strtype = this.strtype = bytes[offset];
if (isInt32(strtype)) {
int symbol = readInt32Value();
if (symbol < 0) {
return symbolTable.getName(-symbol);
}
if (symbol == 0) {
this.strtype = symbol0StrType;
strlen = symbol0Length;
strBegin = symbol0Begin;
return getFieldName();
}
int index = symbol * 2 + 1;
long strInfo = symbols[index];
this.strtype = (byte) strInfo;
strlen = ((int) strInfo) >> 8;
strBegin = (int) (strInfo >> 32);
return getString();
}
offset++;
}
strBegin = offset;
Charset charset = null;
String str = null;
if (strtype == BC_STR_ASCII_FIX_MIN + 1) {
str = TypeUtils.toString((char) (bytes[offset] & 0xff));
strlen = 1;
offset++;
} else if (strtype == BC_STR_ASCII_FIX_MIN + 2) {
str = TypeUtils.toString(
(char) (bytes[offset] & 0xff),
(char) (bytes[offset + 1] & 0xff)
);
strlen = 2;
offset += 2;
} else if (strtype >= BC_STR_ASCII_FIX_MIN && strtype <= BC_STR_ASCII) {
long nameValue0 = -1, nameValue1 = -1;
if (strtype == BC_STR_ASCII) {
strlen = readLength();
strBegin = offset;
} else {
final int offset = this.offset;
strlen = strtype - BC_STR_ASCII_FIX_MIN;
if (offset + strlen > bytes.length) {
throw new JSONException("illegal jsonb data");
}
switch (strlen) {
case 3:
nameValue0
= (bytes[offset + 2] << 16)
+ ((bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
break;
case 4:
nameValue0 = UNSAFE.getInt(bytes, BASE + offset);
break;
case 5:
nameValue0
= (((long) bytes[offset + 4]) << 32)
+ (UNSAFE.getInt(bytes, BASE + offset) & 0xFFFFFFFFL);
break;
case 6:
nameValue0
= (((long) bytes[offset + 5]) << 40)
+ ((bytes[offset + 4] & 0xFFL) << 32)
+ (UNSAFE.getInt(bytes, BASE + offset) & 0xFFFFFFFFL);
break;
case 7:
nameValue0
= (((long) bytes[offset + 6]) << 48)
+ ((bytes[offset + 5] & 0xFFL) << 40)
+ ((bytes[offset + 4] & 0xFFL) << 32)
+ (UNSAFE.getInt(bytes, BASE + offset) & 0xFFFFFFFFL);
break;
case 8:
nameValue0 = UNSAFE.getLong(bytes, BASE + offset);
break;
case 9:
nameValue0 = bytes[offset];
nameValue1 = UNSAFE.getLong(bytes, BASE + offset + 1);
break;
case 10:
nameValue0 = UNSAFE.getShort(bytes, BASE + offset);
nameValue1 = UNSAFE.getLong(bytes, BASE + offset + 2);
break;
case 11:
nameValue0
= (bytes[offset] << 16)
+ ((bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset + 2] & 0xFFL);
nameValue1 = UNSAFE.getLong(bytes, BASE + offset + 3);
break;
case 12:
nameValue0 = UNSAFE.getInt(bytes, BASE + offset);
nameValue1 = UNSAFE.getLong(bytes, BASE + offset + 4);
break;
case 13:
nameValue0
= (((long) bytes[offset + 4]) << 32)
+ (UNSAFE.getInt(bytes, BASE + offset) & 0xFFFFFFFFL);
nameValue1 = UNSAFE.getLong(bytes, BASE + offset + 5);
break;
case 14:
nameValue0
= (((long) bytes[offset + 5]) << 40)
+ ((bytes[offset + 4] & 0xFFL) << 32)
+ (UNSAFE.getInt(bytes, BASE + offset) & 0xFFFFFFFFL);
nameValue1 = UNSAFE.getLong(bytes, BASE + offset + 6);
break;
case 15:
nameValue0
= (((long) bytes[offset + 6]) << 48)
+ ((bytes[offset + 5] & 0xFFL) << 40)
+ ((bytes[offset + 4] & 0xFFL) << 32)
+ (UNSAFE.getInt(bytes, BASE + offset) & 0xFFFFFFFFL);
nameValue1 = UNSAFE.getLong(bytes, BASE + offset + 7);
break;
case 16:
nameValue0 = UNSAFE.getLong(bytes, BASE + offset);
nameValue1 = UNSAFE.getLong(bytes, BASE + offset + 8);
break;
default:
break;
}
}
final int strlen = this.strlen;
if (bytes[offset + strlen - 1] > 0 && nameValue0 != -1) {
if (nameValue1 != -1) {
long nameValue01 = nameValue0 ^ nameValue1;
int indexMask = ((int) (nameValue01 ^ (nameValue01 >>> 32))) & (NAME_CACHE2.length - 1);
JSONFactory.NameCacheEntry2 entry = NAME_CACHE2[indexMask];
if (entry == null) {
String name;
if (STRING_CREATOR_JDK8 != null) {
name = latin1StringJDK8(bytes, offset, strlen);
} else {
name = new String(bytes, offset, strlen, ISO_8859_1);
}
NAME_CACHE2[indexMask] = new JSONFactory.NameCacheEntry2(name, nameValue0, nameValue1);
offset += strlen;
str = name;
} else if (entry.value0 == nameValue0 && entry.value1 == nameValue1) {
offset += strlen;
str = entry.name;
}
} else {
int indexMask = ((int) (nameValue0 ^ (nameValue0 >>> 32))) & (NAME_CACHE.length - 1);
JSONFactory.NameCacheEntry entry = NAME_CACHE[indexMask];
if (entry == null) {
String name;
if (STRING_CREATOR_JDK8 != null) {
name = latin1StringJDK8(bytes, offset, strlen);
} else {
name = new String(bytes, offset, strlen, ISO_8859_1);
}
NAME_CACHE[indexMask] = new JSONFactory.NameCacheEntry(name, nameValue0);
offset += strlen;
str = name;
} else if (entry.value == nameValue0) {
offset += strlen;
str = entry.name;
}
}
}
if (str == null) {
if (strlen >= 0) {
if (STRING_CREATOR_JDK8 != null) {
str = latin1StringJDK8(bytes, offset, strlen);
offset += strlen;
} else if (STRING_CREATOR_JDK11 != null) {
byte[] chars = new byte[strlen];
System.arraycopy(bytes, offset, chars, 0, strlen);
str = STRING_CREATOR_JDK11.apply(chars, LATIN1);
offset += strlen;
}
}
charset = ISO_8859_1;
}
} else if (strtype == BC_STR_UTF8) {
strlen = readLength();
strBegin = offset;
if (STRING_CREATOR_JDK11 != null && !JDKUtils.BIG_ENDIAN) {
if (valueBytes == null) {
valueBytes = BYTES_UPDATER.getAndSet(cacheItem, null);
if (valueBytes == null) {
valueBytes = new byte[8192];
}
}
int minCapacity = strlen << 1;
if (minCapacity > valueBytes.length) {
valueBytes = new byte[minCapacity];
}
int utf16_len = IOUtils.decodeUTF8(bytes, offset, strlen, valueBytes);
if (utf16_len != -1) {
byte[] value = new byte[utf16_len];
System.arraycopy(valueBytes, 0, value, 0, utf16_len);
str = STRING_CREATOR_JDK11.apply(value, UTF16);
offset += strlen;
}
}
charset = StandardCharsets.UTF_8;
} else if (strtype == BC_STR_UTF16) {
strlen = readLength();
strBegin = offset;
charset = StandardCharsets.UTF_16;
} else if (strtype == BC_STR_UTF16LE) {
strlen = readLength();
strBegin = offset;
if (STRING_CREATOR_JDK11 != null && !JDKUtils.BIG_ENDIAN) {
byte[] chars = new byte[strlen];
System.arraycopy(bytes, offset, chars, 0, strlen);
str = STRING_CREATOR_JDK11.apply(chars, UTF16);
offset += strlen;
}
charset = StandardCharsets.UTF_16LE;
} else if (strtype == BC_STR_UTF16BE) {
strlen = readLength();
strBegin = offset;
if (STRING_CREATOR_JDK11 != null && JDKUtils.BIG_ENDIAN) {
byte[] chars = new byte[strlen];
System.arraycopy(bytes, offset, chars, 0, strlen);
str = STRING_CREATOR_JDK11.apply(chars, UTF16);
offset += strlen;
}
charset = StandardCharsets.UTF_16BE;
} else if (strtype == BC_STR_GB18030) {
strlen = readLength();
if (GB18030 == null) {
GB18030 = Charset.forName("GB18030");
}
charset = GB18030;
}
if (strlen < 0) {
str = symbolTable.getName(-strlen);
}
if (str == null) {
str = new String(bytes, offset, strlen, charset);
offset += strlen;
}
if (typeSymbol) {
int symbol = readInt32Value();
if (symbol == 0) {
symbol0Begin = strBegin;
symbol0Length = strlen;
symbol0StrType = strtype;
} else {
int minCapacity = symbol * 2 + 2;
if (symbols == null) {
symbols = new long[Math.max(minCapacity, 32)];
} else if (symbols.length < minCapacity) {
symbols = Arrays.copyOf(symbols, symbols.length + 16);
}
long strInfo = ((long) strBegin << 32) + ((long) strlen << 8) + strtype;
symbols[symbol * 2 + 1] = strInfo;
}
}
return str;
}
@Override
public String getFieldName() {
return getString();
}
@Override
public String readString() {
byte[] bytes = this.bytes;
final byte strtype = this.strtype = bytes[offset++];
if (strtype == BC_NULL) {
return null;
}
strBegin = offset;
if (strtype >= BC_STR_ASCII_FIX_MIN && strtype <= BC_STR_ASCII) {
final int strlen;
if (strtype == BC_STR_ASCII) {
byte strType = bytes[offset];
if (isInt32Num(strType)) {
offset++;
strlen = strType;
} else {
strlen = readLength();
}
strBegin = offset;
} else {
strlen = strtype - BC_STR_ASCII_FIX_MIN;
}
this.strlen = strlen;
String str = null;
if (strlen >= 0) {
if (STRING_CREATOR_JDK11 != null) {
byte[] chars = new byte[strlen];
System.arraycopy(bytes, offset, chars, 0, strlen);
str = STRING_CREATOR_JDK11.apply(chars, LATIN1);
} else if (STRING_CREATOR_JDK8 != null) {
str = latin1StringJDK8(bytes, offset, strlen);
}
}
if (str != null) {
offset += strlen;
return stringValue(str, context.features);
}
}
return readStringNonAscii();
}
private String readStringNonAscii() {
String str = null;
Charset charset;
int strtype = this.strtype;
if (strtype >= BC_STR_ASCII_FIX_MIN && strtype <= BC_STR_ASCII) {
charset = ISO_8859_1;
} else if (strtype == BC_STR_UTF8) {
str = readStringUTF8();
charset = StandardCharsets.UTF_8;
} else if (strtype == BC_STR_UTF16) {
strlen = readLength();
strBegin = offset;
charset = StandardCharsets.UTF_16;
} else if (strtype == BC_STR_UTF16LE) {
str = readUTF16LE();
charset = StandardCharsets.UTF_16LE;
} else if (strtype == BC_STR_UTF16BE) {
str = readUTF16BE();
if (str != null) {
return str;
}
charset = StandardCharsets.UTF_16BE;
} else if (strtype == BC_STR_GB18030) {
readGB18030();
charset = GB18030;
} else {
return readStringTypeNotMatch();
}
if (str != null) {
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
// empty string to null
if (str.isEmpty() && (context.features & Feature.EmptyStringAsNull.mask) != 0) {
str = null;
}
return str;
}
return readString(charset);
}
private String readString(Charset charset) {
String str;
if (strlen < 0) {
return symbolTable.getName(-strlen);
}
char[] chars = null;
if (JVM_VERSION == 8 && strtype == BC_STR_UTF8 && strlen < 8192) {
final int cacheIndex = System.identityHashCode(Thread.currentThread()) & (CACHE_ITEMS.length - 1);
final CacheItem cacheItem = CACHE_ITEMS[cacheIndex];
chars = CHARS_UPDATER.getAndSet(cacheItem, null);
if (chars == null) {
chars = new char[8192];
}
}
if (chars != null) {
int len = IOUtils.decodeUTF8(bytes, offset, strlen, chars);
str = new String(chars, 0, len);
if (chars.length < CACHE_THRESHOLD) {
CHARS_UPDATER.lazySet(cacheItem, chars);
}
} else {
str = new String(bytes, offset, strlen, charset);
}
offset += strlen;
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
// empty string to null
if (str.isEmpty() && (context.features & Feature.EmptyStringAsNull.mask) != 0) {
str = null;
}
return str;
}
private void readGB18030() {
strlen = readLength();
strBegin = offset;
if (GB18030 == null) {
GB18030 = Charset.forName("GB18030");
}
}
private String readUTF16BE() {
strlen = readLength();
strBegin = offset;
if (STRING_CREATOR_JDK11 != null && JDKUtils.BIG_ENDIAN) {
byte[] chars = new byte[strlen];
System.arraycopy(bytes, offset, chars, 0, strlen);
String str = STRING_CREATOR_JDK11.apply(chars, UTF16);
offset += strlen;
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
// empty string to null
if (str.isEmpty() && (context.features & Feature.EmptyStringAsNull.mask) != 0) {
str = null;
}
return str;
}
return null;
}
private String readUTF16LE() {
byte strType = bytes[offset];
if (isInt32Num(strType)) {
offset++;
strlen = strType;
} else if (isInt32Byte(strType)) { // strType >= BC_INT32_BYTE_MIN && strType <= BC_INT32_BYTE_MAX
strlen = getIntByte(bytes, offset + 1, strType);
offset += 2;
} else {
strlen = readLength();
}
strBegin = offset;
if (strlen == 0) {
return "";
}
if (STRING_CREATOR_JDK11 != null && !JDKUtils.BIG_ENDIAN) {
byte[] chars = new byte[strlen];
System.arraycopy(bytes, offset, chars, 0, strlen);
String str = STRING_CREATOR_JDK11.apply(chars, UTF16);
offset += strlen;
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
// empty string to null
if (str.isEmpty() && (context.features & Feature.EmptyStringAsNull.mask) != 0) {
str = null;
}
return str;
}
return null;
}
private String readStringUTF8() {
byte strType = bytes[offset];
if (isInt32Num(strType)) {
offset++;
strlen = strType;
} else if (isInt32Byte(strType)) {
strlen = getIntByte(bytes, offset + 1, strType);
offset += 2;
} else {
strlen = readLength();
}
strBegin = offset;
if (STRING_CREATOR_JDK11 != null && !JDKUtils.BIG_ENDIAN) {
if (valueBytes == null) {
valueBytes = BYTES_UPDATER.getAndSet(cacheItem, null);
if (valueBytes == null) {
valueBytes = new byte[8192];
}
}
int minCapacity = strlen << 1;
if (minCapacity > valueBytes.length) {
valueBytes = new byte[minCapacity];
}
int utf16_len = IOUtils.decodeUTF8(bytes, offset, strlen, valueBytes);
if (utf16_len != -1) {
byte[] value = new byte[utf16_len];
System.arraycopy(valueBytes, 0, value, 0, utf16_len);
String str = STRING_CREATOR_JDK11.apply(value, UTF16);
offset += strlen;
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
// empty string to null
if (str.isEmpty() && (context.features & Feature.EmptyStringAsNull.mask) != 0) {
str = null;
}
return str;
}
}
return null;
}
private String readStringTypeNotMatch() {
int end = this.end;
final byte strtype = this.strtype;
if (isInt32Num(strtype)) {
return Byte.toString(strtype);
} else if (isInt32Byte(strtype)) {
return Integer.toString(getIntByte(bytes, offset++, strtype));
} else if (isInt32Short(strtype) && offset + 1 < end) {
int int3 = getInt3(bytes, offset, strtype);
offset += 2;
return Integer.toString(int3);
} else if (isInt64Num(strtype)) {
int intValue = INT64_NUM_LOW_VALUE + (strtype - BC_INT64_NUM_MIN);
return Integer.toString(intValue);
} else if (isInt64Byte(strtype)) {
return Integer.toString(
getLongByte(bytes, offset++, strtype));
} else if (isInt64Short(strtype) && offset + 1 < end) {
int intValue = getLong3(bytes, offset, strtype);
offset += 2;
return Integer.toString(intValue);
}
switch (strtype) {
case BC_NULL:
return null;
case BC_DOUBLE_NUM_0:
return "0.0";
case BC_DOUBLE_NUM_1:
return "1.0";
case BC_INT64_INT:
case BC_INT32: {
int int32Value = IOUtils.getIntBE(bytes, check3(offset, end));
offset += 4;
return Long.toString(int32Value);
}
case BC_FLOAT_INT:
return Float.toString(
readInt32Value());
case BC_FLOAT: {
int int32Value = IOUtils.getIntBE(bytes, check3(offset, end));
offset += 4;
return Float.toString(
Float.intBitsToFloat(int32Value)
);
}
case BC_DOUBLE: {
long int64Value = getLongBE(bytes, check7(offset, end));
offset += 8;
return Double.toString(
Double.longBitsToDouble(int64Value)
);
}
case BC_TIMESTAMP_SECONDS: {
long millis = getIntBE(bytes, check3(offset, end)) * 1000L;
offset += 4;
return DateUtils.toString(
new Date(millis)
);
}
case BC_TIMESTAMP_MINUTES: {
long millis = getIntBE(bytes, check3(offset, end)) * 60000L;
offset += 4;
return DateUtils.toString(
new Date(millis)
);
}
case BC_TIMESTAMP_MILLIS: {
long millis = getLongBE(bytes, check7(offset, end));
offset += 8;
return DateUtils.toString(
new Date(millis)
);
}
case BC_INT64:
long int64Value = getLongBE(bytes, check7(offset, end));
offset += 8;
return Long.toString(int64Value);
case BC_BIGINT: {
int len = readInt32Value();
byte[] bytes = new byte[len];
System.arraycopy(this.bytes, offset, bytes, 0, len);
offset += len;
return new BigInteger(bytes).toString();
}
case BC_DECIMAL: {
int scale = readInt32Value();
BigInteger unscaledValue = readBigInteger();
BigDecimal decimal;
if (scale == 0) {
decimal = new BigDecimal(unscaledValue);
} else {
decimal = new BigDecimal(unscaledValue, scale);
}
return decimal.toString();
}
case BC_TYPED_ANY: {
offset--;
Object typedAny = readAny();
return typedAny == null ? null : JSON.toJSONString(typedAny, JSONWriter.Feature.WriteThrowableClassName);
}
case BC_DECIMAL_LONG:
case BC_BIGINT_LONG: {
return Long.toString(
readInt64Value()
);
}
case BC_DOUBLE_LONG: {
double doubleValue = readInt64Value();
return Double.toString(doubleValue);
}
default:
break;
}
throw notSupportString();
}
public String[] readStringArray() {
if (nextIfMatch(BC_TYPED_ANY)) {
long typeHash = readTypeHashCode();
if (typeHash != ObjectReaderImplStringArray.HASH_TYPE) {
throw new JSONException(info("not support type " + getString()));
}
}
int entryCnt = startArray();
if (entryCnt == -1) {
return null;
}
String[] array = new String[entryCnt];
for (int i = 0; i < entryCnt; i++) {
array[i] = readString();
}
return array;
}
@Override
public char readCharValue() {
byte type = bytes[offset];
if (type == BC_CHAR) {
offset++;
return (char) readInt32Value();
} else if (type == BC_STR_ASCII_FIX_0) {
offset++;
return '\0';
} else if (type > BC_STR_ASCII_FIX_0 && type < BC_STR_ASCII_FIX_MAX) {
offset++;
return (char) (bytes[offset++] & 0xff);
}
String str = readString();
if (str == null || str.isEmpty()) {
return '\0';
}
return str.charAt(0);
}
@Override
public int[] readInt32ValueArray() {
if (nextIfMatch(JSONB.Constants.BC_TYPED_ANY)) {
long typeHash = readTypeHashCode();
if (typeHash != ObjectReaderImplInt64ValueArray.HASH_TYPE
&& typeHash != ObjectReaderImplInt64Array.HASH_TYPE
&& typeHash != ObjectReaderImplInt32Array.HASH_TYPE
&& typeHash != ObjectReaderImplInt32ValueArray.HASH_TYPE
) {
throw new JSONException(info("not support " + getString()));
}
}
int entryCnt = startArray();
if (entryCnt == -1) {
return null;
}
int[] array = new int[entryCnt];
for (int i = 0; i < entryCnt; i++) {
array[i] = readInt32Value();
}
return array;
}
@Override
public long[] readInt64ValueArray() {
if (nextIfMatch(JSONB.Constants.BC_TYPED_ANY)) {
long typeHash = readTypeHashCode();
if (typeHash != ObjectReaderImplInt64ValueArray.HASH_TYPE
&& typeHash != ObjectReaderImplInt64Array.HASH_TYPE
&& typeHash != ObjectReaderImplInt32Array.HASH_TYPE
&& typeHash != ObjectReaderImplInt32ValueArray.HASH_TYPE
) {
throw new JSONException(info("not support " + getString()));
}
}
int entryCnt = startArray();
if (entryCnt == -1) {
return null;
}
long[] array = new long[entryCnt];
for (int i = 0; i < entryCnt; i++) {
array[i] = readInt64Value();
}
return array;
}
@Override
public long readInt64Value() {
wasNull = false;
final byte[] bytes = this.bytes;
int offset = this.offset, end = this.end;
byte type = bytes[offset++];
long int64Value;
if (isInt64Num(type)) {
int64Value = INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
} else if (isInt64Byte(type)) {
int64Value = getLongByte(bytes, offset++, type);
} else if (isInt64Short(type) && offset + 1 < end) {
int64Value = getLong3(bytes, offset, type);
offset += 2;
} else if (type == BC_INT64_INT && offset + 3 < end) {
int64Value = getIntBE(bytes, offset);
offset += 4;
} else if (type == BC_INT64 && offset + 7 < end) {
int64Value = getLongBE(bytes, offset);
offset += 8;
} else {
this.offset = offset;
return readInt64Value0(bytes, type);
}
this.offset = offset;
return int64Value;
}
private long readInt64Value0(byte[] bytes, byte type) {
{
int offset = this.offset;
if (isInt32Num(type)) {
return type;
}
if (isInt32Byte(type)) {
long value = getIntByte(bytes, offset, type);
this.offset = offset + 1;
return value;
}
if (isInt32Short(type) && offset + 1 < this.end) {
this.offset = offset + 2;
return getInt3(bytes, offset, type);
}
}
switch (type) {
case BC_NULL:
if ((context.features & Feature.ErrorOnNullForPrimitives.mask) != 0) {
throw new JSONException(info("long value not support input null"));
}
wasNull = true;
return 0;
case BC_FALSE:
case BC_DOUBLE_NUM_0:
return 0;
case BC_TRUE:
case BC_DOUBLE_NUM_1:
return 1;
case BC_INT8:
return bytes[offset++];
case BC_INT16:
int int16Value =
((bytes[offset + 1] & 0xFF) +
(bytes[offset] << 8));
offset += 2;
return int16Value;
case BC_INT32: {
int int32Value = IOUtils.getIntBE(bytes, check3(offset, end));
offset += 4;
return int32Value;
}
case BC_FLOAT: {
int int32Value = IOUtils.getIntBE(bytes, check3(offset, end));
offset += 4;
float floatValue = Float.intBitsToFloat(int32Value);
return (long) floatValue;
}
case BC_DOUBLE: {
offset--;
return (long) readDoubleValue();
}
case BC_FLOAT_INT:
return (long) ((float) readInt32Value());
case BC_DOUBLE_LONG:
return (long) ((double) readInt64Value());
case BC_TIMESTAMP_MINUTES: {
long minutes = getIntBE(bytes, check3(offset, end));
offset += 4;
return minutes * 60 * 1000;
}
case BC_TIMESTAMP_SECONDS: {
long seconds = getIntBE(bytes, check3(offset, end));
offset += 4;
return seconds * 1000;
}
case BC_TIMESTAMP_MILLIS:
long int64Value = getLongBE(bytes, check7(offset, end));
offset += 8;
return int64Value;
case BC_DECIMAL: {
int scale = readInt32Value();
BigInteger unscaledValue = readBigInteger();
BigDecimal decimal;
if (scale == 0) {
decimal = new BigDecimal(unscaledValue);
} else {
decimal = new BigDecimal(unscaledValue, scale);
}
return decimal.longValue();
}
case BC_STR_ASCII: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, ISO_8859_1);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
case BC_STR_UTF8: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_8);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
case BC_STR_UTF16LE: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_16LE);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
default:
if (type >= BC_STR_ASCII_FIX_MIN && type <= BC_STR_ASCII_FIX_MAX) {
int strlen = type - BC_STR_ASCII_FIX_MIN;
String str = readFixedAsciiString(strlen);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).longValue();
} else {
return toBigDecimal(str).longValue();
}
}
break;
}
throw readInt64ValueError(type);
}
@Override
public int readInt32Value() {
final byte[] bytes = this.bytes;
int offset = this.offset, end = this.end;
int type = bytes[offset++]; // reuse type as value
if (isInt32Num(type)) {
// noop
} else if (isInt32Byte(type)) {
type = getIntByte(bytes, offset, type);
offset++;
} else if (isInt32Short(type) && offset + 1 < end) {
type = getInt3(bytes, offset, type);
offset += 2;
} else if (type == BC_INT32 && offset + 3 < end) {
type = getIntBE(bytes, offset);
offset += 4;
} else {
this.offset = offset;
return readInt32Value0(bytes, (byte) type);
}
this.offset = offset;
return type;
}
private int readInt32Value0(byte[] bytes, byte type) {
if (isInt64Num(type)) {
return INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
}
if (isInt64Byte(type)) {
return getLongByte(bytes, offset++, type);
}
int end = this.end;
if (isInt64Short(type) && offset + 1 < end) {
int value = getLong3(bytes, offset, type);
offset += 2;
return value;
}
switch (type) {
case BC_NULL:
if ((context.features & Feature.ErrorOnNullForPrimitives.mask) != 0) {
throw new JSONException(info("int value not support input null"));
}
wasNull = true;
return 0;
case BC_FALSE:
case BC_DOUBLE_NUM_0:
return 0;
case BC_TRUE:
case BC_DOUBLE_NUM_1:
return 1;
case BC_INT8:
return bytes[offset++];
case BC_INT16:
int int16Value =
((bytes[offset + 1] & 0xFF) +
(bytes[offset] << 8));
offset += 2;
return int16Value;
case BC_DOUBLE_LONG: {
return (int) readInt64Value();
}
case BC_INT64: {
long int64Value = getLongBE(bytes, check7(offset, end));
offset += 8;
return (int) int64Value;
}
case BC_FLOAT_INT:
return (int) (float) readInt32Value();
case BC_FLOAT: {
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
float floatValue = Float.intBitsToFloat(int32Value);
return (int) floatValue;
}
case BC_DOUBLE: {
offset--;
return (int) readDoubleValue();
}
case BC_TIMESTAMP_MINUTES:
case BC_TIMESTAMP_SECONDS:
case BC_INT64_INT:
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
return int32Value;
case BC_STR_ASCII: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, ISO_8859_1);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
case BC_STR_UTF16LE: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_16LE);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
case BC_STR_UTF8: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_8);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
case BC_DECIMAL: {
int scale = readInt32Value();
BigInteger unscaledValue = readBigInteger();
BigDecimal decimal;
if (scale == 0) {
decimal = new BigDecimal(unscaledValue);
} else {
decimal = new BigDecimal(unscaledValue, scale);
}
return decimal.intValue();
}
case BC_TIMESTAMP_MILLIS:
long millis = getLongBE(bytes, check7(offset, end));
offset += 8;
return (int) millis;
default:
if (type >= BC_STR_ASCII_FIX_MIN && type <= BC_STR_ASCII_FIX_MAX) {
int strlen = type - BC_STR_ASCII_FIX_MIN;
String str = readFixedAsciiString(strlen);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
break;
}
throw readInt32ValueError(type);
}
@Override
public boolean isBinary() {
return bytes[offset] == BC_BINARY;
}
@Override
public byte[] readBinary() {
byte type = bytes[offset++];
if (type != BC_BINARY) {
throw notSupportType(type);
}
int len = readLength();
byte[] bytes = new byte[len];
System.arraycopy(this.bytes, offset, bytes, 0, len);
offset += len;
return bytes;
}
@Override
public Integer readInt32() {
final byte[] bytes = this.bytes;
int offset = this.offset, end = this.end;
byte type = bytes[offset++];
if (type == BC_NULL) {
this.offset = offset;
return null;
}
int int32Value;
if (isInt32Num(type)) {
int32Value = type;
} else if (isInt32Byte(type)) {
int32Value = getIntByte(bytes, offset++, type);
} else if (isInt32Short(type) && offset + 1 < end) {
int32Value = getInt3(bytes, offset, type);
offset += 2;
} else if (type == BC_INT32 && offset + 3 < end) {
int32Value = getIntBE(bytes, offset);
offset += 4;
} else {
this.offset = offset;
return readInt32Value0(bytes, type);
}
this.offset = offset;
return int32Value;
}
@Override
public Long readInt64() {
final byte[] bytes = this.bytes;
int offset = this.offset, end = this.end;
byte type = bytes[offset++];
if (type == BC_NULL) {
this.offset = offset;
return null;
}
long int64Value;
if (isInt64Num(type)) {
int64Value = INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
} else if (isInt64Byte(type)) {
int64Value = getLongByte(bytes, offset++, type);
} else if (isInt64Short(type) && offset + 1 < end) {
int64Value = getLong3(bytes, offset, type);
offset += 2;
} else if (type == BC_INT64_INT && offset + 3 < end) {
int64Value = getIntBE(bytes, offset);
offset += 4;
} else if (type == BC_INT64 && offset + 7 < end) {
int64Value = getLongBE(bytes, offset);
offset += 8;
} else {
this.offset = offset;
return readInt64Value0(bytes, type);
}
this.offset = offset;
return int64Value;
}
String readFixedAsciiString(int strlen) {
byte[] bytes = this.bytes;
int offset = this.offset;
String str;
if (strlen == 1) {
str = TypeUtils.toString((char) (bytes[offset] & 0xff));
} else if (strlen == 2) {
str = TypeUtils.toString(
(char) (bytes[offset] & 0xff),
(char) (bytes[offset + 1] & 0xff)
);
} else if (STRING_CREATOR_JDK8 != null) {
str = latin1StringJDK8(bytes, offset, strlen);
} else {
str = new String(bytes, offset, strlen, ISO_8859_1);
}
return str;
}
public Float readFloat() {
byte[] bytes = this.bytes;
int offset = this.offset;
byte type = bytes[offset];
if (type == BC_FLOAT) {
int int32Value = ((bytes[offset + 4] & 0xFF)) +
((bytes[offset + 3] & 0xFF) << 8) +
((bytes[offset + 2] & 0xFF) << 16) +
((bytes[offset + 1]) << 24);
this.offset = offset + 5;
return Float.intBitsToFloat(int32Value);
} else if (type == BC_NULL) {
this.offset = offset + 1;
return null;
}
return readFloat0();
}
@Override
public float readFloatValue() {
byte[] bytes = this.bytes;
int offset = this.offset;
if (bytes[offset] == BC_FLOAT) {
int int32Val = getIntBE(bytes, check3(offset + 1, end));
this.offset = offset + 5;
return Float.intBitsToFloat(int32Val);
}
return readFloat0();
}
private float readFloat0() {
int end = this.end;
final byte[] bytes = this.bytes;
byte type = bytes[offset++];
switch (type) {
case BC_NULL:
if ((context.features & Feature.ErrorOnNullForPrimitives.mask) != 0) {
throw new JSONException(info("long value not support input null"));
}
wasNull = true;
return 0;
case BC_INT8:
return bytes[offset++];
case BC_INT16:
int int16Value =
((bytes[offset + 1] & 0xFF) +
(bytes[offset] << 8));
offset += 2;
return int16Value;
case BC_INT64: {
long int64Value = getLongBE(bytes, check7(offset, end));
offset += 8;
return (float) int64Value;
}
case BC_INT64_INT:
case BC_INT32: {
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
return int32Value;
}
case BC_DOUBLE: {
long int64Value = getLongBE(bytes, check7(offset, end));
offset += 8;
return (float) Double.longBitsToDouble(int64Value);
}
case BC_FLOAT_INT: {
return (float) readInt32Value();
}
case BC_DOUBLE_LONG: {
return (float) (double) readInt64Value();
}
case BC_STR_ASCII: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, ISO_8859_1);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
case BC_STR_UTF16LE: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_16LE);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
case BC_STR_UTF8: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_8);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
case BC_DECIMAL: {
int scale = readInt32Value();
BigInteger unscaledValue = readBigInteger();
BigDecimal decimal;
if (scale == 0) {
decimal = new BigDecimal(unscaledValue);
} else {
decimal = new BigDecimal(unscaledValue, scale);
}
return decimal.intValue();
}
case BC_FALSE:
// case FLOAT_NUM_0:
case BC_DOUBLE_NUM_0:
return 0;
case BC_TRUE:
// case FLOAT_NUM_1:
case BC_DOUBLE_NUM_1:
return 1;
default:
if (isInt32Num(type)) {
return type;
}
if (isInt32Byte(type)) {
return getIntByte(bytes, offset++, type);
}
if (isInt32Short(type) && offset + 1 < end) {
int int3 = getInt3(bytes, offset, type);
this.offset = offset + 2;
return int3;
}
if (isInt64Num(type)) {
return (float) (INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN));
}
if (isInt64Byte(type)) {
return getLongByte(bytes, offset++, type);
}
if (isInt64Short(type) && offset + 1 < end) {
int value = getLong3(bytes, offset, type);
offset += 2;
return value;
}
if (type >= BC_STR_ASCII_FIX_MIN && type <= BC_STR_ASCII_FIX_MAX) {
int strlen = type - BC_STR_ASCII_FIX_MIN;
String str = readFixedAsciiString(strlen);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
break;
}
throw notSupportType(type);
}
@Override
public double readDoubleValue() {
byte[] bytes = this.bytes;
int offset = this.offset;
if (bytes[offset] == BC_DOUBLE) {
long int64Value = ((bytes[offset + 8] & 0xFFL)) +
((bytes[offset + 7] & 0xFFL) << 8) +
((bytes[offset + 6] & 0xFFL) << 16) +
((bytes[offset + 5] & 0xFFL) << 24) +
((bytes[offset + 4] & 0xFFL) << 32) +
((bytes[offset + 3] & 0xFFL) << 40) +
((bytes[offset + 2] & 0xFFL) << 48) +
((long) (bytes[offset + 1]) << 56);
this.offset = offset + 9;
return Double.longBitsToDouble(int64Value);
}
return readDoubleValue0();
}
private double readDoubleValue0() {
final byte[] bytes = this.bytes;
byte type = bytes[offset++];
int end = this.end;
switch (type) {
case BC_NULL:
if ((context.features & Feature.ErrorOnNullForPrimitives.mask) != 0) {
throw new JSONException(info("long value not support input null"));
}
wasNull = true;
return 0;
case BC_INT8:
return bytes[offset++];
case BC_INT16:
int int16Value =
((bytes[offset + 1] & 0xFF) +
(bytes[offset] << 8));
offset += 2;
return int16Value;
case BC_INT64: {
long int64Value = getLongBE(bytes, check7(offset, end));
offset += 8;
return (double) int64Value;
}
case BC_INT64_INT:
case BC_INT32: {
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
return int32Value;
}
case BC_FLOAT:
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
return Float.intBitsToFloat(int32Value);
case BC_FLOAT_INT: {
return (float) readInt32Value();
}
case BC_DOUBLE_LONG:
return readInt64Value();
case BC_STR_ASCII: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, ISO_8859_1);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
case BC_STR_UTF16LE: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_16LE);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
case BC_STR_UTF8: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_8);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
case BC_DECIMAL: {
int scale = readInt32Value();
BigInteger unscaledValue = readBigInteger();
BigDecimal decimal;
if (scale == 0) {
decimal = new BigDecimal(unscaledValue);
} else {
decimal = new BigDecimal(unscaledValue, scale);
}
return decimal.intValue();
}
case BC_FALSE:
// case FLOAT_NUM_0:
case BC_DOUBLE_NUM_0:
return 0;
// case FLOAT_NUM_1:
case BC_DOUBLE_NUM_1:
case BC_TRUE:
return 1;
default:
if (isInt32Num(type)) {
return type;
}
if (isInt32Byte(type)) {
return getIntByte(bytes, offset++, type);
}
if (isInt32Short(type) && offset + 1 < end) {
int int3 = getInt3(bytes, offset, type);
this.offset = offset + 2;
return int3;
}
if (isInt64Num(type)) {
return (long) INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
}
if (isInt64Byte(type)) {
return getLongByte(bytes, offset++, type);
}
if (isInt64Short(type) && offset + 1 < end) {
int value = getLong3(bytes, offset, type);
offset += 2;
return value;
}
if (type >= BC_STR_ASCII_FIX_MIN && type <= BC_STR_ASCII_FIX_MAX) {
int strlen = type - BC_STR_ASCII_FIX_MIN;
String str = readFixedAsciiString(strlen);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return toBigDecimal(str).intValue();
}
}
break;
}
throw notSupportType(type);
}
@Override
protected void readNumber0() {
throw new JSONException("UnsupportedOperation");
}
@Override
public Number readNumber() {
byte type = bytes[offset++];
if (isInt32Num(type)) {
return (int) type;
}
if (isInt32Byte(type)) {
return getIntByte(bytes, offset++, type);
}
int end = this.end;
if (isInt32Short(type) && offset + 1 < end) {
int int3 = getInt3(bytes, offset, type);
this.offset = offset + 2;
return int3;
}
if (isInt64Num(type)) {
return (long) INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
}
if (isInt64Byte(type)) {
return (long) getLongByte(bytes, offset++, type);
}
if (isInt64Short(type) && offset + 1 < end) {
int value = getLong3(bytes, offset, type);
offset += 2;
return value;
}
switch (type) {
case BC_NULL:
return null;
case BC_FALSE:
case BC_DOUBLE_NUM_0:
return 0D;
case BC_TRUE:
case BC_DOUBLE_NUM_1:
return 1D;
case BC_INT8:
return bytes[offset++];
case BC_INT16: {
int int16Value =
((bytes[offset + 1] & 0xFF) +
(bytes[offset] << 8));
offset += 2;
return (short) int16Value;
}
case BC_INT32: {
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
return int32Value;
}
case BC_INT64_INT: {
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
return (long) int32Value;
}
case BC_INT64: {
long int64Value = IOUtils.getLongBE(bytes, check7(offset, end));
offset += 8;
return int64Value;
}
case BC_BIGINT: {
int len = readInt32Value();
byte[] bytes = new byte[len];
System.arraycopy(this.bytes, offset, bytes, 0, len);
offset += len;
return new BigInteger(bytes);
}
case BC_BIGINT_LONG: {
return BigInteger.valueOf(
readInt64Value()
);
}
case BC_FLOAT: {
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
return Float.intBitsToFloat(int32Value);
}
case BC_FLOAT_INT: {
return (float) readInt32Value();
}
case BC_DOUBLE:
long int64Value = getLongBE(bytes, check7(offset, end));
offset += 8;
return Double.longBitsToDouble(int64Value);
case BC_DOUBLE_LONG:
return (double) readInt64Value();
case BC_DECIMAL: {
int scale = readInt32Value();
BigInteger unscaledValue = readBigInteger();
if (scale == 0) {
return new BigDecimal(unscaledValue);
} else {
return new BigDecimal(unscaledValue, scale);
}
}
case BC_DECIMAL_LONG: {
return BigDecimal.valueOf(
readInt64Value()
);
}
case BC_STR_ASCII: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, ISO_8859_1);
offset += strlen;
return toBigDecimal(str);
}
case BC_STR_UTF8: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_8);
offset += strlen;
return toBigDecimal(str);
}
case BC_TYPED_ANY: {
String typeName = readString();
throw new JSONException("not support input type : " + typeName);
}
default:
if (type >= BC_STR_ASCII_FIX_MIN && type <= BC_STR_ASCII_FIX_MAX) {
int strlen = type - BC_STR_ASCII_FIX_MIN;
String str = readFixedAsciiString(strlen);
offset += strlen;
return toBigDecimal(str);
}
break;
}
throw notSupportType(type);
}
@Override
public BigDecimal readBigDecimal() {
final byte[] bytes = this.bytes;
byte type = bytes[offset++];
BigDecimal decimal;
if (type == BC_DECIMAL) {
int scale = readInt32Value();
if (bytes[offset] == BC_BIGINT_LONG) {
offset++;
long unscaledLongValue = readInt64Value();
decimal = BigDecimal.valueOf(unscaledLongValue, scale);
} else if (bytes[offset] == BC_INT32) {
decimal = BigDecimal.valueOf(getIntBE(bytes, check3(offset + 1, end)), scale);
offset += 5;
} else if (bytes[offset] == BC_INT64) {
decimal = BigDecimal.valueOf(
IOUtils.getLongBE(bytes, check7(offset + 1, end)),
scale);
offset += 9;
} else {
BigInteger unscaledValue = readBigInteger();
decimal = scale == 0
? new BigDecimal(unscaledValue)
: new BigDecimal(unscaledValue, scale);
}
} else if (type == BC_DECIMAL_LONG) {
decimal = BigDecimal.valueOf(
readInt64Value()
);
} else {
decimal = readDecimal0(type);
}
return decimal;
}
private BigDecimal readDecimal0(byte type) {
int end = this.end;
switch (type) {
case BC_NULL:
return null;
case BC_DOUBLE_NUM_0:
case BC_FALSE:
return BigDecimal.ZERO;
case BC_DOUBLE_NUM_1:
case BC_TRUE:
return BigDecimal.ONE;
case BC_INT8:
return BigDecimal.valueOf(bytes[offset++]);
case BC_INT16:
int int16Value =
((bytes[offset + 1] & 0xFF) +
(bytes[offset] << 8));
offset += 2;
return BigDecimal.valueOf(int16Value);
case BC_INT64_INT:
case BC_INT32: {
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
return BigDecimal.valueOf(int32Value);
}
case BC_FLOAT_INT: {
float floatValue = (float) readInt32Value();
return BigDecimal.valueOf((long) floatValue);
}
case BC_FLOAT: {
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
float floatValue = Float.intBitsToFloat(int32Value);
return BigDecimal.valueOf((long) floatValue);
}
case BC_DOUBLE: {
long int64Value = getLongBE(bytes, check7(offset, end));
offset += 8;
double doubleValue = Double.longBitsToDouble(int64Value);
return BigDecimal.valueOf(
(long) doubleValue);
}
case BC_INT64: {
long int64Value = getLongBE(bytes, check7(offset, end));
offset += 8;
return BigDecimal.valueOf(int64Value);
}
case BC_BIGINT: {
BigInteger bigInt = readBigInteger();
return new BigDecimal(bigInt);
}
case BC_DOUBLE_LONG: {
double doubleValue = readInt64Value();
return BigDecimal.valueOf((long) doubleValue);
}
case BC_STR_ASCII: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, ISO_8859_1);
offset += strlen;
return toBigDecimal(str);
}
case BC_STR_UTF16LE: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_16LE);
offset += strlen;
return toBigDecimal(str);
}
case BC_STR_UTF8: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_8);
offset += strlen;
return toBigDecimal(str);
}
default:
if (isInt32Num(type)) {
return BigDecimal.valueOf(type);
}
if (isInt32Byte(type)) {
return BigDecimal.valueOf(
getIntByte(bytes, offset++, type)
);
}
if (isInt32Short(type) && offset + 1 < end) {
int int3 = getInt3(bytes, offset, type);
this.offset = offset + 2;
return BigDecimal.valueOf(int3);
}
if (isInt64Num(type)) {
int intValue = INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
return BigDecimal.valueOf(intValue);
}
if (isInt64Byte(type)) {
return BigDecimal.valueOf(
getLongByte(bytes, offset++, type)
);
}
if (isInt64Short(type) && offset + 1 < end) {
int intValue = getLong3(bytes, offset, type);
offset += 2;
return BigDecimal.valueOf(intValue);
}
if (type >= BC_STR_ASCII_FIX_MIN && type <= BC_STR_ASCII_FIX_MAX) {
int strlen = type - BC_STR_ASCII_FIX_MIN;
String str = readFixedAsciiString(strlen);
offset += strlen;
return toBigDecimal(str);
}
break;
}
throw notSupportType(type);
}
@Override
public BigInteger readBigInteger() {
byte type = bytes[offset++];
BigInteger bigInt;
if (type == BC_BIGINT_LONG) {
bigInt = BigInteger.valueOf(
readInt64Value()
);
} else if (type == BC_BIGINT) {
int len = readInt32Value();
byte[] bytes = new byte[len];
System.arraycopy(this.bytes, offset, bytes, 0, len);
offset += len;
bigInt = new BigInteger(bytes);
} else {
bigInt = readBigInteger0(type);
}
return bigInt;
}
private BigInteger readBigInteger0(byte type) {
final byte[] bytes = this.bytes;
int end = this.end;
switch (type) {
case BC_NULL:
return null;
case BC_DOUBLE_NUM_0:
case BC_FALSE:
return BigInteger.ZERO;
case BC_DOUBLE_NUM_1:
case BC_TRUE:
return BigInteger.ONE;
case BC_INT8:
return BigInteger.valueOf(bytes[offset++]);
case BC_INT16:
int int16Value =
((bytes[offset + 1] & 0xFF) +
(bytes[offset] << 8));
offset += 2;
return BigInteger.valueOf(int16Value);
case BC_INT64_INT:
case BC_INT32: {
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
return BigInteger.valueOf(int32Value);
}
case BC_FLOAT_INT: {
float floatValue = (float) readInt32Value();
return BigInteger.valueOf(
(long) floatValue);
}
case BC_FLOAT: {
int int32Value = getIntBE(bytes, check3(offset, end));
offset += 4;
float floatValue = Float.intBitsToFloat(int32Value);
return BigInteger.valueOf(
(long) floatValue);
}
case BC_DOUBLE: {
long int64Value = getLongBE(bytes, check7(offset, end));
offset += 8;
double doubleValue = Double.longBitsToDouble(int64Value);
return BigInteger.valueOf(
(long) doubleValue);
}
case BC_INT64: {
long int64Value = getLongBE(bytes, check7(offset, end));
offset += 8;
return BigInteger.valueOf(int64Value);
}
case BC_BINARY: {
int len = readInt32Value();
byte[] buf = new byte[len];
System.arraycopy(this.bytes, offset, buf, 0, len);
offset += len;
return new BigInteger(buf);
}
case BC_DECIMAL: {
int scale = readInt32Value();
BigInteger unscaledValue = readBigInteger();
BigDecimal decimal;
if (scale == 0) {
decimal = new BigDecimal(unscaledValue);
} else {
decimal = new BigDecimal(unscaledValue, scale);
}
return decimal.toBigInteger();
}
case BC_DOUBLE_LONG: {
double doubleValue = readInt64Value();
return BigInteger.valueOf((long) doubleValue);
}
case BC_STR_ASCII: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, ISO_8859_1);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str);
} else {
return toBigDecimal(str).toBigInteger();
}
}
case BC_STR_UTF8: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_8);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str);
} else {
return toBigDecimal(str).toBigInteger();
}
}
case BC_STR_UTF16LE: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_16LE);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str);
} else {
return toBigDecimal(str).toBigInteger();
}
}
default:
if (isInt32Num(type)) {
return BigInteger.valueOf(type);
}
if (isInt32Byte(type)) {
return BigInteger.valueOf(
getIntByte(bytes, offset++, type)
);
}
if (isInt32Short(type) && offset + 1 < end) {
int int3 = getInt3(bytes, offset, type);
this.offset = offset + 2;
return BigInteger.valueOf(int3);
}
if (isInt64Num(type)) {
int intValue = INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
return BigInteger.valueOf(intValue);
}
if (isInt64Byte(type)) {
return BigInteger.valueOf(
getLongByte(bytes, offset++, type)
);
}
if (isInt64Short(type) && offset + 1 < end) {
int intValue = getLong3(bytes, offset, type);
offset += 2;
return BigInteger.valueOf(intValue);
}
if (type >= BC_STR_ASCII_FIX_MIN && type <= BC_STR_ASCII_FIX_MAX) {
int strlen = type - BC_STR_ASCII_FIX_MIN;
String str = readFixedAsciiString(strlen);
offset += strlen;
return new BigInteger(str);
}
break;
}
throw notSupportType(type);
}
@Override
public LocalDate readLocalDate() {
int offset = this.offset;
byte[] bytes = this.bytes;
int type = bytes[offset++];
if (type == BC_LOCAL_DATE && offset + 3 < this.end) {
int year = getShortBE(bytes, offset);
int month = getByte(bytes, offset + 2);
int dayOfMonth = getByte(bytes, offset + 3);
this.offset = offset + 4;
return LocalDate.of(year, month, dayOfMonth);
}
if (type == BC_NULL) {
this.offset = offset;
return null;
}
return readLocalDate0(type);
}
private LocalDate readLocalDate0(int type) {
if (type == BC_LOCAL_DATETIME) {
return readLocalDateTime().toLocalDate();
}
if (type == BC_TIMESTAMP_WITH_TIMEZONE) {
return readZonedDateTime().toLocalDate();
}
if (type >= BC_STR_ASCII_FIX_MIN && type <= BC_STR_ASCII_FIX_MAX) {
int len = getStringLength();
switch (len) {
case 8:
return readLocalDate8();
case 9:
return readLocalDate9();
case 10:
return readLocalDate10();
case 11:
return readLocalDate11();
default:
if (bytes[offset + len] == 'Z') {
ZonedDateTime zdt = readZonedDateTime();
return zdt.toInstant().atZone(context.getZoneId()).toLocalDate();
}
break;
}
throw new JSONException("TODO : " + len + ", " + readString());
}
if (type == BC_STR_UTF8 || type == BC_STR_ASCII) {
strtype = (byte) type;
offset++;
strlen = readLength();
switch (strlen) {
case 8:
return readLocalDate8();
case 9:
return readLocalDate9();
case 10: {
return readLocalDate10();
}
case 11:
return readLocalDate11();
default:
break;
}
}
throw notSupportType((byte) type);
}
@Override
public LocalDateTime readLocalDateTime() {
int type = bytes[offset];
if (type == BC_LOCAL_DATETIME) {
offset++;
int year = (bytes[offset++] << 8) + (bytes[offset++] & 0xFF);
int month = bytes[offset++];
int dayOfMonth = bytes[offset++];
int hour = bytes[offset++];
int minute = bytes[offset++];
int second = bytes[offset++];
int nano = readInt32Value();
return LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nano);
}
if (type == BC_NULL) {
offset++;
return null;
}
return readLocalDateTime0(type);
}
private LocalDateTime readLocalDateTime0(int type) {
/**
* ������������������<code>LocalDateTime</code>������������������������������<code>@JSONField(format = "yyyy-MM-dd")</code>���������������<code>LocalDate</code>������
*/
if (type == BC_LOCAL_DATE) {
LocalDate localDate = readLocalDate();
return localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
}
if (type == BC_TIMESTAMP_WITH_TIMEZONE) {
return readZonedDateTime().toLocalDateTime();
}
if (type >= BC_STR_ASCII_FIX_MIN && type <= BC_STR_ASCII_FIX_MAX) {
int len = getStringLength();
LocalDate localDate;
switch (len) {
case 8:
localDate = readLocalDate8();
return localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
case 9:
localDate = readLocalDate9();
return localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
case 10:
localDate = readLocalDate10();
return localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
case 11:
localDate = readLocalDate11();
return localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
case 16:
return readLocalDateTime16();
case 17:
return readLocalDateTime17();
case 18:
return readLocalDateTime18();
case 19:
return readLocalDateTime19();
case 20:
return readLocalDateTime20();
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29:
LocalDateTime ldt = readLocalDateTimeX(len);
if (ldt != null) {
return ldt;
}
ZonedDateTime zdt = readZonedDateTimeX(len);
if (zdt != null) {
return zdt.toLocalDateTime();
}
break;
default:
break;
}
throw new JSONException("TODO : " + len + ", " + readString());
}
throw notSupportType((byte) type);
}
@Override
protected LocalDateTime readLocalDateTime12() {
LocalDateTime ldt;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 12
|| (ldt = DateUtils.parseLocalDateTime12(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 13;
return ldt;
}
@Override
protected LocalDateTime readLocalDateTime14() {
LocalDateTime ldt;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 14
|| (ldt = DateUtils.parseLocalDateTime14(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 15;
return ldt;
}
@Override
protected LocalDateTime readLocalDateTime16() {
LocalDateTime ldt;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 16
|| (ldt = DateUtils.parseLocalDateTime16(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 17;
return ldt;
}
@Override
protected LocalDateTime readLocalDateTime17() {
LocalDateTime ldt;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 17
|| (ldt = DateUtils.parseLocalDateTime17(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 18;
return ldt;
}
@Override
protected LocalTime readLocalTime10() {
LocalTime time;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 10
|| (time = DateUtils.parseLocalTime10(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 11;
return time;
}
@Override
protected LocalTime readLocalTime11() {
LocalTime time;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 11
|| (time = DateUtils.parseLocalTime11(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 12;
return time;
}
@Override
protected ZonedDateTime readZonedDateTimeX(int len) {
type = bytes[offset];
if (type < BC_STR_ASCII_FIX_MIN || type > BC_STR_ASCII_FIX_MAX) {
throw new JSONException("date only support string input");
}
ZonedDateTime ldt;
if (len < 19
|| (ldt = DateUtils.parseZonedDateTime(bytes, offset + 1, len, context.zoneId)) == null
) {
throw new JSONException("illegal LocalDateTime string : " + readString());
}
offset += (len + 1);
return ldt;
}
@Override
public void skipComment() {
throw new JSONException("UnsupportedOperation");
}
@Override
public LocalTime readLocalTime() {
int type = bytes[offset];
if (type == BC_LOCAL_TIME) {
offset++;
int hour = bytes[offset++];
int minute = bytes[offset++];
int second = bytes[offset++];
int nano = readInt32Value();
return LocalTime.of(hour, minute, second, nano);
}
if (type == BC_NULL) {
offset++;
return null;
}
if (type >= BC_STR_ASCII_FIX_MIN && type <= BC_STR_ASCII_FIX_MAX) {
int len = getStringLength();
switch (len) {
case 5:
return readLocalTime5();
case 6:
return readLocalTime6();
case 7:
return readLocalTime7();
case 8:
return readLocalTime8();
case 9:
return readLocalTime9();
case 10:
return readLocalTime10();
case 11:
return readLocalTime11();
case 12:
return readLocalTime12();
case 18:
return readLocalTime18();
default:
break;
}
throw new JSONException("not support len : " + len);
}
throw new UnsupportedOperationException();
}
@Override
public Instant readInstant() {
int type = bytes[offset++];
switch (type) {
case BC_TIMESTAMP: {
return Instant.ofEpochSecond(
readInt64Value(),
readInt32Value()
);
}
case BC_TIMESTAMP_MINUTES: {
long minutes = getIntBE(bytes, check3(offset, end));
offset += 4;
return Instant.ofEpochSecond(minutes * 60, 0);
}
case BC_TIMESTAMP_SECONDS: {
long seconds = getIntBE(bytes, check3(offset, end));
offset += 4;
return Instant.ofEpochSecond(seconds, 0);
}
case BC_INT64:
case BC_TIMESTAMP_MILLIS: {
long millis = getLongBE(bytes, check7(offset, end));
offset += 8;
return Instant.ofEpochMilli(millis);
}
default:
break;
}
throw new UnsupportedOperationException();
}
@Override
public OffsetTime readOffsetTime() {
ZonedDateTime zdt = readZonedDateTime();
return zdt == null ? null : zdt.toOffsetDateTime().toOffsetTime();
}
@Override
public OffsetDateTime readOffsetDateTime() {
ZonedDateTime zdt = readZonedDateTime();
return zdt == null ? null : zdt.toOffsetDateTime();
}
@Override
public ZonedDateTime readZonedDateTime() {
byte[] bytes = this.bytes;
int type = bytes[offset++];
if (type == BC_TIMESTAMP_WITH_TIMEZONE) {
int offset = this.offset;
int year = (bytes[offset] << 8) + (bytes[offset + 1] & 0xFF);
int month = bytes[offset + 2];
int dayOfMonth = bytes[offset + 3];
int hour = bytes[offset + 4];
int minute = bytes[offset + 5];
int second = bytes[offset + 6];
this.offset = offset + 7;
int nano = readInt32Value();
LocalDateTime ldt = LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nano);
ZoneId zoneId;
long zoneIdHash = readValueHashCode();
final long SHANGHAI_ZONE_ID_HASH = -4800907791268808639L; // Fnv.hashCode64("Asia/Shanghai");
if (zoneIdHash == SHANGHAI_ZONE_ID_HASH) {
zoneId = SHANGHAI_ZONE_ID;
} else {
String zoneIdStr = getString();
ZoneId contextZoneId = context.getZoneId();
if (contextZoneId.getId().equals(zoneIdStr)) {
zoneId = contextZoneId;
} else {
zoneId = DateUtils.getZoneId(zoneIdStr, SHANGHAI_ZONE_ID);
}
}
return ZonedDateTime.ofLocal(ldt, zoneId, null);
}
return readZonedDateTime0(type);
}
private ZonedDateTime readZonedDateTime0(int type) {
switch (type) {
case BC_NULL:
return null;
case BC_TIMESTAMP: {
long second = readInt64Value();
int nano = readInt32Value();
Instant instant = Instant.ofEpochSecond(second, nano);
return ZonedDateTime.ofInstant(instant, DEFAULT_ZONE_ID);
}
case BC_TIMESTAMP_MINUTES: {
long minutes = getIntBE(bytes, check3(offset, end));
offset += 4;
Instant instant = Instant.ofEpochSecond(minutes * 60);
return ZonedDateTime.ofInstant(instant, DEFAULT_ZONE_ID);
}
case BC_TIMESTAMP_SECONDS: {
long seconds = getIntBE(bytes, check3(offset, end));
offset += 4;
Instant instant = Instant.ofEpochSecond(seconds);
return ZonedDateTime.ofInstant(instant, DEFAULT_ZONE_ID);
}
case BC_LOCAL_DATE: {
int year = (bytes[offset++] << 8) + (bytes[offset++] & 0xFF);
byte month = bytes[offset++];
byte dayOfMonth = bytes[offset++];
LocalDate localDate = LocalDate.of(year, month, dayOfMonth);
return ZonedDateTime.of(localDate, LocalTime.MIN, DEFAULT_ZONE_ID);
}
case BC_LOCAL_DATETIME: {
int year = (bytes[offset++] << 8) + (bytes[offset++] & 0xFF);
byte month = bytes[offset++];
byte dayOfMonth = bytes[offset++];
byte hour = bytes[offset++];
byte minute = bytes[offset++];
byte second = bytes[offset++];
int nano = readInt32Value();
LocalDateTime ldt = LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nano);
return ZonedDateTime.of(ldt, DEFAULT_ZONE_ID);
}
case BC_INT64:
case BC_TIMESTAMP_MILLIS: {
long millis = getLongBE(bytes, check7(offset, end));
offset += 8;
Instant instant = Instant.ofEpochMilli(millis);
return ZonedDateTime.ofInstant(instant, DEFAULT_ZONE_ID);
}
default:
if (type >= BC_STR_ASCII_FIX_0 && type <= BC_STR_ASCII_FIX_MAX) {
offset--;
return readZonedDateTimeX(type - BC_STR_ASCII_FIX_MIN);
}
break;
}
throw notSupportType((byte) type);
}
@Override
public UUID readUUID() {
final byte[] bytes = this.bytes;
byte type = bytes[offset++];
UUID uuid;
switch (type) {
case BC_NULL:
uuid = null;
break;
case BC_BINARY:
int len = bytes[offset++];
if (len != 16 && offset + 15 >= end) {
throw new JSONException("uuid not support " + len);
}
uuid = new UUID(
getLongBE(bytes, offset),
getLongBE(bytes, offset + 8));
offset += 16;
break;
case BC_STR_ASCII_FIX_32: {
uuid = readUUID32(bytes, offset);
offset += 32;
break;
}
case BC_STR_ASCII_FIX_36: {
if (bytes[offset + 8] == '-'
&& bytes[offset + 13] == '-'
&& bytes[offset + 18] == '-'
&& bytes[offset + 23] == '-') {
uuid = readUUID36(bytes, offset);
offset += 36;
break;
}
throw new JSONException("Invalid UUID string: " + new String(bytes, offset, 36, ISO_8859_1));
}
case BC_STR_ASCII:
case BC_STR_UTF8: {
int strlen = readLength();
if (strlen == 32) {
uuid = readUUID32(bytes, offset);
offset += 32;
break;
} else if (strlen == 36) {
if (bytes[offset + 8] == '-'
&& bytes[offset + 13] == '-'
&& bytes[offset + 18] == '-'
&& bytes[offset + 23] == '-') {
uuid = readUUID36(bytes, offset);
offset += 36;
break;
}
}
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_8);
throw new JSONException("Invalid UUID string: " + str);
}
default:
throw notSupportType(type);
}
return uuid;
}
@Override
public Boolean readBool() {
byte type = this.bytes[offset++];
if (type == BC_NULL) {
return null;
} else if (type == BC_TRUE) {
return true;
} else if (type == BC_FALSE) {
return false;
}
return readBoolValue0(type);
}
@Override
public boolean readBoolValue() {
wasNull = false;
byte type = this.bytes[offset++];
if (type == BC_TRUE) {
return true;
} else if (type == BC_FALSE) {
return false;
}
return readBoolValue0(type);
}
private boolean readBoolValue0(byte type) {
final byte[] bytes = this.bytes;
switch (type) {
case BC_INT32_NUM_1:
return true;
case BC_INT32_NUM_0:
return false;
case BC_NULL:
if ((context.features & Feature.ErrorOnNullForPrimitives.mask) != 0) {
throw new JSONException(info("long value not support input null"));
}
wasNull = true;
return false;
case BC_STR_ASCII_FIX_1:
if (bytes[offset] == '1' || bytes[offset] == 'Y') {
offset++;
return true;
}
if (bytes[offset] == '0' || bytes[offset] == 'N') {
offset++;
return false;
}
case BC_STR_ASCII_FIX_4:
if (bytes[offset] == 't'
&& bytes[offset + 1] == 'r'
&& bytes[offset + 2] == 'u'
&& bytes[offset + 3] == 'e'
) {
offset += 4;
return true;
}
if (bytes[offset] == 'T'
&& bytes[offset + 1] == 'R'
&& bytes[offset + 2] == 'U'
&& bytes[offset + 3] == 'E'
) {
offset += 4;
return true;
}
case BC_STR_ASCII_FIX_5:
if (bytes[offset] == 'f'
&& bytes[offset + 1] == 'a'
&& bytes[offset + 2] == 'l'
&& bytes[offset + 3] == 's'
&& bytes[offset + 4] == 'e'
) {
offset += 5;
return false;
}
if (bytes[offset] == 'F'
&& bytes[offset + 1] == 'A'
&& bytes[offset + 2] == 'L'
&& bytes[offset + 3] == 'S'
&& bytes[offset + 4] == 'E'
) {
offset += 5;
return false;
}
case BC_STR_UTF8:
case BC_STR_ASCII: {
strlen = readLength();
if (strlen == 1) {
if (bytes[offset] == 'Y') {
offset++;
return true;
}
if (bytes[offset] == 'N') {
offset++;
return true;
}
} else if (strlen == 4
&& bytes[offset] == 't'
&& bytes[offset + 1] == 'r'
&& bytes[offset + 2] == 'u'
&& bytes[offset + 3] == 'e'
) {
offset += 4;
return true;
} else if (strlen == 5) {
if (bytes[offset] == 'f'
&& bytes[offset + 1] == 'a'
&& bytes[offset + 2] == 'l'
&& bytes[offset + 3] == 's'
&& bytes[offset + 4] == 'e') {
offset += 5;
return false;
} else if (bytes[offset] == 'F'
&& bytes[offset + 1] == 'A'
&& bytes[offset + 2] == 'L'
&& bytes[offset + 3] == 'S'
&& bytes[offset + 4] == 'E') {
offset += 5;
return false;
}
}
String str = new String(bytes, offset, strlen, ISO_8859_1);
offset += strlen;
throw new JSONException("not support input " + str);
}
case BC_STR_UTF16:
case BC_STR_UTF16BE:
case BC_STR_UTF16LE: {
strlen = readLength();
byte[] chars = new byte[strlen];
System.arraycopy(bytes, offset, chars, 0, strlen);
Charset charset = type == BC_STR_UTF16BE
? StandardCharsets.UTF_16BE
: type == BC_STR_UTF16LE ? StandardCharsets.UTF_16LE : StandardCharsets.UTF_16;
String str = new String(chars, charset);
offset += strlen;
switch (str) {
case "0":
case "N":
case "false":
case "FALSE":
return false;
case "1":
case "Y":
case "true":
case "TRUE":
return true;
default:
throw new JSONException("not support input " + str);
}
}
default:
throw notSupportType(type);
}
}
@Override
public boolean nextIfMatch(byte type) {
if (bytes[offset] == type) {
offset++;
return true;
}
return false;
}
public boolean nextIfMatchTypedAny() {
if (bytes[offset] == BC_TYPED_ANY) {
offset++;
return true;
}
return false;
}
@Override
protected int getStringLength() {
type = bytes[offset];
if (type >= BC_STR_ASCII_FIX_MIN && type < BC_STR_ASCII_FIX_MAX) {
return type - BC_STR_ASCII_FIX_MIN;
}
throw new UnsupportedOperationException();
}
public boolean isDate() {
byte type = bytes[offset];
return type >= BC_LOCAL_TIME && type <= BC_TIMESTAMP;
}
public Date readDate() {
ZonedDateTime zdt = null;
int offset = this.offset;
byte[] bytes = this.bytes;
byte type = bytes[offset];
switch (type) {
case BC_LOCAL_TIME: {
LocalTime localTime = readLocalTime();
LocalDateTime ldt = LocalDateTime.of(LocalDate.of(1970, 1, 1), localTime);
zdt = ZonedDateTime.ofLocal(ldt, context.getZoneId(), null);
break;
}
case BC_LOCAL_DATETIME:
LocalDateTime ldt = readLocalDateTime();
zdt = ZonedDateTime.ofLocal(ldt, context.getZoneId(), null);
break;
case BC_LOCAL_DATE:
LocalDate localDate = readLocalDate();
zdt = ZonedDateTime.ofLocal(
LocalDateTime.of(localDate, LocalTime.MIN),
context.getZoneId(),
null);
break;
case BC_TIMESTAMP_MILLIS: {
long millis = IOUtils.getLongBE(bytes, offset + 1);
this.offset += 9;
return new Date(millis);
}
case BC_TIMESTAMP_MINUTES: {
long minutes = getIntBE(bytes, check3(offset + 1, end));
this.offset += 5;
return new Date(minutes * 60L * 1000L);
}
case BC_TIMESTAMP_SECONDS: {
long seconds = getIntBE(bytes, check3(offset + 1, end));
this.offset += 5;
return new Date(seconds * 1000);
}
case BC_TIMESTAMP_WITH_TIMEZONE: {
this.offset = offset + 1;
zdt = readTimestampWithTimeZone();
break;
}
case BC_TIMESTAMP: {
this.offset = offset + 1;
long epochSeconds = readInt64Value();
int nano = readInt32Value();
return Date.from(
Instant.ofEpochSecond(epochSeconds, nano));
}
default:
break;
}
if (zdt != null) {
long seconds = zdt.toEpochSecond();
int nanos = zdt.toLocalTime().getNano();
long millis;
if (seconds < 0 && nanos > 0) {
millis = (seconds + 1) * 1000;
long adjustment = nanos / 1000_000 - 1000;
millis += adjustment;
} else {
millis = seconds * 1000L;
millis += nanos / 1000_000;
}
return new Date(millis);
}
return super.readDate();
}
@Override
public LocalDate readLocalDate8() {
LocalDate ldt;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 8
|| (ldt = DateUtils.parseLocalDate8(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 9;
return ldt;
}
@Override
public LocalDate readLocalDate9() {
LocalDate ldt;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 9
|| (ldt = DateUtils.parseLocalDate9(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 10;
return ldt;
}
@Override
protected LocalDate readLocalDate10() {
LocalDate ldt;
if ((strtype == BC_STR_ASCII || strtype == BC_STR_UTF8) && strlen == 10) {
ldt = DateUtils.parseLocalDate10(bytes, offset);
} else if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 10
|| (ldt = DateUtils.parseLocalDate10(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 11;
return ldt;
}
@Override
protected LocalDate readLocalDate11() {
LocalDate ldt;
if ((strtype == BC_STR_ASCII || strtype == BC_STR_UTF8) && strlen == 11) {
ldt = DateUtils.parseLocalDate11(bytes, offset);
} else if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 11
|| (ldt = DateUtils.parseLocalDate11(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 12;
return ldt;
}
@Override
protected LocalTime readLocalTime5() {
LocalTime time;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 5
|| (time = DateUtils.parseLocalTime5(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 6;
return time;
}
@Override
protected LocalTime readLocalTime6() {
LocalTime time;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 6
|| (time = DateUtils.parseLocalTime6(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 7;
return time;
}
@Override
protected LocalTime readLocalTime7() {
LocalTime time;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 7
|| (time = DateUtils.parseLocalTime7(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 8;
return time;
}
@Override
protected LocalTime readLocalTime8() {
LocalTime time;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 8
|| (time = DateUtils.parseLocalTime8(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 9;
return time;
}
@Override
protected LocalTime readLocalTime9() {
LocalTime time;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 9
|| (time = DateUtils.parseLocalTime8(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 10;
return time;
}
@Override
protected LocalTime readLocalTime12() {
LocalTime time;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 12
|| (time = DateUtils.parseLocalTime12(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 13;
return time;
}
@Override
protected LocalTime readLocalTime15() {
LocalTime time;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 15
|| (time = DateUtils.parseLocalTime15(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 16;
return time;
}
@Override
protected LocalTime readLocalTime18() {
LocalTime time;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 18
|| (time = DateUtils.parseLocalTime18(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 19;
return time;
}
@Override
protected LocalDateTime readLocalDateTime18() {
LocalDateTime ldt;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 18
|| (ldt = DateUtils.parseLocalDateTime18(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 19;
return ldt;
}
@Override
protected LocalDateTime readLocalDateTime20() {
LocalDateTime ldt;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 20
|| (ldt = DateUtils.parseLocalDateTime20(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 21;
return ldt;
}
@Override
public long readMillis19() {
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 19) {
throw new JSONException("date only support string input");
}
long millis = DateUtils.parseMillis19(bytes, offset + 1, context.zoneId);
offset += 20;
return millis;
}
@Override
protected LocalDateTime readLocalDateTime19() {
type = bytes[offset];
if (type != BC_STR_ASCII_FIX_MIN + 19) {
throw new JSONException("date only support string input");
}
LocalDateTime ldt = DateUtils.parseLocalDateTime19(bytes, offset + 1);
if (ldt == null) {
throw new JSONException("date only support string input");
}
offset += 20;
return ldt;
}
@Override
protected LocalDateTime readLocalDateTimeX(int len) {
type = bytes[offset];
if (type < BC_STR_ASCII_FIX_MIN || type > BC_STR_ASCII_FIX_MAX) {
throw new JSONException("date only support string input");
}
LocalDateTime ldt;
if (len < 21
|| len > 29
|| (ldt = DateUtils.parseLocalDateTimeX(bytes, offset + 1, len)) == null
) {
throw new JSONException("illegal LocalDateTime string : " + readString());
}
offset += (len + 1);
return ldt;
}
@Override
public String readPattern() {
throw new JSONException("UnsupportedOperation");
}
@Override
public boolean nextIfMatchIdent(char c0, char c1) {
throw new JSONException("UnsupportedOperation");
}
@Override
public boolean nextIfMatchIdent(char c0, char c1, char c2) {
throw new JSONException("UnsupportedOperation");
}
@Override
public long readFieldNameHashCodeUnquote() {
return readFieldNameHashCode();
}
@Override
public boolean nextIfSet() {
return false;
}
@Override
public boolean nextIfList() {
return false;
}
@Override
public boolean nextIfInfinity() {
return false;
}
@Override
public boolean nextIfMatchIdent(char c0, char c1, char c2, char c3) {
throw new JSONException("UnsupportedOperation");
}
@Override
public boolean nextIfMatchIdent(char c0, char c1, char c2, char c3, char c4) {
throw new JSONException("UnsupportedOperation");
}
@Override
public boolean nextIfMatchIdent(char c0, char c1, char c2, char c3, char c4, char c5) {
throw new JSONException("UnsupportedOperation");
}
@Override
public SavePoint mark() {
return new SavePoint(this.offset, this.type);
}
@Override
public void reset(SavePoint savePoint) {
this.offset = savePoint.offset;
this.type = (byte) savePoint.current;
}
@Override
public void close() {
byte[] valueBytes = this.valueBytes;
if (valueBytes != null && valueBytes.length < CACHE_THRESHOLD) {
BYTES_UPDATER.lazySet(cacheItem, valueBytes);
}
char[] nameChars = this.charBuf;
if (nameChars != null && nameChars.length < CACHE_THRESHOLD) {
CHARS_UPDATER.lazySet(cacheItem, nameChars);
}
}
public boolean isEnd() {
return offset >= end;
}
@Override
public int getRawInt() {
return offset + 3 < end
? UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset)
: 0;
}
@Override
public long getRawLong() {
return offset + 7 < end
? UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset)
: 0;
}
@Override
public boolean nextIfName4Match2() {
return false;
}
@Override
public boolean nextIfName4Match3() {
int offset = this.offset + 4;
if (offset > end) {
return false;
}
this.offset = offset;
return true;
}
public boolean nextIfName4Match4(byte name1) {
byte[] bytes = this.bytes;
int offset = this.offset + 5;
if (offset > end || bytes[offset - 1] != name1) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match5(int name1) {
byte[] bytes = this.bytes;
int offset = this.offset + 6;
if (offset > end || UNSAFE.getShort(bytes, BASE + offset - 2) != name1) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match6(int name1) {
byte[] bytes = this.bytes;
int offset = this.offset + 7;
if (offset > end
|| (UNSAFE.getInt(bytes, BASE + offset - 3) & 0xFFFFFF) != name1) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match7(int name1) {
byte[] bytes = this.bytes;
int offset = this.offset + 8;
if (offset > end || UNSAFE.getInt(bytes, BASE + offset - 4) != name1) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match8(int name1, byte name2) {
byte[] bytes = this.bytes;
int offset = this.offset + 9;
if (offset >= end || UNSAFE.getInt(bytes, BASE + offset - 5) != name1 || bytes[offset - 1] != name2) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match9(long name1) {
byte[] bytes = this.bytes;
int offset = this.offset + 10;
if (offset + 1 >= end || (UNSAFE.getLong(bytes, BASE + offset - 6) & 0xFFFFFFFFFFFFL) != name1) {
return false;
}
this.offset = offset;
return true;
}
public boolean nextIfName4Match10(long name1) {
byte[] bytes = this.bytes;
int offset = this.offset + 11;
if (offset >= end || (UNSAFE.getLong(bytes, BASE + offset - 7) & 0xFFFFFFFFFFFFFFL) != name1) {
return false;
}
this.offset = offset;
return true;
}
public boolean nextIfName4Match11(long name1) {
byte[] bytes = this.bytes;
int offset = this.offset + 12;
if (offset >= end || UNSAFE.getLong(bytes, BASE + offset - 8) != name1) {
return false;
}
this.offset = offset;
return true;
}
public boolean nextIfName4Match12(long name1, byte name2) {
byte[] bytes = this.bytes;
int offset = this.offset + 13;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 9) != name1
|| bytes[offset - 1] != name2) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match13(long name1, int name2) {
byte[] bytes = this.bytes;
int offset = this.offset + 14;
if (offset + 1 >= end
|| UNSAFE.getLong(bytes, BASE + offset - 10) != name1
|| UNSAFE.getShort(bytes, BASE + offset - 2) != name2) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match14(long name1, int name2) {
byte[] bytes = this.bytes;
int offset = this.offset + 15;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 11) != name1
|| (UNSAFE.getInt(bytes, BASE + offset - 3) & 0xFFFFFF) != name2) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match15(long name1, int name2) {
byte[] bytes = this.bytes;
int offset = this.offset + 16;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 12) != name1
|| UNSAFE.getInt(bytes, BASE + offset - 4) != name2) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match16(long name1, int name2, byte name3) {
byte[] bytes = this.bytes;
int offset = this.offset + 17;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 13) != name1
|| UNSAFE.getInt(bytes, BASE + offset - 5) != name2
|| bytes[offset - 1] != name3) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match17(long name1, long name2) {
byte[] bytes = this.bytes;
int offset = this.offset + 18;
if (offset + 1 >= end
|| UNSAFE.getLong(bytes, BASE + offset - 14) != name1
|| (UNSAFE.getLong(bytes, BASE + offset - 6) & 0xFFFFFFFFFFFFL) != name2) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match18(long name1, long name2) {
byte[] bytes = this.bytes;
int offset = this.offset + 19;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 15) != name1
|| (UNSAFE.getLong(bytes, BASE + offset - 7) & 0xFFFF_FFFF_FFFF_FFL) != name2) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match19(long name1, long name2) {
byte[] bytes = this.bytes;
int offset = this.offset + 20;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 16) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 8) != name2) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match20(long name1, long name2, byte name3) {
byte[] bytes = this.bytes;
int offset = this.offset + 21;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 17) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 9) != name2
|| bytes[offset - 1] != name3
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match21(long name1, long name2, int name3) {
byte[] bytes = this.bytes;
int offset = this.offset + 22;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 18) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 10) != name2
|| UNSAFE.getShort(bytes, BASE + offset - 2) != name3
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match22(long name1, long name2, int name3) {
byte[] bytes = this.bytes;
int offset = this.offset + 23;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 19) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 11) != name2
|| (UNSAFE.getInt(bytes, BASE + offset - 3) & 0xFFFFFF) != name3
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match23(long name1, long name2, int name3) {
byte[] bytes = this.bytes;
int offset = this.offset + 24;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 20) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 12) != name2
|| UNSAFE.getInt(bytes, BASE + offset - 4) != name3
) {
return false;
}
this.offset = offset;
return true;
}
public boolean nextIfName4Match24(long name1, long name2, int name3, byte name4) {
byte[] bytes = this.bytes;
int offset = this.offset + 25;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 21) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 13) != name2
|| UNSAFE.getInt(bytes, BASE + offset - 5) != name3
|| bytes[offset - 1] != name4
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match25(long name1, long name2, long name3) {
byte[] bytes = this.bytes;
int offset = this.offset + 26;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 22) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 14) != name2
|| (UNSAFE.getLong(bytes, BASE + offset - 6) & 0xFFFF_FFFF_FFFFL) != name3
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match26(long name1, long name2, long name3) {
byte[] bytes = this.bytes;
int offset = this.offset + 27;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 23) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 15) != name2
|| (UNSAFE.getLong(bytes, BASE + offset - 7) & 0xFFFF_FFFF_FFFF_FFL) != name3
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match27(long name1, long name2, long name3) {
byte[] bytes = this.bytes;
int offset = this.offset + 28;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 24) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 16) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 8) != name3
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match28(long name1, long name2, long name3, byte name4) {
byte[] bytes = this.bytes;
int offset = this.offset + 29;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 25) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 17) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 9) != name3
|| bytes[offset - 1] != name4
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match29(long name1, long name2, long name3, int name4) {
byte[] bytes = this.bytes;
int offset = this.offset + 30;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 26) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 18) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 10) != name3
|| UNSAFE.getShort(bytes, BASE + offset - 2) != name4
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match30(long name1, long name2, long name3, int name4) {
byte[] bytes = this.bytes;
int offset = this.offset + 31;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 27) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 19) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 11) != name3
|| (UNSAFE.getInt(bytes, BASE + offset - 3) & 0xFFFFFF) != name4
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match31(long name1, long name2, long name3, int name4) {
byte[] bytes = this.bytes;
int offset = this.offset + 32;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 28) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 20) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 12) != name3
|| UNSAFE.getInt(bytes, BASE + offset - 4) != name4
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match32(long name1, long name2, long name3, int name4, byte name5) {
byte[] bytes = this.bytes;
int offset = this.offset + 33;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 29) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 21) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 13) != name3
|| UNSAFE.getInt(bytes, BASE + offset - 5) != name4
|| bytes[offset - 1] != name5
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match33(long name1, long name2, long name3, long name4) {
byte[] bytes = this.bytes;
int offset = this.offset + 34;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 30) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 22) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 14) != name3
|| (UNSAFE.getLong(bytes, BASE + offset - 6) & 0xFFFF_FFFF_FFFFL) != name4
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match34(long name1, long name2, long name3, long name4) {
byte[] bytes = this.bytes;
int offset = this.offset + 35;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 31) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 23) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 15) != name3
|| (UNSAFE.getLong(bytes, BASE + offset - 7) & 0xFFFF_FFFF_FFFF_FFL) != name4
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match35(long name1, long name2, long name3, long name4) {
byte[] bytes = this.bytes;
int offset = this.offset + 36;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 32) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 24) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 16) != name3
|| UNSAFE.getLong(bytes, BASE + offset - 8) != name4
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match36(long name1, long name2, long name3, long name4, byte name5) {
byte[] bytes = this.bytes;
int offset = this.offset + 37;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 33) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 25) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 17) != name3
|| UNSAFE.getLong(bytes, BASE + offset - 9) != name4
|| bytes[offset - 1] != name5
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match37(long name1, long name2, long name3, long name4, int name5) {
byte[] bytes = this.bytes;
int offset = this.offset + 38;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 34) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 26) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 18) != name3
|| UNSAFE.getLong(bytes, BASE + offset - 10) != name4
|| UNSAFE.getShort(bytes, BASE + offset - 2) != name5
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match38(long name1, long name2, long name3, long name4, int name5) {
byte[] bytes = this.bytes;
int offset = this.offset + 39;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 35) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 27) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 19) != name3
|| UNSAFE.getLong(bytes, BASE + offset - 11) != name4
|| (UNSAFE.getInt(bytes, BASE + offset - 3) & 0xFFFFFF) != name5
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match39(long name1, long name2, long name3, long name4, int name5) {
byte[] bytes = this.bytes;
int offset = this.offset + 40;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 36) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 28) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 20) != name3
|| UNSAFE.getLong(bytes, BASE + offset - 12) != name4
|| UNSAFE.getInt(bytes, BASE + offset - 4) != name5
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match40(long name1, long name2, long name3, long name4, int name5, byte name6) {
byte[] bytes = this.bytes;
int offset = this.offset + 41;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 37) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 29) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 21) != name3
|| UNSAFE.getLong(bytes, BASE + offset - 13) != name4
|| UNSAFE.getInt(bytes, BASE + offset - 5) != name5
|| bytes[offset - 1] != name6
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match41(long name1, long name2, long name3, long name4, long name5) {
byte[] bytes = this.bytes;
int offset = this.offset + 42;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 38) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 30) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 22) != name3
|| UNSAFE.getLong(bytes, BASE + offset - 14) != name4
|| (UNSAFE.getLong(bytes, BASE + offset - 6) & 0xFFFF_FFFF_FFFFL) != name5
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match42(long name1, long name2, long name3, long name4, long name5) {
byte[] bytes = this.bytes;
int offset = this.offset + 43;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 39) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 31) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 23) != name3
|| UNSAFE.getLong(bytes, BASE + offset - 15) != name4
|| (UNSAFE.getLong(bytes, BASE + offset - 7) & 0xFFFF_FFFF_FFFF_FFL) != name5
) {
return false;
}
this.offset = offset;
return true;
}
@Override
public boolean nextIfName4Match43(long name1, long name2, long name3, long name4, long name5) {
byte[] bytes = this.bytes;
int offset = this.offset + 44;
if (offset >= end
|| UNSAFE.getLong(bytes, BASE + offset - 40) != name1
|| UNSAFE.getLong(bytes, BASE + offset - 32) != name2
|| UNSAFE.getLong(bytes, BASE + offset - 24) != name3
|| UNSAFE.getLong(bytes, BASE + offset - 16) != name4
|| UNSAFE.getLong(bytes, BASE + offset - 8) != name5
) {
return false;
}
this.offset = offset;
return true;
}
static int check3(int off, int end) {
if (off + 3 >= end) {
throw outOfBoundsCheckFromToIndex(off, end);
}
return off;
}
static int check7(int off, int end) {
if (off + 7 >= end) {
throw outOfBoundsCheckFromToIndex(off, end);
}
return off;
}
static JSONException outOfBoundsCheckFromToIndex(int offset, int end) {
return new JSONException("offset overflow, offset " + offset + ", end " + end);
}
public void readArray(Collection list, Type itemType) {
int count = startArray();
for (int i = 0; i < count; i++) {
list.add(read(itemType));
}
}
}