package com.jsoniter;
import com.jsoniter.any.Any;
import com.jsoniter.spi.*;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
class CodegenImplNative {
final static Map<String, String> NATIVE_READS = new HashMap<String, String>() {{
put("float", "iter.readFloat()");
put("double", "iter.readDouble()");
put("boolean", "iter.readBoolean()");
put("byte", "iter.readShort()");
put("short", "iter.readShort()");
put("int", "iter.readInt()");
put("char", "iter.readInt()");
put("long", "iter.readLong()");
put(Float.class.getName(), "java.lang.Float.valueOf(iter.readFloat())");
put(Double.class.getName(), "java.lang.Double.valueOf(iter.readDouble())");
put(Boolean.class.getName(), "java.lang.Boolean.valueOf(iter.readBoolean())");
put(Byte.class.getName(), "java.lang.Byte.valueOf((byte)iter.readShort())");
put(Character.class.getName(), "java.lang.Character.valueOf((char)iter.readShort())");
put(Short.class.getName(), "java.lang.Short.valueOf(iter.readShort())");
put(Integer.class.getName(), "java.lang.Integer.valueOf(iter.readInt())");
put(Long.class.getName(), "java.lang.Long.valueOf(iter.readLong())");
put(BigDecimal.class.getName(), "iter.readBigDecimal()");
put(BigInteger.class.getName(), "iter.readBigInteger()");
put(String.class.getName(), "iter.readString()");
put(Object.class.getName(), "iter.read()");
put(Any.class.getName(), "iter.readAny()");
}};
final static Map<Class, Decoder> NATIVE_DECODERS = new HashMap<Class, Decoder>() {{
put(float.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readFloat();
}
});
put(Float.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readFloat();
}
});
put(double.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readDouble();
}
});
put(Double.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readDouble();
}
});
put(boolean.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readBoolean();
}
});
put(Boolean.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readBoolean();
}
});
put(byte.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readShort();
}
});
put(Byte.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readShort();
}
});
put(short.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readShort();
}
});
put(Short.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readShort();
}
});
put(int.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readInt();
}
});
put(Integer.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readInt();
}
});
put(char.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return (char)iter.readInt();
}
});
put(Character.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return (char)iter.readInt();
}
});
put(long.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readLong();
}
});
put(Long.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readLong();
}
});
put(BigDecimal.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readBigDecimal();
}
});
put(BigInteger.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readBigInteger();
}
});
put(String.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readString();
}
});
put(Object.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.read();
}
});
put(Any.class, new Decoder() {
@Override
public Object decode(JsonIterator iter) throws IOException {
return iter.readAny();
}
});
}};
public static String genReadOp(Type type) {
String cacheKey = TypeLiteral.create(type).getDecoderCacheKey();
return String.format("(%s)%s", getTypeName(type), genReadOp(cacheKey, type));
}
public static String getTypeName(Type fieldType) {
if (fieldType instanceof Class) {
Class clazz = (Class) fieldType;
return clazz.getCanonicalName();
} else if (fieldType instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) fieldType;
Class clazz = (Class) pType.getRawType();
return clazz.getCanonicalName();
} else {
throw new JsonException("unsupported type: " + fieldType);
}
}
static String genField(Binding field) {
String fieldCacheKey = field.decoderCacheKey();
Type fieldType = field.valueType;
return String.format("(%s)%s", getTypeName(fieldType), genReadOp(fieldCacheKey, fieldType));
}
private static String genReadOp(String cacheKey, Type valueType) {
// the field decoder might be registered directly
Decoder decoder = JsoniterSpi.getDecoder(cacheKey);
if (decoder == null) {
// if cache key is for field, and there is no field decoder specified
// update cache key for normal type
cacheKey = TypeLiteral.create(valueType).getDecoderCacheKey();
decoder = JsoniterSpi.getDecoder(cacheKey);
if (decoder == null) {
if (valueType instanceof Class) {
Class clazz = (Class) valueType;
String nativeRead = NATIVE_READS.get(clazz.getCanonicalName());
if (nativeRead != null) {
return nativeRead;
}
}
Codegen.getDecoder(cacheKey, valueType);
if (Codegen.canStaticAccess(cacheKey)) {
return String.format("%s.decode_(iter)", cacheKey);
} else {
// can not use static "decode_" method to access, go through codegen cache
return String.format("com.jsoniter.CodegenAccess.read(\"%s\", iter)", cacheKey);
}
}
}
if (valueType == boolean.class) {
if (!(decoder instanceof Decoder.BooleanDecoder)) {
throw new JsonException("decoder for " + cacheKey + "must implement Decoder.BooleanDecoder");
}
return String.format("com.jsoniter.CodegenAccess.readBoolean(\"%s\", iter)", cacheKey);
}
if (valueType == byte.class) {
if (!(decoder instanceof Decoder.ShortDecoder)) {
throw new JsonException("decoder for " + cacheKey + "must implement Decoder.ShortDecoder");
}
return String.format("com.jsoniter.CodegenAccess.readShort(\"%s\", iter)", cacheKey);
}
if (valueType == short.class) {
if (!(decoder instanceof Decoder.ShortDecoder)) {
throw new JsonException("decoder for " + cacheKey + "must implement Decoder.ShortDecoder");
}
return String.format("com.jsoniter.CodegenAccess.readShort(\"%s\", iter)", cacheKey);
}
if (valueType == char.class) {
if (!(decoder instanceof Decoder.IntDecoder)) {
throw new JsonException("decoder for " + cacheKey + "must implement Decoder.IntDecoder");
}
return String.format("com.jsoniter.CodegenAccess.readInt(\"%s\", iter)", cacheKey);
}
if (valueType == int.class) {
if (!(decoder instanceof Decoder.IntDecoder)) {
throw new JsonException("decoder for " + cacheKey + "must implement Decoder.IntDecoder");
}
return String.format("com.jsoniter.CodegenAccess.readInt(\"%s\", iter)", cacheKey);
}
if (valueType == long.class) {
if (!(decoder instanceof Decoder.LongDecoder)) {
throw new JsonException("decoder for " + cacheKey + "must implement Decoder.LongDecoder");
}
return String.format("com.jsoniter.CodegenAccess.readLong(\"%s\", iter)", cacheKey);
}
if (valueType == float.class) {
if (!(decoder instanceof Decoder.FloatDecoder)) {
throw new JsonException("decoder for " + cacheKey + "must implement Decoder.FloatDecoder");
}
return String.format("com.jsoniter.CodegenAccess.readFloat(\"%s\", iter)", cacheKey);
}
if (valueType == double.class) {
if (!(decoder instanceof Decoder.DoubleDecoder)) {
throw new JsonException("decoder for " + cacheKey + "must implement Decoder.DoubleDecoder");
}
return String.format("com.jsoniter.CodegenAccess.readDouble(\"%s\", iter)", cacheKey);
}
return String.format("com.jsoniter.CodegenAccess.read(\"%s\", iter)", cacheKey);
}
}