com.alibaba.fastjson2.JSONWriterJSONB Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fastjson2 Show documentation
Show all versions of fastjson2 Show documentation
Fastjson is a JSON processor (JSON parser + JSON generator) written in Java
package com.alibaba.fastjson2;
import com.alibaba.fastjson2.internal.trove.map.hash.TLongIntHashMap;
import com.alibaba.fastjson2.time.*;
import com.alibaba.fastjson2.util.Fnv;
import com.alibaba.fastjson2.util.IOUtils;
import com.alibaba.fastjson2.util.JDKUtils;
import com.alibaba.fastjson2.writer.ObjectWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.util.*;
import static com.alibaba.fastjson2.JSONB.Constants.*;
import static com.alibaba.fastjson2.JSONFactory.*;
import static com.alibaba.fastjson2.JSONWriter.Feature.WriteNameAsSymbol;
import static com.alibaba.fastjson2.util.JDKUtils.*;
import static com.alibaba.fastjson2.util.TypeUtils.*;
final class JSONWriterJSONB
extends JSONWriter {
static final BigInteger BIGINT_INT32_MIN = BigInteger.valueOf(Integer.MIN_VALUE);
static final BigInteger BIGINT_INT32_MAX = BigInteger.valueOf(Integer.MAX_VALUE);
static final BigInteger BIGINT_INT64_MIN = BigInteger.valueOf(Long.MIN_VALUE);
static final BigInteger BIGINT_INT64_MAX = BigInteger.valueOf(Long.MAX_VALUE);
private final CacheItem cacheItem;
private byte[] bytes;
private TLongIntHashMap symbols;
private int symbolIndex;
protected long rootTypeNameHash;
JSONWriterJSONB(Context ctx, SymbolTable symbolTable) {
super(ctx, symbolTable, true, StandardCharsets.UTF_8);
cacheItem = CACHE_ITEMS[System.identityHashCode(Thread.currentThread()) & (CACHE_ITEMS.length - 1)];
byte[] bytes = BYTES_UPDATER.getAndSet(cacheItem, null);
if (bytes == null) {
bytes = new byte[8192];
}
this.bytes = bytes;
}
@Override
public void close() {
final byte[] bytes = this.bytes;
if (bytes.length < CACHE_THRESHOLD) {
BYTES_UPDATER.lazySet(cacheItem, bytes);
}
}
@Override
public void writeAny(Object value) {
if (value == null) {
writeNull();
return;
}
boolean fieldBased = (context.features & Feature.FieldBased.mask) != 0;
Class> valueClass = value.getClass();
ObjectWriter objectWriter = context.provider.getObjectWriter(valueClass, valueClass, fieldBased);
if (isBeanToArray()) {
objectWriter.writeArrayMappingJSONB(this, value, null, null, 0);
} else {
objectWriter.writeJSONB(this, value, null, null, 0);
}
}
@Override
public void startObject() {
level++;
int off = this.off;
if (off == bytes.length) {
ensureCapacity(off + 1);
}
bytes[off] = BC_OBJECT;
this.off = off + 1;
}
@Override
public void endObject() {
level--;
int off = this.off;
if (off == bytes.length) {
ensureCapacity(off + 1);
}
bytes[off] = BC_OBJECT_END;
this.off = off + 1;
}
@Override
public void startArray() {
throw new JSONException("unsupported operation");
}
@Override
public void startArray(Object array, int size) {
if (isWriteTypeInfo(array)) {
writeTypeName(array.getClass().getName());
}
int off = this.off;
if (off == bytes.length) {
ensureCapacity(off + 1);
}
final byte[] bytes = this.bytes;
boolean tinyInt = size <= ARRAY_FIX_LEN;
bytes[off] = tinyInt ? (byte) (BC_ARRAY_FIX_MIN + size) : BC_ARRAY;
this.off = off + 1;
if (!tinyInt) {
writeInt32(size);
}
}
@Override
public void startArray(int size) {
int off = this.off;
if (off == bytes.length) {
ensureCapacity(off + 1);
}
final byte[] bytes = this.bytes;
boolean tinyInt = size <= ARRAY_FIX_LEN;
bytes[off] = tinyInt ? (byte) (BC_ARRAY_FIX_MIN + size) : BC_ARRAY;
this.off = off + 1;
if (!tinyInt) {
writeInt32(size);
}
}
@Override
public void writeRaw(byte b) {
if (off == bytes.length) {
ensureCapacity(off + 1);
}
bytes[off++] = b;
}
@Override
public void writeChar(char ch) {
if (off == bytes.length) {
ensureCapacity(off + 1);
}
bytes[off++] = BC_CHAR;
writeInt32(ch);
}
@Override
public void writeName(String name) {
writeString(name);
}
@Override
public void writeNull() {
if (off == bytes.length) {
ensureCapacity(off + 1);
}
bytes[off++] = BC_NULL;
}
@Override
public void writeStringNull() {
if (off == bytes.length) {
ensureCapacity(off + 1);
}
bytes[off++] = BC_NULL;
}
@Override
public void endArray() {
}
@Override
public void writeComma() {
throw new JSONException("unsupported operation");
}
@Override
protected void write0(char ch) {
throw new JSONException("unsupported operation");
}
@Override
public void writeString(char[] chars, int off, int len, boolean quote) {
if (chars == null) {
writeNull();
return;
}
boolean ascii = true;
for (int i = 0; i < len; ++i) {
if (chars[i + off] > 0x00FF) {
ascii = false;
break;
}
}
if (ascii) {
if (len <= STR_ASCII_FIX_LEN) {
bytes[this.off++] = (byte) (len + BC_STR_ASCII_FIX_MIN);
} else {
bytes[this.off++] = BC_STR_ASCII;
writeInt32(len);
}
for (int i = 0; i < len; ++i) {
bytes[this.off++] = (byte) chars[off + i];
}
return;
}
writeString(new String(chars, off, len));
}
public void writeStringLatin1(final byte[] value) {
if (value == null) {
writeStringNull();
return;
}
int off = this.off;
int strlen = value.length;
int minCapacity = value.length
+ off
+ 5 /*max str len*/
+ 1;
if (minCapacity - bytes.length > 0) {
ensureCapacity(minCapacity);
}
final byte[] bytes = this.bytes;
if (strlen <= STR_ASCII_FIX_LEN) {
bytes[off++] = (byte) (strlen + BC_STR_ASCII_FIX_MIN);
} else if (strlen <= INT32_BYTE_MAX) {
putStringSizeSmall(bytes, off, strlen);
off += 3;
} else {
off += putStringSizeLarge(bytes, off, strlen);
}
System.arraycopy(value, 0, bytes, off, value.length);
this.off = off + strlen;
}
private static void putStringSizeSmall(byte[] bytes, int off, int val) {
bytes[off] = BC_STR_ASCII;
bytes[off + 1] = (byte) (BC_INT32_BYTE_ZERO + (val >> 8));
bytes[off + 2] = (byte) (val);
}
private static int putStringSizeLarge(byte[] bytes, int off, int strlen) {
if (strlen <= INT32_SHORT_MAX) {
bytes[off] = BC_STR_ASCII;
putInt3(bytes, off + 1, strlen);
return 4;
}
bytes[off] = BC_STR_ASCII;
bytes[off + 1] = BC_INT32;
bytes[off + 2] = (byte) (strlen >>> 24);
bytes[off + 3] = (byte) (strlen >>> 16);
bytes[off + 4] = (byte) (strlen >>> 8);
bytes[off + 5] = (byte) strlen;
return 6;
}
@Override
public void writeString(final char[] chars) {
if (chars == null) {
writeNull();
return;
}
int off = this.off;
boolean ascii = true;
int strlen = chars.length;
if (chars.length < STR_ASCII_FIX_LEN) {
int minCapacity = off + 1 + strlen;
if (minCapacity - bytes.length > 0) {
ensureCapacity(minCapacity);
}
bytes[off++] = (byte) (strlen + BC_STR_ASCII_FIX_MIN);
for (int i = 0; i < chars.length; i++) {
char ch = chars[i];
if (ch > 0x00FF) {
ascii = false;
break;
}
bytes[off++] = (byte) ch;
}
if (ascii) {
this.off = off;
return;
} else {
off = this.off;
}
}
{
int i = 0;
int upperBound = chars.length & ~3;
for (; i < upperBound; i += 4) {
char c0 = chars[i];
char c1 = chars[i + 1];
char c2 = chars[i + 2];
char c3 = chars[i + 3];
if (c0 > 0x00FF || c1 > 0x00FF || c2 > 0x00FF || c3 > 0x00FF) {
ascii = false;
break;
}
}
if (ascii) {
for (; i < chars.length; ++i) {
if (chars[i] > 0x00FF) {
ascii = false;
break;
}
}
}
}
int minCapacity = (ascii ? strlen : strlen * 3)
+ off
+ 5 /*max str len*/
+ 1;
if (minCapacity - bytes.length > 0) {
ensureCapacity(minCapacity);
}
if (ascii) {
if (strlen <= STR_ASCII_FIX_LEN) {
bytes[off++] = (byte) (strlen + BC_STR_ASCII_FIX_MIN);
} else if (strlen <= INT32_BYTE_MAX) {
putStringSizeSmall(bytes, off, strlen);
off += 3;
} else {
off += putStringSizeLarge(bytes, off, strlen);
}
for (int i = 0; i < chars.length; i++) {
bytes[off++] = (byte) chars[i];
}
} else {
int maxSize = chars.length * 3;
int lenByteCnt = sizeOfInt(maxSize);
ensureCapacity(off + maxSize + lenByteCnt + 1);
int result = IOUtils.encodeUTF8(chars, 0, chars.length, bytes, off + lenByteCnt + 1);
int utf8len = result - off - lenByteCnt - 1;
int utf8lenByteCnt = sizeOfInt(utf8len);
if (lenByteCnt != utf8lenByteCnt) {
System.arraycopy(bytes, off + lenByteCnt + 1, bytes, off + utf8lenByteCnt + 1, utf8len);
}
bytes[off++] = BC_STR_UTF8;
if (utf8len >= BC_INT32_NUM_MIN && utf8len <= BC_INT32_NUM_MAX) {
bytes[off++] = (byte) utf8len;
} else if (utf8len >= INT32_BYTE_MIN && utf8len <= INT32_BYTE_MAX) {
bytes[off] = (byte) (BC_INT32_BYTE_ZERO + (utf8len >> 8));
bytes[off + 1] = (byte) (utf8len);
off += 2;
} else {
off += writeInt32(bytes, off, utf8len);
}
off += utf8len;
}
this.off = off;
}
@Override
public void writeString(final char[] chars, final int off, final int len) {
if (chars == null) {
writeNull();
return;
}
boolean ascii = true;
if (len < STR_ASCII_FIX_LEN) {
final int mark = this.off;
int minCapacity = this.off + 1 + len;
if (minCapacity - bytes.length > 0) {
ensureCapacity(minCapacity);
}
bytes[this.off++] = (byte) (len + BC_STR_ASCII_FIX_MIN);
for (int i = off; i < len; i++) {
char ch = chars[i];
if (ch > 0x00FF) {
ascii = false;
break;
}
bytes[this.off++] = (byte) ch;
}
if (ascii) {
return;
}
this.off = mark;
}
{
int i = off;
int upperBound = chars.length & ~3;
for (; i < upperBound; i += 4) {
char c0 = chars[i];
char c1 = chars[i + 1];
char c2 = chars[i + 2];
char c3 = chars[i + 3];
if (c0 > 0x00FF || c1 > 0x00FF || c2 > 0x00FF || c3 > 0x00FF) {
ascii = false;
break;
}
}
if (ascii) {
for (; i < chars.length; ++i) {
if (chars[i] > 0x00FF) {
ascii = false;
break;
}
}
}
}
int minCapacity = (ascii ? len : len * 3)
+ this.off
+ 5 /*max str len*/
+ 1;
if (minCapacity - bytes.length > 0) {
ensureCapacity(minCapacity);
}
if (ascii) {
if (len <= STR_ASCII_FIX_LEN) {
bytes[this.off++] = (byte) (len + BC_STR_ASCII_FIX_MIN);
} else if (len <= INT32_BYTE_MAX) {
bytes[this.off++] = BC_STR_ASCII;
bytes[this.off++] = (byte) (BC_INT32_BYTE_ZERO + (len >> 8));
bytes[this.off++] = (byte) (len);
} else {
bytes[this.off++] = BC_STR_ASCII;
writeInt32(len);
}
for (int i = 0; i < chars.length; i++) {
bytes[this.off++] = (byte) chars[i];
}
} else {
int maxSize = chars.length * 3;
int lenByteCnt = sizeOfInt(maxSize);
ensureCapacity(this.off + maxSize + lenByteCnt + 1);
int result = IOUtils.encodeUTF8(chars, 0, chars.length, bytes, this.off + lenByteCnt + 1);
int utf8len = result - this.off - lenByteCnt - 1;
int utf8lenByteCnt = sizeOfInt(utf8len);
if (lenByteCnt != utf8lenByteCnt) {
System.arraycopy(bytes, this.off + lenByteCnt + 1, bytes, this.off + utf8lenByteCnt + 1, utf8len);
}
bytes[this.off++] = BC_STR_UTF8;
if (utf8len >= BC_INT32_NUM_MIN && utf8len <= BC_INT32_NUM_MAX) {
bytes[this.off++] = (byte) utf8len;
} else if (utf8len >= INT32_BYTE_MIN && utf8len <= INT32_BYTE_MAX) {
bytes[this.off++] = (byte) (BC_INT32_BYTE_ZERO + (utf8len >> 8));
bytes[this.off++] = (byte) (utf8len);
} else {
writeInt32(utf8len);
}
this.off += utf8len;
}
}
public void writeString(String[] strings) {
if (strings == null) {
writeArrayNull();
return;
}
startArray(strings.length);
for (int i = 0; i < strings.length; i++) {
String item = strings[i];
if (item == null) {
if (isEnabled(JSONWriter.Feature.NullAsDefaultValue.mask | JSONWriter.Feature.WriteNullStringAsEmpty.mask)) {
writeString("");
} else {
writeNull();
}
continue;
}
writeString(item);
}
}
@Override
public void writeSymbol(String str) {
if (str == null) {
writeNull();
return;
}
if (symbolTable != null) {
int ordinal = symbolTable.getOrdinal(str);
if (ordinal >= 0) {
writeRaw(BC_SYMBOL);
writeInt32(-ordinal);
return;
}
}
writeString(str);
}
@Override
public void writeTypeName(String typeName) {
if (off == bytes.length) {
ensureCapacity(off + 1);
}
this.bytes[off++] = BC_TYPED_ANY;
long hash = Fnv.hashCode64(typeName);
int symbol = -1;
if (symbolTable != null) {
symbol = symbolTable.getOrdinalByHashCode(hash);
if (symbol == -1 && symbols != null) {
symbol = symbols.get(hash);
}
} else if (symbols != null) {
symbol = symbols.get(hash);
}
if (symbol == -1) {
if (symbols == null) {
symbols = new TLongIntHashMap();
}
symbols.put(hash, symbol = symbolIndex++);
} else {
if (off == bytes.length) {
ensureCapacity(off + 1);
}
writeInt32(symbol);
return;
}
writeString(typeName);
writeInt32(symbol);
}
@Override
public boolean writeTypeName(byte[] typeName, long hash) {
if (symbolTable != null) {
int symbol = symbolTable.getOrdinalByHashCode(hash);
if (symbol != -1) {
return writeTypeNameSymbol(symbol);
}
}
boolean symbolExists = false;
int symbol;
if (rootTypeNameHash == hash) {
symbolExists = true;
symbol = 0;
} else if (symbols != null) {
symbol = symbols.putIfAbsent(hash, symbolIndex);
if (symbol != symbolIndex) {
symbolExists = true;
} else {
symbolIndex++;
}
} else {
symbol = symbolIndex++;
if (symbol == 0) {
rootTypeNameHash = hash;
}
if (symbol != 0 || (context.features & WriteNameAsSymbol.mask) != 0) {
symbols = new TLongIntHashMap(hash, symbol);
}
}
if (symbolExists) {
writeTypeNameSymbol(-symbol);
return false;
}
int off = this.off;
int minCapacity = off + 2 + typeName.length;
if (minCapacity > bytes.length) {
ensureCapacity(minCapacity);
}
final byte[] bytes = this.bytes;
bytes[off++] = BC_TYPED_ANY;
System.arraycopy(typeName, 0, bytes, off, typeName.length);
off += typeName.length;
if (symbol >= BC_INT32_NUM_MIN && symbol <= BC_INT32_NUM_MAX) {
bytes[off] = (byte) symbol;
this.off = off + 1;
} else {
this.off = off;
writeInt32(symbol);
}
return false;
}
private boolean writeTypeNameSymbol(int symbol) {
int off = this.off;
if (off + 2 >= bytes.length) {
ensureCapacity(off + 2);
}
this.bytes[off++] = BC_TYPED_ANY;
this.off = off;
writeInt32(-symbol);
return false;
}
static int sizeOfInt(int i) {
if (i >= BC_INT32_NUM_MIN && i <= BC_INT32_NUM_MAX) {
return 1;
}
if (i >= INT32_BYTE_MIN && i <= INT32_BYTE_MAX) {
return 2;
}
if (i >= INT32_SHORT_MIN && i <= INT32_SHORT_MAX) {
return 3;
}
return 5;
}
public void writeString(List list) {
if (list == null) {
writeArrayNull();
return;
}
final int size = list.size();
startArray(size);
for (int i = 0; i < size; i++) {
String str = list.get(i);
writeString(str);
}
}
@Override
public void writeString(String str) {
if (str == null) {
writeNull();
return;
}
writeString(
str.toCharArray()
);
}
@Override
public void writeString(boolean value) {
writeString(Boolean.toString(value));
}
@Override
public void writeString(byte value) {
writeString(Integer.toString(value));
}
@Override
public void writeString(short value) {
writeString(Integer.toString(value));
}
@Override
public void writeString(int value) {
writeString(Integer.toString(value));
}
@Override
public void writeString(long value) {
writeString(Long.toString(value));
}
@Override
public void writeString(boolean[] value) {
if (value == null) {
writeArrayNull();
return;
}
startArray(value.length);
for (int i = 0; i < value.length; i++) {
writeString(value[i]);
}
}
@Override
public void writeString(byte[] value) {
if (value == null) {
writeArrayNull();
return;
}
startArray(value.length);
for (int i = 0; i < value.length; i++) {
writeString(value[i]);
}
}
@Override
public void writeString(short[] value) {
if (value == null) {
writeArrayNull();
return;
}
startArray(value.length);
for (int i = 0; i < value.length; i++) {
writeString(value[i]);
}
}
@Override
public void writeString(int[] value) {
if (value == null) {
writeArrayNull();
return;
}
startArray(value.length);
for (int i = 0; i < value.length; i++) {
writeString(value[i]);
}
}
@Override
public void writeString(long[] value) {
if (value == null) {
writeArrayNull();
return;
}
startArray(value.length);
for (int i = 0; i < value.length; i++) {
writeString(value[i]);
}
}
@Override
public void writeString(float[] value) {
if (value == null) {
writeArrayNull();
return;
}
startArray(value.length);
for (int i = 0; i < value.length; i++) {
writeString(value[i]);
}
}
@Override
public void writeString(double[] value) {
if (value == null) {
writeArrayNull();
return;
}
startArray(value.length);
for (int i = 0; i < value.length; i++) {
writeString(value[i]);
}
}
public void writeStringUTF16(byte[] value) {
int off = this.off;
final int strlen = value.length;
int minCapacity = off + strlen + 6;
if (minCapacity >= bytes.length) {
ensureCapacity(minCapacity);
}
final byte[] bytes = this.bytes;
bytes[off++] = JDKUtils.BIG_ENDIAN ? BC_STR_UTF16BE : BC_STR_UTF16LE;
off += writeInt32(bytes, off, strlen);
System.arraycopy(value, 0, bytes, off, strlen);
this.off = off + strlen;
}
void ensureCapacity(int minCapacity) {
if (minCapacity >= bytes.length) {
int oldCapacity = bytes.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
if (newCapacity > maxArraySize) {
throw new OutOfMemoryError("try enabling LargeObject feature instead");
}
// minCapacity is usually close to size, so this is a win:
bytes = Arrays.copyOf(bytes, newCapacity);
}
}
@Override
public void writeMillis(long millis) {
int off = this.off;
int minCapacity = off + 9;
if (minCapacity >= bytes.length) {
ensureCapacity(minCapacity);
}
final byte[] bytes = this.bytes;
if (millis % 1000 == 0) {
long seconds = (millis / 1000);
if (seconds >= Integer.MIN_VALUE && seconds <= Integer.MAX_VALUE) {
int secondsInt = (int) seconds;
bytes[off] = BC_TIMESTAMP_SECONDS;
bytes[off + 1] = (byte) (secondsInt >>> 24);
bytes[off + 2] = (byte) (secondsInt >>> 16);
bytes[off + 3] = (byte) (secondsInt >>> 8);
bytes[off + 4] = (byte) secondsInt;
this.off = off + 5;
return;
}
if (seconds % 60 == 0) {
long minutes = seconds / 60;
if (minutes >= Integer.MIN_VALUE && minutes <= Integer.MAX_VALUE) {
int minutesInt = (int) minutes;
bytes[off] = BC_TIMESTAMP_MINUTES;
bytes[off + 1] = (byte) (minutesInt >>> 24);
bytes[off + 2] = (byte) (minutesInt >>> 16);
bytes[off + 3] = (byte) (minutesInt >>> 8);
bytes[off + 4] = (byte) minutesInt;
this.off = off + 5;
return;
}
}
}
bytes[off] = BC_TIMESTAMP_MILLIS;
bytes[off + 1] = (byte) (millis >>> 56);
bytes[off + 2] = (byte) (millis >>> 48);
bytes[off + 3] = (byte) (millis >>> 40);
bytes[off + 4] = (byte) (millis >>> 32);
bytes[off + 5] = (byte) (millis >>> 24);
bytes[off + 6] = (byte) (millis >>> 16);
bytes[off + 7] = (byte) (millis >>> 8);
bytes[off + 8] = (byte) millis;
this.off = off + 9;
}
@Override
public void writeInt64(long val) {
int minCapacity = off + 9;
if (minCapacity > bytes.length) {
ensureCapacity(minCapacity);
}
final byte[] bytes = this.bytes;
int off = this.off;
int size;
if (val >= INT64_NUM_LOW_VALUE && val <= INT64_NUM_HIGH_VALUE) {
bytes[off] = (byte) (BC_INT64_NUM_MIN + (val - INT64_NUM_LOW_VALUE));
size = 1;
} else if (val >= INT64_BYTE_MIN && val <= INT64_BYTE_MAX) {
bytes[off] = (byte) (BC_INT64_BYTE_ZERO + (val >> 8));
bytes[off + 1] = (byte) (val);
size = 2;
} else if (val >= INT64_SHORT_MIN && val <= INT64_SHORT_MAX) {
putLong3(bytes, off, (int) val);
size = 3;
} else if (val >= Integer.MIN_VALUE && val <= Integer.MAX_VALUE) {
bytes[off] = BC_INT64_INT;
putInt(bytes, off + 1, (int) val);
size = 5;
} else {
bytes[off] = BC_INT64;
putLong(bytes, off + 1, val);
size = 9;
}
this.off = off + size;
}
static void putLong3(byte[] bytes, int off, int val) {
bytes[off] = (byte) (BC_INT64_SHORT_ZERO + (val >> 16));
bytes[off + 1] = (byte) (val >> 8);
bytes[off + 2] = (byte) (val);
}
@Override
public void writeInt64(long[] value) {
if (value == null) {
writeArrayNull();
return;
}
int size = value.length;
int off = this.off;
int minCapacity = off + value.length * 9 + 5;
if (minCapacity >= bytes.length) {
ensureCapacity(minCapacity);
}
final byte[] bytes = this.bytes;
if (size <= ARRAY_FIX_LEN) {
bytes[off++] = (byte) (BC_ARRAY_FIX_MIN + size);
} else {
bytes[off] = BC_ARRAY;
off += writeInt32(bytes, off + 1, size) + 1;
}
for (int i = 0; i < value.length; i++) {
long val = value[i];
if (val >= BC_INT32_NUM_MIN && val <= BC_INT32_NUM_MAX) {
bytes[off++] = (byte) val;
continue;
}
if (val >= INT64_BYTE_MIN && val <= INT64_BYTE_MAX) {
bytes[off] = (byte) (BC_INT64_BYTE_ZERO + (val >> 8));
bytes[off + 1] = (byte) (val);
off += 2;
continue;
}
if (val >= INT64_SHORT_MIN && val <= INT64_SHORT_MAX) {
putLong3(bytes, off, (int) val);
off += 3;
continue;
}
if (val >= Integer.MIN_VALUE && val <= Integer.MAX_VALUE) {
bytes[off] = BC_INT64_INT;
putInt(bytes, off + 1, (int) val);
off += 5;
continue;
}
bytes[off] = BC_INT64;
putLong(bytes, off + 1, val);
off += 9;
}
this.off = off;
}
private static void putInt(byte[] bytes, int off, int val) {
bytes[off] = (byte) (val >>> 24);
bytes[off + 1] = (byte) (val >>> 16);
bytes[off + 2] = (byte) (val >>> 8);
bytes[off + 3] = (byte) val;
}
private static void putLong(byte[] bytes, int off, long val) {
bytes[off] = (byte) (val >>> 56);
bytes[off + 1] = (byte) (val >>> 48);
bytes[off + 2] = (byte) (val >>> 40);
bytes[off + 3] = (byte) (val >>> 32);
bytes[off + 4] = (byte) (val >>> 24);
bytes[off + 5] = (byte) (val >>> 16);
bytes[off + 6] = (byte) (val >>> 8);
bytes[off + 7] = (byte) val;
}
@Override
public void writeFloat(float value) {
int off = this.off;
int minCapacity = off + 5;
if (minCapacity >= bytes.length) {
ensureCapacity(minCapacity);
}
final byte[] bytes = this.bytes;
int i = (int) value;
if (i == value && value >= INT32_SHORT_MIN && value <= INT32_SHORT_MAX) {
bytes[off] = BC_FLOAT_INT;
off += writeInt32(bytes, off + 1, i) + 1;
} else {
bytes[off] = BC_FLOAT;
i = Float.floatToIntBits(value);
putInt(bytes, off + 1, i);
off += 5;
}
this.off = off;
}
@Override
public void writeFloat(float[] value) {
if (value == null) {
writeNull();
return;
}
startArray(value.length);
for (int i = 0; i < value.length; i++) {
writeFloat(value[i]);
}
endArray();
}
@Override
public void writeDouble(double value) {
if (value == 0) {
ensureCapacity(off + 1);
bytes[off++] = BC_DOUBLE_NUM_0;
return;
}
if (value == 1) {
ensureCapacity(off + 1);
bytes[off++] = BC_DOUBLE_NUM_1;
return;
}
if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) {
long longValue = (long) value;
if (longValue == value) {
ensureCapacity(off + 1);
bytes[off++] = BC_DOUBLE_LONG;
writeInt64(longValue);
return;
}
}
int off = this.off;
ensureCapacity(off + 9);
final byte[] bytes = this.bytes;
bytes[off] = BC_DOUBLE;
long i = Double.doubleToLongBits(value);
bytes[off + 1] = (byte) (i >>> 56);
bytes[off + 2] = (byte) (i >>> 48);
bytes[off + 3] = (byte) (i >>> 40);
bytes[off + 4] = (byte) (i >>> 32);
bytes[off + 5] = (byte) (i >>> 24);
bytes[off + 6] = (byte) (i >>> 16);
bytes[off + 7] = (byte) (i >>> 8);
bytes[off + 8] = (byte) i;
this.off = off + 9;
}
@Override
public void writeDouble(double[] value) {
if (value == null) {
writeNull();
return;
}
startArray(value.length);
for (int i = 0; i < value.length; i++) {
writeDouble(value[i]);
}
endArray();
}
@Override
public void writeInt16(short[] value) {
if (value == null) {
writeNull();
return;
}
startArray(value.length);
for (int i = 0; i < value.length; i++) {
writeInt32(value[i]);
}
endArray();
}
@Override
public void writeInt32(int[] values) {
if (values == null) {
writeArrayNull();
return;
}
// inline startArray(value.length);
int size = values.length;
if (off == bytes.length) {
ensureCapacity(off + 1);
}
if (size <= ARRAY_FIX_LEN) {
bytes[off++] = (byte) (BC_ARRAY_FIX_MIN + size);
} else {
bytes[off++] = BC_ARRAY;
writeInt32(size);
}
int off = this.off;
int minCapacity = off + values.length * 5;
if (minCapacity - bytes.length > 0) {
ensureCapacity(minCapacity);
}
final byte[] bytes = this.bytes;
for (int i = 0; i < values.length; i++) {
int val = values[i];
if (val >= BC_INT32_NUM_MIN && val <= BC_INT32_NUM_MAX) {
bytes[off++] = (byte) val;
continue;
}
if (val >= INT32_BYTE_MIN && val <= INT32_BYTE_MAX) {
bytes[off++] = (byte) (BC_INT32_BYTE_ZERO + (val >> 8));
bytes[off++] = (byte) (val);
continue;
}
if (val >= INT32_SHORT_MIN && val <= INT32_SHORT_MAX) {
putInt3(bytes, off, val);
off += 3;
continue;
}
bytes[off] = BC_INT32;
putInt(bytes, off + 1, val);
off += 5;
}
this.off = off;
}
@Override
public void writeInt8(byte val) {
int off = this.off;
int minCapacity = off + 2;
if (minCapacity - bytes.length > 0) {
ensureCapacity(minCapacity);
}
final byte[] bytes = this.bytes;
bytes[off] = BC_INT8;
bytes[off + 1] = val;
this.off = off + 2;
}
@Override
public void writeInt16(short val) {
int off = this.off;
int minCapacity = off + 3;
if (minCapacity >= bytes.length) {
ensureCapacity(minCapacity);
}
final byte[] bytes = this.bytes;
bytes[off] = BC_INT16;
bytes[off + 1] = (byte) (val >>> 8);
bytes[off + 2] = (byte) val;
this.off = off + 3;
}
@Override
public void writeEnum(Enum e) {
if (e == null) {
writeNull();
return;
}
if ((context.features & Feature.WriteEnumUsingToString.mask) != 0) {
writeString(e.toString());
} else if ((context.features & Feature.WriteEnumsUsingName.mask) != 0) {
writeString(e.name());
} else {
int val = e.ordinal();
if (val <= BC_INT32_NUM_MAX) {
if (off == bytes.length) {
ensureCapacity(off + 1);
}
bytes[off++] = (byte) val;
return;
}
writeInt32(val);
}
}
@Override
public void writeInt32(int val) {
int minCapacity = off + 5;
if (minCapacity >= bytes.length) {
ensureCapacity(minCapacity);
}
final byte[] bytes = this.bytes;
int size;
int off = this.off;
if (val >= BC_INT32_NUM_MIN && val <= BC_INT32_NUM_MAX) {
bytes[off] = (byte) val;
size = 1;
} else if (val >= INT32_BYTE_MIN && val <= INT32_BYTE_MAX) {
bytes[off] = (byte) (BC_INT32_BYTE_ZERO + (val >> 8));
bytes[off + 1] = (byte) (val);
size = 2;
} else if (val >= INT32_SHORT_MIN && val <= INT32_SHORT_MAX) {
putInt3(bytes, off, val);
size = 3;
} else {
bytes[off] = BC_INT32;
putInt(bytes, off + 1, val);
size = 5;
}
this.off += size;
}
static void putInt3(byte[] bytes, int off, int val) {
bytes[off] = (byte) (BC_INT32_SHORT_ZERO + (val >> 16));
bytes[off + 1] = (byte) (val >> 8);
bytes[off + 2] = (byte) (val);
}
public static int writeInt32(byte[] bytes, int off, int val) {
if (val >= BC_INT32_NUM_MIN && val <= BC_INT32_NUM_MAX) {
bytes[off] = (byte) val;
return 1;
} else if (val >= INT32_BYTE_MIN && val <= INT32_BYTE_MAX) {
bytes[off] = (byte) (BC_INT32_BYTE_ZERO + (val >> 8));
bytes[off + 1] = (byte) (val);
return 2;
} else if (val >= INT32_SHORT_MIN && val <= INT32_SHORT_MAX) {
putInt3(bytes, off, val);
return 3;
} else {
bytes[off] = BC_INT32;
putInt(bytes, off + 1, val);
return 5;
}
}
@Override
public void writeArrayNull() {
if (off == bytes.length) {
ensureCapacity(off + 1);
}
if ((this.context.features & (Feature.NullAsDefaultValue.mask | Feature.WriteNullListAsEmpty.mask)) != 0) {
bytes[off++] = BC_ARRAY_FIX_MIN;
} else {
bytes[off++] = BC_NULL;
}
}
@Override
public void writeRaw(String str) {
throw new JSONException("unsupported operation");
}
@Override
public void writeRaw(byte[] bytes) {
int minCapacity = this.off + bytes.length;
if (minCapacity - this.bytes.length > 0) {
ensureCapacity(minCapacity);
}
System.arraycopy(bytes, 0, this.bytes, off, bytes.length);
off += bytes.length;
}
public void writeSymbol(int symbol) {
int minCapacity = off + 3;
if (minCapacity >= bytes.length) {
ensureCapacity(minCapacity);
}
this.bytes[off++] = BC_SYMBOL;
if (symbol >= BC_INT32_NUM_MIN && symbol <= BC_INT32_NUM_MAX) {
bytes[off++] = (byte) symbol;
return;
}
if (symbol >= INT32_BYTE_MIN && symbol <= INT32_BYTE_MAX) {
bytes[off++] = (byte) (BC_INT32_BYTE_ZERO + (symbol >> 8));
bytes[off++] = (byte) (symbol);
return;
}
writeInt32(symbol);
}
@Override
public void writeNameRaw(byte[] name, long nameHash) {
int off = this.off;
int minCapacity = off + name.length + 2;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
final byte[] bytes = this.bytes;
int symbol;
if (symbolTable == null
|| (symbol = symbolTable.getOrdinalByHashCode(nameHash)) == -1
) {
if ((context.features & WriteNameAsSymbol.mask) == 0) {
System.arraycopy(name, 0, bytes, off, name.length);
this.off = off + name.length;
return;
}
boolean symbolExists = false;
if (symbols != null) {
if ((symbol = symbols.putIfAbsent(nameHash, symbolIndex)) != symbolIndex) {
symbolExists = true;
} else {
symbolIndex++;
}
} else {
(symbols = new TLongIntHashMap())
.put(nameHash, symbol = symbolIndex++);
}
if (!symbolExists) {
bytes[off++] = BC_SYMBOL;
System.arraycopy(name, 0, bytes, off, name.length);
this.off = off + name.length;
if (symbol >= BC_INT32_NUM_MIN && symbol <= BC_INT32_NUM_MAX) {
bytes[this.off++] = (byte) symbol;
} else {
writeInt32(symbol);
}
return;
}
symbol = -symbol;
}
bytes[off++] = BC_SYMBOL;
int intValue = -symbol;
if (intValue >= BC_INT32_NUM_MIN && intValue <= BC_INT32_NUM_MAX) {
bytes[off] = (byte) intValue;
this.off = off + 1;
} else {
this.off = off;
writeInt32(intValue);
}
}
@Override
public void writeLocalDateTime(LocalDateTime dateTime) {
if (dateTime == null) {
writeNull();
return;
}
int off = this.off;
ensureCapacity(off + 8);
final byte[] bytes = this.bytes;
bytes[off] = BC_LOCAL_DATETIME;
int year = dateTime.date.year;
bytes[off + 1] = (byte) (year >>> 8);
bytes[off + 2] = (byte) year;
bytes[off + 3] = (byte) dateTime.date.monthValue;
bytes[off + 4] = (byte) dateTime.date.dayOfMonth;
bytes[off + 5] = dateTime.time.hour;
bytes[off + 6] = dateTime.time.minute;
bytes[off + 7] = dateTime.time.second;
this.off = off + 8;
int nano = dateTime.time.nano;
writeInt32(nano);
}
@Override
public void writeInstant(long second, int nano) {
ensureCapacity(off + 1);
bytes[off++] = BC_TIMESTAMP;
writeInt64(second);
writeInt32(nano);
}
@Override
public void writeUUID(UUID value) {
if (value == null) {
writeNull();
return;
}
long msb = value.getMostSignificantBits();
long lsb = value.getLeastSignificantBits();
int off = this.off;
ensureCapacity(off + 18);
final byte[] bytes = this.bytes;
bytes[off] = BC_BINARY;
bytes[off + 1] = BC_INT32_NUM_16;
bytes[off + 2] = (byte) (msb >>> 56);
bytes[off + 3] = (byte) (msb >>> 48);
bytes[off + 4] = (byte) (msb >>> 40);
bytes[off + 5] = (byte) (msb >>> 32);
bytes[off + 6] = (byte) (msb >>> 24);
bytes[off + 7] = (byte) (msb >>> 16);
bytes[off + 8] = (byte) (msb >>> 8);
bytes[off + 9] = (byte) msb;
bytes[off + 10] = (byte) (lsb >>> 56);
bytes[off + 11] = (byte) (lsb >>> 48);
bytes[off + 12] = (byte) (lsb >>> 40);
bytes[off + 13] = (byte) (lsb >>> 32);
bytes[off + 14] = (byte) (lsb >>> 24);
bytes[off + 15] = (byte) (lsb >>> 16);
bytes[off + 16] = (byte) (lsb >>> 8);
bytes[off + 17] = (byte) lsb;
this.off = off + 18;
}
@Override
public void writeBigInt(BigInteger value, long features) {
if (value == null) {
writeNull();
return;
}
if (isInt64(value)) {
if (off == bytes.length) {
ensureCapacity(off + 1);
}
bytes[off++] = BC_BIGINT_LONG;
long int64Value = value.longValue();
writeInt64(int64Value);
return;
}
byte[] valueBytes = value.toByteArray();
ensureCapacity(off + 5 + valueBytes.length);
bytes[off++] = BC_BIGINT;
writeInt32(valueBytes.length);
System.arraycopy(valueBytes, 0, bytes, off, valueBytes.length);
off += valueBytes.length;
}
@Override
public void writeBinary(byte[] bytes) {
if (bytes == null) {
writeNull();
return;
}
ensureCapacity(off + 6 + bytes.length);
this.bytes[off++] = BC_BINARY;
writeInt32(bytes.length);
System.arraycopy(bytes, 0, this.bytes, off, bytes.length);
off += bytes.length;
}
@Override
public void writeDecimal(BigDecimal value, long features, DecimalFormat format) {
if (value == null) {
writeNull();
return;
}
int scale = value.scale();
BigInteger unscaledValue = value.unscaledValue();
if (scale == 0
&& isInt64(unscaledValue)) {
ensureCapacity(off + 1);
this.bytes[off++] = BC_DECIMAL_LONG;
long longValue = unscaledValue.longValue();
writeInt64(longValue);
return;
}
ensureCapacity(off + 1);
this.bytes[off++] = BC_DECIMAL;
writeInt32(scale);
if (isInt32(unscaledValue)) {
int intValue = unscaledValue.intValue();
writeInt32(intValue);
} else if (isInt64(unscaledValue)) {
long longValue = unscaledValue.longValue();
writeInt64(longValue);
} else {
writeBigInt(unscaledValue, 0);
}
}
private static boolean isInt32(BigInteger value) {
return value.compareTo(BIGINT_INT32_MIN) >= 0 && value.compareTo(BIGINT_INT32_MAX) <= 0;
}
private static boolean isInt64(BigInteger value) {
return value.compareTo(BIGINT_INT64_MIN) >= 0 && value.compareTo(BIGINT_INT64_MAX) <= 0;
}
@Override
public void writeBool(boolean value) {
if (off == bytes.length) {
ensureCapacity(off + 1);
}
this.bytes[off++] = value ? BC_TRUE : BC_FALSE;
}
@Override
public void writeBool(boolean[] value) {
if (value == null) {
writeNull();
return;
}
startArray(value.length);
for (int i = 0; i < value.length; i++) {
writeBool(value[i]);
}
endArray();
}
@Override
public void writeReference(String path) {
if (off == bytes.length) {
ensureCapacity(off + 1);
}
bytes[off++] = BC_REFERENCE;
if (path == this.lastReference) {
writeString("#-1");
} else {
writeString(path);
}
this.lastReference = path;
}
@Override
public void writeDateTime14(
int year,
int month,
int dayOfMonth,
int hour,
int minute,
int second
) {
int off = this.off;
ensureCapacity(off + 8);
final byte[] bytes = this.bytes;
bytes[off] = BC_LOCAL_DATETIME;
bytes[off + 1] = (byte) (year >>> 8);
bytes[off + 2] = (byte) year;
bytes[off + 3] = (byte) month;
bytes[off + 4] = (byte) dayOfMonth;
bytes[off + 5] = (byte) hour;
bytes[off + 6] = (byte) minute;
bytes[off + 7] = (byte) second;
this.off = off + 8;
int nano = 0;
writeInt32(nano);
}
@Override
public void writeDateTime19(
int year,
int month,
int dayOfMonth,
int hour,
int minute,
int second
) {
int off = this.off;
ensureCapacity(off + 8);
final byte[] bytes = this.bytes;
bytes[off] = BC_LOCAL_DATETIME;
bytes[off + 1] = (byte) (year >>> 8);
bytes[off + 2] = (byte) year;
bytes[off + 3] = (byte) month;
bytes[off + 4] = (byte) dayOfMonth;
bytes[off + 5] = (byte) hour;
bytes[off + 6] = (byte) minute;
bytes[off + 7] = (byte) second;
this.off = off + 8;
int nano = 0;
writeInt32(nano);
}
@Override
public void writeDateTimeISO8601(
int year,
int month,
int dayOfMonth,
int hour,
int minute,
int second,
int millis,
int offsetSeconds,
boolean timeZone
) {
throw new JSONException("unsupported operation");
}
@Override
public void writeDateYYYMMDD8(int year, int month, int dayOfMonth) {
int off = this.off;
ensureCapacity(off + 5);
final byte[] bytes = this.bytes;
bytes[off] = BC_LOCAL_DATE;
bytes[off + 1] = (byte) (year >>> 8);
bytes[off + 2] = (byte) year;
bytes[off + 3] = (byte) month;
bytes[off + 4] = (byte) dayOfMonth;
this.off = off + 5;
}
@Override
public void writeDateYYYMMDD10(int year, int month, int dayOfMonth) {
throw new JSONException("unsupported operation");
}
@Override
public void writeTimeHHMMSS8(int hour, int minute, int second) {
throw new JSONException("unsupported operation");
}
@Override
public void writeBase64(byte[] bytes) {
throw new JSONException("UnsupportedOperation");
}
@Override
public void writeHex(byte[] bytes) {
writeBinary(bytes);
}
@Override
public void writeRaw(char ch) {
throw new JSONException("UnsupportedOperation");
}
@Override
public void writeNameRaw(byte[] bytes) {
writeRaw(bytes);
}
@Override
public void writeName2Raw(long name) {
int off = this.off;
int minCapacity = off + 8;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name);
this.off = off + 2;
}
@Override
public void writeName3Raw(long name) {
int off = this.off;
int minCapacity = off + 8;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name);
this.off = off + 3;
}
@Override
public void writeName4Raw(long name) {
int off = this.off;
int minCapacity = off + 8;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name);
this.off = off + 4;
}
@Override
public void writeName5Raw(long name) {
int off = this.off;
int minCapacity = off + 8;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name);
this.off = off + 5;
}
@Override
public void writeName6Raw(long name) {
int off = this.off;
int minCapacity = off + 8;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name);
this.off = off + 6;
}
@Override
public void writeName7Raw(long name) {
int off = this.off;
int minCapacity = off + 8;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name);
this.off = off + 7;
}
@Override
public void writeName8Raw(long name) {
int off = this.off;
int minCapacity = off + 8;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name);
this.off = off + 8;
}
@Override
public void writeName9Raw(long name0, int name1) {
int off = this.off;
int minCapacity = off + 12;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name0);
UNSAFE.putInt(bytes, ARRAY_BYTE_BASE_OFFSET + off + 8, name1);
this.off = off + 9;
}
@Override
public void writeName10Raw(long name0, long name1) {
int off = this.off;
int minCapacity = off + 16;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name0);
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off + 8, name1);
this.off = off + 10;
}
@Override
public void writeName11Raw(long name0, long name1) {
int off = this.off;
int minCapacity = off + 16;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name0);
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off + 8, name1);
this.off = off + 11;
}
@Override
public void writeName12Raw(long name0, long name1) {
int off = this.off;
int minCapacity = off + 16;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name0);
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off + 8, name1);
this.off = off + 12;
}
@Override
public void writeName13Raw(long name0, long name1) {
int off = this.off;
int minCapacity = off + 16;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name0);
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off + 8, name1);
this.off = off + 13;
}
@Override
public void writeName14Raw(long name0, long name1) {
int off = this.off;
int minCapacity = off + 16;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name0);
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off + 8, name1);
this.off = off + 14;
}
@Override
public void writeName15Raw(long name0, long name1) {
int off = this.off;
int minCapacity = off + 16;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name0);
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off + 8, name1);
this.off = off + 15;
}
@Override
public void writeName16Raw(long name0, long name1) {
int off = this.off;
int minCapacity = off + 16;
if (minCapacity >= this.bytes.length) {
ensureCapacity(minCapacity);
}
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name0);
UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off + 8, name1);
this.off = off + 16;
}
@Override
public void writeNameRaw(char[] chars) {
throw new JSONException("UnsupportedOperation");
}
@Override
public void writeNameRaw(char[] bytes, int offset, int len) {
throw new JSONException("UnsupportedOperation");
}
@Override
public void writeColon() {
throw new JSONException("UnsupportedOperation");
}
@Override
public void write(List array) {
if (array == null) {
writeArrayNull();
return;
}
final int size = array.size();
startArray(size);
for (int i = 0; i < size; i++) {
Object item = array.get(i);
writeAny(item);
}
}
@Override
public void write(Map map) {
if (map == null) {
writeNull();
return;
}
startObject();
for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) {
Map.Entry entry = it.next();
writeAny(entry.getKey());
writeAny(entry.getValue());
}
endObject();
}
@Override
public void write(JSONObject object) {
if (object == null) {
writeNull();
return;
}
startObject();
for (Iterator> it = object.entrySet().iterator(); it.hasNext(); ) {
Map.Entry entry = it.next();
writeAny(entry.getKey());
writeAny(entry.getValue());
}
endObject();
}
@Override
public byte[] getBytes() {
return Arrays.copyOf(bytes, off);
}
@Override
public int size() {
return off;
}
@Override
public byte[] getBytes(Charset charset) {
throw new JSONException("not support operator");
}
@Override
public int flushTo(OutputStream to) throws IOException {
int len = off;
to.write(bytes, 0, off);
off = 0;
return len;
}
@Override
public int flushTo(OutputStream out, Charset charset) throws IOException {
throw new JSONException("UnsupportedOperation");
}
@Override
public String toString() {
if (bytes.length == 0) {
return "";
}
byte[] jsonbBytes = getBytes();
JSONReader reader = JSONReader.ofJSONB(jsonbBytes);
JSONWriter writer = JSONWriter.of();
try {
Object object = reader.readAny();
writer.writeAny(object);
return writer.toString();
} catch (Exception ex) {
return JSONB.typeName(bytes[0]) + ", bytes length " + off;
}
}
}