1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000-2005 INRIA, France Telecom
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  *    contributors may be used to endorse or promote products derived from
16  *    this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 package org.objectweb.asm.optimizer;
31 
32 import org.objectweb.asm.ClassWriter;
33 
34 /**
35  * A constant pool item.
36  *
37  * @author Eric Bruneton
38  */
39 class Constant {
40 
41     /**
42      * Type of this constant pool item. A single class is used to represent all
43      * constant pool item types, in order to minimize the bytecode size of this
44      * package. The value of this field is I, J, F, D, S, s, C, T, G, M, or N
45      * (for Constant Integer, Long, Float, Double, STR, UTF8, Class, NameType,
46      * Fieldref, Methodref, or InterfaceMethodref constant pool items
47      * respectively).
48      */
49     char type;
50 
51     /**
52      * Value of this item, for an integer item.
53      */
54     int intVal;
55 
56     /**
57      * Value of this item, for a long item.
58      */
59     long longVal;
60 
61     /**
62      * Value of this item, for a float item.
63      */
64     float floatVal;
65 
66     /**
67      * Value of this item, for a double item.
68      */
69     double doubleVal;
70 
71     /**
72      * First part of the value of this item, for items that do not hold a
73      * primitive value.
74      */
75     String strVal1;
76 
77     /**
78      * Second part of the value of this item, for items that do not hold a
79      * primitive value.
80      */
81     String strVal2;
82 
83     /**
84      * Third part of the value of this item, for items that do not hold a
85      * primitive value.
86      */
87     String strVal3;
88 
89     /**
90      * The hash code value of this constant pool item.
91      */
92     int hashCode;
93 
94     public Constant() {
95     }
96 
97     public Constant(final Constant i) {
98         type = i.type;
99         intVal = i.intVal;
100         longVal = i.longVal;
101         floatVal = i.floatVal;
102         doubleVal = i.doubleVal;
103         strVal1 = i.strVal1;
104         strVal2 = i.strVal2;
105         strVal3 = i.strVal3;
106         hashCode = i.hashCode;
107     }
108 
109     /**
110      * Sets this item to an integer item.
111      *
112      * @param intVal the value of this item.
113      */
114     void set(final int intVal) {
115         this.type = 'I';
116         this.intVal = intVal;
117         this.hashCode = 0x7FFFFFFF & (type + intVal);
118     }
119 
120     /**
121      * Sets this item to a long item.
122      *
123      * @param longVal the value of this item.
124      */
125     void set(final long longVal) {
126         this.type = 'J';
127         this.longVal = longVal;
128         this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
129     }
130 
131     /**
132      * Sets this item to a float item.
133      *
134      * @param floatVal the value of this item.
135      */
136     void set(final float floatVal) {
137         this.type = 'F';
138         this.floatVal = floatVal;
139         this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
140     }
141 
142     /**
143      * Sets this item to a double item.
144      *
145      * @param doubleVal the value of this item.
146      */
147     void set(final double doubleVal) {
148         this.type = 'D';
149         this.doubleVal = doubleVal;
150         this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
151     }
152 
153     /**
154      * Sets this item to an item that do not hold a primitive value.
155      *
156      * @param type the type of this item.
157      * @param strVal1 first part of the value of this item.
158      * @param strVal2 second part of the value of this item.
159      * @param strVal3 third part of the value of this item.
160      */
161     void set(
162         final char type,
163         final String strVal1,
164         final String strVal2,
165         final String strVal3)
166     {
167         this.type = type;
168         this.strVal1 = strVal1;
169         this.strVal2 = strVal2;
170         this.strVal3 = strVal3;
171         switch (type) {
172             case 's':
173             case 'S':
174             case 'C':
175                 hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
176                 return;
177             case 'T':
178                 hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
179                         * strVal2.hashCode());
180                 return;
181             // case 'G':
182             // case 'M':
183             // case 'N':
184             default:
185                 hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
186                         * strVal2.hashCode() * strVal3.hashCode());
187         }
188     }
189 
190     void write(final ClassWriter cw) {
191         switch (type) {
192             case 'I':
193                 cw.newConst(new Integer(intVal));
194                 break;
195             case 'J':
196                 cw.newConst(new Long(longVal));
197                 break;
198             case 'F':
199                 cw.newConst(new Float(floatVal));
200                 break;
201             case 'D':
202                 cw.newConst(new Double(doubleVal));
203                 break;
204             case 'S':
205                 cw.newConst(strVal1);
206                 break;
207             case 's':
208                 cw.newUTF8(strVal1);
209                 break;
210             case 'C':
211                 cw.newClass(strVal1);
212                 break;
213             case 'T':
214                 cw.newNameType(strVal1, strVal2);
215                 break;
216             case 'G':
217                 cw.newField(strVal1, strVal2, strVal3);
218                 break;
219             case 'M':
220                 cw.newMethod(strVal1, strVal2, strVal3, false);
221                 break;
222             case 'N':
223                 cw.newMethod(strVal1, strVal2, strVal3, true);
224                 break;
225         }
226     }
227 
228     public boolean equals(final Object o) {
229         if (!(o instanceof Constant)) {
230             return false;
231         }
232         Constant c = (Constant) o;
233         if (c.type == type) {
234             switch (type) {
235                 case 'I':
236                     return c.intVal == intVal;
237                 case 'J':
238                     return c.longVal == longVal;
239                 case 'F':
240                     return c.floatVal == floatVal;
241                 case 'D':
242                     return c.doubleVal == doubleVal;
243                 case 's':
244                 case 'S':
245                 case 'C':
246                     return c.strVal1.equals(strVal1);
247                 case 'T':
248                     return c.strVal1.equals(strVal1)
249                             && c.strVal2.equals(strVal2);
250                 // case 'G':
251                 // case 'M':
252                 // case 'N':
253                 default:
254                     return c.strVal1.equals(strVal1)
255                             && c.strVal2.equals(strVal2)
256                             && c.strVal3.equals(strVal3);
257             }
258         }
259         return false;
260     }
261 
262     public int hashCode() {
263         return hashCode;
264     }
265 }
266