28
28
import java .util .ArrayList ;
29
29
import java .util .Arrays ;
30
30
import java .util .List ;
31
+ import java .util .Objects ;
31
32
import java .util .Optional ;
32
33
import java .util .function .Function ;
33
34
@@ -158,8 +159,7 @@ public ClassEntry thisClassEntry() {
158
159
@ Override
159
160
public Optional <ClassEntry > superclassEntry () {
160
161
if (superclass == null ) {
161
- int scIndex = readU2 (thisClassPos + 2 );
162
- superclass = Optional .ofNullable (scIndex == 0 ? null : (ClassEntry ) entryByIndex (scIndex ));
162
+ superclass = Optional .ofNullable (readEntryOrNull (thisClassPos + 2 , ClassEntry .class ));
163
163
}
164
164
return superclass ;
165
165
}
@@ -338,10 +338,42 @@ void writeConstantPoolEntries(BufWriter buf) {
338
338
// Constantpool
339
339
@ Override
340
340
public PoolEntry entryByIndex (int index ) {
341
- return entryByIndex (index , 0 , 0xff );
341
+ return entryByIndex (index , PoolEntry .class );
342
+ }
343
+
344
+ private static boolean checkTag (int tag , Class <?> cls ) {
345
+ var type = switch (tag ) {
346
+ // JVMS Table 4.4-B. Constant pool tags
347
+ case TAG_UTF8 -> AbstractPoolEntry .Utf8EntryImpl .class ;
348
+ case TAG_INTEGER -> AbstractPoolEntry .IntegerEntryImpl .class ;
349
+ case TAG_FLOAT -> AbstractPoolEntry .FloatEntryImpl .class ;
350
+ case TAG_LONG -> AbstractPoolEntry .LongEntryImpl .class ;
351
+ case TAG_DOUBLE -> AbstractPoolEntry .DoubleEntryImpl .class ;
352
+ case TAG_CLASS -> AbstractPoolEntry .ClassEntryImpl .class ;
353
+ case TAG_STRING -> AbstractPoolEntry .StringEntryImpl .class ;
354
+ case TAG_FIELDREF -> AbstractPoolEntry .FieldRefEntryImpl .class ;
355
+ case TAG_METHODREF -> AbstractPoolEntry .MethodRefEntryImpl .class ;
356
+ case TAG_INTERFACEMETHODREF -> AbstractPoolEntry .InterfaceMethodRefEntryImpl .class ;
357
+ case TAG_NAMEANDTYPE -> AbstractPoolEntry .NameAndTypeEntryImpl .class ;
358
+ case TAG_METHODHANDLE -> AbstractPoolEntry .MethodHandleEntryImpl .class ;
359
+ case TAG_METHODTYPE -> AbstractPoolEntry .MethodTypeEntryImpl .class ;
360
+ case TAG_CONSTANTDYNAMIC -> AbstractPoolEntry .ConstantDynamicEntryImpl .class ;
361
+ case TAG_INVOKEDYNAMIC -> AbstractPoolEntry .InvokeDynamicEntryImpl .class ;
362
+ case TAG_MODULE -> AbstractPoolEntry .ModuleEntryImpl .class ;
363
+ case TAG_PACKAGE -> AbstractPoolEntry .PackageEntryImpl .class ;
364
+ default -> null ;
365
+ };
366
+ return type != null && cls .isAssignableFrom (type );
367
+ }
368
+
369
+ static <T extends PoolEntry > T checkType (PoolEntry e , int index , Class <T > cls ) {
370
+ if (cls .isInstance (e )) return cls .cast (e );
371
+ throw new ConstantPoolException ("Not a " + cls .getSimpleName () + " at index: " + index );
342
372
}
343
373
344
- private PoolEntry entryByIndex (int index , int lowerBoundTag , int upperBoundTag ) {
374
+ @ Override
375
+ public <T extends PoolEntry > T entryByIndex (int index , Class <T > cls ) {
376
+ Objects .requireNonNull (cls );
345
377
if (index <= 0 || index >= constantPoolCount ) {
346
378
throw new ConstantPoolException ("Bad CP index: " + index );
347
379
}
@@ -352,9 +384,9 @@ private PoolEntry entryByIndex(int index, int lowerBoundTag, int upperBoundTag)
352
384
throw new ConstantPoolException ("Unusable CP index: " + index );
353
385
}
354
386
int tag = readU1 (offset );
355
- if (tag < lowerBoundTag || tag > upperBoundTag ) {
387
+ if (! checkTag ( tag , cls ) ) {
356
388
throw new ConstantPoolException (
357
- "Bad tag (" + tag + ") at index (" + index + ") position (" + offset + ")" );
389
+ "Bad tag (" + tag + ") at index (" + index + ") position (" + offset + "), expected " + cls . getSimpleName () );
358
390
}
359
391
final int q = offset + 1 ;
360
392
info = switch (tag ) {
@@ -374,7 +406,7 @@ private PoolEntry entryByIndex(int index, int lowerBoundTag, int upperBoundTag)
374
406
case TAG_NAMEANDTYPE -> new AbstractPoolEntry .NameAndTypeEntryImpl (this , index , (AbstractPoolEntry .Utf8EntryImpl ) readUtf8Entry (q ),
375
407
(AbstractPoolEntry .Utf8EntryImpl ) readUtf8Entry (q + 2 ));
376
408
case TAG_METHODHANDLE -> new AbstractPoolEntry .MethodHandleEntryImpl (this , index , readU1 (q ),
377
- readEntry (q + 1 , AbstractPoolEntry .AbstractMemberRefEntry .class , TAG_FIELDREF , TAG_INTERFACEMETHODREF ));
409
+ readEntry (q + 1 , AbstractPoolEntry .AbstractMemberRefEntry .class ));
378
410
case TAG_METHODTYPE -> new AbstractPoolEntry .MethodTypeEntryImpl (this , index , (AbstractPoolEntry .Utf8EntryImpl ) readUtf8Entry (q ));
379
411
case TAG_CONSTANTDYNAMIC -> new AbstractPoolEntry .ConstantDynamicEntryImpl (this , index , readU2 (q ), (AbstractPoolEntry .NameAndTypeEntryImpl ) readNameAndTypeEntry (q + 2 ));
380
412
case TAG_INVOKEDYNAMIC -> new AbstractPoolEntry .InvokeDynamicEntryImpl (this , index , readU2 (q ), (AbstractPoolEntry .NameAndTypeEntryImpl ) readNameAndTypeEntry (q + 2 ));
@@ -385,15 +417,7 @@ private PoolEntry entryByIndex(int index, int lowerBoundTag, int upperBoundTag)
385
417
};
386
418
cp [index ] = info ;
387
419
}
388
- return info ;
389
- }
390
-
391
- @ Override
392
- public AbstractPoolEntry .Utf8EntryImpl utf8EntryByIndex (int index ) {
393
- if (entryByIndex (index , TAG_UTF8 , TAG_UTF8 ) instanceof AbstractPoolEntry .Utf8EntryImpl utf8 ) {
394
- return utf8 ;
395
- }
396
- throw new ConstantPoolException ("Not a UTF8 - index: " + index );
420
+ return checkType (info , index , cls );
397
421
}
398
422
399
423
public int skipAttributeHolder (int offset ) {
@@ -418,17 +442,8 @@ public PoolEntry readEntry(int pos) {
418
442
419
443
@ Override
420
444
public <T extends PoolEntry > T readEntry (int pos , Class <T > cls ) {
421
- return readEntry (pos , cls , 0 , 0xff );
422
- }
423
-
424
- private <T extends PoolEntry > T readEntry (int pos , Class <T > cls , int expectedTag ) {
425
- return readEntry (pos , cls , expectedTag , expectedTag );
426
- }
427
-
428
- private <T extends PoolEntry > T readEntry (int pos , Class <T > cls , int lowerBoundTag , int upperBoundTag ) {
429
- var e = entryByIndex (readU2 (pos ), lowerBoundTag , upperBoundTag );
430
- if (cls .isInstance (e )) return cls .cast (e );
431
- throw new ConstantPoolException ("Not a " + cls .getSimpleName () + " at index: " + readU2 (pos ));
445
+ Objects .requireNonNull (cls );
446
+ return entryByIndex (readU2 (pos ), cls );
432
447
}
433
448
434
449
@ Override
@@ -440,44 +455,49 @@ public PoolEntry readEntryOrNull(int pos) {
440
455
return entryByIndex (index );
441
456
}
442
457
458
+ @ Override
459
+ public <T extends PoolEntry > T readEntryOrNull (int offset , Class <T > cls ) {
460
+ Objects .requireNonNull (cls );
461
+ int index = readU2 (offset );
462
+ if (index == 0 ) {
463
+ return null ;
464
+ }
465
+ return entryByIndex (index , cls );
466
+ }
467
+
443
468
@ Override
444
469
public Utf8Entry readUtf8Entry (int pos ) {
445
- int index = readU2 (pos );
446
- return utf8EntryByIndex (index );
470
+ return readEntry (pos , Utf8Entry .class );
447
471
}
448
472
449
473
@ Override
450
474
public Utf8Entry readUtf8EntryOrNull (int pos ) {
451
- int index = readU2 (pos );
452
- if (index == 0 ) {
453
- return null ;
454
- }
455
- return utf8EntryByIndex (index );
475
+ return readEntryOrNull (pos , Utf8Entry .class );
456
476
}
457
477
458
478
@ Override
459
479
public ModuleEntry readModuleEntry (int pos ) {
460
- return readEntry (pos , ModuleEntry .class , TAG_MODULE );
480
+ return readEntry (pos , ModuleEntry .class );
461
481
}
462
482
463
483
@ Override
464
484
public PackageEntry readPackageEntry (int pos ) {
465
- return readEntry (pos , PackageEntry .class , TAG_PACKAGE );
485
+ return readEntry (pos , PackageEntry .class );
466
486
}
467
487
468
488
@ Override
469
489
public ClassEntry readClassEntry (int pos ) {
470
- return readEntry (pos , ClassEntry .class , TAG_CLASS );
490
+ return readEntry (pos , ClassEntry .class );
471
491
}
472
492
473
493
@ Override
474
494
public NameAndTypeEntry readNameAndTypeEntry (int pos ) {
475
- return readEntry (pos , NameAndTypeEntry .class , TAG_NAMEANDTYPE );
495
+ return readEntry (pos , NameAndTypeEntry .class );
476
496
}
477
497
478
498
@ Override
479
499
public MethodHandleEntry readMethodHandleEntry (int pos ) {
480
- return readEntry (pos , MethodHandleEntry .class , TAG_METHODHANDLE );
500
+ return readEntry (pos , MethodHandleEntry .class );
481
501
}
482
502
483
503
@ Override
0 commit comments