io.quarkus.qson.writer.JsonByteWriter Maven / Gradle / Ivy
package io.quarkus.qson.writer;
import io.quarkus.qson.QsonException;
import io.quarkus.qson.util.IntChar;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
public abstract class JsonByteWriter implements JsonWriter {
static final byte[] TRUE = {'t', 'r', 'u', 'e'};
static final byte[] FALSE = {'f', 'a', 'l', 's', 'e'};
static final byte[] TRUE_PROPERTY_VALUE = {':', 't', 'r', 'u', 'e'};
static final byte[] FALSE_PROPERTY_VALUE = {':', 'f', 'a', 'l', 's', 'e'};
public static Charset UTF8 = StandardCharsets.UTF_8;
@Override
public void writeLCurley() {
writeByte(IntChar.INT_LCURLY);
}
@Override
public void writeRCurley() {
writeByte(IntChar.INT_RCURLY);
}
@Override
public void writeLBracket() {
writeByte(IntChar.INT_LBRACKET);
}
@Override
public void writeRBracket() {
writeByte(IntChar.INT_RBRACKET);
}
@Override
public void writeSeparator() {
writeByte(IntChar.INT_COLON);
}
@Override
public void writeComma() {
writeByte(IntChar.INT_COMMA);
}
@Override
public void writeQuote() {
writeByte(IntChar.INT_QUOTE);
}
@Override
public void write(short val) {
write((long)val);
}
@Override
public void write(int val) {
write((long)val);
}
@Override
public void write(long x) {
long places = 1;
long n = x / 10;
for (; n != 0; n /= 10l) places *= 10l;
if (x < 0) {
writeByte('-');
for (long place = places; place >=1; place /= 10l) {
int i = (int)(x / place);
writeByte('0' - i);
x -= i * place;
}
} else {
for (long place = places; place >=1; place /= 10l) {
int i = (int)(x / place);
writeByte('0' + i);
x -= i * place;
}
}
}
@Override
public void write(boolean val) {
if (val) writeBytes(TRUE);
else writeBytes(FALSE);
}
@Override
public void write(byte val) {
write((long)val);
}
@Override
public void write(float val) {
writeBytes(Float.toString(val).getBytes(UTF8));
}
@Override
public void write(double val) {
writeBytes(Double.toString(val).getBytes(UTF8));
}
@Override
public void write(char val) {
write(Character.toString(val));
}
@Override
public void write(Character val) {
write(val.charValue());
}
@Override
public void write(Short val) {
write(val.longValue());
}
@Override
public void write(Integer val) {
write(val.longValue());
}
@Override
public void write(Long val) {
write(val.longValue());
}
@Override
public void write(Boolean val) {
write(val.booleanValue());
}
@Override
public void write(Byte val) {
write(val.longValue());
}
@Override
public void write(Float val) {
write(val.floatValue());
}
@Override
public void write(Double val) {
write(val.doubleValue());
}
@Override
public void write(String val) {
writeByte(IntChar.INT_QUOTE);
final int[] escCodes = sOutputEscapes128;
for (int i = 0; i < val.length(); i++) {
int ch = val.charAt(i);
if (ch <= 0x7F) {
int escape = escCodes[ch];
if (escape == 0) {
writeByte(ch);
} else if (escape > 0) { // 2-char escape
writeByte(IntChar.INT_BACKSLASH);
writeByte(escape);
} else {
// ctrl-char, 6-byte escape...
writeGenericEscape(ch);
}
} else if (ch <= 0x7FF) { // fine, just needs 2 byte output
writeByte(0xc0 | (ch >> 6));
writeByte(0x80 | (ch & 0x3f));
} else {
outputMultiByteChar(ch);
}
}
writeByte(IntChar.INT_QUOTE);
}
@Override
public void write(Enum e) {
write(e.name());
}
private final static int[] HEX_CHARS;
static {
String hex = "0123456789ABCDEF";
int len = hex.length();
HEX_CHARS = new int[len];
for (int i = 0; i < len; ++i) {
HEX_CHARS[i] = hex.charAt(i);
}
}
private void writeGenericEscape(int charToEscape)
{
writeByte(IntChar.INT_BACKSLASH);
writeByte(IntChar.INT_u);
if (charToEscape > 0xFF) {
int hi = (charToEscape >> 8) & 0xFF;
writeByte(HEX_CHARS[hi >> 4]);
writeByte(HEX_CHARS[hi & 0xF]);
charToEscape &= 0xFF;
} else {
writeByte(IntChar.INT_0);
writeByte(IntChar.INT_0);
}
// We know it's a control char, so only the last 2 chars are non-0
writeByte(HEX_CHARS[charToEscape >> 4]);
writeByte(HEX_CHARS[charToEscape & 0xF]);
}
public final static int SURR1_FIRST = 0xD800;
public final static int SURR1_LAST = 0xDBFF;
public final static int SURR2_FIRST = 0xDC00;
public final static int SURR2_LAST = 0xDFFF;
private final void outputMultiByteChar(int ch)
{
if (ch >= SURR1_FIRST && ch <= SURR2_LAST) { // yes, outside of BMP; add an escape
writeByte(IntChar.INT_BACKSLASH);
writeByte(IntChar.INT_u);
writeByte(HEX_CHARS[(ch >> 12) & 0xF]);
writeByte(HEX_CHARS[(ch >> 8) & 0xF]);
writeByte(HEX_CHARS[(ch >> 4) & 0xF]);
writeByte(HEX_CHARS[ch & 0xF]);
} else {
writeByte(0xe0 | (ch >> 12));
writeByte(0x80 | ((ch >> 6) & 0x3f));
writeByte(0x80 | (ch & 0x3f));
}
}
/**
* Lookup table used for determining which output characters in
* 7-bit ASCII range need to be quoted.
*/
private final static int[] sOutputEscapes128;
static {
int[] table = new int[128];
// Control chars need generic escape sequence
for (int i = 0; i < 32; ++i) {
table[i] = -1;
}
// Others (and some within that range too) have explicit shorter sequences
table['"'] = '"';
table['\\'] = '\\';
// Escaping of slash is optional, so let's not add it
table[0x08] = 'b';
table[0x09] = 't';
table[0x0C] = 'f';
table[0x0A] = 'n';
table[0x0D] = 'r';
sOutputEscapes128 = table;
}
@Override
public void writeObject(Object obj) {
if (obj instanceof Map) {
write((Map)obj);
} else if (obj instanceof List || obj instanceof Set) {
write((Collection)obj);
} else if (obj instanceof String) {
write((String)obj);
} else if (obj instanceof Short) {
write((Short)obj);
} else if (obj instanceof Byte) {
write((Byte)obj);
} else if (obj instanceof Integer) {
write((Integer) obj);
} else if (obj instanceof Long) {
write((Long)obj);
} else if (obj instanceof Float) {
write((Float)obj);
} else if (obj instanceof Double) {
write((Double)obj);
} else if (obj instanceof Boolean) {
write((Boolean)obj);
} else if (obj instanceof Character) {
write((Character) obj);
} else if (obj instanceof Enum) {
write((Enum)obj);
} else {
throw new QsonException("Unable to determine type to write: " + obj.getClass().getName());
}
}
@Override
public void write(Map val) {
writeByte(IntChar.INT_LCURLY);
writeAny(val, false);
writeByte(IntChar.INT_RCURLY);
}
@Override
public void write(Map val, QsonObjectWriter valueWriter) {
writeByte(IntChar.INT_LCURLY);
if (!val.isEmpty()) {
Set> set = val.entrySet();
Iterator> it = set.iterator();
Map.Entry
© 2015 - 2025 Weber Informatics LLC | Privacy Policy