5
5
import javassist .CtMethod ;
6
6
import javassist .CtNewMethod ;
7
7
8
- import java .io .IOException ;
9
8
import java .lang .reflect .*;
10
9
import java .math .BigDecimal ;
11
10
import java .math .BigInteger ;
12
11
import java .util .*;
13
12
14
13
class Codegen {
15
14
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
+ }};
16
25
final static Map <String , String > NATIVE_READS = new HashMap <String , String >() {{
17
26
put ("float" , "iter.readFloat()" );
18
27
put ("double" , "iter.readDouble()" );
@@ -42,7 +51,6 @@ class Codegen {
42
51
add (Vector .class );
43
52
}};
44
53
static volatile Map <String , Decoder > cache = new HashMap <String , Decoder >();
45
- static List <Extension > extensions = new ArrayList <Extension >();
46
54
static ClassPool pool = ClassPool .getDefault ();
47
55
48
56
static Decoder getDecoder (String cacheKey , Type type , Type ... typeArgs ) {
@@ -141,17 +149,6 @@ private static String genSource(String cacheKey, Class clazz, Type[] typeArgs) {
141
149
return genCollection (clazz , compType );
142
150
}
143
151
}
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
- // }
155
152
if (strictMode ) {
156
153
return genObjectUsingSlice (clazz , cacheKey );
157
154
} else {
@@ -207,19 +204,31 @@ public static void addNewDecoder(String cacheKey, Decoder decoder) {
207
204
}
208
205
209
206
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 );
212
210
ArrayList <Binding > allBindings = new ArrayList <Binding >(fields );
213
211
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
+ }
214
218
StringBuilder lines = new StringBuilder ();
215
219
append (lines , "public static Object decode_(com.jsoniter.Jsoniter iter) {" );
216
220
append (lines , "if (iter.readNull()) { return null; }" );
217
221
for (Binding parameter : ctor .parameters ) {
218
- append (lines , String . format ( "%s _%s_ = null;" , getTypeName ( parameter . valueType ), parameter . name ) );
222
+ appendVarDef (lines , parameter );
219
223
}
220
224
append (lines , "if (!com.jsoniter.CodegenAccess.readObjectStart(iter)) { return {{newInst}}; }" );
221
225
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
+ }
223
232
}
224
233
append (lines , "switch (com.jsoniter.CodegenAccess.readObjectFieldAsHash(iter)) {" );
225
234
HashSet <Integer > knownHashes = new HashSet <Integer >();
@@ -270,6 +279,30 @@ private static String genObjectUsingHash(Class clazz, String cacheKey) {
270
279
for (Binding field : fields ) {
271
280
append (lines , String .format ("obj.%s = _%s_;" , field .name , field .name ));
272
281
}
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();" );
273
306
append (lines , "return obj;" );
274
307
append (lines , "}" );
275
308
return lines .toString ()
@@ -284,48 +317,23 @@ private static String genNewInstCode(Class clazz, CustomizedConstructor ctor) {
284
317
} else {
285
318
code .append (String .format ("%s.%s" , clazz .getCanonicalName (), ctor .staticMethodName ));
286
319
}
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 ) {
287
326
code .append ("(" );
288
327
boolean isFirst = true ;
289
- for (Binding ctorParam : ctor . parameters ) {
328
+ for (Binding ctorParam : params ) {
290
329
if (isFirst ) {
291
330
isFirst = false ;
292
331
} else {
293
332
code .append ("," );
294
333
}
295
- code .append ("_" + ctorParam .name + "_" );
334
+ code .append (String . format ( "_%s_" , ctorParam .name ) );
296
335
}
297
336
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 ;
329
337
}
330
338
331
339
private static String genObjectUsingSlice (Class clazz , String cacheKey ) {
@@ -368,12 +376,12 @@ private static String genObjectUsingSlice(Class clazz, String cacheKey) {
368
376
append (lines , "}" );
369
377
return lines .toString ()
370
378
.replace ("{{clazz}}" , clazz .getCanonicalName ())
371
- .replace ("{{newInst}}" , genNewInstCode (clazz , getCtor (clazz )));
379
+ .replace ("{{newInst}}" , genNewInstCode (clazz , ExtensionManager . getCtor (clazz )));
372
380
}
373
381
374
382
private static Map <Integer , Object > buildTriTree (Class clazz ) {
375
383
Map <Integer , Object > trieTree = new HashMap <Integer , Object >();
376
- for (Binding field : getFields (clazz )) {
384
+ for (Binding field : ExtensionManager . getFields (clazz )) {
377
385
for (String fromName : field .fromNames ) {
378
386
byte [] fromNameBytes = fromName .getBytes ();
379
387
Map <Byte , Object > current = (Map <Byte , Object >) trieTree .get (fromNameBytes .length );
@@ -397,16 +405,18 @@ private static Map<Integer, Object> buildTriTree(Class clazz) {
397
405
}
398
406
399
407
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 ;
406
412
}
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 ;
410
420
}
411
421
412
422
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) {
672
682
lines .append ("\n " );
673
683
}
674
684
675
- public static void registerExtension (Extension extension ) {
676
- extensions .add (extension );
677
- }
678
-
679
685
public static Decoder .IntDecoder getIntDecoder (String cacheKey ) {
680
686
return (Decoder .IntDecoder ) cache .get (cacheKey );
681
687
}
0 commit comments