1   // Copyright 2012- Bill Campbell, Swami Iyer and Bahar Akbal-Delibas
2   
3   package jminusminus;
4   
5   import java.io.DataOutputStream;
6   import java.io.IOException;
7   
8   import static jminusminus.CLConstants.*;
9   
10  /**
11   * Representation of cp_info structure.
12   */
13  abstract class CLCPInfo {
14      /**
15       * Index of this object in the constant pool.
16       */
17      public int cpIndex;
18  
19      /**
20       * cp_info.tag item.
21       */
22      public short tag;
23  
24      /**
25       * Writes the contents of this constant pool item to the specified output stream.
26       *
27       * @param out output stream.
28       * @throws IOException if an error occurs while writing.
29       */
30      public void write(CLOutputStream out) throws IOException {
31          out.writeByte(tag);
32      }
33  
34      /**
35       * Return true if this CLCPInfo object is the same as other, and false otherwise.
36       *
37       * @param other the reference CLCPInfo object with which to compare.
38       * @return true if this CLCPInfo object is the same as other, and false otherwise.
39       */
40      public boolean equals(Object other) {
41          return false;
42      }
43  }
44  
45  /**
46   * Representation of CONSTANT_Class_info structure.
47   */
48  class CLConstantClassInfo extends CLCPInfo {
49      /**
50       * CONSTANT_Class_info.name_index item.
51       */
52      public int nameIndex;
53  
54      /**
55       * Constructs a CLConstantClassInfo object.
56       *
57       * @param nameIndex CONSTANT_Class_info.name_index item.
58       */
59      public CLConstantClassInfo(int nameIndex) {
60          super.tag = CONSTANT_Class;
61          this.nameIndex = nameIndex;
62      }
63  
64      /**
65       * {@inheritDoc}
66       */
67      public void write(CLOutputStream out) throws IOException {
68          super.write(out);
69          out.writeShort(nameIndex);
70      }
71  
72      /**
73       * {@inheritDoc}
74       */
75      public boolean equals(Object other) {
76          if (other instanceof CLConstantClassInfo) {
77              CLConstantClassInfo c = (CLConstantClassInfo) other;
78              if (c.nameIndex == nameIndex) {
79                  return true;
80              }
81          }
82          return false;
83      }
84  }
85  
86  /**
87   * Abstract super class of CONSTANT_Fieldref_info, CONSTANT_Methodref_info,
88   * CONSTANT_InterfaceMethodref_info structures.
89   */
90  abstract class CLConstantMemberRefInfo extends CLCPInfo {
91      /**
92       * CONSTANT_Memberref_info.class_index item.
93       */
94      public int classIndex;
95  
96      /**
97       * CONSTANT_Memberref_info.name_and_type_index item.
98       */
99      public int nameAndTypeIndex;
100 
101     /**
102      * Constructs a CLConstantMemberRefInfo object.
103      *
104      * @param classIndex       CONSTANT_Memberref_info.class_index item.
105      * @param nameAndTypeIndex CONSTANT_Memberref_info.name_and_type_index item.
106      * @param tag              CONSTANT_Memberref_info.tag item.
107      */
108     protected CLConstantMemberRefInfo(int classIndex, int nameAndTypeIndex, short tag) {
109         super.tag = tag;
110         this.classIndex = classIndex;
111         this.nameAndTypeIndex = nameAndTypeIndex;
112     }
113 
114     /**
115      * {@inheritDoc}
116      */
117     public void write(CLOutputStream out) throws IOException {
118         super.write(out);
119         out.writeShort(classIndex);
120         out.writeShort(nameAndTypeIndex);
121     }
122 
123     /**
124      * {@inheritDoc}
125      */
126     public boolean equals(Object other) {
127         if (other instanceof CLConstantMemberRefInfo) {
128             CLConstantMemberRefInfo c = (CLConstantMemberRefInfo) other;
129             if ((c.tag == tag) && (c.classIndex == classIndex)
130                     && (c.nameAndTypeIndex == nameAndTypeIndex)) {
131                 return true;
132             }
133         }
134         return false;
135     }
136 }
137 
138 /**
139  * Representation of CONSTANT_Fieldref_info structure.
140  */
141 class CLConstantFieldRefInfo extends CLConstantMemberRefInfo {
142     /**
143      * Constructs a CLConstantFieldRefInfo object.
144      *
145      * @param classIndex       CONSTANT_Fieldref_info.class_index item.
146      * @param nameAndTypeIndex CONSTANT_Fieldref_info.name_and_type_index item.
147      */
148 
149     public CLConstantFieldRefInfo(int classIndex, int nameAndTypeIndex) {
150         super(classIndex, nameAndTypeIndex, CONSTANT_Fieldref);
151     }
152 }
153 
154 /**
155  * Representation of CONSTANT_Methodref_info structure.
156  */
157 class CLConstantMethodRefInfo extends CLConstantMemberRefInfo {
158     /**
159      * Constructs a CLConstantMethodRefInfo object.
160      *
161      * @param classIndex       CONSTANT_Methodref_info.class_index item.
162      * @param nameAndTypeIndex CONSTANT_Methodref_info.name_and_type_index item.
163      */
164     public CLConstantMethodRefInfo(int classIndex, int nameAndTypeIndex) {
165         super(classIndex, nameAndTypeIndex, CONSTANT_Methodref);
166     }
167 }
168 
169 /**
170  * Representation of CONSTANT_InterfaceMethodref_info structure.
171  */
172 class CLConstantInterfaceMethodRefInfo extends CLConstantMemberRefInfo {
173     /**
174      * Constructs a CLConstantInterfaceMethodRefInfo object.
175      *
176      * @param classIndex       CONSTANT_InterfaceMethodref_info.class_index item.
177      * @param nameAndTypeIndex CONSTANT_InterfaceMethodref_info.name_and_type_index item.
178      */
179     public CLConstantInterfaceMethodRefInfo(int classIndex, int nameAndTypeIndex) {
180         super(classIndex, nameAndTypeIndex, CONSTANT_InterfaceMethodref);
181     }
182 }
183 
184 /**
185  * Representation of CONSTANT_String_info structure.
186  */
187 class CLConstantStringInfo extends CLCPInfo {
188     /**
189      * CONSTANT_String_info.string_index item.
190      */
191     public int stringIndex;
192 
193     /**
194      * Constructs a CLConstantStringInfo object.
195      *
196      * @param stringIndex CONSTANT_String_info.string_index item.
197      */
198     public CLConstantStringInfo(int stringIndex) {
199         super.tag = CONSTANT_String;
200         this.stringIndex = stringIndex;
201     }
202 
203     /**
204      * {@inheritDoc}
205      */
206     public void write(CLOutputStream out) throws IOException {
207         super.write(out);
208         out.writeShort(stringIndex);
209     }
210 
211     /**
212      * {@inheritDoc}
213      */
214     public boolean equals(Object other) {
215         if (other instanceof CLConstantStringInfo) {
216             CLConstantStringInfo c = (CLConstantStringInfo) other;
217             if (c.stringIndex == stringIndex) {
218                 return true;
219             }
220         }
221         return false;
222     }
223 }
224 
225 /**
226  * Representation of CONSTANT_Integer_info structure.
227  */
228 class CLConstantIntegerInfo extends CLCPInfo {
229     /**
230      * The int number.
231      */
232     public int i;
233 
234     /**
235      * Constructs a CLConstantIntegerInfo object.
236      *
237      * @param i the int number.
238      */
239     public CLConstantIntegerInfo(int i) {
240         super.tag = CONSTANT_Integer;
241         this.i = i;
242     }
243 
244     /**
245      * Returns CONSTANT_Integer_info.bytes item.
246      *
247      * @return CONSTANT_Integer_info.bytes item.
248      */
249     public short[] bytes() {
250         short[] s = new short[4];
251         short mask = 0xFF;
252         int k = i;
253         for (int j = 0; j < 4; j++) {
254             s[3 - j] = (short) (k & mask);
255             k >>>= 8;
256         }
257         return s;
258     }
259 
260     /**
261      * {@inheritDoc}
262      */
263     public void write(CLOutputStream out) throws IOException {
264         super.write(out);
265 
266         // out is cast to DataOutputStream to resolve the writeInt() ambiguity.
267         ((DataOutputStream) out).writeInt(i);
268     }
269 
270     /**
271      * {@inheritDoc}
272      */
273     public boolean equals(Object other) {
274         if (other instanceof CLConstantIntegerInfo) {
275             CLConstantIntegerInfo c = (CLConstantIntegerInfo) other;
276             if (c.i == i) {
277                 return true;
278             }
279         }
280         return false;
281     }
282 }
283 
284 /**
285  * Representation of CONSTANT_Float_info structure.
286  */
287 class CLConstantFloatInfo extends CLCPInfo {
288     /**
289      * The floating-point number.
290      */
291     public float f;
292 
293     /**
294      * Constructs a CLConstantFloatInfo object.
295      *
296      * @param f the floating-point number.
297      */
298     public CLConstantFloatInfo(float f) {
299         super.tag = CONSTANT_Float;
300         this.f = f;
301     }
302 
303     /**
304      * Returns CONSTANT_Float_info.bytes item.
305      *
306      * @return CONSTANT_Float_info.bytes item.
307      */
308     public short[] bytes() {
309         short[] s = new short[4];
310         short mask = 0xFF;
311         int i = Float.floatToIntBits(f);
312         for (int j = 0; j < 4; j++) {
313             s[3 - j] = (short) (i & mask);
314             i >>>= 8;
315         }
316         return s;
317     }
318 
319     /**
320      * {@inheritDoc}
321      */
322     public void write(CLOutputStream out) throws IOException {
323         super.write(out);
324         out.writeFloat(f);
325     }
326 
327     /**
328      * {@inheritDoc}
329      */
330     public boolean equals(Object other) {
331         if (other instanceof CLConstantFloatInfo) {
332             CLConstantFloatInfo c = (CLConstantFloatInfo) other;
333             if (c.f == f) {
334                 return true;
335             }
336         }
337         return false;
338     }
339 }
340 
341 /**
342  * Representation of CONSTANT_Long_info structure.
343  */
344 class CLConstantLongInfo extends CLCPInfo {
345     /**
346      * The long number.
347      */
348     public long l;
349 
350     /**
351      * Returns the 8 bytes of the long value.
352      *
353      * @return the 8 bytes of the long value.
354      */
355     private short[] bytes() {
356         short[] s = new short[8];
357         short mask = 0xFF;
358         long k = l;
359         for (int j = 0; j < 8; j++) {
360             s[7 - j] = (short) (k & mask);
361             k >>>= 8;
362         }
363         return s;
364     }
365 
366     /**
367      * Constructs a CLConstantLongInfo object.
368      *
369      * @param l the long number.
370      */
371     public CLConstantLongInfo(long l) {
372         super.tag = CONSTANT_Long;
373         this.l = l;
374     }
375 
376     /**
377      * Returns CONSTANT_Long_info.low_bytes item.
378      *
379      * @return CONSTANT_Long_info.low_bytes item.
380      */
381     public short[] lowBytes() {
382         short[] s = bytes();
383         short[] l = new short[4];
384         l[0] = s[4];
385         l[1] = s[5];
386         l[2] = s[6];
387         l[3] = s[7];
388         return l;
389     }
390 
391     /**
392      * Returns CONSTANT_Long_info.high_bytes item.
393      *
394      * @return CONSTANT_Long_info.high_bytes item.
395      */
396     public short[] highBytes() {
397         short[] s = bytes();
398         short[] h = new short[4];
399         h[0] = s[0];
400         h[1] = s[1];
401         h[2] = s[2];
402         h[3] = s[3];
403         return h;
404     }
405 
406     /**
407      * {@inheritDoc}
408      */
409     public void write(CLOutputStream out) throws IOException {
410         super.write(out);
411         out.writeLong(l);
412     }
413 
414     /**
415      * {@inheritDoc}
416      */
417     public boolean equals(Object other) {
418         if (other instanceof CLConstantLongInfo) {
419             CLConstantLongInfo c = (CLConstantLongInfo) other;
420             if (c.l == l) {
421                 return true;
422             }
423         }
424         return false;
425     }
426 }
427 
428 /**
429  * Representation of CONSTANT_Double_info structure.
430  */
431 class CLConstantDoubleInfo extends CLCPInfo {
432     /**
433      * The double precision floating-point number.
434      */
435     public double d;
436 
437     /**
438      * Returns the 8 bytes of the double precision floating-point value.
439      *
440      * @return the 8 bytes of the double precision floating-point value.
441      */
442     private short[] bytes() {
443         short[] s = new short[8];
444         short mask = 0xFF;
445         long l = Double.doubleToLongBits(d);
446         for (int j = 0; j < 8; j++) {
447             s[7 - j] = (short) (l & mask);
448             l >>>= 8;
449         }
450         return s;
451     }
452 
453     /**
454      * Constructs a CLConstantDoubleInfo object.
455      *
456      * @param d the double precision floating-point number.
457      */
458     public CLConstantDoubleInfo(double d) {
459         super.tag = CONSTANT_Double;
460         this.d = d;
461     }
462 
463     /**
464      * Returns CONSTANT_Double_info.low_bytes item.
465      *
466      * @return CONSTANT_Double_info.low_bytes item.
467      */
468     public short[] lowBytes() {
469         short[] s = bytes();
470         short[] l = new short[4];
471         l[0] = s[4];
472         l[1] = s[5];
473         l[2] = s[6];
474         l[3] = s[7];
475         return l;
476     }
477 
478     /**
479      * Returns CONSTANT_Double_info.high_bytes item.
480      *
481      * @return CONSTANT_Double_info.high_bytes item.
482      */
483     public short[] highBytes() {
484         short[] s = bytes();
485         short[] h = new short[4];
486         h[0] = s[0];
487         h[1] = s[1];
488         h[2] = s[2];
489         h[3] = s[3];
490         return h;
491     }
492 
493     /**
494      * {@inheritDoc}
495      */
496     public void write(CLOutputStream out) throws IOException {
497         super.write(out);
498         out.writeDouble(d);
499     }
500 
501     /**
502      * {@inheritDoc}
503      */
504     public boolean equals(Object other) {
505         if (other instanceof CLConstantDoubleInfo) {
506             CLConstantDoubleInfo c = (CLConstantDoubleInfo) other;
507             if (c.d == d) {
508                 return true;
509             }
510         }
511         return false;
512     }
513 }
514 
515 /**
516  * Representation of CONSTANT_NameAndType_info structure.
517  */
518 class CLConstantNameAndTypeInfo extends CLCPInfo {
519     /**
520      * CONSTANT_NameAndType_info.name_index item.
521      */
522     public int nameIndex;
523 
524     /**
525      * CONSTANT_NameAndType_info.descriptor_index item.
526      */
527     public int descriptorIndex;
528 
529     /**
530      * Constructs a CLConstantNameAndTypeInfo object.
531      *
532      * @param nameIndex       CONSTANT_NameAndType_info.name_index item.
533      * @param descriptorIndex CONSTANT_NameAndType_info.descriptor_index item.
534      */
535     public CLConstantNameAndTypeInfo(int nameIndex, int descriptorIndex) {
536         super.tag = CONSTANT_NameAndType;
537         this.nameIndex = nameIndex;
538         this.descriptorIndex = descriptorIndex;
539     }
540 
541     /**
542      * {@inheritDoc}
543      */
544     public void write(CLOutputStream out) throws IOException {
545         super.write(out);
546         out.writeShort(nameIndex);
547         out.writeShort(descriptorIndex);
548     }
549 
550     /**
551      * {@inheritDoc}
552      */
553 
554     public boolean equals(Object other) {
555         if (other instanceof CLConstantNameAndTypeInfo) {
556             CLConstantNameAndTypeInfo c = (CLConstantNameAndTypeInfo) other;
557             if ((c.nameIndex == nameIndex) && (c.descriptorIndex == descriptorIndex)) {
558                 return true;
559             }
560         }
561         return false;
562     }
563 }
564 
565 /**
566  * Representation of CONSTANT_Utf8_info structure.
567  */
568 class CLConstantUtf8Info extends CLCPInfo {
569     /**
570      * CONSTANT_Utf8_info.bytes item.
571      */
572     public byte[] b;
573 
574     /**
575      * Constructs a CLConstantUtf8Info object.
576      *
577      * @param b a constant string value.
578      */
579     public CLConstantUtf8Info(byte[] b) {
580         super.tag = CONSTANT_Utf8;
581         this.b = b;
582     }
583 
584     /**
585      * Returns CONSTANT_Utf8_info.length item.
586      *
587      * @return CONSTANT_Utf8_info.length item.
588      */
589     public int length() {
590         return b.length;
591     }
592 
593     /**
594      * {@inheritDoc}
595      */
596     public void write(CLOutputStream out) throws IOException {
597         super.write(out);
598         out.writeUTF(new String(b));
599     }
600 
601     /**
602      * {@inheritDoc}
603      */
604     public boolean equals(Object other) {
605         if (other instanceof CLConstantUtf8Info) {
606             CLConstantUtf8Info c = (CLConstantUtf8Info) other;
607             if ((new String(b)).equals(new String(c.b))) {
608                 return true;
609             }
610         }
611         return false;
612     }
613 }
614