
hydraql.shaded.fastjson2.JSONReaderJSONB Maven / Gradle / Ivy
package hydraql.shaded.fastjson2;
import hydraql.shaded.fastjson2.reader.ObjectReader;
import hydraql.shaded.fastjson2.reader.ObjectReaderProvider;
import hydraql.shaded.fastjson2.util.*;
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 hydraql.shaded.fastjson2.JSONB.Constants.*;
import static hydraql.shaded.fastjson2.JSONB.typeName;
import static hydraql.shaded.fastjson2.JSONFactory.*;
import static hydraql.shaded.fastjson2.util.DateUtils.localDateTime;
import static hydraql.shaded.fastjson2.util.IOUtils.SHANGHAI_ZONE_ID;
import static hydraql.shaded.fastjson2.util.JDKUtils.*;
import static hydraql.shaded.fastjson2.util.UUIDUtils.parse4Nibbles;
class JSONReaderJSONB
extends JSONReader {
static Charset GB18030;
protected final byte[] bytes;
protected final int length;
protected final int end;
protected byte type;
protected int strlen;
protected byte strtype;
protected int strBegin;
protected byte[] valueBytes;
protected final int cachedIndex = System.identityHashCode(Thread.currentThread()) & (CACHE_SIZE - 1);
protected final SymbolTable symbolTable;
protected long[] symbols = new long[32];
JSONReaderJSONB(Context ctx, byte[] bytes, int off, int length) {
super(ctx);
this.bytes = bytes;
this.offset = off;
this.length = length;
this.end = off + length;
this.symbolTable = ctx.symbolTable;
}
@Override
public boolean isJSONB() {
return true;
}
@Override
public String getString() {
if (strtype == BC_NULL) {
return null;
}
if (strlen < 0) {
return symbolTable.getName(-strlen);
}
Charset charset;
if (strtype == BC_STR_ASCII) {
charset = StandardCharsets.US_ASCII;
} else if (strtype >= BC_STR_ASCII_FIX_MIN && strtype <= BC_STR_ASCII_FIX_MAX) {
if (STRING_CREATOR_JDK8 != null) {
char[] chars = new char[strlen];
for (int i = 0; i < strlen; ++i) {
chars[i] = (char) bytes[strBegin + i];
}
return STRING_CREATOR_JDK8.apply(chars, Boolean.TRUE);
} 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 = StandardCharsets.US_ASCII;
} 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;
if (symbol < 0) {
return symbolTable.getName(-symbol);
}
int index = symbol * 2;
// return symbols[index];
throw new JSONException("TODO : " + JSONB.typeName(strtype));
} else {
throw new JSONException("TODO : " + JSONB.typeName(strtype));
}
return new String(bytes, strBegin, strlen, charset);
}
public int readLength() {
byte type = bytes[offset++];
if (type >= BC_INT32_NUM_MIN && type <= BC_INT32_NUM_MAX) {
return type;
}
if (type >= BC_INT32_BYTE_MIN && type <= BC_INT32_BYTE_MAX) {
return ((type - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT32_SHORT_MIN && type <= BC_INT32_SHORT_MAX) {
return ((type - BC_INT32_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type == BC_INT32) {
int len = (bytes[offset++] << 24)
+ ((bytes[offset++] & 0xFF) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
if (len > 1024 * 1024 * 256) {
throw new JSONException("input length overflow");
}
return len;
}
throw new JSONException("not support length type : " + typeName(type));
}
@Override
public final boolean isArray() {
if (offset >= bytes.length) {
return false;
}
byte type = bytes[offset];
return type >= BC_ARRAY_FIX_MIN && type <= BC_ARRAY;
}
@Override
public final boolean isObject() {
return offset < end && bytes[offset] == BC_OBJECT;
}
@Override
public boolean isNumber() {
byte type = bytes[offset];
return type >= BC_DOUBLE_LONG && type <= BC_INT32;
}
@Override
public boolean isString() {
return offset < bytes.length
&& (type = bytes[offset]) >= BC_STR_ASCII_FIX_MIN;
}
@Override
public boolean nextIfMatch(char ch) {
throw new JSONException("UnsupportedOperation");
}
@Override
public boolean nextIfObjectStart() {
if (bytes[offset] != BC_OBJECT) {
return false;
}
offset++;
return true;
}
@Override
public final boolean nextIfObjectEnd() {
if (bytes[offset] != BC_OBJECT_END) {
return false;
}
offset++;
return true;
}
@Override
public final boolean nextIfEmptyString() {
if (bytes[offset] != BC_STR_ASCII_FIX_MIN) {
return false;
}
offset += 1;
return true;
}
@Override
public 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 read(Class 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 readObject() {
type = bytes[offset++];
if (type == BC_NULL) {
return null;
}
if (type >= BC_OBJECT) {
Map map;
if ((context.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;
}
String name = readFieldName();
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 (valueType >= BC_INT32_NUM_MIN && valueType <= BC_INT32_NUM_MAX) {
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++;
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
offset += 8;
value = int64Value;
} else if (valueType >= BC_ARRAY_FIX_MIN && valueType <= BC_ARRAY) {
offset++;
int len;
if (valueType == BC_ARRAY) {
byte itemType = bytes[offset];
if (itemType >= BC_INT32_NUM_MIN && itemType <= BC_INT32_NUM_MAX) {
offset++;
len = itemType;
} else {
len = readLength();
}
} else {
len = 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 (valueType >= BC_INT32_BYTE_MIN && valueType <= BC_INT32_BYTE_MAX) {
offset++;
value = ((valueType - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
} else if (valueType >= BC_INT32_SHORT_MIN && valueType <= BC_INT32_SHORT_MAX) {
offset++;
int int32Value = ((valueType - BC_INT32_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
value = new Integer(int32Value);
} else if (valueType == BC_INT32) {
offset++;
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
value = new Integer(int32Value);
} else {
value = readAny();
}
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 new JSONException("object not support input " + error(type));
}
@Override
public Object readAny() {
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 =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return new Integer(int32Value);
}
case BC_INT64_INT: {
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return new Long(int32Value);
}
case BC_INT64: {
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
offset += 8;
return Long.valueOf(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_FLOAT: {
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return Float.intBitsToFloat(int32Value);
}
case BC_FLOAT_INT: {
return (float) readInt32Value();
}
case BC_DOUBLE: {
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
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 = JSONFactory.allocateByteArray(cachedIndex);
}
int minCapacity = strlen << 1;
if (valueBytes == null) {
valueBytes = new byte[minCapacity];
} else {
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, 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, 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 =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return new Date(minutes * 60L * 1000L);
}
case BC_TIMESTAMP_SECONDS: {
long seconds =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return new Date(seconds * 1000);
}
case BC_TIMESTAMP_MILLIS: {
long millis =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
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();
}
throw new JSONException("auoType 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("auoType 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 && type <= BC_STR_GB18030) {
long hash = readFieldNameHashCode();
if (hash == ObjectReader.HASH_TYPE && supportAutoType) {
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("auotype 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 && type <= BC_SYMBOL) {
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 (valueType >= BC_INT32_NUM_MIN && valueType <= BC_INT32_NUM_MAX) {
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();
}
map.put(name, value);
}
if (map == null) {
if ((context.features & Feature.UseNativeObject.mask) != 0) {
map = new HashMap();
} else {
map = new JSONObject();
}
}
return map;
}
default:
if (type >= BC_INT32_NUM_MIN && type <= BC_INT32_NUM_MAX) {
return (int) type;
}
if (type >= BC_INT32_BYTE_MIN && type <= BC_INT32_BYTE_MAX) {
return ((type - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT32_SHORT_MIN && type <= BC_INT32_SHORT_MAX) {
return ((type - BC_INT32_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT64_NUM_MIN && type <= BC_INT64_NUM_MAX) {
return (long) INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
}
if (type >= BC_INT64_BYTE_MIN && type <= BC_INT64_BYTE_MAX) {
return (long) ((type - BC_INT64_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT64_SHORT_MIN && type <= BC_INT64_SHORT_MAX) {
return (long) (((type - BC_INT64_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF));
}
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) {
char[] chars = new char[strlen];
for (int i = 0; i < strlen; ++i) {
chars[i] = (char) bytes[offset + i];
}
offset += strlen;
String str = STRING_CREATOR_JDK8.apply(chars, Boolean.TRUE);
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
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();
}
return str;
}
String str = new String(bytes, offset, strlen, StandardCharsets.US_ASCII);
offset += strlen;
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
return str;
}
throw new JSONException("not support type : " + error(type));
}
}
@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 (valueType >= BC_INT32_NUM_MIN && valueType <= BC_INT32_NUM_MAX) {
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++;
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
offset += 8;
value = int64Value;
} 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 (valueType >= BC_INT32_BYTE_MIN && valueType <= BC_INT32_BYTE_MAX) {
offset++;
value = ((valueType - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
} else if (valueType >= BC_INT32_SHORT_MIN && valueType <= BC_INT32_SHORT_MAX) {
offset++;
int int32Value = ((valueType - BC_INT32_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
value = new Integer(int32Value);
} else if (valueType == BC_INT32) {
offset++;
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
value = new Integer(int32Value);
} 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;
}
int entryCnt = startArray();
JSONArray array = new JSONArray(entryCnt);
for (int i = 0; i < entryCnt; i++) {
array.add(read(itemType));
}
return array;
}
protected byte[] readHex() {
throw new JSONException("UnsupportedOperation");
}
@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));
}
@Override
public ObjectReader checkAutoType(Class expectClass, long expectClassHash, long features) {
ObjectReader autoTypeObjectReader = null;
type = bytes[offset];
if (type == BC_TYPED_ANY) {
offset++;
long typeHash = readTypeHashCode();
if (expectClassHash == typeHash) {
ObjectReader objectReader = context.getObjectReader(expectClass);
Class objectClass = objectReader.getObjectClass();
if (objectClass != null && objectClass == expectClass) {
context.getProvider().registerIfAbsent(typeHash, objectReader);
return objectReader;
}
}
if (context.autoTypeBeforeHandler != null) {
Class> objectClass = context.autoTypeBeforeHandler.apply(typeHash, expectClass, features);
if (objectClass == null) {
String typeName = getString();
objectClass = context.autoTypeBeforeHandler.apply(typeName, expectClass, features);
}
if (objectClass != null) {
ObjectReader objectReader = context.getObjectReader(objectClass);
if (objectReader != null) {
return objectReader;
}
}
}
boolean isSupportAutoType = ((context.features | features) & Feature.SupportAutoType.mask) != 0;
if (!isSupportAutoType) {
String typeName = getString();
throw new JSONException("autoType not support input " + typeName);
}
ObjectReaderProvider provider = context.provider;
autoTypeObjectReader = provider.getObjectReader(typeHash);
if (autoTypeObjectReader != null) {
Class objectClass = autoTypeObjectReader.getObjectClass();
if (objectClass != null) {
ClassLoader objectClassLoader = objectClass.getClassLoader();
if (objectClassLoader != null) {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
if (objectClassLoader != contextClassLoader) {
String typeName = getString();
Class contextClass = TypeUtils.getMapping(typeName);
if (contextClass == null) {
try {
if (contextClassLoader == null) {
contextClassLoader = JSON.class.getClassLoader();
}
contextClass = contextClassLoader.loadClass(typeName);
} catch (ClassNotFoundException ignored) {
}
}
if (contextClass != null && !objectClass.equals(contextClass)) {
autoTypeObjectReader = getObjectReader(contextClass);
}
}
}
}
}
if (autoTypeObjectReader == null) {
String typeName = getString();
autoTypeObjectReader = provider.getObjectReader(typeName, expectClass, context.features | features);
}
if (autoTypeObjectReader == null) {
throw new JSONException("auotype not support : " + getString());
}
type = bytes[offset];
}
return autoTypeObjectReader;
}
@Override
public int startArray() {
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 final void next() {
offset++;
}
@Override
public long readFieldNameHashCode() {
strtype = bytes[offset++];
boolean typeSymbol = strtype == BC_SYMBOL;
if (typeSymbol) {
strtype = bytes[offset];
if (strtype >= BC_INT32_NUM_MIN && strtype <= BC_INT32) {
int symbol;
if (strtype >= BC_INT32_NUM_MIN && strtype <= BC_INT32_NUM_MAX) {
offset++;
symbol = strtype;
} else {
symbol = readInt32Value();
}
if (symbol < 0) {
return symbolTable.getHashCode(-symbol);
}
int index = symbol * 2;
long strInfo = symbols[index + 1];
this.strtype = (byte) strInfo;
strlen = ((int) strInfo) >> 8;
strBegin = (int) (strInfo >> 32);
return symbols[index];
}
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) {
strlen = readLength();
strBegin = offset;
} else {
StringBuffer message = new StringBuffer()
.append("fieldName not support input type ")
.append(typeName(strtype));
if (strtype == BC_REFERENCE) {
message.append(" ")
.append(readString());
}
message.append(", offset ")
.append(offset);
throw new JSONException(message.toString());
}
long hashCode;
if (strlen < 0) {
hashCode = symbolTable.getHashCode(-strlen);
} else {
long nameValue = 0;
if (MIXED_HASH_ALGORITHM && strlen <= 8) {
switch (strlen) {
case 1:
nameValue = bytes[offset];
break;
case 2:
nameValue = (bytes[offset + 1] << 8)
+ (bytes[offset] & 0xFF);
break;
case 3:
nameValue = (bytes[offset + 2] << 16)
+ ((bytes[offset + 1] & 0xFF) << 8)
+ (bytes[offset] & 0xFF);
break;
case 4:
nameValue = (bytes[offset + 3] << 24)
+ ((bytes[offset + 2] & 0xFF) << 16)
+ ((bytes[offset + 1] & 0xFF) << 8)
+ (bytes[offset] & 0xFF);
break;
case 5:
nameValue = (((long) bytes[offset + 4]) << 32)
+ (((long) bytes[offset + 3] & 0xFFL) << 24)
+ (((long) bytes[offset + 2] & 0xFFL) << 16)
+ (((long) bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
break;
case 6:
nameValue = (((long) bytes[offset + 5]) << 40)
+ (((long) bytes[offset + 4] & 0xFFL) << 32)
+ (((long) bytes[offset + 3] & 0xFFL) << 24)
+ (((long) bytes[offset + 2] & 0xFFL) << 16)
+ (((long) bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
break;
case 7:
nameValue = (((long) bytes[offset + 6]) << 48)
+ (((long) bytes[offset + 5] & 0xFFL) << 40)
+ (((long) bytes[offset + 4] & 0xFFL) << 32)
+ (((long) bytes[offset + 3] & 0xFFL) << 24)
+ (((long) bytes[offset + 2] & 0xFFL) << 16)
+ (((long) bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
break;
case 8:
nameValue = (((long) bytes[offset + 7]) << 56)
+ (((long) bytes[offset + 6] & 0xFFL) << 48)
+ (((long) bytes[offset + 5] & 0xFFL) << 40)
+ (((long) bytes[offset + 4] & 0xFFL) << 32)
+ (((long) bytes[offset + 3] & 0xFFL) << 24)
+ (((long) bytes[offset + 2] & 0xFFL) << 16)
+ (((long) bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
break;
default:
break;
}
}
if (nameValue != 0) {
offset += strlen;
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;
}
}
}
if (typeSymbol) {
int symbol;
if ((type = bytes[offset]) >= BC_INT32_NUM_MIN && type <= BC_INT32_NUM_MAX) {
symbol = type;
offset++;
} else {
symbol = readInt32Value();
}
long strInfo = ((long) strBegin << 32) + ((long) strlen << 8) + strtype;
int minCapacity = symbol * 2 + 2;
if (symbols.length < minCapacity) {
symbols = Arrays.copyOf(symbols, minCapacity + 16);
}
symbols[symbol * 2] = hashCode;
symbols[symbol * 2 + 1] = strInfo;
}
return hashCode;
}
@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() {
strtype = bytes[offset];
if (strtype >= BC_INT32_NUM_MIN && strtype <= BC_INT32) {
int typeIndex;
if (strtype >= BC_INT32_NUM_MIN && strtype <= BC_INT32_NUM_MAX) {
offset++;
typeIndex = strtype;
} else if (strtype >= BC_INT32_BYTE_MIN && strtype <= BC_INT32_BYTE_MAX) {
offset++;
return ((strtype - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
} else {
typeIndex = readInt32Value();
}
long refTypeHash;
if (typeIndex < 0) {
strlen = strtype;
refTypeHash = symbolTable.getHashCode(-typeIndex);
} else {
refTypeHash = symbols[typeIndex * 2];
if (refTypeHash == 0) {
long strInfo = symbols[typeIndex * 2 + 1];
strtype = (byte) strInfo;
strlen = ((int) strInfo) >> 8;
strBegin = (int) (strInfo >> 32);
refTypeHash = Fnv.hashCode64(getString());
}
}
if (refTypeHash == -1) {
throw new JSONException("type ref not found : " + 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
) {
strlen = readLength();
strBegin = offset;
} else {
throw new JSONException("string value not support input " + typeName(type)
+ " offset " + offset + "/" + bytes.length);
}
long hashCode;
if (strlen < 0) {
hashCode = symbolTable.getHashCode(-strlen);
} else if (strtype == BC_STR_UTF8) {
hashCode = Fnv.MAGIC_HASH_CODE;
int end = offset + strlen;
for (; offset < end; ) {
int c = bytes[offset];
if (c >= 0) {
offset++;
} else {
c &= 0xFF;
switch (c >> 4) {
case 12:
case 13: {
/* 110x xxxx 10xx xxxx*/
int c2 = bytes[offset + 1];
if ((c2 & 0xC0) != 0x80) {
throw new JSONException("malformed input around byte " + offset);
}
c = (char) (((c & 0x1F) << 6)
| (c2 & 0x3F));
offset += 2;
break;
}
case 14: {
int c2 = bytes[offset + 1];
int c3 = bytes[offset + 2];
if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80)) {
throw new JSONException("malformed input around byte " + offset);
}
c = (char) (((c & 0x0F) << 12) |
((c2 & 0x3F) << 6) |
((c3 & 0x3F) << 0));
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 (MIXED_HASH_ALGORITHM && 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 ((type = bytes[offset]) >= BC_INT32_NUM_MIN && type <= BC_INT32_NUM_MAX) {
symbol = type;
offset++;
} else {
symbol = readInt32Value();
}
int minCapacity = symbol * 2 + 2;
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 hashCode;
}
@Override
public long readValueHashCode() {
strtype = bytes[offset];
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 {
throw new JSONException("string value not support input " + typeName(type)
+ " offset " + offset + "/" + bytes.length);
}
long hashCode;
if (strlen < 0) {
hashCode = symbolTable.getHashCode(-strlen);
} else if (strtype == BC_STR_UTF8) {
hashCode = Fnv.MAGIC_HASH_CODE;
int end = offset + strlen;
for (; offset < end; ) {
int c = bytes[offset];
if (c >= 0) {
offset++;
} else {
c &= 0xFF;
switch (c >> 4) {
case 12:
case 13: {
/* 110x xxxx 10xx xxxx*/
int c2 = bytes[offset + 1];
if ((c2 & 0xC0) != 0x80) {
throw new JSONException("malformed input around byte " + offset);
}
c = (char) (((c & 0x1F) << 6)
| (c2 & 0x3F));
offset += 2;
break;
}
case 14: {
int c2 = bytes[offset + 1];
int c3 = bytes[offset + 2];
if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80)) {
throw new JSONException("malformed input around byte " + offset);
}
c = (char) (((c & 0x0F) << 12) |
((c2 & 0x3F) << 6) |
((c3 & 0x3F) << 0));
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) {
hashCode = Fnv.MAGIC_HASH_CODE;
if (bytes[offset] == (byte) 0xFE
&& bytes[offset + 1] == (byte) 0xFF
) {
if (MIXED_HASH_ALGORITHM && 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) {
if (MIXED_HASH_ALGORITHM && 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) {
if (MIXED_HASH_ALGORITHM && 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 (MIXED_HASH_ALGORITHM && 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;
}
@Override
public long getNameHashCodeLCase() {
int offset = strBegin;
if (MIXED_HASH_ALGORITHM) {
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 == '-') {
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 == '-') {
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:
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:
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:
readInt64Value();
return;
case BC_DECIMAL:
// TODO skip big decimal
readInt32Value();
readBigInteger();
return;
case BC_DECIMAL_LONG:
readInt64Value();
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: {
for (int i = 0; ; ++i) {
if (bytes[offset] == BC_OBJECT_END) {
offset++;
break;
}
skipName();
skipValue();
}
return;
}
case BC_REFERENCE: {
if (isString()) {
skipName();
return;
}
throw new JSONException("skip not support type " + typeName(type));
}
default:
if (type >= BC_INT32_NUM_MIN && type <= BC_INT32_NUM_MAX) {
return;
}
if (type >= BC_INT64_NUM_MIN && type <= BC_INT64_NUM_MAX) {
return;
}
if (type >= BC_INT32_BYTE_MIN && type <= BC_INT32_BYTE_MAX) {
offset++;
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_INT64_NUM_MIN && type <= BC_INT64_NUM_MAX) {
return;
}
if (type >= BC_INT64_BYTE_MIN && type <= BC_INT64_BYTE_MAX) {
offset++;
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) {
skipValue();
}
return;
}
throw new JSONException("skip not support type " + typeName(type));
}
}
@Override
public boolean skipName() {
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_STR_ASCII_FIX_MIN && strtype <= BC_STR_UTF16BE) {
return true;
}
if (strtype == BC_SYMBOL) {
int type = bytes[offset];
if (type >= BC_INT32_NUM_MIN && type <= BC_INT32) {
readInt32Value();
return true;
}
String str = readString();
readInt32Value();
return true;
}
throw new JSONException("name not support input : " + typeName(strtype));
}
@Override
public String readFieldName() {
strtype = bytes[offset];
if (strtype == BC_NULL) {
offset++;
return null;
}
offset++;
boolean typeSymbol = strtype == BC_SYMBOL;
if (typeSymbol) {
strtype = bytes[offset];
if (strtype >= BC_INT32_NUM_MIN && strtype <= BC_INT32) {
int symbol = readInt32Value();
if (symbol < 0) {
return symbolTable.getName(-symbol);
}
int index = symbol * 2 + 1;
long strInfo = symbols[index];
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 && strtype <= BC_STR_ASCII) {
long nameValue0 = -1, nameValue1 = -1;
if (strtype == BC_STR_ASCII) {
strlen = readLength();
strBegin = offset;
} else {
strlen = strtype - BC_STR_ASCII_FIX_MIN;
switch (strlen) {
case 1:
nameValue0 = bytes[offset];
break;
case 2:
nameValue0
= (bytes[offset + 1] << 8)
+ (bytes[offset] & 0xFFL);
break;
case 3:
nameValue0
= (bytes[offset + 2] << 16)
+ ((bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
break;
case 4:
nameValue0
= (bytes[offset + 3] << 24)
+ ((bytes[offset + 2] & 0xFFL) << 16)
+ ((bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
break;
case 5:
nameValue0
= (((long) bytes[offset + 4]) << 32)
+ ((bytes[offset + 3] & 0xFFL) << 24)
+ ((bytes[offset + 2] & 0xFFL) << 16)
+ ((bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
break;
case 6:
nameValue0
= (((long) bytes[offset + 5]) << 40)
+ ((bytes[offset + 4] & 0xFFL) << 32)
+ ((bytes[offset + 3] & 0xFFL) << 24)
+ ((bytes[offset + 2] & 0xFFL) << 16)
+ ((bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset + 0] & 0xFFL);
break;
case 7:
nameValue0
= (((long) bytes[offset + 6]) << 48)
+ ((bytes[offset + 5] & 0xFFL) << 40)
+ ((bytes[offset + 4] & 0xFFL) << 32)
+ ((bytes[offset + 4] & 0xFFL) << 24)
+ ((bytes[offset + 3] & 0xFFL) << 16)
+ ((bytes[offset + 2] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
break;
case 8:
nameValue0
= (((long) bytes[offset + 7]) << 56)
+ ((bytes[offset + 6] & 0xFFL) << 48)
+ ((bytes[offset + 5] & 0xFFL) << 40)
+ ((bytes[offset + 4] & 0xFFL) << 32)
+ ((bytes[offset + 3] & 0xFFL) << 24)
+ ((bytes[offset + 2] & 0xFFL) << 16)
+ ((bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
break;
case 9:
nameValue0 = bytes[offset + 0];
nameValue1
= (((long) bytes[offset + 8]) << 56)
+ ((bytes[offset + 7]) << 48)
+ ((bytes[offset + 6] & 0xFFL) << 40)
+ ((bytes[offset + 5] & 0xFFL) << 32)
+ ((bytes[offset + 4] & 0xFFL) << 24)
+ ((bytes[offset + 3] & 0xFFL) << 16)
+ ((bytes[offset + 2] & 0xFFL) << 8)
+ (bytes[offset + 1] & 0xFFL);
break;
case 10:
nameValue0
= (bytes[offset + 1] << 8)
+ (bytes[offset] & 0xFFL);
nameValue1
= (((long) bytes[offset + 9]) << 56)
+ ((bytes[offset + 8] & 0xFFL) << 48)
+ ((bytes[offset + 7] & 0xFFL) << 40)
+ ((bytes[offset + 6] & 0xFFL) << 32)
+ ((bytes[offset + 5] & 0xFFL) << 24)
+ ((bytes[offset + 4] & 0xFFL) << 16)
+ ((bytes[offset + 3] & 0xFFL) << 8)
+ (bytes[offset + 2] & 0xFFL);
break;
case 11:
nameValue0
= (bytes[offset + 2] << 16)
+ ((bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
nameValue1
= (((long) bytes[offset + 10]) << 56)
+ ((bytes[offset + 9] & 0xFFL) << 48)
+ ((bytes[offset + 8] & 0xFFL) << 40)
+ ((bytes[offset + 7] & 0xFFL) << 32)
+ ((bytes[offset + 6] & 0xFFL) << 24)
+ ((bytes[offset + 5] & 0xFFL) << 16)
+ ((bytes[offset + 4] & 0xFFL) << 8)
+ (bytes[offset + 3] & 0xFFL);
break;
case 12:
nameValue0
= (bytes[offset + 3] << 24)
+ ((bytes[offset + 2] & 0xFFL) << 16)
+ ((bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
nameValue1
= (((long) bytes[offset + 11]) << 56)
+ ((bytes[offset + 10] & 0xFFL) << 48)
+ ((bytes[offset + 9] & 0xFFL) << 40)
+ ((bytes[offset + 8] & 0xFFL) << 32)
+ ((bytes[offset + 7] & 0xFFL) << 24)
+ ((bytes[offset + 6] & 0xFFL) << 16)
+ ((bytes[offset + 5] & 0xFFL) << 8)
+ (bytes[offset + 4] & 0xFFL);
break;
case 13:
nameValue0
= (((long) bytes[offset + 4]) << 32)
+ ((bytes[offset + 3] & 0xFFL) << 24)
+ ((bytes[offset + 2] & 0xFFL) << 16)
+ ((bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
nameValue1
= (((long) bytes[offset + 12]) << 56)
+ ((bytes[offset + 11] & 0xFFL) << 48)
+ ((bytes[offset + 10] & 0xFFL) << 40)
+ ((bytes[offset + 9] & 0xFFL) << 32)
+ ((bytes[offset + 8] & 0xFFL) << 24)
+ ((bytes[offset + 7] & 0xFFL) << 16)
+ ((bytes[offset + 6] & 0xFFL) << 8)
+ (bytes[offset + 5] & 0xFFL);
break;
case 14:
nameValue0
= (((long) bytes[offset + 5]) << 40)
+ ((bytes[offset + 4] & 0xFFL) << 32)
+ ((bytes[offset + 3] & 0xFFL) << 24)
+ ((bytes[offset + 2] & 0xFFL) << 16)
+ ((bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
nameValue1
= (((long) bytes[offset + 13]) << 56)
+ ((bytes[offset + 12] & 0xFFL) << 48)
+ ((bytes[offset + 11] & 0xFFL) << 40)
+ ((bytes[offset + 10] & 0xFFL) << 32)
+ ((bytes[offset + 9] & 0xFFL) << 24)
+ ((bytes[offset + 8] & 0xFFL) << 16)
+ ((bytes[offset + 7] & 0xFFL) << 8)
+ (bytes[offset + 6] & 0xFFL);
break;
case 15:
nameValue0
= (((long) bytes[offset + 6]) << 48)
+ ((bytes[offset + 5] & 0xFFL) << 40)
+ ((bytes[offset + 4] & 0xFFL) << 32)
+ ((bytes[offset + 3] & 0xFFL) << 24)
+ ((bytes[offset + 2] & 0xFFL) << 16)
+ ((bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
nameValue1
= (((long) bytes[offset + 14]) << 56)
+ ((bytes[offset + 13] & 0xFFL) << 48)
+ ((bytes[offset + 12] & 0xFFL) << 40)
+ ((bytes[offset + 11] & 0xFFL) << 32)
+ ((bytes[offset + 10] & 0xFFL) << 24)
+ ((bytes[offset + 9] & 0xFFL) << 16)
+ ((bytes[offset + 8] & 0xFFL) << 8)
+ (bytes[offset + 7] & 0xFFL);
break;
case 16:
nameValue0
= (((long) bytes[offset + 7]) << 56)
+ ((bytes[offset + 6]) << 48)
+ ((bytes[offset + 5] & 0xFFL) << 40)
+ ((bytes[offset + 4] & 0xFFL) << 32)
+ ((bytes[offset + 3] & 0xFFL) << 24)
+ ((bytes[offset + 2] & 0xFFL) << 16)
+ ((bytes[offset + 1] & 0xFFL) << 8)
+ (bytes[offset] & 0xFFL);
nameValue1
= (((long) bytes[offset + 15]) << 56)
+ ((bytes[offset + 14] & 0xFFL) << 48)
+ ((bytes[offset + 13] & 0xFFL) << 40)
+ ((bytes[offset + 12] & 0xFFL) << 32)
+ ((bytes[offset + 11] & 0xFFL) << 24)
+ ((bytes[offset + 10] & 0xFFL) << 16)
+ ((bytes[offset + 9] & 0xFFL) << 8)
+ (bytes[offset + 8] & 0xFFL);
break;
default:
break;
}
}
if (nameValue0 != -1) {
if (nameValue1 != -1) {
int indexMask = ((int) nameValue1) & (NAME_CACHE2.length - 1);
JSONFactory.NameCacheEntry2 entry = NAME_CACHE2[indexMask];
if (entry == null) {
String name;
if (STRING_CREATOR_JDK8 != null) {
char[] chars = new char[strlen];
for (int i = 0; i < strlen; ++i) {
chars[i] = (char) bytes[offset + i];
}
name = STRING_CREATOR_JDK8.apply(chars, Boolean.TRUE);
} else {
name = new String(bytes, offset, strlen, StandardCharsets.US_ASCII);
}
NAME_CACHE2[indexMask] = new JSONFactory.NameCacheEntry2(name, nameValue0, nameValue1);
offset += strlen;
return name;
} else if (entry.value0 == nameValue0 && entry.value1 == nameValue1) {
offset += strlen;
return entry.name;
}
} else {
int indexMask = ((int) nameValue0) & (NAME_CACHE.length - 1);
JSONFactory.NameCacheEntry entry = NAME_CACHE[indexMask];
if (entry == null) {
String name;
if (STRING_CREATOR_JDK8 != null) {
char[] chars = new char[strlen];
for (int i = 0; i < strlen; ++i) {
chars[i] = (char) bytes[offset + i];
}
name = STRING_CREATOR_JDK8.apply(chars, Boolean.TRUE);
} else {
name = new String(bytes, offset, strlen, StandardCharsets.US_ASCII);
}
NAME_CACHE[indexMask] = new JSONFactory.NameCacheEntry(name, nameValue0);
offset += strlen;
return name;
} else if (entry.value == nameValue0) {
offset += strlen;
return entry.name;
}
}
}
if (STRING_CREATOR_JDK8 != null && strlen >= 0) {
char[] chars = new char[strlen];
for (int i = 0; i < strlen; ++i) {
chars[i] = (char) bytes[offset + i];
}
offset += strlen;
str = STRING_CREATOR_JDK8.apply(chars, Boolean.TRUE);
} else if (STRING_CREATOR_JDK11 != null && strlen >= 0) {
byte[] chars = new byte[strlen];
System.arraycopy(bytes, offset, chars, 0, strlen);
str = STRING_CREATOR_JDK11.apply(chars, LATIN1);
offset += strlen;
}
charset = StandardCharsets.US_ASCII;
} else if (strtype == BC_STR_UTF8) {
strlen = readLength();
strBegin = offset;
if (STRING_CREATOR_JDK11 != null && !JDKUtils.BIG_ENDIAN) {
if (valueBytes == null) {
valueBytes = JSONFactory.allocateByteArray(cachedIndex);
}
int minCapacity = strlen << 1;
if (valueBytes == null) {
valueBytes = new byte[minCapacity];
} else {
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) 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;
}
if (strlen < 0) {
str = symbolTable.getName(-strlen);
}
if (str == null) {
str = new String(bytes, offset, strlen, charset);
offset += strlen;
}
if (typeSymbol) {
int symbol = readInt32Value();
int minCapacity = symbol * 2 + 2;
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() {
strtype = bytes[offset++];
if (strtype == BC_NULL) {
return null;
}
strBegin = offset;
Charset charset;
String str;
if (strtype >= BC_STR_ASCII_FIX_MIN && strtype <= BC_STR_ASCII) {
if (strtype == BC_STR_ASCII) {
byte strType = bytes[offset];
if (strType >= BC_INT32_NUM_MIN && strType <= BC_INT32_NUM_MAX) {
offset++;
strlen = strType;
} else if (strType >= BC_INT32_BYTE_MIN && strType <= BC_INT32_BYTE_MAX) {
offset++;
strlen = ((strType - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
} else {
strlen = readLength();
}
strBegin = offset;
} else {
strlen = strtype - BC_STR_ASCII_FIX_MIN;
}
if (strlen >= 0) {
if (STRING_CREATOR_JDK8 != null) {
char[] chars = new char[strlen];
for (int i = 0; i < strlen; ++i) {
chars[i] = (char) bytes[offset + i];
}
offset += strlen;
str = STRING_CREATOR_JDK8.apply(chars, Boolean.TRUE);
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
return str;
} 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;
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
return str;
}
}
charset = StandardCharsets.US_ASCII;
} else if (strtype == BC_STR_UTF8) {
byte strType = bytes[offset];
if (strType >= BC_INT32_NUM_MIN && strType <= BC_INT32_NUM_MAX) {
offset++;
strlen = strType;
} else if (strType >= BC_INT32_BYTE_MIN && strType <= BC_INT32_BYTE_MAX) {
offset++;
strlen = ((strType - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
} else {
strlen = readLength();
}
strBegin = offset;
if (STRING_CREATOR_JDK11 != null && !JDKUtils.BIG_ENDIAN) {
if (valueBytes == null) {
valueBytes = JSONFactory.allocateByteArray(cachedIndex);
}
int minCapacity = strlen << 1;
if (valueBytes == null) {
valueBytes = new byte[minCapacity];
} else {
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;
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
return str;
}
}
charset = StandardCharsets.UTF_8;
} else if (strtype == BC_STR_UTF16) {
strlen = readLength();
strBegin = offset;
charset = StandardCharsets.UTF_16;
} else if (strtype == BC_STR_UTF16LE) {
byte strType = bytes[offset];
if (strType >= BC_INT32_NUM_MIN && strType <= BC_INT32_NUM_MAX) {
offset++;
strlen = strType;
} else if (strType >= BC_INT32_BYTE_MIN && strType <= BC_INT32_BYTE_MAX) {
offset++;
strlen = ((strType - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
} 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);
str = STRING_CREATOR_JDK11.apply(chars, UTF16);
offset += strlen;
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
return str;
}
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;
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
return str;
}
charset = StandardCharsets.UTF_16BE;
} else if (strtype == BC_STR_GB18030) {
strlen = readLength();
strBegin = offset;
if (GB18030 == null) {
GB18030 = Charset.forName("GB18030");
}
charset = GB18030;
} else if (strtype >= BC_INT32_NUM_MIN && strtype <= BC_INT32_NUM_MAX) {
return Byte.toString(strtype);
} else if (strtype >= BC_INT32_BYTE_MIN && strtype <= BC_INT32_BYTE_MAX) {
int intValue = ((strtype - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
return Integer.toString(intValue);
} else if (strtype >= BC_INT32_SHORT_MIN && strtype <= BC_INT32_SHORT_MAX) {
int intValue = ((strtype - BC_INT32_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
return Integer.toString(intValue);
} else if (strtype >= BC_INT64_NUM_MIN && strtype <= BC_INT64_NUM_MAX) {
int intValue = INT64_NUM_LOW_VALUE + (strtype - BC_INT64_NUM_MIN);
return Integer.toString(intValue);
} else if (strtype >= BC_INT64_BYTE_MIN && strtype <= BC_INT64_BYTE_MAX) {
int intValue = ((strtype - BC_INT64_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
return Integer.toString(intValue);
} else if (strtype >= BC_INT64_SHORT_MIN && strtype <= BC_INT64_SHORT_MAX) {
int intValue = ((strtype - BC_INT64_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
return Integer.toString(intValue);
} else {
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: {
long int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return Long.toString(int32Value);
}
case BC_FLOAT_INT:
return Float.toString(
readInt32Value());
case BC_FLOAT: {
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
float floatValue = Float.intBitsToFloat(int32Value);
return Float.toString(floatValue);
}
case BC_DOUBLE: {
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
offset += 8;
double doubleValue = Double.longBitsToDouble(int64Value);
return Double.toString(doubleValue);
}
case BC_TIMESTAMP_SECONDS: {
long int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return Long.toString(int32Value * 1000);
}
case BC_TIMESTAMP_MINUTES: {
long minutes =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return Long.toString(minutes * 60 * 1000);
}
case BC_TIMESTAMP_MILLIS:
case BC_INT64:
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
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: {
Object typedAny = readAny();
return typedAny == null ? null : typedAny.toString();
}
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 new JSONException("readString not support type " + typeName(strtype) + ", offset " + offset + "/" + bytes.length);
}
if (strlen < 0) {
return symbolTable.getName(-strlen);
}
char[] chars = null;
if (JVM_VERSION == 8 && strtype == BC_STR_UTF8 && strlen < 8192) {
final int cachedIndex = System.identityHashCode(Thread.currentThread()) & (CACHE_SIZE - 1);
chars = allocateCharArray(cachedIndex);
}
if (chars != null) {
int len = IOUtils.decodeUTF8(bytes, offset, strlen, chars);
str = new String(chars, 0, len);
releaseCharArray(cachedIndex, chars);
} else {
str = new String(bytes, offset, strlen, charset);
}
offset += strlen;
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
return str;
}
@Override
public char readCharValue() {
byte type = bytes[offset];
if (type == BC_CHAR) {
offset++;
return (char) readInt32Value();
} else if (type >= BC_STR_ASCII_FIX_0 && type < BC_STR_ASCII_FIX_MAX) {
offset++;
return (char) bytes[offset++];
}
String str = readString();
if (str == null || str.isEmpty()) {
wasNull = true;
return '\0';
}
return str.charAt(0);
}
@Override
public long readInt64Value() {
wasNull = false;
byte type = bytes[offset++];
if (type >= BC_INT32_NUM_MIN && type <= BC_INT32_NUM_MAX) {
return type;
}
if (type >= BC_INT64_NUM_MIN && type <= BC_INT64_NUM_MAX) {
return (long) INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
}
if (type >= BC_INT32_BYTE_MIN && type <= BC_INT32_BYTE_MAX) {
return ((type - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT64_BYTE_MIN && type <= BC_INT64_BYTE_MAX) {
return ((type - BC_INT64_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT64_SHORT_MIN && type <= BC_INT64_SHORT_MAX) {
return ((type - BC_INT64_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT32_SHORT_MIN && type <= BC_INT32_SHORT_MAX) {
return ((type - BC_INT32_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
}
switch (type) {
case BC_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_INT64_INT:
case BC_INT32: {
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return int32Value;
}
case BC_FLOAT: {
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
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 =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return minutes * 60 * 1000;
}
case BC_TIMESTAMP_SECONDS: {
long seconds =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return seconds * 1000;
}
case BC_TIMESTAMP_MILLIS:
case BC_INT64:
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
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, StandardCharsets.US_ASCII);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return new BigDecimal(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 new BigDecimal(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 new BigDecimal(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 new BigDecimal(str).longValue();
}
}
break;
}
throw new JSONException("readInt64Value not support " + typeName(type) + ", offset " + offset + "/" + bytes.length);
}
@Override
public int readInt32Value() {
byte type = bytes[offset++];
if (type >= BC_INT32_NUM_MIN && type <= BC_INT32_NUM_MAX) {
return type;
}
if (type >= BC_INT32_BYTE_MIN && type <= BC_INT32_BYTE_MAX) {
return ((type - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT32_SHORT_MIN && type <= BC_INT32_SHORT_MAX) {
return ((type - BC_INT32_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT64_NUM_MIN && type <= BC_INT64_NUM_MAX) {
return (int) INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
}
if (type >= BC_INT64_BYTE_MIN && type <= BC_INT64_BYTE_MAX) {
return ((type - BC_INT64_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT64_SHORT_MIN && type <= BC_INT64_SHORT_MAX) {
return ((type - BC_INT64_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
}
switch (type) {
case BC_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 =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
offset += 8;
return (int) int64Value;
}
case BC_FLOAT_INT:
return (int) (float) readInt32Value();
case BC_FLOAT: {
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
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_INT32:
case BC_INT64_INT:
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return int32Value;
case BC_STR_ASCII: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.US_ASCII);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return new BigDecimal(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 new BigDecimal(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 new BigDecimal(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();
}
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 new BigDecimal(str).intValue();
}
}
break;
}
throw new JSONException("readInt32Value not support " + typeName(type) + ", offset " + offset + "/" + bytes.length);
}
@Override
public boolean isBinary() {
return bytes[offset] == BC_BINARY;
}
@Override
public byte[] readBinary() {
byte type = bytes[offset++];
if (type != BC_BINARY) {
throw new JSONException("not support input : " + typeName(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() {
wasNull = false;
int value = readInt32Value();
if (wasNull) {
return null;
}
return value;
}
@Override
public Long readInt64() {
long value = readInt64Value();
if (wasNull) {
return null;
}
return value;
}
protected final String readFixedAsciiString(int strlen) {
String str;
if (STRING_CREATOR_JDK8 != null) {
char[] chars = new char[strlen];
for (int i = 0; i < strlen; ++i) {
chars[i] = (char) bytes[offset + i];
}
str = STRING_CREATOR_JDK8.apply(chars, Boolean.TRUE);
} else {
str = new String(bytes, offset, strlen, StandardCharsets.ISO_8859_1);
}
return str;
}
@Override
public float readFloatValue() {
byte type = bytes[offset++];
switch (type) {
case BC_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 =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
offset += 8;
return (float) int64Value;
}
case BC_INT64_INT:
case BC_INT32: {
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return int32Value;
}
case BC_FLOAT: {
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return Float.intBitsToFloat(int32Value);
}
case BC_DOUBLE: {
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
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, StandardCharsets.US_ASCII);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return new BigDecimal(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 new BigDecimal(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 new BigDecimal(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 (type >= BC_INT32_NUM_MIN && type <= BC_INT32_NUM_MAX) {
return type;
}
if (type >= BC_INT32_BYTE_MIN && type <= BC_INT32_BYTE_MAX) {
return ((type - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT32_SHORT_MIN && type <= BC_INT32_SHORT_MAX) {
return ((type - BC_INT32_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT64_NUM_MIN && type <= BC_INT64_NUM_MAX) {
return (float) (INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN));
}
if (type >= BC_INT64_BYTE_MIN && type <= BC_INT64_BYTE_MAX) {
return ((type - BC_INT64_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT64_SHORT_MIN && type <= BC_INT64_SHORT_MAX) {
return ((type - BC_INT64_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
}
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 new BigDecimal(str).intValue();
}
}
break;
}
throw new JSONException("TODO : " + typeName(type));
}
@Override
public double readDoubleValue() {
byte type = bytes[offset++];
switch (type) {
case BC_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 =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
offset += 8;
return (double) int64Value;
}
case BC_INT64_INT:
case BC_INT32: {
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return int32Value;
}
case BC_FLOAT:
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return Float.intBitsToFloat(int32Value);
case BC_FLOAT_INT: {
return (float) readInt32Value();
}
case BC_DOUBLE:
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
offset += 8;
return Double.longBitsToDouble(int64Value);
case BC_DOUBLE_LONG:
return readInt64Value();
case BC_STR_ASCII: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.US_ASCII);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str).intValue();
} else {
return new BigDecimal(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 new BigDecimal(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 new BigDecimal(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 (type >= BC_INT32_NUM_MIN && type <= BC_INT32_NUM_MAX) {
return type;
}
if (type >= BC_INT32_BYTE_MIN && type <= BC_INT32_BYTE_MAX) {
return ((type - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT32_SHORT_MIN && type <= BC_INT32_SHORT_MAX) {
return ((type - BC_INT32_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT64_NUM_MIN && type <= BC_INT64_NUM_MAX) {
return (long) INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
}
if (type >= BC_INT64_BYTE_MIN && type <= BC_INT64_BYTE_MAX) {
return ((type - BC_INT64_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT64_SHORT_MIN && type <= BC_INT64_SHORT_MAX) {
return ((type - BC_INT64_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
}
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 new BigDecimal(str).intValue();
}
}
break;
}
throw new JSONException("TODO : " + typeName(type));
}
@Override
protected void readNumber0() {
throw new JSONException("UnsupportedOperation");
}
@Override
public Number readNumber() {
byte type = bytes[offset++];
if (type >= BC_INT32_NUM_MIN && type <= BC_INT32_NUM_MAX) {
return (int) type;
}
if (type >= BC_INT32_BYTE_MIN && type <= BC_INT32_BYTE_MAX) {
return ((type - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT32_SHORT_MIN && type <= BC_INT32_SHORT_MAX) {
return ((type - BC_INT32_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT64_NUM_MIN && type <= BC_INT64_NUM_MAX) {
return (long) INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
}
if (type >= BC_INT64_BYTE_MIN && type <= BC_INT64_BYTE_MAX) {
return ((type - BC_INT64_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
}
if (type >= BC_INT64_SHORT_MIN && type <= BC_INT64_SHORT_MAX) {
return ((type - BC_INT64_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
}
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 =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return int32Value;
}
case BC_INT64_INT: {
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return (long) int32Value;
}
case BC_INT64: {
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
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 =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return Float.intBitsToFloat(int32Value);
}
case BC_FLOAT_INT: {
return (float) readInt32Value();
}
case BC_DOUBLE:
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
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, StandardCharsets.US_ASCII);
offset += strlen;
return new BigDecimal(str);
}
case BC_STR_UTF8: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_8);
offset += strlen;
return new BigDecimal(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 new BigDecimal(str);
}
break;
}
throw new JSONException("not support type :" + typeName(type));
}
@Override
public BigDecimal readBigDecimal() {
byte type = bytes[offset++];
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 =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return BigDecimal.valueOf(int32Value);
}
case BC_FLOAT_INT: {
float floatValue = (float) readInt32Value();
return BigDecimal.valueOf((long) floatValue);
}
case BC_FLOAT: {
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
float floatValue = Float.intBitsToFloat(int32Value);
return BigDecimal.valueOf((long) floatValue);
}
case BC_DOUBLE: {
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
offset += 8;
double doubleValue = Double.longBitsToDouble(int64Value);
return BigDecimal.valueOf(
(long) doubleValue);
}
case BC_INT64: {
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
offset += 8;
return BigDecimal.valueOf(int64Value);
}
case BC_BIGINT: {
return new BigDecimal(
readBigInteger()
);
}
case BC_DECIMAL: {
int scale = readInt32Value();
if (bytes[offset] == BC_BIGINT_LONG) {
offset++;
long unscaledLongValue = readInt64Value();
return BigDecimal.valueOf(unscaledLongValue, scale);
}
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_DOUBLE_LONG: {
double doubleValue = readInt64Value();
return BigDecimal.valueOf((long) doubleValue);
}
case BC_STR_ASCII: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.US_ASCII);
offset += strlen;
return new BigDecimal(str);
}
case BC_STR_UTF16LE: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_16LE);
offset += strlen;
return new BigDecimal(str);
}
case BC_STR_UTF8: {
int strlen = readInt32Value();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_8);
offset += strlen;
return new BigDecimal(str);
}
default:
if (type >= BC_INT32_NUM_MIN && type <= BC_INT32_NUM_MAX) {
return BigDecimal.valueOf(type);
}
if (type >= BC_INT32_BYTE_MIN && type <= BC_INT32_BYTE_MAX) {
int intValue = ((type - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
return BigDecimal.valueOf(intValue);
}
if (type >= BC_INT32_SHORT_MIN && type <= BC_INT32_SHORT_MAX) {
int intValue = ((type - BC_INT32_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
return BigDecimal.valueOf(intValue);
}
if (type >= BC_INT64_NUM_MIN && type <= BC_INT64_NUM_MAX) {
int intValue = INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
return BigDecimal.valueOf(intValue);
}
if (type >= BC_INT64_BYTE_MIN && type <= BC_INT64_BYTE_MAX) {
int intValue = ((type - BC_INT64_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
return BigDecimal.valueOf(intValue);
}
if (type >= BC_INT64_SHORT_MIN && type <= BC_INT64_SHORT_MAX) {
int intValue = ((type - BC_INT64_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
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 new BigDecimal(str);
}
break;
}
throw new JSONException("not support type :" + typeName(type));
}
@Override
public BigInteger readBigInteger() {
byte type = bytes[offset++];
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 =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
return BigInteger.valueOf(int32Value);
}
case BC_FLOAT_INT: {
float floatValue = (float) readInt32Value();
return BigInteger.valueOf(
(long) floatValue);
}
case BC_FLOAT: {
int int32Value =
((bytes[offset + 3] & 0xFF)) +
((bytes[offset + 2] & 0xFF) << 8) +
((bytes[offset + 1] & 0xFF) << 16) +
((bytes[offset]) << 24);
offset += 4;
float floatValue = Float.intBitsToFloat(int32Value);
return BigInteger.valueOf(
(long) floatValue);
}
case BC_DOUBLE: {
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
offset += 8;
double doubleValue = Double.longBitsToDouble(int64Value);
return BigInteger.valueOf(
(long) doubleValue);
}
case BC_INT64: {
long int64Value =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
offset += 8;
return BigInteger.valueOf(int64Value);
}
case BC_BIGINT:
case BC_BINARY: {
int len = readInt32Value();
byte[] bytes = new byte[len];
System.arraycopy(this.bytes, offset, bytes, 0, len);
offset += len;
return new BigInteger(bytes);
}
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_BIGINT_LONG: {
return BigInteger.valueOf(
readInt64Value()
);
}
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, StandardCharsets.US_ASCII);
offset += strlen;
if (str.indexOf('.') == -1) {
return new BigInteger(str);
} else {
return new BigDecimal(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 new BigDecimal(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 new BigDecimal(str).toBigInteger();
}
}
default:
if (type >= BC_INT32_NUM_MIN && type <= BC_INT32_NUM_MAX) {
return BigInteger.valueOf(type);
}
if (type >= BC_INT32_BYTE_MIN && type <= BC_INT32_BYTE_MAX) {
int intValue = ((type - BC_INT32_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
return BigInteger.valueOf(intValue);
}
if (type >= BC_INT32_SHORT_MIN && type <= BC_INT32_SHORT_MAX) {
int intValue = ((type - BC_INT32_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
return BigInteger.valueOf(intValue);
}
if (type >= BC_INT64_NUM_MIN && type <= BC_INT64_NUM_MAX) {
int intValue = INT64_NUM_LOW_VALUE + (type - BC_INT64_NUM_MIN);
return BigInteger.valueOf(intValue);
}
if (type >= BC_INT64_BYTE_MIN && type <= BC_INT64_BYTE_MAX) {
int intValue = ((type - BC_INT64_BYTE_ZERO) << 8)
+ (bytes[offset++] & 0xFF);
return BigInteger.valueOf(intValue);
}
if (type >= BC_INT64_SHORT_MIN && type <= BC_INT64_SHORT_MAX) {
int intValue = ((type - BC_INT64_SHORT_ZERO) << 16)
+ ((bytes[offset++] & 0xFF) << 8)
+ (bytes[offset++] & 0xFF);
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 new JSONException("not support type :" + typeName(type));
}
@Override
public LocalDate readLocalDate() {
int type = bytes[offset];
if (type == BC_LOCAL_DATE) {
offset++;
int year = (bytes[offset++] << 8) + (bytes[offset++] & 0xFF);
int month = bytes[offset++];
int dayOfMonth = bytes[offset++];
return LocalDate.of(year, month, dayOfMonth);
}
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:
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 new UnsupportedOperationException();
}
@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_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 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 new UnsupportedOperationException();
}
@Override
protected LocalDateTime readLocalDateTime16() {
throw new JSONException("UnsupportedOperation");
}
@Override
protected LocalDateTime readLocalDateTime17() {
throw new JSONException("UnsupportedOperation");
}
@Override
protected LocalTime readLocalTime10() {
throw new JSONException("UnsupportedOperation");
}
@Override
protected LocalTime readLocalTime11() {
throw new JSONException("UnsupportedOperation");
}
@Override
protected LocalDate readLocalDate11() {
throw new JSONException("UnsupportedOperation");
}
@Override
protected ZonedDateTime readZonedDateTimeX(int len) {
throw new JSONException("UnsupportedOperation");
}
@Override
public void skipLineComment() {
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_STR_ASCII_FIX_MIN && type <= BC_STR_ASCII_FIX_MAX) {
int len = getStringLength();
switch (len) {
case 8:
return readLocalTime8();
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);
}
if (type == BC_STR_UTF8 || type == BC_STR_ASCII) {
strtype = (byte) type;
offset++;
strlen = readLength();
switch (strlen) {
case 8:
return readLocalTime8();
case 10:
return readLocalTime10();
case 11:
return readLocalTime11();
case 12:
return readLocalTime12();
case 18:
return readLocalTime18();
default:
break;
}
throw new JSONException("not support len : " + strlen);
}
throw new UnsupportedOperationException();
}
@Override
public Instant readInstant() {
int type = bytes[offset++];
switch (type) {
case BC_TIMESTAMP: {
long second = readInt64Value();
int nano = readInt32Value();
return Instant.ofEpochSecond(second, nano);
}
case BC_TIMESTAMP_MINUTES: {
long second = readInt32Value() * 60;
return Instant.ofEpochSecond(second, 0);
}
case BC_TIMESTAMP_SECONDS: {
long second = readInt32Value();
return Instant.ofEpochSecond(second, 0);
}
case BC_INT64:
case BC_TIMESTAMP_MILLIS: {
long millis = readInt64Value();
return Instant.ofEpochMilli(millis);
}
default:
break;
}
throw new UnsupportedOperationException();
}
@Override
public ZonedDateTime readZonedDateTime() {
int type = bytes[offset++];
switch (type) {
case BC_TIMESTAMP: {
long second = readInt64Value();
int nano = readInt32Value();
Instant instant = Instant.ofEpochSecond(second, nano);
return ZonedDateTime.ofInstant(instant, ZoneOffset.UTC);
}
case BC_TIMESTAMP_MINUTES: {
long second = readInt32Value() * 60;
Instant instant = Instant.ofEpochSecond(second);
return ZonedDateTime.ofInstant(instant, ZoneOffset.UTC);
}
case BC_TIMESTAMP_SECONDS: {
long second = readInt32Value();
Instant instant = Instant.ofEpochSecond(second);
return ZonedDateTime.ofInstant(instant, ZoneOffset.UTC);
}
case BC_INT64:
case BC_TIMESTAMP_MILLIS: {
long millis = readInt64Value();
Instant instant = Instant.ofEpochMilli(millis);
return ZonedDateTime.ofInstant(instant, ZoneOffset.UTC);
}
case BC_TIMESTAMP_WITH_TIMEZONE:
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();
LocalDateTime ldt = LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nano);
ZoneId zoneId;
long zoneIdHash = readValueHashCode();
if (zoneIdHash == SHANGHAI_ZONE_ID_HASH) {
zoneId = SHANGHAI_ZONE_ID;
} else {
String zoneIdStr = getString();
ZoneId contextZondId = context.getZoneId();
if (contextZondId.getId().equals(zoneIdStr)) {
zoneId = contextZondId;
} else {
zoneId = ZoneId.of(zoneIdStr);
}
}
return ZonedDateTime.of(ldt, zoneId);
default:
break;
}
throw new UnsupportedOperationException();
}
@Override
public UUID readUUID() {
byte type = bytes[offset++];
switch (type) {
case BC_NULL:
return null;
case BC_BINARY:
int len = readLength();
if (len != 16) {
throw new JSONException("uuid not support " + len);
}
long msb =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
offset += 8;
long lsb =
((bytes[offset + 7] & 0xFFL)) +
((bytes[offset + 6] & 0xFFL) << 8) +
((bytes[offset + 5] & 0xFFL) << 16) +
((bytes[offset + 4] & 0xFFL) << 24) +
((bytes[offset + 3] & 0xFFL) << 32) +
((bytes[offset + 2] & 0xFFL) << 40) +
((bytes[offset + 1] & 0xFFL) << 48) +
((long) (bytes[offset]) << 56);
offset += 8;
return new UUID(msb, lsb);
case BC_STR_ASCII_FIX_32: {
long msb1 = parse4Nibbles(bytes, offset + 0);
long msb2 = parse4Nibbles(bytes, offset + 4);
long msb3 = parse4Nibbles(bytes, offset + 8);
long msb4 = parse4Nibbles(bytes, offset + 12);
long lsb1 = parse4Nibbles(bytes, offset + 16);
long lsb2 = parse4Nibbles(bytes, offset + 20);
long lsb3 = parse4Nibbles(bytes, offset + 24);
long lsb4 = parse4Nibbles(bytes, offset + 28);
if ((msb1 | msb2 | msb3 | msb4 | lsb1 | lsb2 | lsb3 | lsb4) >= 0) {
offset += 32;
return new UUID(
msb1 << 48 | msb2 << 32 | msb3 << 16 | msb4,
lsb1 << 48 | lsb2 << 32 | lsb3 << 16 | lsb4);
}
throw new JSONException("Invalid UUID string: " + new String(bytes, offset, 32, StandardCharsets.US_ASCII));
}
case BC_STR_ASCII_FIX_36: {
byte ch1 = bytes[offset + 8];
byte ch2 = bytes[offset + 13];
byte ch3 = bytes[offset + 18];
byte ch4 = bytes[offset + 23];
if (ch1 == '-' && ch2 == '-' && ch3 == '-' && ch4 == '-') {
long msb1 = parse4Nibbles(bytes, offset + 0);
long msb2 = parse4Nibbles(bytes, offset + 4);
long msb3 = parse4Nibbles(bytes, offset + 9);
long msb4 = parse4Nibbles(bytes, offset + 14);
long lsb1 = parse4Nibbles(bytes, offset + 19);
long lsb2 = parse4Nibbles(bytes, offset + 24);
long lsb3 = parse4Nibbles(bytes, offset + 28);
long lsb4 = parse4Nibbles(bytes, offset + 32);
if ((msb1 | msb2 | msb3 | msb4 | lsb1 | lsb2 | lsb3 | lsb4) >= 0) {
offset += 36;
return new UUID(
msb1 << 48 | msb2 << 32 | msb3 << 16 | msb4,
lsb1 << 48 | lsb2 << 32 | lsb3 << 16 | lsb4);
}
}
throw new JSONException("Invalid UUID string: " + new String(bytes, offset, 36, StandardCharsets.US_ASCII));
}
case BC_STR_ASCII:
case BC_STR_UTF8: {
int strlen = readLength();
if (strlen == 32) {
long msb1 = parse4Nibbles(bytes, offset + 0);
long msb2 = parse4Nibbles(bytes, offset + 4);
long msb3 = parse4Nibbles(bytes, offset + 8);
long msb4 = parse4Nibbles(bytes, offset + 12);
long lsb1 = parse4Nibbles(bytes, offset + 16);
long lsb2 = parse4Nibbles(bytes, offset + 20);
long lsb3 = parse4Nibbles(bytes, offset + 24);
long lsb4 = parse4Nibbles(bytes, offset + 28);
if ((msb1 | msb2 | msb3 | msb4 | lsb1 | lsb2 | lsb3 | lsb4) >= 0) {
offset += 32;
return new UUID(
msb1 << 48 | msb2 << 32 | msb3 << 16 | msb4,
lsb1 << 48 | lsb2 << 32 | lsb3 << 16 | lsb4);
}
} else if (strlen == 36) {
byte ch1 = bytes[offset + 8];
byte ch2 = bytes[offset + 13];
byte ch3 = bytes[offset + 18];
byte ch4 = bytes[offset + 23];
if (ch1 == '-' && ch2 == '-' && ch3 == '-' && ch4 == '-') {
long msb1 = parse4Nibbles(bytes, offset + 0);
long msb2 = parse4Nibbles(bytes, offset + 4);
long msb3 = parse4Nibbles(bytes, offset + 9);
long msb4 = parse4Nibbles(bytes, offset + 14);
long lsb1 = parse4Nibbles(bytes, offset + 19);
long lsb2 = parse4Nibbles(bytes, offset + 24);
long lsb3 = parse4Nibbles(bytes, offset + 28);
long lsb4 = parse4Nibbles(bytes, offset + 32);
if ((msb1 | msb2 | msb3 | msb4 | lsb1 | lsb2 | lsb3 | lsb4) >= 0) {
offset += 36;
return new UUID(
msb1 << 48 | msb2 << 32 | msb3 << 16 | msb4,
lsb1 << 48 | lsb2 << 32 | lsb3 << 16 | lsb4);
}
}
}
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_8);
offset += strlen;
throw new JSONException("Invalid UUID string: " + str);
}
default:
throw new JSONException("type not support : " + JSONB.typeName(type));
}
}
@Override
public boolean readBoolValue() {
wasNull = false;
byte type = bytes[offset++];
switch (type) {
case BC_INT32_NUM_1:
case BC_TRUE:
return true;
case BC_INT32_NUM_0:
case BC_FALSE:
return false;
case BC_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_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, StandardCharsets.US_ASCII);
offset += strlen;
throw new JSONException("not support input " + str);
}
case BC_STR_UTF16LE: {
strlen = readLength();
String str = new String(bytes, offset, strlen, StandardCharsets.UTF_16LE);
offset += strlen;
switch (str) {
case "0":
case "N":
return false;
case "1":
case "Y":
return true;
default:
throw new JSONException("not support input " + str);
}
}
default:
throw new JSONException("not support type : " + typeName(type));
}
}
@Override
public boolean nextIfMatch(byte type) {
if (bytes[offset] == type) {
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();
}
@Override
public LocalDate readLocalDate8() {
type = bytes[offset];
if (type != BC_STR_ASCII_FIX_MIN + 8) {
throw new JSONException("date only support string input");
}
byte c0 = bytes[offset + 1];
byte c1 = bytes[offset + 2];
byte c2 = bytes[offset + 3];
byte c3 = bytes[offset + 4];
byte c4 = bytes[offset + 5];
byte c5 = bytes[offset + 6];
byte c6 = bytes[offset + 7];
byte c7 = bytes[offset + 8];
char y0, y1, y2, y3, m0, m1, d0, d1;
if (c4 == '-' && c6 == '-') {
y0 = (char) c0;
y1 = (char) c1;
y2 = (char) c2;
y3 = (char) c3;
m0 = '0';
m1 = (char) c5;
d0 = '0';
d1 = (char) c7;
} else {
y0 = (char) c0;
y1 = (char) c1;
y2 = (char) c2;
y3 = (char) c3;
m0 = (char) c4;
m1 = (char) c5;
d0 = (char) c6;
d1 = (char) c7;
}
int year;
if (y0 >= '0' && y0 <= '9'
&& y1 >= '0' && y1 <= '9'
&& y2 >= '0' && y2 <= '9'
&& y3 >= '0' && y3 <= '9'
) {
year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0');
} else {
return null;
}
int month;
if (m0 >= '0' && m0 <= '9'
&& m1 >= '0' && m1 <= '9'
) {
month = (m0 - '0') * 10 + (m1 - '0');
} else {
return null;
}
int dom;
if (d0 >= '0' && d0 <= '9'
&& d1 >= '0' && d1 <= '9'
) {
dom = (d0 - '0') * 10 + (d1 - '0');
} else {
return null;
}
LocalDate ldt = LocalDate.of(year, month, dom);
offset += 9;
return ldt;
}
@Override
public LocalDate readLocalDate9() {
type = bytes[offset];
if (type != BC_STR_ASCII_FIX_MIN + 9) {
throw new JSONException("date only support string input");
}
byte c0 = bytes[offset + 1];
byte c1 = bytes[offset + 2];
byte c2 = bytes[offset + 3];
byte c3 = bytes[offset + 4];
byte c4 = bytes[offset + 5];
byte c5 = bytes[offset + 6];
byte c6 = bytes[offset + 7];
byte c7 = bytes[offset + 8];
byte c8 = bytes[offset + 9];
char y0, y1, y2, y3, m0, m1, d0, d1;
if (c4 == '-' && c6 == '-') {
y0 = (char) c0;
y1 = (char) c1;
y2 = (char) c2;
y3 = (char) c3;
m0 = '0';
m1 = (char) c5;
d0 = (char) c7;
d1 = (char) c8;
} else if (c4 == '-' && c7 == '-') {
y0 = (char) c0;
y1 = (char) c1;
y2 = (char) c2;
y3 = (char) c3;
m0 = (char) c5;
m1 = (char) c6;
d0 = '0';
d1 = (char) c8;
} else {
return null;
}
int year;
if (y0 >= '0' && y0 <= '9'
&& y1 >= '0' && y1 <= '9'
&& y2 >= '0' && y2 <= '9'
&& y3 >= '0' && y3 <= '9'
) {
year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0');
} else {
return null;
}
int month;
if (m0 >= '0' && m0 <= '9'
&& m1 >= '0' && m1 <= '9'
) {
month = (m0 - '0') * 10 + (m1 - '0');
} else {
return null;
}
int dom;
if (d0 >= '0' && d0 <= '9'
&& d1 >= '0' && d1 <= '9'
) {
dom = (d0 - '0') * 10 + (d1 - '0');
} else {
return null;
}
LocalDate ldt = LocalDate.of(year, month, dom);
offset += 10;
return ldt;
}
@Override
protected LocalDate readLocalDate10() {
byte c0, c1, c2, c3, c4, c5, c6, c7, c8, c9;
if (bytes[offset] == BC_STR_ASCII_FIX_MIN + 10) {
c0 = bytes[offset + 1];
c1 = bytes[offset + 2];
c2 = bytes[offset + 3];
c3 = bytes[offset + 4];
c4 = bytes[offset + 5];
c5 = bytes[offset + 6];
c6 = bytes[offset + 7];
c7 = bytes[offset + 8];
c8 = bytes[offset + 9];
c9 = bytes[offset + 10];
} else if ((strtype == BC_STR_UTF8 || strtype == BC_STR_ASCII) && strlen == 10) {
c0 = bytes[offset + 0];
c1 = bytes[offset + 1];
c2 = bytes[offset + 2];
c3 = bytes[offset + 3];
c4 = bytes[offset + 4];
c5 = bytes[offset + 5];
c6 = bytes[offset + 6];
c7 = bytes[offset + 7];
c8 = bytes[offset + 8];
c9 = bytes[offset + 9];
} else {
throw new JSONException("date only support string input");
}
byte y0, y1, y2, y3, m0, m1, d0, d1;
if (c4 == '-' && c7 == '-') {
y0 = c0;
y1 = c1;
y2 = c2;
y3 = c3;
m0 = c5;
m1 = c6;
d0 = c8;
d1 = c9;
} else if (c4 == '/' && c7 == '/') { // tw : yyyy/mm/dd
y0 = c0;
y1 = c1;
y2 = c2;
y3 = c3;
m0 = c5;
m1 = c6;
d0 = c8;
d1 = c9;
} else if (c2 == '.' && c5 == '.') {
d0 = c0;
d1 = c1;
m0 = c3;
m1 = c4;
y0 = c6;
y1 = c7;
y2 = c8;
y3 = c9;
} else if (c2 == '-' && c5 == '-') {
d0 = c0;
d1 = c1;
m0 = c3;
m1 = c4;
y0 = c6;
y1 = c7;
y2 = c8;
y3 = c9;
} else {
return null;
}
int year;
if (y0 >= '0' && y0 <= '9'
&& y1 >= '0' && y1 <= '9'
&& y2 >= '0' && y2 <= '9'
&& y3 >= '0' && y3 <= '9'
) {
year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0');
} else {
return null;
}
int month;
if (m0 >= '0' && m0 <= '9'
&& m1 >= '0' && m1 <= '9'
) {
month = (m0 - '0') * 10 + (m1 - '0');
} else {
return null;
}
int dom;
if (d0 >= '0' && d0 <= '9'
&& d1 >= '0' && d1 <= '9'
) {
dom = (d0 - '0') * 10 + (d1 - '0');
} else {
return null;
}
if (year == 0 && month == 0 && dom == 0) {
return null;
}
LocalDate ldt = LocalDate.of(year, month, dom);
offset += 11;
return ldt;
}
@Override
protected LocalTime readLocalTime5() {
type = bytes[offset];
if (type != BC_STR_ASCII_FIX_MIN + 5) {
throw new JSONException("date only support string input");
}
byte c0 = bytes[offset + 1];
byte c1 = bytes[offset + 2];
byte c2 = bytes[offset + 3];
byte c3 = bytes[offset + 4];
byte c4 = bytes[offset + 5];
byte h0, h1, i0, i1, s0, s1;
if (c2 == ':') {
h0 = c0;
h1 = c1;
i0 = c3;
i1 = c4;
} else {
return null;
}
int hour;
if (h0 >= '0' && h0 <= '9'
&& h1 >= '0' && h1 <= '9'
) {
hour = (h0 - '0') * 10 + (h1 - '0');
} else {
return null;
}
int minute;
if (i0 >= '0' && i0 <= '9'
&& i1 >= '0' && i1 <= '9'
) {
minute = (i0 - '0') * 10 + (i1 - '0');
} else {
return null;
}
offset += 6;
return LocalTime.of(hour, minute);
}
@Override
protected LocalTime readLocalTime8() {
type = bytes[offset];
if (type != BC_STR_ASCII_FIX_MIN + 8) {
throw new JSONException("date only support string input");
}
byte c0 = bytes[offset + 1];
byte c1 = bytes[offset + 2];
byte c2 = bytes[offset + 3];
byte c3 = bytes[offset + 4];
byte c4 = bytes[offset + 5];
byte c5 = bytes[offset + 6];
byte c6 = bytes[offset + 7];
byte c7 = bytes[offset + 8];
byte h0, h1, i0, i1, s0, s1;
if (c2 == ':' && c5 == ':') {
h0 = c0;
h1 = c1;
i0 = c3;
i1 = c4;
s0 = c6;
s1 = c7;
} else {
return null;
}
int hour;
if (h0 >= '0' && h0 <= '9'
&& h1 >= '0' && h1 <= '9'
) {
hour = (h0 - '0') * 10 + (h1 - '0');
} else {
return null;
}
int minute;
if (i0 >= '0' && i0 <= '9'
&& i1 >= '0' && i1 <= '9'
) {
minute = (i0 - '0') * 10 + (i1 - '0');
} else {
return null;
}
int seccond;
if (s0 >= '0' && s0 <= '9'
&& s1 >= '0' && s1 <= '9'
) {
seccond = (s0 - '0') * 10 + (s1 - '0');
} else {
return null;
}
offset += 9;
return LocalTime.of(hour, minute, seccond);
}
@Override
protected LocalTime readLocalTime12() {
byte c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11;
if (bytes[offset] == BC_STR_ASCII_FIX_MIN + 12) {
c0 = bytes[offset + 1];
c1 = bytes[offset + 2];
c2 = bytes[offset + 3];
c3 = bytes[offset + 4];
c4 = bytes[offset + 5];
c5 = bytes[offset + 6];
c6 = bytes[offset + 7];
c7 = bytes[offset + 8];
c8 = bytes[offset + 9];
c9 = bytes[offset + 10];
c10 = bytes[offset + 11];
c11 = bytes[offset + 12];
} else if ((strtype == BC_STR_UTF8 || strtype == BC_STR_ASCII) && strlen == 12) {
c0 = bytes[offset];
c1 = bytes[offset + 1];
c2 = bytes[offset + 2];
c3 = bytes[offset + 3];
c4 = bytes[offset + 4];
c5 = bytes[offset + 5];
c6 = bytes[offset + 6];
c7 = bytes[offset + 7];
c8 = bytes[offset + 8];
c9 = bytes[offset + 9];
c10 = bytes[offset + 10];
c11 = bytes[offset + 11];
} else {
throw new JSONException("date only support string input");
}
byte h0, h1, i0, i1, s0, s1, m0, m1, m2;
if (c2 == ':' && c5 == ':' && c8 == '.') {
h0 = c0;
h1 = c1;
i0 = c3;
i1 = c4;
s0 = c6;
s1 = c7;
m0 = c9;
m1 = c10;
m2 = c11;
} else {
return null;
}
int hour;
if (h0 >= '0' && h0 <= '9'
&& h1 >= '0' && h1 <= '9'
) {
hour = (h0 - '0') * 10 + (h1 - '0');
} else {
return null;
}
int minute;
if (i0 >= '0' && i0 <= '9'
&& i1 >= '0' && i1 <= '9'
) {
minute = (i0 - '0') * 10 + (i1 - '0');
} else {
return null;
}
int seccond;
if (s0 >= '0' && s0 <= '9'
&& s1 >= '0' && s1 <= '9'
) {
seccond = (s0 - '0') * 10 + (s1 - '0');
} else {
return null;
}
int millis;
if (m0 >= '0' && m0 <= '9'
&& m1 >= '0' && m1 <= '9'
&& m2 >= '0' && m2 <= '9'
) {
millis = (m0 - '0') * 100 + (m1 - '0') * 10 + (m2 - '0');
millis *= 1000_000;
} else {
return null;
}
offset += 13;
return LocalTime.of(hour, minute, seccond, millis);
}
@Override
protected LocalTime readLocalTime18() {
byte c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17;
if (bytes[offset] == BC_STR_ASCII_FIX_MIN + 18) {
c0 = bytes[offset + 1];
c1 = bytes[offset + 2];
c2 = bytes[offset + 3];
c3 = bytes[offset + 4];
c4 = bytes[offset + 5];
c5 = bytes[offset + 6];
c6 = bytes[offset + 7];
c7 = bytes[offset + 8];
c8 = bytes[offset + 9];
c9 = bytes[offset + 10];
c10 = bytes[offset + 11];
c11 = bytes[offset + 12];
c12 = bytes[offset + 13];
c13 = bytes[offset + 14];
c14 = bytes[offset + 15];
c15 = bytes[offset + 16];
c16 = bytes[offset + 17];
c17 = bytes[offset + 18];
} else if ((strtype == BC_STR_UTF8 || strtype == BC_STR_ASCII) && strlen == 18) {
c0 = bytes[offset];
c1 = bytes[offset + 1];
c2 = bytes[offset + 2];
c3 = bytes[offset + 3];
c4 = bytes[offset + 4];
c5 = bytes[offset + 5];
c6 = bytes[offset + 6];
c7 = bytes[offset + 7];
c8 = bytes[offset + 8];
c9 = bytes[offset + 9];
c10 = bytes[offset + 10];
c11 = bytes[offset + 11];
c12 = bytes[offset + 12];
c13 = bytes[offset + 13];
c14 = bytes[offset + 14];
c15 = bytes[offset + 15];
c16 = bytes[offset + 16];
c17 = bytes[offset + 17];
} else {
throw new JSONException("date only support string input");
}
byte h0, h1, i0, i1, s0, s1, m0, m1, m2, m3, m4, m5, m6, m7, m8;
if (c2 == ':' && c5 == ':' && c8 == '.') {
h0 = c0;
h1 = c1;
i0 = c3;
i1 = c4;
s0 = c6;
s1 = c7;
m0 = c9;
m1 = c10;
m2 = c11;
m3 = c12;
m4 = c13;
m5 = c14;
m6 = c15;
m7 = c16;
m8 = c17;
} else {
return null;
}
int hour;
if (h0 >= '0' && h0 <= '9'
&& h1 >= '0' && h1 <= '9'
) {
hour = (h0 - '0') * 10 + (h1 - '0');
} else {
return null;
}
int minute;
if (i0 >= '0' && i0 <= '9'
&& i1 >= '0' && i1 <= '9'
) {
minute = (i0 - '0') * 10 + (i1 - '0');
} else {
return null;
}
int seccond;
if (s0 >= '0' && s0 <= '9'
&& s1 >= '0' && s1 <= '9'
) {
seccond = (s0 - '0') * 10 + (s1 - '0');
} else {
return null;
}
int millis;
if (m0 >= '0' && m0 <= '9'
&& m1 >= '0' && m1 <= '9'
&& m2 >= '0' && m2 <= '9'
&& m3 >= '0' && m3 <= '9'
&& m4 >= '0' && m4 <= '9'
&& m5 >= '0' && m5 <= '9'
&& m6 >= '0' && m6 <= '9'
&& m7 >= '0' && m7 <= '9'
&& m8 >= '0' && m8 <= '9'
) {
millis = (m0 - '0') * 1000_000_00
+ (m1 - '0') * 1000_000_0
+ (m2 - '0') * 1000_000
+ (m3 - '0') * 1000_00
+ (m4 - '0') * 1000_0
+ (m5 - '0') * 1000
+ (m6 - '0') * 100
+ (m7 - '0') * 10
+ (m8 - '0');
} else {
return null;
}
offset += 19;
return LocalTime.of(hour, minute, seccond, millis);
}
@Override
protected LocalDateTime readLocalDateTime18() {
throw new JSONException("UnsupportedOperation");
}
@Override
public long readMillis19() {
type = bytes[offset];
if (type != BC_STR_ASCII_FIX_MIN + 19) {
throw new JSONException("date only support string input");
}
char c0 = (char) bytes[offset + 1];
char c1 = (char) bytes[offset + 2];
char c2 = (char) bytes[offset + 3];
char c3 = (char) bytes[offset + 4];
char c4 = (char) bytes[offset + 5];
char c5 = (char) bytes[offset + 6];
char c6 = (char) bytes[offset + 7];
char c7 = (char) bytes[offset + 8];
char c8 = (char) bytes[offset + 9];
char c9 = (char) bytes[offset + 10];
char c10 = (char) bytes[offset + 11];
char c11 = (char) bytes[offset + 12];
char c12 = (char) bytes[offset + 13];
char c13 = (char) bytes[offset + 14];
char c14 = (char) bytes[offset + 15];
char c15 = (char) bytes[offset + 16];
char c16 = (char) bytes[offset + 17];
char c17 = (char) bytes[offset + 18];
char c18 = (char) bytes[offset + 19];
char y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0, s1, S0, S1, S2;
if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') {
y0 = c0;
y1 = c1;
y2 = c2;
y3 = c3;
m0 = c5;
m1 = c6;
d0 = c8;
d1 = c9;
h0 = c11;
h1 = c12;
i0 = c14;
i1 = c15;
s0 = c17;
s1 = c18;
S0 = '0';
S1 = '0';
S2 = '0';
} else if (c4 == '/' && c7 == '/' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') {
y0 = c0;
y1 = c1;
y2 = c2;
y3 = c3;
m0 = c5;
m1 = c6;
d0 = c8;
d1 = c9;
h0 = c11;
h1 = c12;
i0 = c14;
i1 = c15;
s0 = c17;
s1 = c18;
S0 = '0';
S1 = '0';
S2 = '0';
} else {
wasNull = true;
return 0;
}
int year;
if (y0 >= '0' && y0 <= '9'
&& y1 >= '0' && y1 <= '9'
&& y2 >= '0' && y2 <= '9'
&& y3 >= '0' && y3 <= '9'
) {
year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0');
} else {
wasNull = true;
return 0;
}
int month;
if (m0 >= '0' && m0 <= '9'
&& m1 >= '0' && m1 <= '9'
) {
month = (m0 - '0') * 10 + (m1 - '0');
} else {
wasNull = true;
return 0;
}
int dom;
if (d0 >= '0' && d0 <= '9'
&& d1 >= '0' && d1 <= '9'
) {
dom = (d0 - '0') * 10 + (d1 - '0');
} else {
wasNull = true;
return 0;
}
int hour;
if (h0 >= '0' && h0 <= '9'
&& h1 >= '0' && h1 <= '9'
) {
hour = (h0 - '0') * 10 + (h1 - '0');
} else {
wasNull = true;
return 0;
}
int minute;
if (i0 >= '0' && i0 <= '9'
&& i1 >= '0' && i1 <= '9'
) {
minute = (i0 - '0') * 10 + (i1 - '0');
} else {
wasNull = true;
return 0;
}
int second;
if (s0 >= '0' && s0 <= '9'
&& s1 >= '0' && s1 <= '9'
) {
second = (s0 - '0') * 10 + (s1 - '0');
} else {
wasNull = true;
return 0;
}
int nanoOfSecond;
if (S0 >= '0' && S0 <= '9'
&& S1 >= '0' && S1 <= '9'
&& S2 >= '0' && S2 <= '9'
) {
nanoOfSecond = (S0 - '0') * 100
+ (S1 - '0') * 10
+ (S2 - '0');
nanoOfSecond *= 1000_000;
} else {
wasNull = true;
return 0;
}
offset += 20;
return DateUtils.millis(context.getZoneId(), year, month, dom, hour, minute, second, nanoOfSecond);
}
@Override
protected LocalDateTime readLocalDateTime19() {
type = bytes[offset];
if (type != BC_STR_ASCII_FIX_MIN + 19) {
throw new JSONException("date only support string input");
}
char c0 = (char) bytes[offset + 1];
char c1 = (char) bytes[offset + 2];
char c2 = (char) bytes[offset + 3];
char c3 = (char) bytes[offset + 4];
char c4 = (char) bytes[offset + 5];
char c5 = (char) bytes[offset + 6];
char c6 = (char) bytes[offset + 7];
char c7 = (char) bytes[offset + 8];
char c8 = (char) bytes[offset + 9];
char c9 = (char) bytes[offset + 10];
char c10 = (char) bytes[offset + 11];
char c11 = (char) bytes[offset + 12];
char c12 = (char) bytes[offset + 13];
char c13 = (char) bytes[offset + 14];
char c14 = (char) bytes[offset + 15];
char c15 = (char) bytes[offset + 16];
char c16 = (char) bytes[offset + 17];
char c17 = (char) bytes[offset + 18];
char c18 = (char) bytes[offset + 19];
char y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0, s1, S0, S1, S2;
if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') {
y0 = c0;
y1 = c1;
y2 = c2;
y3 = c3;
m0 = c5;
m1 = c6;
d0 = c8;
d1 = c9;
h0 = c11;
h1 = c12;
i0 = c14;
i1 = c15;
s0 = c17;
s1 = c18;
S0 = '0';
S1 = '0';
S2 = '0';
} else if (c4 == '/' && c7 == '/' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') {
y0 = c0;
y1 = c1;
y2 = c2;
y3 = c3;
m0 = c5;
m1 = c6;
d0 = c8;
d1 = c9;
h0 = c11;
h1 = c12;
i0 = c14;
i1 = c15;
s0 = c17;
s1 = c18;
S0 = '0';
S1 = '0';
S2 = '0';
} else {
return null;
}
int year;
if (y0 >= '0' && y0 <= '9'
&& y1 >= '0' && y1 <= '9'
&& y2 >= '0' && y2 <= '9'
&& y3 >= '0' && y3 <= '9'
) {
year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0');
} else {
return null;
}
int month;
if (m0 >= '0' && m0 <= '9'
&& m1 >= '0' && m1 <= '9'
) {
month = (m0 - '0') * 10 + (m1 - '0');
} else {
return null;
}
int dom;
if (d0 >= '0' && d0 <= '9'
&& d1 >= '0' && d1 <= '9'
) {
dom = (d0 - '0') * 10 + (d1 - '0');
} else {
return null;
}
int hour;
if (h0 >= '0' && h0 <= '9'
&& h1 >= '0' && h1 <= '9'
) {
hour = (h0 - '0') * 10 + (h1 - '0');
} else {
return null;
}
int minute;
if (i0 >= '0' && i0 <= '9'
&& i1 >= '0' && i1 <= '9'
) {
minute = (i0 - '0') * 10 + (i1 - '0');
} else {
return null;
}
int second;
if (s0 >= '0' && s0 <= '9'
&& s1 >= '0' && s1 <= '9'
) {
second = (s0 - '0') * 10 + (s1 - '0');
} else {
return null;
}
int millis;
if (S0 >= '0' && S0 <= '9'
&& S1 >= '0' && S1 <= '9'
&& S2 >= '0' && S2 <= '9'
) {
millis = (S0 - '0') * 100
+ (S1 - '0') * 10
+ (S2 - '0');
millis *= 1000_000;
} else {
return null;
}
LocalDateTime ldt = LocalDateTime.of(year, month, dom, hour, minute, second, millis);
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");
}
if (len < 21 || len > 29) {
throw new JSONException("illeal localdatetime string : " + readString());
}
byte c0 = bytes[offset + 1];
byte c1 = bytes[offset + 2];
byte c2 = bytes[offset + 3];
byte c3 = bytes[offset + 4];
byte c4 = bytes[offset + 5];
byte c5 = bytes[offset + 6];
byte c6 = bytes[offset + 7];
byte c7 = bytes[offset + 8];
byte c8 = bytes[offset + 9];
byte c9 = bytes[offset + 10];
byte c10 = bytes[offset + 11];
byte c11 = bytes[offset + 12];
byte c12 = bytes[offset + 13];
byte c13 = bytes[offset + 14];
byte c14 = bytes[offset + 15];
byte c15 = bytes[offset + 16];
byte c16 = bytes[offset + 17];
byte c17 = bytes[offset + 18];
byte c18 = bytes[offset + 19];
byte c19 = bytes[offset + 20];
byte c20, c21 = '0', c22 = '0', c23 = '0', c24 = '0', c25 = '0', c26 = '0', c27 = '0', c28 = '0';
switch (len) {
case 21:
c20 = bytes[offset + 21];
break;
case 22:
c20 = bytes[offset + 21];
c21 = bytes[offset + 22];
break;
case 23:
c20 = bytes[offset + 21];
c21 = bytes[offset + 22];
c22 = bytes[offset + 23];
break;
case 24:
c20 = bytes[offset + 21];
c21 = bytes[offset + 22];
c22 = bytes[offset + 23];
c23 = bytes[offset + 24];
break;
case 25:
c20 = bytes[offset + 21];
c21 = bytes[offset + 22];
c22 = bytes[offset + 23];
c23 = bytes[offset + 24];
c24 = bytes[offset + 25];
break;
case 26:
c20 = bytes[offset + 21];
c21 = bytes[offset + 22];
c22 = bytes[offset + 23];
c23 = bytes[offset + 24];
c24 = bytes[offset + 25];
c25 = bytes[offset + 26];
break;
case 27:
c20 = bytes[offset + 21];
c21 = bytes[offset + 22];
c22 = bytes[offset + 23];
c23 = bytes[offset + 24];
c24 = bytes[offset + 25];
c25 = bytes[offset + 26];
c26 = bytes[offset + 27];
break;
case 28:
c20 = bytes[offset + 21];
c21 = bytes[offset + 22];
c22 = bytes[offset + 23];
c23 = bytes[offset + 24];
c24 = bytes[offset + 25];
c25 = bytes[offset + 26];
c26 = bytes[offset + 27];
c27 = bytes[offset + 28];
break;
default:
c20 = bytes[offset + 21];
c21 = bytes[offset + 22];
c22 = bytes[offset + 23];
c23 = bytes[offset + 24];
c24 = bytes[offset + 25];
c25 = bytes[offset + 26];
c26 = bytes[offset + 27];
c27 = bytes[offset + 28];
c28 = bytes[offset + 29];
break;
}
char y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0, s1, S0, S1, S2, S3, S4, S5, S6, S7, S8;
if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':' && c19 == '.') {
y0 = (char) c0;
y1 = (char) c1;
y2 = (char) c2;
y3 = (char) c3;
m0 = (char) c5;
m1 = (char) c6;
d0 = (char) c8;
d1 = (char) c9;
h0 = (char) c11;
h1 = (char) c12;
i0 = (char) c14;
i1 = (char) c15;
s0 = (char) c17;
s1 = (char) c18;
S0 = (char) c20;
S1 = (char) c21;
S2 = (char) c22;
S3 = (char) c23;
S4 = (char) c24;
S5 = (char) c25;
S6 = (char) c26;
S7 = (char) c27;
S8 = (char) c28;
} else {
return null;
}
LocalDateTime ldt = localDateTime(y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0, s1, S0, S1, S2, S3, S4, S5, S6, S7, S8);
if (ldt == null) {
return null;
}
offset += (len + 1);
return ldt;
}
@Override
public String readPattern() {
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 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 final void close() {
if (valueBytes != null) {
JSONFactory.releaseByteArray(cachedIndex, valueBytes);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy