+ * @author wenshao[szujobs@hotmail.com]
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.METHOD, ElementType.FIELD })
+@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
public @interface JSONField {
+ /**
+ * config encode/decode ordinal
+ * @since 1.1.42
+ * @return
+ */
+ int ordinal() default 0;
String name() default "";
diff --git a/src/main/java/com/alibaba/fastjson/annotation/JSONType.java b/src/main/java/com/alibaba/fastjson/annotation/JSONType.java
new file mode 100755
index 0000000000..f5ddd5d57d
--- /dev/null
+++ b/src/main/java/com/alibaba/fastjson/annotation/JSONType.java
@@ -0,0 +1,32 @@
+package com.alibaba.fastjson.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.alibaba.fastjson.parser.Feature;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+
+/**
+ * @author wenshao[szujobs@hotmail.com]
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE })
+public @interface JSONType {
+
+ boolean asm() default true;
+
+ String[] orders() default {};
+
+ String[] includes() default {};
+
+ String[] ignores() default {};
+
+ SerializerFeature[] serialzeFeatures() default {};
+ Feature[] parseFeatures() default {};
+
+ boolean alphabetic() default true;
+
+ Class> mappingTo() default Void.class;
+}
diff --git a/src/main/java/com/alibaba/fastjson/asm/ASMException.java b/src/main/java/com/alibaba/fastjson/asm/ASMException.java
new file mode 100755
index 0000000000..350f9aff6a
--- /dev/null
+++ b/src/main/java/com/alibaba/fastjson/asm/ASMException.java
@@ -0,0 +1,12 @@
+package com.alibaba.fastjson.asm;
+
+import com.alibaba.fastjson.JSONException;
+
+public class ASMException extends JSONException {
+
+ private static final long serialVersionUID = 1L;
+
+ public ASMException(String message){
+ super(message);
+ }
+}
diff --git a/src/main/java/com/alibaba/fastjson/asm/ByteVector.java b/src/main/java/com/alibaba/fastjson/asm/ByteVector.java
old mode 100644
new mode 100755
diff --git a/src/main/java/com/alibaba/fastjson/asm/ClassWriter.java b/src/main/java/com/alibaba/fastjson/asm/ClassWriter.java
old mode 100644
new mode 100755
index 08edae65fc..1c93e0883d
--- a/src/main/java/com/alibaba/fastjson/asm/ClassWriter.java
+++ b/src/main/java/com/alibaba/fastjson/asm/ClassWriter.java
@@ -30,9 +30,6 @@
package com.alibaba.fastjson.asm;
/**
- * A {@link ClassVisitor} that generates classes in bytecode form. More precisely this visitor generates a byte array
- * conforming to the Java class file format. It can be used alone, to generate a Java class "from scratch", or with one
- * or more and adapter class visitor to generate a modified class from one or more existing Java classes.
*
* @author Eric Bruneton
*/
@@ -50,8 +47,8 @@ public class ClassWriter {
/**
* Flag to automatically compute the stack map frames of methods from scratch. If this flag is set, then the calls
- * to the {@link MethodVisitor#visitFrame} method are ignored, and the stack map frames are recomputed from the
- * methods bytecode. The arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
+ * to the MethodVisitor#visitFrame method are ignored, and the stack map frames are recomputed from the
+ * methods bytecode. The arguments of the MethodVisitor#visitMaxs method are also ignored and
* recomputed from the bytecode. In other words, computeFrames implies computeMaxs.
*
* @see #ClassWriter(int)
@@ -467,9 +464,6 @@ public MethodVisitor visitMethod(final int access, final String name, final Stri
return new MethodWriter(this, access, name, desc, signature, exceptions);
}
- public void visitEnd() {
- }
-
// ------------------------------------------------------------------------
// Other public methods
// ------------------------------------------------------------------------
@@ -538,7 +532,10 @@ public byte[] toByteArray() {
* @return a new or already existing constant item with the given value.
*/
Item newConstItem(final Object cst) {
- if (cst instanceof String) {
+ if (cst instanceof Integer) {
+ int val = ((Integer) cst).intValue();
+ return newInteger(val);
+ } else if (cst instanceof String) {
return newString((String) cst);
} else if (cst instanceof Type) {
Type t = (Type) cst;
@@ -547,6 +544,17 @@ Item newConstItem(final Object cst) {
throw new IllegalArgumentException("value " + cst);
}
}
+
+ Item newInteger(final int value) {
+ key.set(value);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(INT).putInt(value);
+ result = new Item(index++, key);
+ put(result);
+ }
+ return result;
+ }
public int newUTF8(final String value) {
key.set(UTF8, value, null, null);
diff --git a/src/main/java/com/alibaba/fastjson/asm/FieldVisitor.java b/src/main/java/com/alibaba/fastjson/asm/FieldVisitor.java
old mode 100644
new mode 100755
diff --git a/src/main/java/com/alibaba/fastjson/asm/FieldWriter.java b/src/main/java/com/alibaba/fastjson/asm/FieldWriter.java
old mode 100644
new mode 100755
diff --git a/src/main/java/com/alibaba/fastjson/asm/Item.java b/src/main/java/com/alibaba/fastjson/asm/Item.java
old mode 100644
new mode 100755
index 1b1a559892..a7ae9f3153
--- a/src/main/java/com/alibaba/fastjson/asm/Item.java
+++ b/src/main/java/com/alibaba/fastjson/asm/Item.java
@@ -141,6 +141,17 @@ void set(final int type, final String strVal1, final String strVal2, final Strin
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() * strVal2.hashCode() * strVal3.hashCode());
}
}
+
+ /**
+ * Sets this item to an integer item.
+ *
+ * @param intVal the value of this item.
+ */
+ void set(final int intVal) {
+ this.type = ClassWriter.INT;
+ this.intVal = intVal;
+ this.hashCode = 0x7FFFFFFF & (type + intVal);
+ }
/**
* Indicates if the given item is equal to this one. This method assumes that the two items have the same
@@ -163,8 +174,6 @@ boolean isEqualTo(final Item i) {
case ClassWriter.INT:
case ClassWriter.FLOAT:
return i.intVal == intVal;
- case ClassWriter.TYPE_UNINIT:
- return i.intVal == intVal && i.strVal1.equals(strVal1);
case ClassWriter.NAME_TYPE:
return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
// case ClassWriter.FIELD:
diff --git a/src/main/java/com/alibaba/fastjson/asm/Label.java b/src/main/java/com/alibaba/fastjson/asm/Label.java
old mode 100644
new mode 100755
index 5adbd03e1c..0d1119c0c2
--- a/src/main/java/com/alibaba/fastjson/asm/Label.java
+++ b/src/main/java/com/alibaba/fastjson/asm/Label.java
@@ -47,7 +47,7 @@ public class Label {
/**
* Field used to associate user information to a label. Warning: this field is used by the ASM tree package. In
* order to use it with the ASM tree package you must override the
- * {@link com.alibaba.fastjson.asm.tree.MethodNode#getLabelNode} method.
+ *com.alibaba.fastjson.asm.tree.MethodNode#getLabelNode method.
*/
public Object info;
@@ -74,7 +74,7 @@ public class Label {
* reference, while the second is the position of the first byte of the forward reference itself. In fact the sign
* of the first integer indicates if this reference uses 2 or 4 bytes, and its absolute value gives the position of
* the bytecode instruction. This array is also used as a bitset to store the subroutines to which a basic block
- * belongs. This information is needed in {@linked MethodWriter#visitMaxs}, after all forward references have been
+ * belongs. This information is needed in MethodWriter#visitMaxs, after all forward references have been
* resolved. Hence the same array can be used for both purposes without problems.
*/
private int[] srcAndRefPositions;
@@ -90,7 +90,7 @@ public class Label {
* stack map frames are similar and use two steps. The first step, during the visit of each instruction, builds
* information about the state of the local variables and the operand stack at the end of each basic block, called
* the "output frame", relatively to the frame state at the beginning of the basic block, which is called the
- * "input frame", and which is unknown during this step. The second step, in {@link MethodWriter#visitMaxs},
+ * "input frame", and which is unknown during this step. The second step, in link MethodWriter#visitMaxs,
* is a fix point algorithm that computes information about the input frame of each basic block, from the input
* state of the first basic block (known from the method signature), and by the using the previously computed
* relative output frames. The algorithm used to compute the maximum stack size only computes the relative output
@@ -117,7 +117,7 @@ public class Label {
/**
* The successor of this label, in the order they are visited. This linked list does not include labels used for
- * debug info only. If {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it does not contain
+ * debug info only. If ClassWriter#COMPUTE_FRAMES option is used then, in addition, it does not contain
* successive labels that denote the same bytecode position (in this case only the first label appears in this
* list).
*/
@@ -204,45 +204,18 @@ private void addReference(final int sourcePosition, final int referencePosition)
* @throws IllegalArgumentException if this label has already been resolved, or if it has not been created by the
* given code writer.
*/
- boolean resolve(final MethodWriter owner, final int position, final byte[] data) {
- boolean needUpdate = false;
+ void resolve(final MethodWriter owner, final int position, final byte[] data) {
this.status |= RESOLVED;
this.position = position;
int i = 0;
while (i < referenceCount) {
int source = srcAndRefPositions[i++];
int reference = srcAndRefPositions[i++];
- int offset;
- if (source >= 0) {
- offset = position - source;
- if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
- /*
- * changes the opcode of the jump instruction, in order to be able to find it later (see
- * resizeInstructions in MethodWriter). These temporary opcodes are similar to jump instruction
- * opcodes, except that the 2 bytes offset is unsigned (and can therefore represent values from 0 to
- * 65535, which is sufficient since the size of a method is limited to 65535 bytes).
- */
- int opcode = data[reference - 1] & 0xFF;
- if (opcode <= Opcodes.JSR) {
- // changes IFEQ ... JSR to opcodes 202 to 217
- data[reference - 1] = (byte) (opcode + 49);
- } else {
- // changes IFNULL and IFNONNULL to opcodes 218 and 219
- data[reference - 1] = (byte) (opcode + 20);
- }
- needUpdate = true;
- }
- data[reference++] = (byte) (offset >>> 8);
- data[reference] = (byte) offset;
- } else {
- offset = position + source + 1;
- data[reference++] = (byte) (offset >>> 24);
- data[reference++] = (byte) (offset >>> 16);
- data[reference++] = (byte) (offset >>> 8);
- data[reference] = (byte) offset;
- }
+ int offset = position - source;
+ data[reference++] = (byte) (offset >>> 8);
+ data[reference] = (byte) offset;
+
}
- return needUpdate;
}
}
diff --git a/src/main/java/com/alibaba/fastjson/asm/MethodVisitor.java b/src/main/java/com/alibaba/fastjson/asm/MethodVisitor.java
old mode 100644
new mode 100755
index 1c916ddd16..cd45660d59
--- a/src/main/java/com/alibaba/fastjson/asm/MethodVisitor.java
+++ b/src/main/java/com/alibaba/fastjson/asm/MethodVisitor.java
@@ -30,15 +30,6 @@
package com.alibaba.fastjson.asm;
/**
- * A visitor to visit a Java method. The methods of this interface must be called in the following order: [
- * visitAnnotationDefault ] ( visitAnnotation | visitParameterAnnotation |
- * visitAttribute )* [ visitCode ( visitFrame | visitXInsn |
- * visitLabel | visitTryCatchBlock | visitLocalVariable | visitLineNumber)*
- * visitMaxs ] visitEnd. In addition, the visitXInsn and visitLabel
- * methods must be called in the sequential order of the bytecode instructions of the visited code,
- * visitTryCatchBlock must be called before the labels passed as arguments have been visited, and the
- * visitLocalVariable and visitLineNumber methods must be called after the labels passed as
- * arguments have been visited.
*
* @author Eric Bruneton
*/
diff --git a/src/main/java/com/alibaba/fastjson/asm/MethodWriter.java b/src/main/java/com/alibaba/fastjson/asm/MethodWriter.java
old mode 100644
new mode 100755
index 4ec9776ce0..4cb3fd364d
--- a/src/main/java/com/alibaba/fastjson/asm/MethodWriter.java
+++ b/src/main/java/com/alibaba/fastjson/asm/MethodWriter.java
@@ -144,11 +144,6 @@ class MethodWriter implements MethodVisitor {
*/
private int maxLocals;
- /**
- * Indicates if some jump instructions are too small and need to be resized.
- */
- private boolean resize;
-
// ------------------------------------------------------------------------
/*
@@ -286,7 +281,7 @@ public void visitJumpInsn(final int opcode, final Label label) {
public void visitLabel(final Label label) {
// resolves previous forward references to label, if any
- resize |= label.resolve(this, code.length, code.data);
+ label.resolve(this, code.length, code.data);
}
public void visitLdcInsn(final Object cst) {
@@ -305,11 +300,11 @@ public void visitLdcInsn(final Object cst) {
public void visitIincInsn(final int var, final int increment) {
// adds the instruction to the bytecode of the method
- if ((var > 255) || (increment > 127) || (increment < -128)) {
- code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var).putShort(increment);
- } else {
+// if ((var > 255) || (increment > 127) || (increment < -128)) {
+// code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var).putShort(increment);
+// } else {
code.putByte(Opcodes.IINC).put11(var, increment);
- }
+// }
}
public void visitMaxs(final int maxStack, final int maxLocals) {
@@ -338,10 +333,6 @@ public void visitEnd() {
* @return the size of the bytecode of this method.
*/
final int getSize() {
- if (resize) {
- // replaces the temporary jump opcodes introduced by Label.resolve.
- throw new UnsupportedOperationException();
- }
int size = 8;
if (code.length > 0) {
cw.newUTF8("Code");
diff --git a/src/main/java/com/alibaba/fastjson/asm/Opcodes.java b/src/main/java/com/alibaba/fastjson/asm/Opcodes.java
old mode 100644
new mode 100755
index cc9e9b6ac5..3126e5e5fb
--- a/src/main/java/com/alibaba/fastjson/asm/Opcodes.java
+++ b/src/main/java/com/alibaba/fastjson/asm/Opcodes.java
@@ -54,6 +54,8 @@ public interface Opcodes {
int ACC_PUBLIC = 0x0001; // class, field, method
int ACC_PRIVATE = 0x0002; // class, field, method
+ int ACC_STATIC = 0x0008; // field, method
+ int ACC_FINAL = 0x0010; // class, field, method
int ACC_SUPER = 0x0020; // class
int ACC_SYNTHETIC = 0x1000; // class, field, method
@@ -104,7 +106,7 @@ public interface Opcodes {
int DCONST_0 = 14; // -
int DCONST_1 = 15; // -
int BIPUSH = 16; // visitIntInsn
-// int SIPUSH = 17; // -
+ // int SIPUSH = 17; // -
int LDC = 18; // visitLdcInsn
// int LDC_W = 19; // -
// int LDC2_W = 20; // -
@@ -166,72 +168,72 @@ public interface Opcodes {
// int ASTORE_1 = 76; // -
// int ASTORE_2 = 77; // -
// int ASTORE_3 = 78; // -
- // int IASTORE = 79; // visitInsn
- // int LASTORE = 80; // -
- // int FASTORE = 81; // -
- // int DASTORE = 82; // -
- // int AASTORE = 83; // -
- // int BASTORE = 84; // -
- // int CASTORE = 85; // -
- // int SASTORE = 86; // -
+ // int IASTORE = 79; // visitInsn
+ // int LASTORE = 80; // -
+ // int FASTORE = 81; // -
+ // int DASTORE = 82; // -
+ // int AASTORE = 83; // -
+ // int BASTORE = 84; // -
+ // int CASTORE = 85; // -
+ // int SASTORE = 86; // -
int POP = 87; // -
int POP2 = 88; // -
int DUP = 89; // -
-// int DUP_X1 = 90; // -
-// int DUP_X2 = 91; // -
-// int DUP2 = 92; // -
-// int DUP2_X1 = 93; // -
-// int DUP2_X2 = 94; // -
-// int SWAP = 95; // -
+ // int DUP_X1 = 90; // -
+ // int DUP_X2 = 91; // -
+ // int DUP2 = 92; // -
+ // int DUP2_X1 = 93; // -
+ // int DUP2_X2 = 94; // -
+ // int SWAP = 95; // -
int IADD = 96; // -
int LADD = 97; // -
-// int FADD = 98; // -
-// int DADD = 99; // -
+ // int FADD = 98; // -
+ // int DADD = 99; // -
int ISUB = 100; // -
-// int LSUB = 101; // -
-// int FSUB = 102; // -
-// int DSUB = 103; // -
-// int IMUL = 104; // -
-// int LMUL = 105; // -
-// int FMUL = 106; // -
-// int DMUL = 107; // -
-// int IDIV = 108; // -
-// int LDIV = 109; // -
-// int FDIV = 110; // -
-// int DDIV = 111; // -
-// int IREM = 112; // -
-// int LREM = 113; // -
-// int FREM = 114; // -
-// int DREM = 115; // -
-// int INEG = 116; // -
-// int LNEG = 117; // -
-// int FNEG = 118; // -
-// int DNEG = 119; // -
-// int ISHL = 120; // -
-// int LSHL = 121; // -
-// int ISHR = 122; // -
-// int LSHR = 123; // -
-// int IUSHR = 124; // -
-// int LUSHR = 125; // -
-// int IAND = 126; // -
-// int LAND = 127; // -
-// int IOR = 128; // -
-// int LOR = 129; // -
-// int IXOR = 130; // -
-// int LXOR = 131; // -
+ // int LSUB = 101; // -
+ // int FSUB = 102; // -
+ // int DSUB = 103; // -
+ // int IMUL = 104; // -
+ // int LMUL = 105; // -
+ // int FMUL = 106; // -
+ // int DMUL = 107; // -
+ // int IDIV = 108; // -
+ // int LDIV = 109; // -
+ // int FDIV = 110; // -
+ // int DDIV = 111; // -
+ // int IREM = 112; // -
+ // int LREM = 113; // -
+ // int FREM = 114; // -
+ // int DREM = 115; // -
+ // int INEG = 116; // -
+ // int LNEG = 117; // -
+ // int FNEG = 118; // -
+ // int DNEG = 119; // -
+ // int ISHL = 120; // -
+ // int LSHL = 121; // -
+ // int ISHR = 122; // -
+ // int LSHR = 123; // -
+ // int IUSHR = 124; // -
+ // int LUSHR = 125; // -
+ int IAND = 126; // -
+ // int LAND = 127; // -
+ int IOR = 128; // -
+ // int LOR = 129; // -
+ // int IXOR = 130; // -
+ // int LXOR = 131; // -
int IINC = 132; // visitIincInsn
-// int I2L = 133; // visitInsn
-// int I2F = 134; // -
-// int I2D = 135; // -
-// int L2I = 136; // -
-// int L2F = 137; // -
-// int L2D = 138; // -
-// int F2I = 139; // -
-// int F2L = 140; // -
-// int F2D = 141; // -
-// int D2I = 142; // -
-// int D2L = 143; // -
-// int D2F = 144; // -
+ // int I2L = 133; // visitInsn
+ // int I2F = 134; // -
+ // int I2D = 135; // -
+ // int L2I = 136; // -
+ // int L2F = 137; // -
+ // int L2D = 138; // -
+ // int F2I = 139; // -
+ // int F2L = 140; // -
+ // int F2D = 141; // -
+ // int D2I = 142; // -
+ // int D2L = 143; // -
+ // int D2F = 144; // -
int I2B = 145; // -
int I2C = 146; // -
int I2S = 147; // -
@@ -257,12 +259,12 @@ public interface Opcodes {
int GOTO = 167; // -
int JSR = 168; // -
int RET = 169; // visitVarInsn
-// int TABLESWITCH = 170; // visiTableSwitchInsn
-// int LOOKUPSWITCH = 171; // visitLookupSwitch
+ // int TABLESWITCH = 170; // visiTableSwitchInsn
+ // int LOOKUPSWITCH = 171; // visitLookupSwitch
int IRETURN = 172; // visitInsn
-// int LRETURN = 173; // -
-// int FRETURN = 174; // -
-// int DRETURN = 175; // -
+ // int LRETURN = 173; // -
+ // int FRETURN = 174; // -
+ // int DRETURN = 175; // -
int ARETURN = 176; // -
int RETURN = 177; // -
int GETSTATIC = 178; // visitFieldInsn
@@ -275,16 +277,16 @@ public interface Opcodes {
int INVOKEINTERFACE = 185; // -
// int INVOKEDYNAMIC = 186; // -
int NEW = 187; // visitTypeInsn
-// int NEWARRAY = 188; // visitIntInsn
-// int ANEWARRAY = 189; // visitTypeInsn
-// int ARRAYLENGTH = 190; // visitInsn
-// int ATHROW = 191; // -
+ // int NEWARRAY = 188; // visitIntInsn
+ // int ANEWARRAY = 189; // visitTypeInsn
+ // int ARRAYLENGTH = 190; // visitInsn
+ // int ATHROW = 191; // -
int CHECKCAST = 192; // visitTypeInsn
int INSTANCEOF = 193; // -
-// int MONITORENTER = 194; // visitInsn
-// int MONITOREXIT = 195; // -
- // int WIDE = 196; // NOT VISITED
-// int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
+ // int MONITORENTER = 194; // visitInsn
+ // int MONITOREXIT = 195; // -
+ // int WIDE = 196; // NOT VISITED
+ // int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
int IFNULL = 198; // visitJumpInsn
int IFNONNULL = 199; // -
// int GOTO_W = 200; // -
diff --git a/src/main/java/com/alibaba/fastjson/asm/Type.java b/src/main/java/com/alibaba/fastjson/asm/Type.java
old mode 100644
new mode 100755
index cfc0751724..3be38c3d77
--- a/src/main/java/com/alibaba/fastjson/asm/Type.java
+++ b/src/main/java/com/alibaba/fastjson/asm/Type.java
@@ -38,57 +38,57 @@
public class Type {
/**
- * The sort of the void type. See {@link #getSort getSort}.
+ * The sort of the void type.
*/
public static final int VOID = 0;
/**
- * The sort of the boolean type. See {@link #getSort getSort}.
+ * The sort of the boolean type.
*/
public static final int BOOLEAN = 1;
/**
- * The sort of the char type. See {@link #getSort getSort}.
+ * The sort of the char type.
*/
public static final int CHAR = 2;
/**
- * The sort of the byte type. See {@link #getSort getSort}.
+ * The sort of the byte type.
*/
public static final int BYTE = 3;
/**
- * The sort of the short type. See {@link #getSort getSort}.
+ * The sort of the short type.
*/
public static final int SHORT = 4;
/**
- * The sort of the int type. See {@link #getSort getSort}.
+ * The sort of the int type.
*/
public static final int INT = 5;
/**
- * The sort of the float type. See {@link #getSort getSort}.
+ * The sort of the float type.
*/
public static final int FLOAT = 6;
/**
- * The sort of the long type. See {@link #getSort getSort}.
+ * The sort of the long type.
*/
public static final int LONG = 7;
/**
- * The sort of the double type. See {@link #getSort getSort}.
+ * The sort of the double type.
*/
public static final int DOUBLE = 8;
/**
- * The sort of array reference types. See {@link #getSort getSort}.
+ * The sort of array reference types.
*/
public static final int ARRAY = 9;
/**
- * The sort of object reference type. See {@link #getSort getSort}.
+ * The sort of object reference type.
*/
public static final int OBJECT = 10;
@@ -192,14 +192,6 @@ public static Type getType(final String typeDescriptor) {
return getType(typeDescriptor.toCharArray(), 0);
}
- /**
- * Computes the size of the arguments and of the return value of a method.
- *
- * @param desc the descriptor of a method.
- * @return the size of the arguments of the method (plus one for the implicit this argument), argSize, and the size
- * of its return value, retSize, packed into a single int i = (argSize << 2) | retSize (argSize is
- * therefore equal to i >> 2, and retSize to i & 0x03).
- */
public static int getArgumentsAndReturnSizes(final String desc) {
int n = 1;
int c = 1;
@@ -212,13 +204,13 @@ public static int getArgumentsAndReturnSizes(final String desc) {
while (desc.charAt(c++) != ';') {
}
n += 1;
- } else if (car == '[') {
- while ((car = desc.charAt(c)) == '[') {
- ++c;
- }
- if (car == 'D' || car == 'J') {
- n -= 1;
- }
+// } else if (car == '[') {
+// while ((car = desc.charAt(c)) == '[') {
+// ++c;
+// }
+// if (car == 'D' || car == 'J') {
+// n -= 1;
+// }
} else if (car == 'D' || car == 'J') {
n += 2;
} else {
@@ -312,20 +304,7 @@ public String getInternalName() {
*
* @return the descriptor corresponding to this Java type.
*/
- public String getDescriptor() {
- StringBuffer buf = new StringBuffer();
-
- if (this.buf == null) {
- // descriptor is in byte 3 of 'off' for primitive types (buf == null)
- buf.append((char) ((off & 0xFF000000) >>> 24));
- } else if (sort == ARRAY) {
- buf.append(this.buf, off, len);
- } else { // sort == OBJECT
- buf.append('L');
- buf.append(this.buf, off, len);
- buf.append(';');
- }
-
- return buf.toString();
+ String getDescriptor() {
+ return new String(this.buf, off, len);
}
}
diff --git a/src/main/java/com/alibaba/fastjson/asm/package.html b/src/main/java/com/alibaba/fastjson/asm/package.html
deleted file mode 100644
index fd6caf73f6..0000000000
--- a/src/main/java/com/alibaba/fastjson/asm/package.html
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-
- Provides a small and fast bytecode manipulation framework.
-
-
- The ASM framework is
- organized around the {@link org.objectweb.asm.ClassVisitor
- ClassVisitor}, {@link org.objectweb.asm.FieldVisitor FieldVisitor} and
- {@link org.objectweb.asm.MethodVisitor MethodVisitor} interfaces,
- which allow one to visit the fields and methods of a class, including
- the bytecode instructions of each method.
-
In addition to these main interfaces, ASM provides a {@link
- org.objectweb.asm.ClassReader ClassReader} class, that can parse an
- existing class and make a given visitor visit it. ASM also provides a
- {@link org.objectweb.asm.ClassWriter ClassWriter} class, which is a
- visitor that generates Java class files.
-
- In order to generate a class from scratch, only the {@link
- org.objectweb.asm.ClassWriter ClassWriter} class is necessary. Indeed,
- in order to generate a class, one must just call its visitXXX
- methods with the appropriate arguments to generate the desired fields
- and methods. See the "helloworld" example in the ASM distribution for
- more details about class generation.
-
In order to modify existing classes, one must use a {@link
- org.objectweb.asm.ClassReader ClassReader} class to analyze the
- original class, a class modifier, and a {@link
- org.objectweb.asm.ClassWriter ClassWriter} to construct the modified
- class. The class modifier is just a {@link
- org.objectweb.asm.ClassVisitor ClassVisitor} that delegates most of
- the work to another {@link org.objectweb.asm.ClassVisitor
- ClassVisitor}, but that sometimes changes some parameter values, or
- call additional methods, in order to implement the desired
- modification process. In order to make it easier to implement such
- class modifiers, ASM provides the {@link
- org.objectweb.asm.ClassAdapter ClassAdapter} and {@link
- org.objectweb.asm.MethodAdapter MethodAdapter} classes, which
- implement the {@link org.objectweb.asm.ClassVisitor ClassVisitor} and
- {@link org.objectweb.asm.MethodVisitor MethodVisitor} interfaces by
- delegating all work to other visitors. See the "adapt" example in the
- ASM distribution for more details about class modification.
-
- The size of the core ASM library,
- asm.jar
- , is only 42KB, which is much smaller than the size of the BCEL library (504KB), and
- than the size of the SERP
- library (150KB). ASM is also much faster than these tools. Indeed the
- overhead of a load time class transformation process is of the order
- of 60% with ASM, 700% or more with BCEL, and 1100% or more with SERP
- (see the
- test/perf
- directory in the ASM distribution)! @since ASM 1.3
-
-
diff --git a/src/main/java/com/alibaba/fastjson/codegen/ClassGen.java b/src/main/java/com/alibaba/fastjson/codegen/ClassGen.java
new file mode 100644
index 0000000000..20baebf86c
--- /dev/null
+++ b/src/main/java/com/alibaba/fastjson/codegen/ClassGen.java
@@ -0,0 +1,105 @@
+package com.alibaba.fastjson.codegen;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+
+public abstract class ClassGen {
+
+ protected Class> clazz;
+ protected Type type;
+ protected Appendable out;
+
+ private String indent = "\t";
+ private int indentCount = 0;
+
+ public ClassGen(Class> clazz, Appendable out){
+ this(clazz, null, out);
+ }
+
+ public ClassGen(Class> clazz, Type type, Appendable out){
+ this.clazz = clazz;
+ this.type = type;
+ this.out = out;
+ }
+
+ public abstract void gen() throws IOException;
+
+ protected void println() throws IOException {
+ out.append("\n");
+ printIndent();
+ }
+
+ protected void println(String text) throws IOException {
+ out.append(text);
+ out.append("\n");
+ printIndent();
+ }
+
+ protected void print(String text) throws IOException {
+ out.append(text);
+ }
+
+ protected void printPackage() throws IOException {
+ print("package ");
+ print(clazz.getPackage().getName());
+ println(";");
+ }
+
+ protected void beginClass(String className) throws IOException {
+ print("public class ");
+ print(className);
+ print(" implements ObjectDeserializer {");
+ incrementIndent();
+ println();
+ }
+
+ protected void endClass() throws IOException {
+ decrementIndent();
+ println();
+ print("}");
+ println();
+ }
+
+ protected void genField(String name, Class> feildClass) throws IOException {
+ if (feildClass == char[].class) {
+ print("char[]");
+ }
+
+ print(" ");
+ print(name);
+ println(";");
+ }
+
+ protected void beginInit(String className) throws IOException {
+ print("public ");
+ print(className);
+ println(" () {");
+ incrementIndent();
+ }
+
+ protected void endInit() throws IOException {
+ decrementIndent();
+ print("}");
+ println();
+ }
+
+ public void decrementIndent() {
+ this.indentCount -= 1;
+ }
+
+ public void incrementIndent() {
+ this.indentCount += 1;
+ }
+
+ public void printIndent() throws IOException {
+ for (int i = 0; i < this.indentCount; ++i) {
+ print(this.indent);
+ }
+ }
+
+ protected void printClassName(Class> clazz) throws IOException {
+ String name = clazz.getName();
+ name = name.replace('$', '.');
+ print(name);
+ }
+}
diff --git a/src/main/java/com/alibaba/fastjson/codegen/DeserializerGen.java b/src/main/java/com/alibaba/fastjson/codegen/DeserializerGen.java
new file mode 100644
index 0000000000..621844c91f
--- /dev/null
+++ b/src/main/java/com/alibaba/fastjson/codegen/DeserializerGen.java
@@ -0,0 +1,649 @@
+package com.alibaba.fastjson.codegen;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.TreeSet;
+
+import com.alibaba.fastjson.util.DeserializeBeanInfo;
+import com.alibaba.fastjson.util.FieldInfo;
+import com.alibaba.fastjson.util.TypeUtils;
+
+public class DeserializerGen extends ClassGen {
+
+ private DeserializeBeanInfo beanInfo;
+ private String genClassName;
+
+ public DeserializerGen(Class> clazz, Appendable out){
+ super(clazz, out);
+ }
+
+ @Override
+ public void gen() throws IOException {
+ beanInfo = DeserializeBeanInfo.computeSetters(clazz, type);
+ genClassName = clazz.getSimpleName() + "GenDecoder";
+
+ print("package ");
+ print(clazz.getPackage().getName());
+ println(";");
+ println();
+
+ println("import java.lang.reflect.Type;");
+ println();
+
+ println("import com.alibaba.fastjson.parser.DefaultJSONParser;");
+ println("import com.alibaba.fastjson.parser.DefaultJSONParser.ResolveTask;");
+ println("import com.alibaba.fastjson.parser.ParserConfig;");
+ println("import com.alibaba.fastjson.parser.Feature;");
+ println("import com.alibaba.fastjson.parser.JSONLexerBase;");
+ println("import com.alibaba.fastjson.parser.JSONToken;");
+ println("import com.alibaba.fastjson.parser.ParseContext;");
+ println("import com.alibaba.fastjson.parser.deserializer.ASMJavaBeanDeserializer;");
+ println("import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;");
+ println();
+
+ print("public class ");
+ print(genClassName);
+ print(" extends ASMJavaBeanDeserializer implements ObjectDeserializer {");
+ incrementIndent();
+ println();
+
+ genConstructor();
+
+ genCreateInstance();
+
+ genDeserialze();
+
+ endClass();
+ }
+
+ protected void genCreateInstance() throws IOException {
+ println();
+ print("public Object createInstance(DefaultJSONParser parser, Type type) {");
+ incrementIndent();
+ println();
+
+ print("return new ");
+ print(clazz.getSimpleName());
+ print("();");
+ println();
+
+ decrementIndent();
+ println();
+ print("}");
+ }
+
+ protected void genDeserialze() throws IOException {
+ if (beanInfo.getFieldList().size() == 0) {
+ return;
+ }
+
+ for (FieldInfo fieldInfo : beanInfo.getFieldList()) {
+ Class> fieldClass = fieldInfo.getFieldClass();
+ Type fieldType = fieldInfo.getFieldType();
+
+ if (fieldClass == char.class) {
+ return;
+ }
+
+ if (Collection.class.isAssignableFrom(fieldClass)) {
+ if (fieldType instanceof ParameterizedType) {
+ Type itemType = ((ParameterizedType) fieldType).getActualTypeArguments()[0];
+ if (itemType instanceof Class) {
+ continue;
+ } else {
+ return;
+ }
+ } else {
+ return;
+ }
+ }
+ }
+
+ List fieldList = new ArrayList(beanInfo.getFieldList());
+ Collections.sort(fieldList);
+
+ println();
+ print("public Object deserialze(DefaultJSONParser parser, Type type, Object fieldName) {");
+ incrementIndent();
+ println();
+
+ println("JSONLexerBase lexer = (JSONLexerBase) parser.getLexer();");
+ println();
+
+ println("if (!lexer.isEnabled(Feature.SortFeidFastMatch)) {");
+ println("\treturn super.deserialze(parser, type, fieldName);");
+ println("}");
+
+ println();
+
+ println("if (isSupportArrayToBean(lexer)) {");
+ println("\t// deserialzeArrayMapping");
+ println("}");
+
+ println();
+ println("if (lexer.scanType(\"Department\") == JSONLexerBase.NOT_MATCH) {");
+ println("\treturn super.deserialze(parser, type, fieldName);");
+ println("}");
+
+ println();
+
+ println("ParseContext mark_context = parser.getContext();");
+ println("int matchedCount = 0;");
+
+ print(clazz.getSimpleName());
+ print(" instance = ");
+ Constructor> defaultConstructor = beanInfo.getDefaultConstructor();
+ if (Modifier.isPublic(defaultConstructor.getModifiers())) {
+ print("new ");
+ print(clazz.getSimpleName());
+ println("();");
+ } else {
+ print("(");
+ print(clazz.getSimpleName());
+ print(") createInstance(parser);");
+ }
+
+ println();
+
+ println("ParseContext context = parser.getContext();");
+ println("ParseContext childContext = parser.setContext(context, instance, fieldName);");
+
+ println();
+
+ println("if (lexer.matchStat == JSONLexerBase.END) {");
+ println("\treturn instance;");
+ println("}");
+
+ println();
+
+ println("int matchStat = 0;");
+
+ int fieldListSize = fieldList.size();
+ for (int i = 0; i < fieldListSize; i += 32) {
+ print("int _asm_flag_");
+ print(Integer.toString(i / 32));
+ println(" = 0;");
+ }
+
+ for (int i = 0; i < fieldListSize; ++i) {
+ FieldInfo fieldInfo = fieldList.get(i);
+ Class> fieldClass = fieldInfo.getFieldClass();
+
+ if (fieldClass == boolean.class) {
+ print("boolean ");
+ printFieldVarName(fieldInfo);
+ println(" = false;");
+ } else if (fieldClass == byte.class //
+ || fieldClass == short.class //
+ || fieldClass == int.class //
+ || fieldClass == long.class //
+ || fieldClass == float.class //
+ || fieldClass == double.class //
+ ) {
+ print(fieldClass.getSimpleName());
+ print(" ");
+ printFieldVarName(fieldInfo);
+ println(" = 0;");
+ } else {
+ if (fieldClass == String.class) {
+ print("String ");
+ printFieldVarName(fieldInfo);
+ println(";");
+
+ println("if (lexer.isEnabled(Feature.InitStringFieldAsEmpty)) {");
+ print("\t");
+ printFieldVarName(fieldInfo);
+ println(" = lexer.stringDefaultValue();");
+ print("\t");
+ genSetFlag(i);
+ println("} else {");
+ print("\t");
+ printFieldVarName(fieldInfo);
+ println(" = null;");
+ println("}");
+ } else {
+ printClassName(fieldClass);
+ print(" ");
+ printFieldVarName(fieldInfo);
+ print(" = null;");
+ println();
+ }
+ }
+ }
+
+ println("boolean endFlag = false, restFlag = false;");
+ println();
+
+ for (int i = 0; i < fieldListSize; ++i) {
+ print("if ((!endFlag) && (!restFlag)) {");
+ incrementIndent();
+ println();
+
+ FieldInfo fieldInfo = fieldList.get(i);
+ Class> fieldClass = fieldInfo.getFieldClass();
+ Type fieldType = fieldInfo.getFieldType();
+
+ if (fieldClass == boolean.class) {
+ printFieldVarName(fieldInfo);
+ print(" = lexer.scanFieldBoolean(");
+ printFieldPrefix(fieldInfo);
+ println(");");
+ } else if (fieldClass == byte.class || fieldClass == short.class || fieldClass == int.class) {
+ printFieldVarName(fieldInfo);
+ print(" = lexer.scanFieldInt(");
+ printFieldPrefix(fieldInfo);
+ println(");");
+ } else if (fieldClass == long.class) {
+ printFieldVarName(fieldInfo);
+ print(" = lexer.scanFieldLong(");
+ printFieldPrefix(fieldInfo);
+ println(");");
+ } else if (fieldClass == float.class) {
+ printFieldVarName(fieldInfo);
+ print(" = lexer.scanFieldFloat(");
+ printFieldPrefix(fieldInfo);
+ println(");");
+ } else if (fieldClass == double.class) {
+ printFieldVarName(fieldInfo);
+ print(" = lexer.scanFieldDouble(");
+ printFieldPrefix(fieldInfo);
+ println(");");
+ } else if (fieldClass == String.class) {
+ printFieldVarName(fieldInfo);
+ print(" = lexer.scanFieldString(");
+ printFieldPrefix(fieldInfo);
+ println(");");
+ } else if (fieldClass.isEnum()) {
+ print("String ");
+ printFieldVarEnumName(fieldInfo);
+
+ print(" = lexer.scanFieldSymbol(");
+ printFieldPrefix(fieldInfo);
+ println(", parser.getSymbolTable());");
+
+ print("if (");
+ printFieldVarEnumName(fieldInfo);
+ println(" == null) {");
+ print("\t");
+ printFieldVarName(fieldInfo);
+ print(" = ");
+ printClassName(fieldClass);
+ print(".valueOf(");
+ printFieldVarEnumName(fieldInfo);
+ println(");");
+ println("}");
+ } else if (Collection.class.isAssignableFrom(fieldClass)) {
+ Class> itemClass = TypeUtils.getCollectionItemClass(fieldType);
+
+ if (itemClass == String.class) {
+ printFieldVarName(fieldInfo);
+ print(" = (");
+ printClassName(fieldClass);
+ print(") lexer.scanFieldStringArray(");
+ printFieldPrefix(fieldInfo);
+ print(", ");
+ printClassName(fieldClass);
+ print(".class);");
+ println();
+ } else {
+ genDeserialzeList(fieldInfo, i, itemClass);
+ if (i == fieldListSize - 1) {
+ genEndCheck();
+ }
+ }
+ } else {
+ genDeserialzeObject(fieldInfo, i);
+
+ if (i == fieldListSize - 1) {
+ genEndCheck();
+ }
+ }
+
+ println("if(lexer.matchStat > 0) {");
+ print("\t");
+ genSetFlag(i);
+ println("\tmatchedCount++;");
+ println("}");
+
+ println("if(lexer.matchStat == JSONLexerBase.NOT_MATCH) {");
+ println("\trestFlag = true;");
+ println("}");
+
+
+ println("if(lexer.matchStat != JSONLexerBase.END) {");
+ println("\tendFlag = true;");
+ println("}");
+
+
+ decrementIndent();
+ println();
+ println("}");
+ }
+
+ genBatchSet(fieldList, true);
+
+ println();
+ println("if (restFlag) {");
+ println("\treturn super.parseRest(parser, type, fieldName, instance);");
+ println("}");
+
+ println();
+ print("return instance;");
+ println();
+
+ decrementIndent();
+ println();
+ print("}");
+ }
+
+ private void genBatchSet(List fieldList, boolean flag) throws IOException {
+ for (int i = 0, size = fieldList.size(); i < size; ++i) {
+ FieldInfo fieldInfo = fieldList.get(i);
+
+ String varName = "_asm_flag_" + (i / 32);
+ if (flag) {
+ print("if ((");
+ print(varName);
+ print(" & ");
+ print(Integer.toString(1 << i));
+ print(") != 0) {");
+ println();
+ incrementIndent();
+ }
+
+ if (fieldInfo.getMethod() != null) {
+ print("\tinstance.");
+ print(fieldInfo.getMethod().getName());
+ print("(");
+ printFieldVarName(fieldInfo);
+ println(");");
+ } else {
+ print("\tinstance.");
+ print(fieldInfo.getField().getName());
+ print(" = ");
+ printFieldVarName(fieldInfo);
+ println(";");
+ }
+
+ if (flag) {
+ decrementIndent();
+ println();
+ println("}");
+ }
+ }
+ }
+
+ private void genEndCheck() throws IOException {
+ println("if (matchedCount <= 0 || lexer.token() != JSONToken.RBRACE) {");
+ println("\trestFlag = true;");
+ println("} else if (lexer.token() == JSONToken.COMMA) {");
+ println("\tlexer.nextToken();");
+ println("}");
+ }
+
+ protected void genDeserialzeList(FieldInfo fieldInfo, int i, Class> itemClass) throws IOException {
+ print("if (lexer.matchField(");
+ printFieldPrefix(fieldInfo);
+ print(")) {");
+ println();
+ print("\t");
+ genSetFlag(i);
+ println("\tif (lexer.token() == JSONToken.NULL) {");
+ println("\t\tlexer.nextToken(JSONToken.COMMA);");
+ println("\t} else {");
+ println("\t\tif (lexer.token() == JSONToken.LBRACKET) {");
+ print("\t\t\tif(");
+ printListFieldItemDeser(fieldInfo);
+ print(" == null) {");
+ println();
+
+ print("\t\t\t\t");
+ printListFieldItemDeser(fieldInfo);
+ print(" = parser.getConfig().getDeserializer(");
+ printClassName(itemClass);
+ print(".class);");
+ println();
+
+ print("\t\t\t}");
+ println();
+
+ print("\t\t\tfinal int fastMatchToken = ");
+ printListFieldItemDeser(fieldInfo);
+ print(".getFastMatchToken();");
+ println();
+ println("\t\t\tlexer.nextToken(fastMatchToken);");
+
+ // _newCollection
+ print("\t\t\t");
+ printFieldVarName(fieldInfo);
+ print(" = ");
+ Class> fieldClass = fieldInfo.getFieldClass();
+ if (fieldClass.isAssignableFrom(ArrayList.class)) {
+ print("new java.util.ArrayList();");
+ } else if (fieldClass.isAssignableFrom(LinkedList.class)) {
+ print("new java.util.LinkedList();");
+ } else if (fieldClass.isAssignableFrom(HashSet.class)) {
+ print("new java.util.HashSet();");
+ } else if (fieldClass.isAssignableFrom(TreeSet.class)) {
+ print("new java.util.TreeSet();");
+ } else {
+ print("new ");
+ printClassName(fieldClass);
+ print("();");
+ }
+ println();
+
+ println("\t\t\tParseContext listContext = parser.getContext();");
+ print("\t\t\tparser.setContext(");
+ printFieldVarName(fieldInfo);
+ print(", \"");
+ print(fieldInfo.getName());
+ print("\");");
+ println();
+
+ println();
+ println("\t\t\tfor(int i = 0; ;++i) {");
+
+ println("\t\t\t\tif (lexer.token() == JSONToken.RBRACKET) {");
+ println("\t\t\t\t\tbreak;");
+ println("\t\t\t\t}");
+ print("\t\t\t\t");
+ printClassName(itemClass);
+ print(" itemValue = ");
+ printListFieldItemDeser(fieldInfo);
+ print(".deserialze(parser, ");
+ printListFieldItemType(fieldInfo);
+ println(", i);");
+
+ print("\t\t\t\t");
+ printFieldVarName(fieldInfo);
+ println(".add(itemValue);");
+
+ print("\t\t\t\tparser.checkListResolve(");
+ printFieldVarName(fieldInfo);
+ println(");");
+
+ println("\t\t\t\tif (lexer.token() == JSONToken.COMMA) {");
+ println("\t\t\t\t\tlexer.nextToken(fastMatchToken);");
+ println("\t\t\t\t}");
+
+ // end for
+ println("\t\t\t}");
+
+ println("\t\t\tparser.setContext(listContext);");
+
+ println("\t\t\tif (lexer.token() != JSONToken.RBRACKET) {");
+ println("\t\t\t\trestFlag = true;");
+ println("\t\t\t}");
+ println("\t\t\tlexer.nextToken(JSONToken.COMMA);");
+
+ println();
+ println("\t\t} else {");
+ println("\t\t\trestFlag = true;");
+ println("\t\t}");
+ println("\t}");
+ println("}");
+ }
+
+ protected void genDeserialzeObject(FieldInfo fieldInfo, int i) throws IOException {
+ print("if (lexer.matchField(");
+ printFieldPrefix(fieldInfo);
+ print(")) {");
+ println();
+ print("\t");
+ genSetFlag(i);
+ println("\tmatchedCount++;");
+
+ // _deserObject
+ print("if (");
+ printFieldDeser(fieldInfo);
+ print(" == null) {");
+ println();
+
+ print("\t");
+ printFieldDeser(fieldInfo);
+ print(" = parser.getConfig().getDeserializer(");
+ printClassName(fieldInfo.getFieldClass());
+ println(".class);");
+ println("}");
+
+ print("\t");
+ printFieldDeser(fieldInfo);
+ print(".deserialze(parser, ");
+ if (fieldInfo.getFieldType() instanceof Class) {
+ printClassName(fieldInfo.getFieldClass());
+ print(".class");
+ } else {
+ print("getFieldType(\"");
+ println(fieldInfo.getName());
+ print("\")");
+ }
+ print(",\"");
+ print(fieldInfo.getName());
+ println("\");");
+
+ println("\tif(parser.getResolveStatus() == DefaultJSONParser.NeedToResolve) {");
+ println("\t\tResolveTask resolveTask = parser.getLastResolveTask();");
+ println("\t\tresolveTask.setOwnerContext(parser.getContext());");
+ print("\t\tresolveTask.setFieldDeserializer(this.getFieldDeserializer(\"");
+ print(fieldInfo.getName());
+ println("\"));");
+ println("\t\tparser.setResolveStatus(DefaultJSONParser.NONE);");
+ println("\t}");
+ println("}");
+ }
+
+ private void printFieldVarName(FieldInfo fieldInfo) throws IOException {
+ print(fieldInfo.getName());
+ print("_gen");
+ }
+
+ private void printFieldVarEnumName(FieldInfo fieldInfo) throws IOException {
+ print(fieldInfo.getName());
+ print("_gen_enum_name");
+ }
+
+ private void printFieldPrefix(FieldInfo fieldInfo) throws IOException {
+ print(fieldInfo.getName());
+ print("_gen_prefix__");
+ }
+
+ private void printListFieldItemDeser(FieldInfo fieldInfo) throws IOException {
+ print(fieldInfo.getName());
+ print("_gen_list_item_deser__");
+ }
+
+ private void printFieldDeser(FieldInfo fieldInfo) throws IOException {
+ print(fieldInfo.getName());
+ print("_gen_deser__");
+ }
+
+ private void printListFieldItemType(FieldInfo fieldInfo) throws IOException {
+ print(fieldInfo.getName());
+ print("_gen_list_item_type__");
+ }
+
+ private void genSetFlag(int flag) throws IOException {
+ String varName = "_asm_flag_" + (flag / 32);
+ print(varName);
+ print(" |= ");
+ print(Integer.toString(1 << flag));
+ print(";");
+ println();
+ }
+
+ protected void genConstructor() throws IOException {
+ for (int i = 0, size = beanInfo.getFieldList().size(); i < size; ++i) {
+ FieldInfo fieldInfo = beanInfo.getFieldList().get(i);
+ print("private char[] ");
+ printFieldPrefix(fieldInfo);
+ print(" = \"\\\"");
+ print(fieldInfo.getName());
+ print("\\\":\".toCharArray();");
+ println();
+ }
+
+ println();
+
+ boolean fieldDeserFlag = false;
+ for (int i = 0, size = beanInfo.getFieldList().size(); i < size; ++i) {
+ FieldInfo fieldInfo = beanInfo.getFieldList().get(i);
+ Class> fieldClass = fieldInfo.getFieldClass();
+
+ if (fieldClass.isPrimitive()) {
+ continue;
+ }
+
+ if (fieldClass.isEnum()) {
+ continue;
+ }
+
+ print("private ObjectDeserializer ");
+
+ if (Collection.class.isAssignableFrom(fieldClass)) {
+ printListFieldItemDeser(fieldInfo);
+ } else {
+ printFieldDeser(fieldInfo);
+ }
+ println(";");
+ fieldDeserFlag = true;
+
+ if (Collection.class.isAssignableFrom(fieldClass)) {
+ print("private Type ");
+ printListFieldItemType(fieldInfo);
+ print(" = ");
+ Class> fieldItemClass = TypeUtils.getCollectionItemClass(fieldInfo.getFieldType());
+ printClassName(fieldItemClass);
+ println(".class;");
+ }
+ }
+
+ if (fieldDeserFlag) {
+ println();
+ }
+
+ // constructor
+ print("public ");
+ print(genClassName);
+ print(" (ParserConfig config, Class clazz) {");
+ incrementIndent();
+ println();
+
+ println("super(config, clazz);");
+
+ decrementIndent();
+ println();
+ print("}");
+ println();
+ }
+
+}
diff --git a/src/main/java/com/alibaba/fastjson/parser/AbstractJSONParser.java b/src/main/java/com/alibaba/fastjson/parser/AbstractJSONParser.java
old mode 100644
new mode 100755
index e6e084653a..0de9a99082
--- a/src/main/java/com/alibaba/fastjson/parser/AbstractJSONParser.java
+++ b/src/main/java/com/alibaba/fastjson/parser/AbstractJSONParser.java
@@ -1,224 +1,5 @@
package com.alibaba.fastjson.parser;
-import static com.alibaba.fastjson.parser.JSONToken.EOF;
-import static com.alibaba.fastjson.parser.JSONToken.FALSE;
-import static com.alibaba.fastjson.parser.JSONToken.LBRACE;
-import static com.alibaba.fastjson.parser.JSONToken.LBRACKET;
-import static com.alibaba.fastjson.parser.JSONToken.LITERAL_FLOAT;
-import static com.alibaba.fastjson.parser.JSONToken.LITERAL_INT;
-import static com.alibaba.fastjson.parser.JSONToken.LITERAL_STRING;
-import static com.alibaba.fastjson.parser.JSONToken.NEW;
-import static com.alibaba.fastjson.parser.JSONToken.NULL;
-import static com.alibaba.fastjson.parser.JSONToken.RBRACKET;
-import static com.alibaba.fastjson.parser.JSONToken.TRUE;
-
-import java.util.Collection;
-import java.util.Date;
-import java.util.Map;
-
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONException;
-import com.alibaba.fastjson.JSONObject;
-
public abstract class AbstractJSONParser {
- @SuppressWarnings("rawtypes")
- public abstract void parseObject(final Map object);
-
- public JSONObject parseObject() {
- JSONObject object = new JSONObject();
- parseObject(object);
- return object;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public final void parseArray(final Collection array) {
- final JSONLexer lexer = getLexer();
-
- if (lexer.token() != JSONToken.LBRACKET) {
- throw new JSONException("syntax error, expect [, actual "
- + JSONToken.name(lexer.token()));
- }
-
- lexer.nextToken(JSONToken.LITERAL_STRING);
-
- for (;;) {
- if (isEnabled(Feature.AllowArbitraryCommas)) {
- while (lexer.token() == JSONToken.COMMA) {
- lexer.nextToken();
- continue;
- }
- }
-
- Object value;
- switch (lexer.token()) {
- case LITERAL_INT:
- value = lexer.integerValue();
- lexer.nextToken(JSONToken.COMMA);
- break;
- case LITERAL_FLOAT:
- if (lexer.isEnabled(Feature.UseBigDecimal)) {
- value = lexer.decimalValue();
- } else {
- value = lexer.doubleValue();
- }
- lexer.nextToken(JSONToken.COMMA);
- break;
- case LITERAL_STRING:
- String stringLiteral = lexer.stringVal();
- lexer.nextToken(JSONToken.COMMA);
-
- if (lexer.isEnabled(Feature.AllowISO8601DateFormat)) {
- JSONScanner iso8601Lexer = new JSONScanner(stringLiteral);
- if (iso8601Lexer.scanISO8601DateIfMatch()) {
- value = iso8601Lexer.getCalendar().getTime();
- } else {
- value = stringLiteral;
- }
- } else {
- value = stringLiteral;
- }
-
- break;
- case TRUE:
- value = Boolean.TRUE;
- lexer.nextToken(JSONToken.COMMA);
- break;
- case FALSE:
- value = Boolean.FALSE;
- lexer.nextToken(JSONToken.COMMA);
- break;
- case LBRACE:
- JSONObject object = new JSONObject();
- parseObject(object);
- value = object;
- break;
- case LBRACKET:
- Collection items = new JSONArray();
- parseArray(items);
- value = items;
- break;
- case NULL:
- value = null;
- lexer.nextToken(JSONToken.LITERAL_STRING);
- break;
- case RBRACKET:
- lexer.nextToken(JSONToken.COMMA);
- return;
- default:
- value = parse();
- break;
- }
-
- array.add(value);
-
- if (lexer.token() == JSONToken.COMMA) {
- lexer.nextToken(JSONToken.LITERAL_STRING);
- continue;
- }
- }
- }
-
- public Object parse() {
- final JSONLexer lexer = getLexer();
- switch (lexer.token()) {
- case LBRACKET:
- JSONArray array = new JSONArray();
- parseArray(array);
- return array;
- case LBRACE:
- JSONObject object = new JSONObject();
- parseObject(object);
- return object;
- case LITERAL_INT:
- Number intValue = lexer.integerValue();
- lexer.nextToken();
- return intValue;
- case LITERAL_FLOAT:
-
- Object value;
- if (isEnabled(Feature.UseBigDecimal)) {
- value = lexer.decimalValue();
- } else {
- value = lexer.doubleValue();
- }
- lexer.nextToken();
- return value;
- case LITERAL_STRING:
- String stringLiteral = lexer.stringVal();
- lexer.nextToken(JSONToken.COMMA);
-
- if (lexer.isEnabled(Feature.AllowISO8601DateFormat)) {
- JSONScanner iso8601Lexer = new JSONScanner(stringLiteral);
- if (iso8601Lexer.scanISO8601DateIfMatch()) {
- return iso8601Lexer.getCalendar().getTime();
- }
- }
-
- return stringLiteral;
- case NULL:
- lexer.nextToken();
- return null;
- case TRUE:
- lexer.nextToken();
- return Boolean.TRUE;
- case FALSE:
- lexer.nextToken();
- return Boolean.FALSE;
- case NEW:
- lexer.nextToken(JSONToken.IDENTIFIER);
-
- if (lexer.token() != JSONToken.IDENTIFIER) {
- throw new JSONException("syntax error");
- }
- lexer.nextToken(JSONToken.LPAREN);
-
- accept(JSONToken.LPAREN);
- long time = ((Number) lexer.integerValue()).longValue();
- accept(JSONToken.LITERAL_INT);
-
- accept(JSONToken.RPAREN);
-
- return new Date(time);
- case EOF:
- if (lexer.isBlankInput()) {
- return null;
- }
- default:
- throw new JSONException("TODO " + JSONToken.name(lexer.token())
- + " " + lexer.stringVal());
- }
- }
-
- public void config(Feature feature, boolean state) {
- getLexer().config(feature, state);
- }
-
- public boolean isEnabled(Feature feature) {
- return getLexer().isEnabled(feature);
- }
-
- public abstract JSONLexer getLexer();
-
- public final void accept(final int token) {
- final JSONLexer lexer = getLexer();
- if (lexer.token() == token) {
- lexer.nextToken();
- } else {
- throw new JSONException("syntax error, expect "
- + JSONToken.name(token) + ", actual "
- + JSONToken.name(lexer.token()));
- }
- }
-
- public void close() {
- final JSONLexer lexer = getLexer();
-
- if (isEnabled(Feature.AutoCloseSource)) {
- if (!lexer.isEOF()) {
- throw new JSONException("not close json text, token : "
- + JSONToken.name(lexer.token()));
- }
- }
- }
}
diff --git a/src/main/java/com/alibaba/fastjson/parser/CharTypes.java b/src/main/java/com/alibaba/fastjson/parser/CharTypes.java
deleted file mode 100644
index c3ab3df2b2..0000000000
--- a/src/main/java/com/alibaba/fastjson/parser/CharTypes.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 1999-2101 Alibaba Group.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.alibaba.fastjson.parser;
-
-/**
- * @author wenshao
- */
-public final class CharTypes {
-
- public final static boolean[] firstIdentifierFlags = new boolean[256];
- static {
- for (char c = 0; c < firstIdentifierFlags.length; ++c) {
- if (c >= 'A' && c <= 'Z') {
- firstIdentifierFlags[c] = true;
- } else if (c >= 'a' && c <= 'z') {
- firstIdentifierFlags[c] = true;
- } else if (c == '_') {
- firstIdentifierFlags[c] = true;
- }
- }
- }
-
- public final static boolean[] identifierFlags = new boolean[256];
-
- static {
- for (char c = 0; c < identifierFlags.length; ++c) {
- if (c >= 'A' && c <= 'Z') {
- identifierFlags[c] = true;
- } else if (c >= 'a' && c <= 'z') {
- identifierFlags[c] = true;
- } else if (c == '_') {
- identifierFlags[c] = true;
- } else if (c >= '0' && c <= '9') {
- identifierFlags[c] = true;
- }
- }
- }
-
- public final static boolean[] specicalFlags_doubleQuotes = new boolean[((int) '\\' + 1)];
- public final static boolean[] specicalFlags_singleQuotes = new boolean[((int) '\\' + 1)];
-
- public static boolean isSpecial_doubleQuotes(char ch) {
- return ch < specicalFlags_doubleQuotes.length && specicalFlags_doubleQuotes[ch];
- }
-
- public final static char[] replaceChars = new char[((int) '\\' + 1)];
- static {
- specicalFlags_doubleQuotes['\b'] = true;
- specicalFlags_doubleQuotes['\n'] = true;
- specicalFlags_doubleQuotes['\f'] = true;
- specicalFlags_doubleQuotes['\r'] = true;
- specicalFlags_doubleQuotes['\"'] = true;
- specicalFlags_doubleQuotes['\\'] = true;
-
- specicalFlags_singleQuotes['\b'] = true;
- specicalFlags_singleQuotes['\n'] = true;
- specicalFlags_singleQuotes['\f'] = true;
- specicalFlags_singleQuotes['\r'] = true;
- specicalFlags_singleQuotes['\''] = true;
- specicalFlags_singleQuotes['\\'] = true;
-
- replaceChars['\b'] = 'b';
- replaceChars['\n'] = 'n';
- replaceChars['\f'] = 'f';
- replaceChars['\r'] = 'r';
- replaceChars['\"'] = '"';
- replaceChars['\''] = '\'';
- replaceChars['\\'] = '\\';
- replaceChars['\t'] = 't';
- }
-
-}
diff --git a/src/main/java/com/alibaba/fastjson/parser/DefaultExtJSONParser.java b/src/main/java/com/alibaba/fastjson/parser/DefaultExtJSONParser.java
old mode 100644
new mode 100755
index 35dc417784..0fe28d94da
--- a/src/main/java/com/alibaba/fastjson/parser/DefaultExtJSONParser.java
+++ b/src/main/java/com/alibaba/fastjson/parser/DefaultExtJSONParser.java
@@ -15,56 +15,13 @@
*/
package com.alibaba.fastjson.parser;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.lang.reflect.WildcardType;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import com.alibaba.fastjson.JSONException;
-import com.alibaba.fastjson.parser.deserializer.DefaultObjectDeserializer;
-import com.alibaba.fastjson.parser.deserializer.IntegerDeserializer;
-import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
-import com.alibaba.fastjson.parser.deserializer.StringDeserializer;
-import com.alibaba.fastjson.util.TypeUtils;
/**
- * @author wenshao
+ * @author wenshao[szujobs@hotmail.com]
*/
-@SuppressWarnings("rawtypes")
+@Deprecated
public class DefaultExtJSONParser extends DefaultJSONParser {
- private DefaultObjectDeserializer derializer = new DefaultObjectDeserializer();
-
- private final static Set> primitiveClasses = new HashSet>();
- static {
- primitiveClasses.add(boolean.class);
- primitiveClasses.add(byte.class);
- primitiveClasses.add(short.class);
- primitiveClasses.add(int.class);
- primitiveClasses.add(long.class);
- primitiveClasses.add(float.class);
- primitiveClasses.add(double.class);
-
- primitiveClasses.add(Boolean.class);
- primitiveClasses.add(Byte.class);
- primitiveClasses.add(Short.class);
- primitiveClasses.add(Integer.class);
- primitiveClasses.add(Long.class);
- primitiveClasses.add(Float.class);
- primitiveClasses.add(Double.class);
-
- primitiveClasses.add(BigInteger.class);
- primitiveClasses.add(BigDecimal.class);
- primitiveClasses.add(String.class);
- }
-
public DefaultExtJSONParser(String input){
this(input, ParserConfig.getGlobalInstance());
}
@@ -81,292 +38,5 @@ public DefaultExtJSONParser(char[] input, int length, ParserConfig mapping, int
super(input, length, mapping, features);
}
- public ParserConfig getConfig() {
- return config;
- }
-
- public void setConfig(ParserConfig config) {
- this.config = config;
- }
-
- // compatible
- @SuppressWarnings("unchecked")
- public T parseObject(Class clazz) {
- return (T) parseObject((Type) clazz);
- }
-
- @SuppressWarnings("unchecked")
- public T parseObject(Type type) {
- if (lexer.token() == JSONToken.NULL) {
- lexer.nextToken();
- return null;
- }
-
- ObjectDeserializer derializer = config.getDeserializer(type);
-
- try {
- return (T) derializer.deserialze(this, type);
- } catch (JSONException e) {
- throw e;
- } catch (Throwable e) {
- throw new JSONException(e.getMessage(), e);
- }
- }
-
- public List parseArray(Class clazz) {
- List array = new ArrayList();
- parseArray(clazz, array);
- return array;
- }
-
- public void parseArray(Class> clazz, Collection array) {
- parseArray((Type) clazz, array);
- }
-
- @SuppressWarnings({ "unchecked" })
- public void parseArray(Type type, Collection array) {
- if (lexer.token() != JSONToken.LBRACKET) {
- throw new JSONException("exepct '[', but " + JSONToken.name(lexer.token()));
- }
-
- ObjectDeserializer deserializer = null;
- if (int.class == type) {
- deserializer = IntegerDeserializer.instance;
- lexer.nextToken(JSONToken.LITERAL_INT);
- } else if (String.class == type) {
- deserializer = StringDeserializer.instance;
- lexer.nextToken(JSONToken.LITERAL_STRING);
- } else {
- deserializer = config.getDeserializer(type);
- lexer.nextToken(deserializer.getFastMatchToken());
- }
-
- for (;;) {
- if (isEnabled(Feature.AllowArbitraryCommas)) {
- while (lexer.token() == JSONToken.COMMA) {
- lexer.nextToken();
- continue;
- }
- }
-
- if (lexer.token() == JSONToken.RBRACKET) {
- break;
- }
-
- if (int.class == type) {
- Object val = IntegerDeserializer.deserialze(this);
- array.add(val);
- } else if (String.class == type) {
- String value;
- if (lexer.token() == JSONToken.LITERAL_STRING) {
- value = lexer.stringVal();
- lexer.nextToken(JSONToken.COMMA);
- } else {
- Object obj = this.parse();
- if (obj == null) {
- value = null;
- } else {
- value = obj.toString();
- }
- }
-
- array.add(value);
- } else {
- Object val = deserializer.deserialze(this, type);
- array.add(val);
- }
-
- if (lexer.token() == JSONToken.COMMA) {
- lexer.nextToken(deserializer.getFastMatchToken());
- continue;
- }
- }
-
- lexer.nextToken(JSONToken.COMMA);
- }
-
- public Object[] parseArray(Type[] types) {
-
- if (lexer.token() != JSONToken.LBRACKET) {
- throw new JSONException("syntax error");
- }
-
- Object[] list = new Object[types.length];
- if (types.length == 0) {
- lexer.nextToken(JSONToken.RBRACKET);
-
- if (lexer.token() != JSONToken.RBRACKET) {
- throw new JSONException("syntax error");
- }
-
- lexer.nextToken(JSONToken.COMMA);
- return new Object[0];
- }
-
- lexer.nextToken(JSONToken.LITERAL_INT);
-
- for (int i = 0; i < types.length; ++i) {
- Object value;
-
- if (lexer.token() == JSONToken.NULL) {
- value = null;
- lexer.nextToken(JSONToken.COMMA);
- } else {
- Type type = types[i];
- if (type == int.class || type == Integer.class) {
- if (lexer.token() == JSONToken.LITERAL_INT) {
- value = Integer.valueOf(lexer.intValue());
- lexer.nextToken(JSONToken.COMMA);
- } else {
- value = this.parse();
- value = TypeUtils.cast(value, type, config);
- }
- } else if (type == String.class) {
- if (lexer.token() == JSONToken.LITERAL_STRING) {
- value = lexer.stringVal();
- lexer.nextToken(JSONToken.COMMA);
- } else {
- value = this.parse();
- value = TypeUtils.cast(value, type, config);
- }
- } else {
- boolean isArray = false;
- Class> componentType = null;
- if (i == types.length - 1) {
- if (type instanceof Class) {
- Class> clazz = (Class>) type;
- isArray = clazz.isArray();
- componentType = clazz.getComponentType();
- }
- }
-
- // support varArgs
- if (isArray && lexer.token() != JSONToken.LBRACKET) {
- List