55import javassist .CtMethod ;
66import javassist .CtNewMethod ;
77
8- import java .io .IOException ;
98import java .lang .reflect .*;
109import java .math .BigDecimal ;
1110import java .math .BigInteger ;
1211import java .util .*;
1312
1413class Codegen {
1514 static boolean strictMode = false ;
15+ final static Map <String , String > DEFAULT_VALUES = new HashMap <String , String >() {{
16+ put ("float" , "0.0f" );
17+ put ("double" , "0.0d" );
18+ put ("boolean" , "false" );
19+ put ("byte" , "0" );
20+ put ("short" , "0" );
21+ put ("int" , "0" );
22+ put ("char" , "0" );
23+ put ("long" , "0" );
24+ }};
1625 final static Map <String , String > NATIVE_READS = new HashMap <String , String >() {{
1726 put ("float" , "iter.readFloat()" );
1827 put ("double" , "iter.readDouble()" );
@@ -42,7 +51,6 @@ class Codegen {
4251 add (Vector .class );
4352 }};
4453 static volatile Map <String , Decoder > cache = new HashMap <String , Decoder >();
45- static List <Extension > extensions = new ArrayList <Extension >();
4654 static ClassPool pool = ClassPool .getDefault ();
4755
4856 static Decoder getDecoder (String cacheKey , Type type , Type ... typeArgs ) {
@@ -141,17 +149,6 @@ private static String genSource(String cacheKey, Class clazz, Type[] typeArgs) {
141149 return genCollection (clazz , compType );
142150 }
143151 }
144- // TODO: re-enable this optimization
145- // if (clazz.getFields().length == 0) {
146- // StringBuilder lines = new StringBuilder();
147- // append(lines, "public static Object decode_(com.jsoniter.Jsoniter iter) {");
148- // append(lines, "if (iter.readNull()) { return null; }");
149- // append(lines, "{{clazz}} obj = {{newInst}};");
150- // append(lines, "iter.skip();");
151- // append(lines, "return obj;");
152- // append(lines, "}");
153- // return lines.toString().replace("{{clazz}}", clazz.getCanonicalName()).replace("{{newInst}}", genNewInstCode(clazz, getCtor(clazz)));
154- // }
155152 if (strictMode ) {
156153 return genObjectUsingSlice (clazz , cacheKey );
157154 } else {
@@ -207,19 +204,31 @@ public static void addNewDecoder(String cacheKey, Decoder decoder) {
207204 }
208205
209206 private static String genObjectUsingHash (Class clazz , String cacheKey ) {
210- CustomizedConstructor ctor = getCtor (clazz );
211- List <Binding > fields = getFields (clazz );
207+ CustomizedConstructor ctor = ExtensionManager .getCtor (clazz );
208+ List <Binding > fields = ExtensionManager .getFields (clazz );
209+ List <CustomizedSetter > setters = ExtensionManager .getSetters (clazz );
212210 ArrayList <Binding > allBindings = new ArrayList <Binding >(fields );
213211 allBindings .addAll (ctor .parameters );
212+ for (CustomizedSetter setter : setters ) {
213+ allBindings .addAll (setter .parameters );
214+ }
215+ if (allBindings .isEmpty ()) {
216+ return genObjectUsingSkip (clazz , ctor );
217+ }
214218 StringBuilder lines = new StringBuilder ();
215219 append (lines , "public static Object decode_(com.jsoniter.Jsoniter iter) {" );
216220 append (lines , "if (iter.readNull()) { return null; }" );
217221 for (Binding parameter : ctor .parameters ) {
218- append (lines , String . format ( "%s _%s_ = null;" , getTypeName ( parameter . valueType ), parameter . name ) );
222+ appendVarDef (lines , parameter );
219223 }
220224 append (lines , "if (!com.jsoniter.CodegenAccess.readObjectStart(iter)) { return {{newInst}}; }" );
221225 for (Binding field : fields ) {
222- append (lines , String .format ("%s _%s_;" , getTypeName (field .valueType ), field .name ));
226+ appendVarDef (lines , field );
227+ }
228+ for (CustomizedSetter setter : setters ) {
229+ for (Binding param : setter .parameters ) {
230+ appendVarDef (lines , param );
231+ }
223232 }
224233 append (lines , "switch (com.jsoniter.CodegenAccess.readObjectFieldAsHash(iter)) {" );
225234 HashSet <Integer > knownHashes = new HashSet <Integer >();
@@ -270,6 +279,30 @@ private static String genObjectUsingHash(Class clazz, String cacheKey) {
270279 for (Binding field : fields ) {
271280 append (lines , String .format ("obj.%s = _%s_;" , field .name , field .name ));
272281 }
282+ for (CustomizedSetter setter : setters ) {
283+ lines .append ("obj." );
284+ lines .append (setter .methodName );
285+ appendInvocation (lines , setter .parameters );
286+ lines .append (";\n " );
287+ }
288+ append (lines , "return obj;" );
289+ append (lines , "}" );
290+ return lines .toString ()
291+ .replace ("{{clazz}}" , clazz .getCanonicalName ())
292+ .replace ("{{newInst}}" , genNewInstCode (clazz , ctor ));
293+ }
294+
295+ private static void appendVarDef (StringBuilder lines , Binding parameter ) {
296+ String typeName = getTypeName (parameter .valueType );
297+ append (lines , String .format ("%s _%s_ = %s;" , typeName , parameter .name , DEFAULT_VALUES .get (typeName )));
298+ }
299+
300+ private static String genObjectUsingSkip (Class clazz , CustomizedConstructor ctor ) {
301+ StringBuilder lines = new StringBuilder ();
302+ append (lines , "public static Object decode_(com.jsoniter.Jsoniter iter) {" );
303+ append (lines , "if (iter.readNull()) { return null; }" );
304+ append (lines , "{{clazz}} obj = {{newInst}};" );
305+ append (lines , "iter.skip();" );
273306 append (lines , "return obj;" );
274307 append (lines , "}" );
275308 return lines .toString ()
@@ -284,48 +317,23 @@ private static String genNewInstCode(Class clazz, CustomizedConstructor ctor) {
284317 } else {
285318 code .append (String .format ("%s.%s" , clazz .getCanonicalName (), ctor .staticMethodName ));
286319 }
320+ List <Binding > params = ctor .parameters ;
321+ appendInvocation (code , params );
322+ return code .toString ();
323+ }
324+
325+ private static void appendInvocation (StringBuilder code , List <Binding > params ) {
287326 code .append ("(" );
288327 boolean isFirst = true ;
289- for (Binding ctorParam : ctor . parameters ) {
328+ for (Binding ctorParam : params ) {
290329 if (isFirst ) {
291330 isFirst = false ;
292331 } else {
293332 code .append ("," );
294333 }
295- code .append ("_" + ctorParam .name + "_" );
334+ code .append (String . format ( "_%s_" , ctorParam .name ) );
296335 }
297336 code .append (")" );
298- return code .toString ();
299- }
300-
301- private static CustomizedConstructor getCtor (Class clazz ) {
302- for (Extension extension : extensions ) {
303- CustomizedConstructor ctor = extension .getConstructor (clazz );
304- if (ctor != null ) {
305- return ctor ;
306- }
307- }
308- return CustomizedConstructor .DEFAULT_INSTANCE ;
309- }
310-
311- private static List <Binding > getFields (Class clazz ) {
312- ArrayList <Binding > bindings = new ArrayList <Binding >();
313- for (Field field : clazz .getFields ()) {
314- Binding binding = new Binding ();
315- binding .fromNames = new String []{field .getName ()};
316- for (Extension extension : extensions ) {
317- String [] fromNames = extension .getAlternativeFieldNames (binding );
318- if (fromNames != null ) {
319- binding .fromNames = fromNames ;
320- break ;
321- }
322- }
323- binding .name = field .getName ();
324- binding .valueType = field .getType ();
325- binding .clazz = clazz ;
326- bindings .add (binding );
327- }
328- return bindings ;
329337 }
330338
331339 private static String genObjectUsingSlice (Class clazz , String cacheKey ) {
@@ -368,12 +376,12 @@ private static String genObjectUsingSlice(Class clazz, String cacheKey) {
368376 append (lines , "}" );
369377 return lines .toString ()
370378 .replace ("{{clazz}}" , clazz .getCanonicalName ())
371- .replace ("{{newInst}}" , genNewInstCode (clazz , getCtor (clazz )));
379+ .replace ("{{newInst}}" , genNewInstCode (clazz , ExtensionManager . getCtor (clazz )));
372380 }
373381
374382 private static Map <Integer , Object > buildTriTree (Class clazz ) {
375383 Map <Integer , Object > trieTree = new HashMap <Integer , Object >();
376- for (Binding field : getFields (clazz )) {
384+ for (Binding field : ExtensionManager . getFields (clazz )) {
377385 for (String fromName : field .fromNames ) {
378386 byte [] fromNameBytes = fromName .getBytes ();
379387 Map <Byte , Object > current = (Map <Byte , Object >) trieTree .get (fromNameBytes .length );
@@ -397,16 +405,18 @@ private static Map<Integer, Object> buildTriTree(Class clazz) {
397405 }
398406
399407 private static Decoder createFieldDecoder (String fieldCacheKey , Binding field ) {
400- for (Extension extension : extensions ) {
401- Decoder decoder = extension .createDecoder (field );
402- if (decoder != null ) {
403- addNewDecoder (fieldCacheKey , decoder );
404- break ;
405- }
408+ // directly registered field decoder
409+ Decoder decoder = cache .get (fieldCacheKey );
410+ if (decoder != null ) {
411+ return decoder ;
406412 }
407- // the decoder can be just created by the factory
408- // or it can be registered directly
409- return cache .get (fieldCacheKey );
413+ // provided by extension
414+ decoder = ExtensionManager .createFieldDecoder (fieldCacheKey , field );
415+ if (decoder != null ) {
416+ addNewDecoder (fieldCacheKey , decoder );
417+ return decoder ;
418+ }
419+ return null ;
410420 }
411421
412422 private static void addFieldDispatch (StringBuilder lines , int len , int i , Map <Byte , Object > current , String cacheKey , List <Byte > bytesToCompare ) {
@@ -672,10 +682,6 @@ private static void append(StringBuilder lines, String str) {
672682 lines .append ("\n " );
673683 }
674684
675- public static void registerExtension (Extension extension ) {
676- extensions .add (extension );
677- }
678-
679685 public static Decoder .IntDecoder getIntDecoder (String cacheKey ) {
680686 return (Decoder .IntDecoder ) cache .get (cacheKey );
681687 }
0 commit comments