001package Torello.Java.Additional;
002
003import Torello.Java.FileRW;
004import Torello.Java.LFEC;
005import Torello.Java.Additional.Ret2;
006import Torello.Java.ReadOnly.ReadOnlyList;
007
008import Torello.JavaDoc.CSSLinks;
009import Torello.JavaDoc.LinkJavaSource;
010
011import java.util.stream.Stream;
012import java.util.Objects;
013
014import static Torello.Java.C.BCYAN;
015import static Torello.Java.C.RESET;
016import static Torello.JavaDoc.Entity.FIELD;
017
018/**
019 * A Data-Class for representing a Java {@code '.class'} File's Constant-Pool.
020 * <EMBED CLASS='external-html' DATA-FILE-ID=CP_TOP_TABLE>
021 */
022public class ConstantPool
023{
024    // ********************************************************************************************
025    // ********************************************************************************************
026    // Static Inner Class: Reference
027    // ********************************************************************************************
028    // ********************************************************************************************
029
030
031    /**
032     * A Data-Class which can represent:
033     * 
034     * <BR /><BR /><UL CLASS=JDUL>
035     * <LI><B>{@link TAG_FIELD_REF}</B> (9)</LI>
036     * <LI><B>{@link TAG_METHOD_REF}</B> (10)</LI>
037     * <LI><B>{@link TAG_INTERFACE_METHOD_REF}</B> (11)</LI>
038     * </UL>
039     * 
040     * <EMBED CLASS='external-html' DATA-FILE-ID=CP_REF_CGPT_DESC>
041     */
042    @CSSLinks(FileNames="ConstantPool.css")
043    public static class Reference
044    {
045        // ****************************************************************************************
046        // ****************************************************************************************
047        // Instance Fields
048        // ****************************************************************************************
049        // ****************************************************************************************
050
051
052        /** The Constant-Pool Table-Index where this {@code Reference} is located */
053        public final int tableIndex;
054
055        /** 
056         * The Constant-Pool Tg-Kind associated with this instance.  This Java {@code 'byte'} may
057         * take only one of only three values: 
058         * 
059         * <BR /><BR /><UL CLASS=JDUL>
060         * <LI><B>{@link TAG_FIELD_REF}</B> (9)</LI>
061         * <LI><B>{@link TAG_METHOD_REF}</B> (10)</LI>
062         * <LI><B>{@link TAG_INTERFACE_METHOD_REF}</B> (11)</LI>
063         * </UL>
064         * 
065         * <EMBED CLASS='external-html' DATA-FILE-ID=CP_IN_TYPE_TAG_NOTE>
066         */
067        public final byte tag;
068
069        /**
070         * The {@code 'className'} field specifies in which class (where) the Method or Field has
071         * actuallly been defined.  For most methods and fields, the {@code 'className'} is the 
072         * same as the actual class whose Constant-Pool was loaded into an instance of
073         * {@code ConstantPool}.
074         * 
075         * <BR /><BR />If the field or method reference is defined in an ancestor or parent class,
076         * then this field would contain the name of that ancestor.
077         */
078        public final String ownerClassName;
079
080        /**
081         * Constant-Pool Table-Index where owner's {@code className 'Class Constant'} was
082         * stored
083         */
084        public final int ownerClassIndex;
085
086        /**
087         * Constant-Pool Table-Index identifying where the {@code UTF-8} Class'
088         * <B STYLE='color; red;'>Name-As-A-{@code String}</B> is located.
089         */
090        public final int ownerClassNameUTF8Index;
091
092        /**
093         * An intermediate Constant-Pool Index-Pair that points to a Name UTF-8 Constant, and 
094         * a Type-Descriptor Constant.
095         */
096        public final int nameAndTypeIndex;
097
098        /**
099         * This is just the name of the Method or Field.  Some common method names are (just for
100         * example) {@cpde 'toString'} and {@code 'equals'}.  This particular Nested-Type has three
101         * fields of it's own, named: {@code 'className, 'name'} and {@code 'descriptor'}.
102         */
103        public final String name;
104
105        /**
106         * Constant-Pool Table-Index identifying where the {@code UTF-8} Method's or Field's
107         * <B STYLE='color; red;'>Name-As-A-{@code String}</B> is located.
108         */
109        public final int nameUTF8Index;
110
111        /**
112         * This is the descriptor of a method or field, which is Java single-line description
113         * which includes type-information stored as a simple {@code String}.  A descriptor is of
114         * the format:
115         * 
116         * <BR /><BR /><UL CLASS=JDUL>
117         * <LI>For a method, the descriptor specifies the parameter types and return type.</LI>
118         * <LI>For a field, the descriptor specifies the field type.</LI>
119         * </UL>
120         */
121        public final String descriptor;
122
123        /**
124         * Constant-Pool Table-Index identifying where the {@code UTF-8} Descriptor's
125         * <B STYLE='color; red;'>Description-As-A-{@code String}</B> is located.
126         */
127        public final int descriptorUTF8Index;
128
129
130        // ****************************************************************************************
131        // ****************************************************************************************
132        // Package-Private Constructor
133        // ****************************************************************************************
134        // ****************************************************************************************
135
136
137        Reference(
138                final ReadOnlyList<Byte>    tags,
139                final ReadOnlyList<Object>  values,
140                final int                   tableIndex
141            )
142        {
143            this.tableIndex = tableIndex;
144
145            // May only be one of three values: TAG_FIELD_REF, TAG_METHOD_REF or
146            // TAG_INTERFACE_METHOD_REF
147            // 
148            // public final byte tag;
149
150            this.tag = tags.get(tableIndex);
151
152            // temporary variable
153            @SuppressWarnings("unchecked")
154            final Ret2<Integer, Integer> methodOrFieldConstantR2 =
155                (Ret2<Integer, Integer>) values.get(tableIndex);
156
157            this.ownerClassIndex = methodOrFieldConstantR2.a;
158
159
160            // Constant-Pool Table-Index identifying where the UTF-8 Class'
161            // Name-As-A-String is located.
162            // 
163            // public final byte ownerClassNameUTF8Index;
164
165            this.ownerClassNameUTF8Index = (Integer) values.get(Reference.this.ownerClassIndex);
166
167
168            // The 'className' field specifies in which class (where) the Method or Field has
169            // actuallly been defined.
170            // 
171            // If the field or method reference is defined in an ancestor or parent class,
172            // then this field would contain the name of that ancestor.
173            // 
174            // public final String ownerClassName;
175
176            this.ownerClassName = (String) values.get(this.ownerClassNameUTF8Index);
177
178            // public final int nameAndTyeIndex;
179            this.nameAndTypeIndex = methodOrFieldConstantR2.b;
180
181            // Temporary Local Variable
182            @SuppressWarnings("unchecked")
183            final Ret2<Integer, Integer> nameAndTypeConstantR2 =
184                (Ret2<Integer, Integer>) values.get(methodOrFieldConstantR2.b);
185
186
187            // Constant-Pool Table-Index identifying where the UTF-8 Method's or Field's
188            // Name-As-A-String is located.
189            // 
190            // public final byte nameUTF8Index;
191
192            this.nameUTF8Index = nameAndTypeConstantR2.a;
193
194
195            // This is just the name of the Method or Field.  Some common method names are (for
196            // example) 'toString' and 'equals'.  This particular Nested-Type has three fields of
197            // it's own, named: 'className, 'name' and 'descriptor'.
198            // 
199            // public final String name;
200
201            this.name = (String) values.get(this.nameUTF8Index);
202
203
204            // Constant-Pool Table-Index identifying where the UTF-8 Descriptor's
205            // Description-As-A-String is located.
206            //
207            // public final byte descriptorUTF8Index;
208
209            this.descriptorUTF8Index = nameAndTypeConstantR2.b;
210
211
212            // This is the descriptor of a method or field.  A descriptor is of the format:
213            // * For a method, the descriptor specifies the parameter types and return type.
214            // * For a field, the descriptor specifies the field type.
215            // 
216            // public final String descriptor;
217
218            this.descriptor = (String) values.get(this.descriptorUTF8Index);
219        }
220
221
222        // ****************************************************************************************
223        // ****************************************************************************************
224        // java.lang.Object
225        // ****************************************************************************************
226        // ****************************************************************************************
227
228
229        /**
230         * Converts {@cpode 'this'} instance into a {@code java.lang.String}.
231         * @return The data-content of this record, as a {@code String}, for printing.
232         */
233        public final String toString()
234        {
235            return
236                "Reference:\n" +
237                "{\n" +
238                "    tag:             " + tag + " - " + ConstantPool.tagNames.get(tag) + '\n' +
239                "    Table-Index:     " + this.tableIndex + '\n' +                
240                "    ownerClassName:  " + this.ownerClassName + '\n' +
241                "    name:            " + this.name + '\n' +
242                "    descriptor:      " + this.descriptor + '\n' +
243                "}";
244        }
245
246        /**
247         * Checks for {@code Object}-equality between {@code 'this'} instance and {@code 'other'}.
248         * 
249         * @param other This may be any Java-{@code Object}, but only an instance of
250         * {@code ConstantPool.Reference} will permit this method to return {@code TRUE}.
251         * 
252         * @return {@code TRUE} if-and-only-if parameter {@code 'other'} is an instance of
253         * {@code Reference} and has identical field values.
254         */
255        public boolean equals(Object other)
256        {
257            if (!(other instanceof Reference)) return false;
258
259            Reference r = (Reference) other;
260
261            return
262                    (this.tag == r.tag)
263
264                &&  Objects.equals(this.ownerClassName, r.ownerClassName)
265                &&  (this.ownerClassIndex           == r.ownerClassIndex)
266                &&  (this.ownerClassNameUTF8Index   == r.ownerClassNameUTF8Index)
267
268                &&  Objects.equals(this.name, r.name)
269                &&  (this.nameUTF8Index == r.nameUTF8Index)
270
271                &&  Objects.equals(this.descriptor, r.descriptor)
272                &&  (this.descriptorUTF8Index == r.descriptorUTF8Index);
273        }
274
275        /**
276         * Generates a Hash-Code.
277         * @return An integer Hash-Code that may be used by Java's Hashing Data-Structures.
278         */
279        public int hashCode()
280        {
281            return this.name.hashCode() +
282                this.ownerClassNameUTF8Index +
283                this.nameUTF8Index +
284                this.descriptorUTF8Index;
285        }
286    }
287
288
289    // ********************************************************************************************
290    // ********************************************************************************************
291    // Static Inner Class: Reference
292    // ********************************************************************************************
293    // ********************************************************************************************
294
295
296    /**
297     * A class representing the "Reference-Kind" values associated with a {@code Method-Handle}.
298     * 
299     * <p>Method-Handles use "Reference-Kinds" to describe the type of operation they perform, 
300     * such as accessing fields or invoking methods.</p>
301     */
302    @CSSLinks(FileNames="ConstantPool.css")
303    public static class MethodHandle
304    {
305        // ****************************************************************************************
306        // ****************************************************************************************
307        // Instance Fields
308        // ****************************************************************************************
309        // ****************************************************************************************
310
311
312        /** The Constant-Pool Table-Index where this {@code Method-Handle} is located */
313        public final int tableIndex;
314
315        /**
316         * Contains a Java {@code byte}.  Guaranteed to be equal to one of the 9 {@code static} 
317         * {@code byte}-Constant Fields (the various "kinds").
318         * 
319         * <BR /><BR />The complete list of <CODE>Method Handle</CODE> 'kinds' may be viewed in
320         * the documentation for the {@code static} field {@link #handleKindNames}.  The table in
321         * the javadoc Documentation-Table there contains 'stringified' versions of all of the 
322         * {@code static} 'kind' {@code byte} constants also provided in this class.
323         */
324        public final byte kind;
325
326        /**
327         * Points to a Constant in the Constant-Pool Table.  This Index-Pointer must be a pointer 
328         * to one of the following: 
329         * {@link #TAG_FIELD_REF Field-Reference}, 
330         * {@link #TAG_METHOD_REF Method-Reference} or a
331         * {@link #TAG_INTERFACE_METHOD_REF Interface-Method-Reference}
332         */
333        public final int referencedIndex;
334
335        /**
336         * This contains the actual Tag-Kind (as a Java {@code byte}) of the Reference to which 
337         * this handle points.  This particular field may hold only one of three different values:
338         * <B>
339         * {@link #TAG_FIELD_REF 9},
340         * {@link #TAG_METHOD_REF 10} or
341         * {@link #TAG_INTERFACE_METHOD_REF 11}
342         * </B>
343         */
344        public final byte referencedTagKind;
345
346        /** The name of the method or field to which this reference points, as a {@code String} */
347        public final String referencedName;
348
349
350        // ****************************************************************************************
351        // ****************************************************************************************
352        // Static, Final Fields: The 9 different Method-Handle "Kinds"
353        // ****************************************************************************************
354        // ****************************************************************************************
355
356
357        /** 
358         * Reference-Kind value for {@code getField}. 
359         * Used to retrieve an instance field from an object.
360         */
361        public static final byte KIND_GET_FIELD = 1;
362
363        /** 
364         * Reference-Kind value for {@code getStatic}. 
365         * Used to retrieve a static field from a class.
366         */
367        public static final byte KIND_GET_STATIC = 2;
368
369        /** 
370         * Reference-Kind value for {@code putField}. 
371         * Used to assign a value to an instance field.
372         */
373        public static final byte KIND_PUT_FIELD = 3;
374
375        /** 
376         * Reference-Kind value for {@code putStatic}. 
377         * Used to assign a value to a static field.
378         */
379        public static final byte KIND_PUT_STATIC = 4;
380
381        /** 
382         * Reference-Kind value for {@code invokeVirtual}. 
383         * Used to invoke an instance method via virtual dispatch.
384         */
385        public static final byte KIND_INVOKE_VIRTUAL = 5;
386
387        /** 
388         * Reference-Kind value for {@code invokeStatic}. 
389         * Used to invoke a static method.
390         */
391        public static final byte KIND_INVOKE_STATIC = 6;
392
393        /** 
394         * Reference-Kind value for {@code invokeSpecial}. 
395         * Used to invoke an instance method directly (e.g., via {@code super} calls).
396         */
397        public static final byte KIND_INVOKE_SPECIAL = 7;
398
399        /** 
400         * Reference-Kind value for {@code newInvokeSpecial}. 
401         * Used to invoke a class constructor.
402         */
403        public static final byte KIND_NEW_INVOKE_SPECIAL = 8;
404
405        /** 
406         * Reference-Kind value for {@code invokeInterface}. 
407         * Used to invoke a method declared in an interface.
408         */
409        public static final byte KIND_INVOKE_INTERFACE = 9;
410
411
412        // ****************************************************************************************
413        // ****************************************************************************************
414        // Static, Final Fields: Lookup Table
415        // ****************************************************************************************
416        // ****************************************************************************************
417
418
419        /**
420         * This list is contains exactly 9 non-null entries.  Each entry in this list corresponds
421         * to one of the 9 Handle "Kind's"
422         * 
423         * <EMBED CLASS='external-html' DATA-FILE-ID=CP_MH_KIND_NAMES>
424         */
425        @SuppressWarnings("unchecked")
426        @LinkJavaSource(handle="MethodHandleData")
427        public static final ReadOnlyList<String> handleKindNames = 
428            (ReadOnlyList<String>) LFEC.readObjectFromFile_JAR
429                (ConstantPool.class, "data-files/data5.roaldat", true, ReadOnlyList.class);
430
431
432        // ****************************************************************************************
433        // ****************************************************************************************
434        // Package-Private Constructor
435        // ****************************************************************************************
436        // ****************************************************************************************
437
438
439        MethodHandle(
440                final ReadOnlyList<Byte>    tags,
441                final ReadOnlyList<Object>  values,
442                final int                   tableIndex
443            )
444        {
445            // The Constant-Pool Table-Index where this Method-Handle is located
446            // public final int tableIndex;
447
448            this.tableIndex = tableIndex;
449
450
451            @SuppressWarnings("unchecked")
452            final Ret2<Byte, Integer> methHandleR2 =
453                (Ret2<Byte, Integer>) values.get(tableIndex);
454
455
456            // Contains a Java byte.  Guaranteed to be equal to one of the 9 static
457            // byte-Constant Fields (the various "kinds"), listed in this class.
458            // 
459            // public final byte kind;
460
461            this.kind = methHandleR2.a;
462
463
464            // Points to a Constant in the Constant-Pool Table.  This Index-Pointer must be a pointer 
465            // to one of the following: TAG_FIELD_REF, TAG_METHOD_REF, TAG_INTERFACE_METHD_REF
466            // 
467            // public final int referencedIndex;
468
469            this.referencedIndex = methHandleR2.b;
470
471
472            // This contains the actual Tag-Kind (as a Java byte) of the Reference to which 
473            // this handle points.  This particular field may hold only one of three different values:
474            // TAG_FIELD_REF, TAG_METHOD_REF, TAG_INTERFACE_METHD_REF
475            // 
476            // public final byte referencedTagKind;
477
478            this.referencedTagKind = tags.get(this.referencedIndex);
479
480            @SuppressWarnings("unchecked")
481            final Ret2<Integer, Integer> referenceR2 = (Ret2<Integer, Integer>)
482                values.get(this.referencedIndex);
483
484            @SuppressWarnings("unchecked")
485            final Ret2<Integer, Integer> nameAndTypeR2 =
486                (Ret2<Integer, Integer>) values.get(referenceR2.b);
487
488
489            // The name of the method or field to which this reference points, as a String
490            // public final String referencedName;
491
492            this.referencedName = (String) values.get(nameAndTypeR2.a);
493        }
494
495
496        // ****************************************************************************************
497        // ****************************************************************************************
498        // java.lang.Object
499        // ****************************************************************************************
500        // ****************************************************************************************
501
502
503        /**
504         * Checks for {@code Object}-equality between {@code 'this'} instance and {@code 'other'}.
505         * 
506         * @param other This may be any Java-{@code Object}, but only an instance of
507         * {@code ConstantPool.MethodHandle} will permit this method to return {@code TRUE}.
508         * 
509         * @return {@code TRUE} if-and-only-if parameter {@code 'other'} is an instance of
510         * {@code MethodHandle} and has identical field values.
511         */
512        public boolean equals(Object other)
513        {
514            if (! (other instanceof MethodHandle)) return false;
515
516            final MethodHandle o = (MethodHandle) other;
517
518            return
519                    (this.tableIndex == o.tableIndex)
520                &&  (this.kind == o.kind)
521                &&  (this.referencedIndex == o.referencedIndex)
522                &&  (this.referencedTagKind == o.referencedTagKind)
523                &&  Objects.equals(this.referencedName, o.referencedName);
524        }
525
526        /**
527         * Generates a hash-code.  Fulfills Java's Hash-Code reuirement.
528         * @return a good attempt at an efficient, but fair hashcode.
529         */
530        public int hashCode()
531        { return this.tableIndex + this.kind + this.referencedIndex; }
532
533        /**
534         * Generate a human readable {@code String}.
535         * @return {@code 'this'} instance as a Java String
536         */
537        public String toString()
538        {
539            return
540                "Method Handle:\n" +
541                "{\n" +
542                "    Handle's Table-Index:               " + this.tableIndex + '\n' +
543                "    Referenced Item's Name:             " + this.referencedName + '\n' +
544                "    Handle Kind:                        " + this.kind + '\n' +
545
546                "    Handle Kind's Name:                 " +
547                    MethodHandle.handleKindNames.get(this.kind) + '\n' +
548
549                "    Referenced Item's Table-Index:      " + this.referencedIndex + '\n' +
550                "    Referenced Item's Kind (as byte):   " + this.referencedTagKind + '\n' +
551
552                "    Referenced Item's Kind (as String): " +
553                    ConstantPool.tagNames.get(this.referencedTagKind) + '\n' +
554                "}";
555        }
556    }
557
558
559    // ********************************************************************************************
560    // ********************************************************************************************
561    // Static Inner Class: Dynamic
562    // ********************************************************************************************
563    // ********************************************************************************************
564
565
566    /**
567     * Used to represent Java {@code '.class'} File Constant's whose Tag-Kind is:
568     * 
569     * <BR /><BR /><UL CLASS=JDUL>
570     * <LI><B>{@link #TAG_DYNAMIC}</B> ({@code 17})</LI>
571     * <LI><B>{@link #TAG_INVOKE_DYNAMIC}</B> ({@code 18})</LI>
572     * </UL>
573     */
574    public static class Dynamic 
575    {
576        // ****************************************************************************************
577        // ****************************************************************************************
578        // Instance Fields
579        // ****************************************************************************************
580        // ****************************************************************************************
581
582
583        /** The Constant-Pool Table-Index where this {@code Reference} is located */
584        public final int tableIndex;
585
586        /**
587         * The Constant-Pool Tg-Kind associated with this instance.  This Java {@code 'byte'} may
588         * take one of only two values:
589         * 
590         * <BR /><BR /><UL CLASS=JDUL>
591         * <LI><B>{@link #TAG_DYNAMIC}</B> ({@code 17})</LI>
592         * <LI><B>{@link #TAG_INVOKE_DYNAMIC}</B> ({@code 18})</LI>
593         * </UL>
594         * 
595         * <EMBED CLASS='external-html' DATA-FILE-ID=CP_IN_TYPE_TAG_NOTE>
596         */
597        public final byte tag;
598
599        /**
600         * This field will be assigned {@code TRUE} if-and-only-if field {@link #tag} has been
601         * assigned <B>{@code 17}</B>.  Tthe only other value which may be assigned to field 
602         * {@link #tag} is <B>{@code 18}</B>, when that field is equal to <B>{@code 18}</B>, this
603         * field be {@code FALSE}.
604         * 
605         * <BR /><BR />{@code boolean} fields such as this are here purely to make life easier,
606         * occasionally.
607         */
608        public final boolean dynamicOrInvokeDynamic;
609
610        /**
611         * The index into the Bootstrap Method Table, pointing to a bootstrap method
612         * definition in the `.class` file attributes.
613         */
614        public final int bootstrapMethodIndex;
615
616        /**
617         * The index into the constant pool, pointing to a {@link #TAG_NAME_AND_TYPE}
618         * Record / Structure that provides the name and type descriptor of this entry.
619         * 
620         * <BR /><BR />The Constant-Pool entry that is stored in the Table-Index specified by
621         * the integer in {@code 'nameAndTypeIndex'} is actually a 4 Byte Integer-Pair.  The two
622         * integers that comprise a "Name And Type" Constant (a "record" or "Structure") are simply
623         * two Index-Pointers back into the Constant-Pool's Table.
624         * 
625         * <BR /><BR />The first Index-Pointer is to a {@code UTF-8 String} storing the "name" of
626         * for the Method of the Method-Handle.  The second Index-Poniter points to a Table-Index 
627         * which contains the Method-Type - also stored as a {@code UTF-8 String}.
628         */
629        public final int nameAndTypeIndex;
630
631        /**
632         * The Constant in the Constant-Pool which may be found at the index specified by field 
633         * {@link #nameAndTypeIndex} is, itself, a "Record" of sorts; and contains two integer data
634         * fields in its Record.  The first integer is a Table Index-Pointer to a "name", and is
635         * represented by a {@code UTF-8} Table-Constant.
636         * 
637         * <BR /><BR />The Constant-Pool Table-Index for the {@code UTF-8 String} Constanta is
638         * saved as an integer in this {@code public, final} field.
639         * 
640         * <BR /><BR />The second integer of the Two-Integer Data-Record
641         * ({@link #nameAndTypeIndex}) stores a "Type as a String."  The index for that
642         * {@code UTF-8 String}  is stored in the {@code public final} field {@link #typeIndex}.
643         */
644        public final int nameIndex;
645
646        /**
647         * This stores the Java 'type' for a Method-Handle as a {@cde UTF-8} Constant.  You should
648         * review the documented explanations for the fields {@link #nameAndTypeIndex} and also for
649         * {@link #nameIndex} for more information.
650         */
651        public final int typeIndex;
652
653        /**
654         * This stores the Method-Name of the Bootstrap-Method specified by this Method-Handle
655         * instance.
656         */
657        public final String name;
658
659
660        // ****************************************************************************************
661        // ****************************************************************************************
662        // Package-Private Constructor
663        // ****************************************************************************************
664        // ****************************************************************************************
665
666
667        Dynamic(
668                final ReadOnlyList<Byte>    tags,
669                final ReadOnlyList<Object>  values,
670                final int                   tableIndex
671            )
672        {
673            // The Constant-Pool Table-Index where this Method-Handle is located
674            // public final int tableIndex;
675
676            this.tableIndex = tableIndex;
677
678            this.tag = tags.get(tableIndex);
679
680            this.dynamicOrInvokeDynamic = (this.tag == 17);
681
682            @SuppressWarnings("unchecked")
683            final Ret2<Integer, Integer> dynamicR2 =
684                (Ret2<Integer, Integer>) values.get(tableIndex);
685
686            this.bootstrapMethodIndex = dynamicR2.a;
687
688            this.nameAndTypeIndex = dynamicR2.b;
689
690            @SuppressWarnings("unchecked")
691            final Ret2<Integer, Integer> nameAndTypeR2 =
692                (Ret2<Integer, Integer>) values.get(nameAndTypeIndex);
693
694            this.nameIndex = nameAndTypeR2.a;
695
696            this.typeIndex = nameAndTypeR2.b;
697
698            this.name = (String) values.get(this.nameIndex);
699        }
700
701
702        // ****************************************************************************************
703        // ****************************************************************************************
704        // java.lang.Object
705        // ****************************************************************************************
706        // ****************************************************************************************
707
708
709        /** Check whether this instance equals parameter {@code 'other'} */
710        public boolean equals(Object other)
711        {
712            if (! (other instanceof ConstantPool.Dynamic)) return false;
713
714            ConstantPool.Dynamic o = (ConstantPool.Dynamic) other;
715
716            return 
717                    (this.tableIndex                == o.tableIndex)
718                &&  (this.tag                       == o.tag)
719                &&  (this.dynamicOrInvokeDynamic    == o.dynamicOrInvokeDynamic)
720                &&  (this.bootstrapMethodIndex      == o.bootstrapMethodIndex)
721                &&  (this.nameAndTypeIndex          == o.nameAndTypeIndex)
722                &&  (this.nameIndex                 == o.nameIndex)
723                &&  (this.typeIndex                 == o.typeIndex)
724                &&  Objects.equals(this.name, o.name);
725        }
726
727        /** Generate a simple, efficient, hash-code for this instance. */
728        public int hashCode()
729        { return this.tableIndex + this.bootstrapMethodIndex + this.nameAndTypeIndex; }
730
731        /** Generate a {@code java.lang.String} representation for this instance. */
732        public String toString()
733        {
734            return
735                "{\n" +
736                "    tableIndex:             " + tableIndex + "\n" +
737                "    tag:                    " + tag + " (" + (dynamicOrInvokeDynamic ? "Dynamic" : "Invoke-Dynamic") + ")\n" +
738                "    dynamicOrInvokeDynamic: " + dynamicOrInvokeDynamic + "\n" +
739                "    name:                   " + name + "\n" +
740                "    bootstrapMethodIndex:   " + bootstrapMethodIndex + "\n" +
741                "    nameAndTypeIndex:       " + nameAndTypeIndex + "\n" +
742                "    nameIndex:              " + nameIndex + "\n" +
743                "    typeIndex:              " + typeIndex + "\n" +
744                "}";
745        }
746    }
747
748
749    // ********************************************************************************************
750    // ********************************************************************************************
751    // Instance Fields: PARALLEL-ARRAYS (all Public-Final Constants & ReadOnly)
752    // ********************************************************************************************
753    // ********************************************************************************************
754
755
756    /** <EMBED CLASS='external-html' DATA-FILE-ID=CP_TABLE_SIZE> */
757    public final int tableSize;
758
759    /** <EMBED CLASS='external-html' DATA-FILE-ID=CP_TABLE_SIZE_BYTES> */
760    public final int tableSizeBytes;
761
762    /**
763     * <EMBED CLASS='external-html' DATA-FILE-ID=CP_TAGS>
764     * @see #tagNames
765     */
766    public final ReadOnlyList<Byte> tags;
767
768
769    /**
770     * <EMBED CLASS='external-html' DATA-FILE-ID=CP_VALUES>
771     * <EMBED CLASS='external-html' DATA-FILE-ID=CP_VALUES_TYPE_NOTE>
772     */
773    public final ReadOnlyList<Object> values;
774
775    /**
776     * <EMBED CLASS='external-html' DATA-FILE-ID=CP_DEREF_VALUES>
777     * <EMBED CLASS='external-html' DATA-FILE-ID=CP_DEREF_VAL_TABLE>
778     */
779    @LinkJavaSource(handle="DereferencedValue")
780    public final ReadOnlyList<Object> dereferencedValues;
781
782    /** Original Byte-Array Indices */
783    public final ReadOnlyList<Integer> indices;
784
785    /** <EMBED CLASS='external-html' DATA-FILE-ID=CP_INDICES_GROUP_BY> */
786    public final ReadOnlyList<ReadOnlyList<Integer>> indicesGroupBy;
787
788
789    // ********************************************************************************************
790    // ********************************************************************************************
791    // Static-Final Constants / ReadOnly Lookup-Tables as Lists.  (List-Index is the "Lookup Key")
792    // ********************************************************************************************
793    // ********************************************************************************************
794
795
796    @SuppressWarnings("rawtypes")
797    private static Ret2 dataFileR2 = LFEC.readObjectFromFile_JAR
798        (ConstantPool.class, "data-files/data3.r2dat", true, Ret2.class);
799
800
801    /**
802     * <EMBED CLASS='external-html' DATA-FILE-ID=CP_TAG_NAMES>
803     * <EMBED CLASS='external-html' DATA-FILE-ID=CP_TAG_NAMES_TABLE>
804     * @see #tags List of Types/Kinds for each Constant
805     * @see #values List of Values for each Constant
806     */
807    @LinkJavaSource(handle="ConstantPoolData", entity=FIELD, name="tagNames")
808    public static final ReadOnlyList<String> tagNames = dataFileR2.GET(1);
809
810
811    /**
812     * <EMBED CLASS='external-html' DATA-FILE-ID=CP_TAG_WIDTH_BYTES>
813     * <EMBED CLASS='external-html' DATA-FILE-ID=CP_TAG_WB_TABLE>
814     */
815    @LinkJavaSource(handle="ConstantPoolData", entity=FIELD, name="tagWidthBytes")
816    public static final ReadOnlyList<Byte> tagWidthBytes = dataFileR2.GET(2);
817
818
819    // Don't need it.  References are loaded into memory now.  Erase it for the G.C.
820    static { dataFileR2 = null; }
821
822
823    // ********************************************************************************************
824    // ********************************************************************************************
825    // Static Constants: This is the "inverse" of the "tagNames" List
826    // ********************************************************************************************
827    // ********************************************************************************************
828    // 
829    // 
830    // NOTE: Here is what I said-to / asked Chat-GPT:
831    // 
832    // It's Monday.  I did a flurry of Round-House Kicks at L.A. Fitness yesterday.  It took 3
833    // years of practice (it feels like) to be able to do that.  I have another Java-Doc
834    // Help/Question for you.  It is about my ConstantPool class again.  Do you think you could
835    // help me write some Java-Doc Comments?  Anywhere between 1 and three lines of Java-Doc would
836    // be great.  I cannot think after such a huge breakfast!
837    // 
838    // Above question was followed-By the list of ...
839    // `public static final byte` - Fields **BUT** WITHOUT the Java-Doc comments included below...
840    // 
841    // Below is how Chat-GPT replied to me (no changes were made to the output - not one character)
842
843    /** 
844     * Tag byte indicating the next constant in the table is a UTF-8 encoded {@code String}.
845     * Typically used for identifiers such as names or other textual data.
846     */
847    public static final byte TAG_UTF_8 = 1;
848
849    /** 
850     * Tag byte indicating the next constant in the table is a 32-bit integer.
851     * Used for numeric constants within the constant pool. 
852     */
853    public static final byte TAG_INTEGER = 3;
854
855    /** 
856     * Tag byte indicating the next constant in the table is a 32-bit floating-point number.
857     * Represents constants of the {@code float} data type.
858     */
859    public static final byte TAG_FLOAT = 4;
860
861    /** 
862     * Tag byte indicating the next constant in the table is a 64-bit long integer.
863     * Represents constants of the {@code long} data type.
864     */
865    public static final byte TAG_LONG = 5;
866
867    /** 
868     * Tag byte indicating the next constant in the table is a 64-bit double-precision floating-point number.
869     * Represents constants of the {@code double} data type.
870     */
871    public static final byte TAG_DOUBLE = 6;
872
873    /** 
874     * Tag byte indicating the next constant in the table is a class reference.
875     * Represents a {@code Class} or interface type.
876     */
877    public static final byte TAG_CLASS = 7;
878
879    /** 
880     * Tag byte indicating the next constant in the table is a {@code String} reference.
881     * The referenced {@code String} is stored elsewhere in the constant pool.
882     */
883    public static final byte TAG_STRING = 8;
884
885    /** 
886     * Tag byte indicating the next constant in the table is a reference to a field.
887     * Used for fields within a {@code Class} or interface.
888     */
889    public static final byte TAG_FIELD_REF = 9;
890
891    /** 
892     * Tag byte indicating the next constant in the table is a reference to a method.
893     * Refers to methods defined in a {@code Class}.
894     */
895    public static final byte TAG_METHOD_REF = 10;
896
897    /** 
898     * Tag byte indicating the next constant in the table is a reference to an interface method.
899     * Refers to methods declared within an interface.
900     */
901    public static final byte TAG_INTERFACE_METHOD_REF = 11;
902
903    /** 
904     * Tag byte indicating the next constant in the table is a name-and-type descriptor.
905     * Encodes the name and type of a field or method.
906     */
907    public static final byte TAG_NAME_AND_TYPE = 12;
908
909    /** 
910     * Tag byte indicating the next constant in the table is a method handle.
911     * Represents a reference to a method handle for dynamic invocation.
912     */
913    public static final byte TAG_METHOD_HANDLE = 15;
914
915    /** 
916     * Tag byte indicating the next constant in the table is a method type.
917     * Encodes the method's descriptor, including parameter and return types.
918     */
919    public static final byte TAG_METHOD_TYPE = 16;
920
921    /** 
922     * Tag byte indicating the next constant in the table is a dynamic constant.
923     * Represents a runtime-computed constant, often linked to lambdas or invokedynamic instructions.
924     */
925    public static final byte TAG_DYNAMIC = 17;
926
927    /** 
928     * Tag byte indicating the next constant in the table is an invoke-dynamic constant.
929     * Represents a bootstrap method and dynamic call site for runtime resolution.
930     */
931    public static final byte TAG_INVOKE_DYNAMIC = 18;
932
933    /** 
934     * Tag byte indicating the next constant in the table is a module reference.
935     * Encodes the name of a module within the constant pool.
936     */
937    public static final byte TAG_MODULE = 19;
938
939    /** 
940     * Tag byte indicating the next constant in the table is a package reference.
941     * Encodes the name of a package within the constant pool.
942     */
943    public static final byte TAG_PACKAGE = 20;
944
945
946    // ********************************************************************************************
947    // ********************************************************************************************
948    // Constructor
949    // ********************************************************************************************
950    // ********************************************************************************************
951
952
953    /**
954     * <EMBED CLASS='external-html' DATA-FILE-ID=CP_CONSTRUCTOR>
955     * @param bArr A Class-File which has been loaded from disk into a memory, as a Java
956     * {@code byte[]} Array.
957     */
958    @LinkJavaSource(handle="ConstPoolCtorHelper")
959    @LinkJavaSource(handle="ReadConstant")
960    @LinkJavaSource(handle="DereferencedValue")
961    @LinkJavaSource(handle="Validate")
962    public ConstantPool(final byte[] bArr)
963    {
964        RetN r = ConstPoolCtorHelper.construct(bArr);
965
966        this.tags               = r.GET(1);
967        this.values             = r.GET(2);
968        this.dereferencedValues = r.GET(3);
969        this.indices            = r.GET(4);
970        this.indicesGroupBy     = r.GET(5);
971        this.tableSizeBytes     = r.GET(6);
972
973        this.tableSize = this.tags.size();
974    }
975
976
977    // ********************************************************************************************
978    // ********************************************************************************************
979    // java.lang.Object Methods
980    // ********************************************************************************************
981    // ********************************************************************************************
982
983
984    /**
985     * Converts the contents of an instance of this class into a User-Readable {@code String}.
986     * @return A Java-{@code String} which explicates a Java {@code '.class'} File's Constant-Pool.
987     */
988    @LinkJavaSource(handle="CPToString")
989    public String toString()
990    { return CPToString.str(this.tags, this.values, this.indicesGroupBy); }
991
992    /**
993     * Checks for equality with another instance of {@code ConstantPool}.
994     * 
995     * @param other Any Java-{@code Object}, but only an instance of {@code ConstantPool} whose 
996     * {@link #tags} and {@link #values} Array-Lists are equal will cause this method to return
997     * {@code TRUE}.
998     * 
999     * @return {@code TRUE} if and only if the contents {@code 'this'} instance of Constant-Pool 
1000     * equals those found in parameter {@code 'other'}
1001     */
1002    public boolean equals(Object other)
1003    {
1004        if (! (other instanceof ConstantPool)) return false;
1005
1006        ConstantPool o = (ConstantPool) other;
1007
1008        return
1009                this.tags.equals(o.tags)
1010            &&  this.values.equals(o.values)
1011            &&  this.indices.equals(o.indices);
1012    }
1013
1014    /**
1015     * Java's traditional Hash-Code generator Method.
1016     * 
1017     * @return a (plausibly unique) Hash-Code, which may be used for placing instances of
1018     * {@code ConstantPool} into Hash-Tables.
1019     */
1020    public int hashCode()
1021    {
1022        // No, this isn't any good... To-Do: Worry about it...
1023        int hash = 0;
1024        for (Byte tag : this.tags) if (tag != null) hash += tag;
1025        return hash;
1026    }
1027
1028
1029    // ********************************************************************************************
1030    // ********************************************************************************************
1031    // Some Easy-To-Use and Easy-To-Write Getters
1032    // ********************************************************************************************
1033    // ********************************************************************************************
1034
1035
1036    /**
1037     * Retrieves the names of all Field-References which were listed in the Constant-Pool
1038     * table that was used to build {@code 'this'} instance.
1039     * 
1040     * @return A Java-{@code Stream} containing the names of any / all fields from the table.
1041     */
1042    @LinkJavaSource(handle="AllNames", name="getAllFieldNames")
1043    public Stream<String> allFieldNames()
1044    {
1045        return AllNames.getAllFieldNames(
1046            this.indicesGroupBy.get(ConstantPool.TAG_FIELD_REF),
1047            this.values
1048        );
1049    }
1050
1051    /**
1052     * <EMBED CLASS='external-html' DATA-FILE-ID=CP_GET_ALL_METHNAME>
1053     * 
1054     * @return A Java-{@code Stream<String>} containing the names of any / all methods and
1055     * "Method References" from the Constant-Pool Table.
1056     */
1057    @LinkJavaSource(handle="AllNames", name="getAllMethodNames")
1058    public Stream<String> allMethodNames()
1059    {
1060        return AllNames.getAllMethodNames(
1061            this.indicesGroupBy.get(ConstantPool.TAG_METHOD_REF),
1062            this.indicesGroupBy.get(ConstantPool.TAG_INTERFACE_METHOD_REF),
1063            this.values
1064        );
1065    }
1066
1067    /**
1068     * All Constants in this Pool whose Tag-Kind are:
1069     * 
1070     * <BR /><BR /><UL CLASS=JDUL>
1071     * <LI><B>{@link #TAG_FIELD_REF}</B> (9)</LI>
1072     * </UL>
1073     * 
1074     * @return All Field-References contained by {@code 'this'} table.  The Java {@code Stream}
1075     * which is returned contains instances of {@link ConstantPool.Reference}.
1076     * 
1077     * @see #dereferencedValues
1078     * @see #indicesGroupBy
1079     */
1080    @SuppressWarnings("unchecked")
1081    public Stream<ConstantPool.Reference> allFields()
1082    {
1083        return this.indicesGroupBy
1084            .get(ConstantPool.TAG_FIELD_REF)
1085            .stream()
1086            .map((Integer index) -> (ConstantPool.Reference) this.dereferencedValues.get(index));
1087    }
1088
1089    /**
1090     * All Constants in this Pool whose Tag-Kind are:
1091     * 
1092     * <BR /><BR /><UL CLASS=JDUL>
1093     * <LI><B>{@link #TAG_METHOD_REF}</B> (10)</LI>
1094     * <LI><B>{@link #TAG_INTERFACE_METHOD_REF}</B> (10)</LI>
1095     * </UL>
1096     * 
1097     * @return All Method-References contained by {@code 'this'} table.  The Java {@code Stream}
1098     * which is returned contains instances of {@link ConstantPool.Reference}. 
1099     * 
1100     * @see #dereferencedValues
1101     * @see #indicesGroupBy
1102     */
1103    @SuppressWarnings("unchecked")
1104    public Stream<ConstantPool.Reference> allMethods()
1105    {
1106        return Stream.concat(
1107                this.indicesGroupBy.get(ConstantPool.TAG_METHOD_REF).stream(),
1108                this.indicesGroupBy.get(ConstantPool.TAG_INTERFACE_METHOD_REF).stream()
1109            )
1110            .map((Integer index) -> (ConstantPool.Reference) this.dereferencedValues.get(index));
1111    }
1112}