001    /***
002     * ASM: a very small and fast Java bytecode manipulation framework
003     * Copyright (c) 2000-2005 INRIA, France Telecom
004     * All rights reserved.
005     *
006     * Redistribution and use in source and binary forms, with or without
007     * modification, are permitted provided that the following conditions
008     * are met:
009     * 1. Redistributions of source code must retain the above copyright
010     *    notice, this list of conditions and the following disclaimer.
011     * 2. Redistributions in binary form must reproduce the above copyright
012     *    notice, this list of conditions and the following disclaimer in the
013     *    documentation and/or other materials provided with the distribution.
014     * 3. Neither the name of the copyright holders nor the names of its
015     *    contributors may be used to endorse or promote products derived from
016     *    this software without specific prior written permission.
017     *
018     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028     * THE POSSIBILITY OF SUCH DAMAGE.
029     */
030    package net.sourceforge.retroweaver.optimizer;
031    
032    import org.objectweb.asm.ClassWriter;
033    
034    /**
035     * A constant pool item.
036     * 
037     * @author Eric Bruneton
038     */
039    public
040    class Constant {
041    
042        /**
043         * Type of this constant pool item. A single class is used to represent all
044         * constant pool item types, in order to minimize the bytecode size of this
045         * package. The value of this field is I, J, F, D, S, s, C, T, G, M, or N
046         * (for Constant Integer, Long, Float, Double, STR, UTF8, Class, NameType,
047         * Fieldref, Methodref, or InterfaceMethodref constant pool items
048         * respectively).
049         */
050        char type;
051    
052        /**
053         * Value of this item, for an integer item.
054         */
055        int intVal;
056    
057        /**
058         * Value of this item, for a long item.
059         */
060        long longVal;
061    
062        /**
063         * Value of this item, for a float item.
064         */
065        float floatVal;
066    
067        /**
068         * Value of this item, for a double item.
069         */
070        double doubleVal;
071    
072        /**
073         * First part of the value of this item, for items that do not hold a
074         * primitive value.
075         */
076        String strVal1;
077    
078        /**
079         * Second part of the value of this item, for items that do not hold a
080         * primitive value.
081         */
082        String strVal2;
083    
084        /**
085         * Third part of the value of this item, for items that do not hold a
086         * primitive value.
087         */
088        String strVal3;
089    
090        /**
091         * The hash code value of this constant pool item.
092         */
093        int hashCode;
094    
095        public Constant() {
096        }
097    
098        public Constant(final Constant i) {
099            type = i.type;
100            intVal = i.intVal;
101            longVal = i.longVal;
102            floatVal = i.floatVal;
103            doubleVal = i.doubleVal;
104            strVal1 = i.strVal1;
105            strVal2 = i.strVal2;
106            strVal3 = i.strVal3;
107            hashCode = i.hashCode;
108        }
109    
110        /**
111         * Sets this item to an integer item.
112         * 
113         * @param intVal the value of this item.
114         */
115        void set(final int intVal) {
116            this.type = 'I';
117            this.intVal = intVal;
118            this.hashCode = 0x7FFFFFFF & (type + intVal);
119        }
120    
121        /**
122         * Sets this item to a long item.
123         * 
124         * @param longVal the value of this item.
125         */
126        void set(final long longVal) {
127            this.type = 'J';
128            this.longVal = longVal;
129            this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
130        }
131    
132        /**
133         * Sets this item to a float item.
134         * 
135         * @param floatVal the value of this item.
136         */
137        void set(final float floatVal) {
138            this.type = 'F';
139            this.floatVal = floatVal;
140            this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
141        }
142    
143        /**
144         * Sets this item to a double item.
145         * 
146         * @param doubleVal the value of this item.
147         */
148        void set(final double doubleVal) {
149            this.type = 'D';
150            this.doubleVal = doubleVal;
151            this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
152        }
153    
154        /**
155         * Sets this item to an item that do not hold a primitive value.
156         * 
157         * @param type the type of this item.
158         * @param strVal1 first part of the value of this item.
159         * @param strVal2 second part of the value of this item.
160         * @param strVal3 third part of the value of this item.
161         */
162        void set(
163            final char type,
164            final String strVal1,
165            final String strVal2,
166            final String strVal3)
167        {
168            this.type = type;
169            this.strVal1 = strVal1;
170            this.strVal2 = strVal2;
171            this.strVal3 = strVal3;
172            switch (type) {
173                case 's':
174                case 'S':
175                case 'C':
176                    hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
177                    return;
178                case 'T':
179                    hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
180                            * strVal2.hashCode());
181                    return;
182                // case 'G':
183                // case 'M':
184                // case 'N':
185                default:
186                    hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
187                            * strVal2.hashCode() * strVal3.hashCode());
188            }
189        }
190    
191        public
192        void write(final ClassWriter cw) {
193            switch (type) {
194                case 'I':
195                    cw.newConst(new Integer(intVal)); // NOPMD by xlv
196                    break;
197                case 'J':
198                    cw.newConst(new Long(longVal));
199                    break;
200                case 'F':
201                    cw.newConst(new Float(floatVal));
202                    break;
203                case 'D':
204                    cw.newConst(new Double(doubleVal));
205                    break;
206                case 'S':
207                    cw.newConst(strVal1);
208                    break;
209                case 's':
210                    cw.newUTF8(strVal1);
211                    break;
212                case 'C':
213                    cw.newClass(strVal1);
214                    break;
215                case 'T':
216                    cw.newNameType(strVal1, strVal2);
217                    break;
218                case 'G':
219                    cw.newField(strVal1, strVal2, strVal3);
220                    break;
221                case 'M':
222                    cw.newMethod(strVal1, strVal2, strVal3, false);
223                    break;
224                case 'N':
225                    cw.newMethod(strVal1, strVal2, strVal3, true);
226                    break;
227            }
228        }
229    
230        public boolean equals(final Object o) {
231            if (!(o instanceof Constant)) {
232                return false;
233            }
234            Constant c = (Constant) o;
235            if (c.type == type) {
236                switch (type) {
237                    case 'I':
238                        return c.intVal == intVal;
239                    case 'J':
240                        return c.longVal == longVal;
241                    case 'F':
242                        return c.floatVal == floatVal;
243                    case 'D':
244                        return c.doubleVal == doubleVal;
245                    case 's':
246                    case 'S':
247                    case 'C':
248                        return c.strVal1.equals(strVal1);
249                    case 'T':
250                        return c.strVal1.equals(strVal1)
251                                && c.strVal2.equals(strVal2);
252                    // case 'G':
253                    // case 'M':
254                    // case 'N':
255                    default:
256                        return c.strVal1.equals(strVal1)
257                                && c.strVal2.equals(strVal2)
258                                && c.strVal3.equals(strVal3);
259                }
260            }
261            return false;
262        }
263    
264        public int hashCode() {
265            return hashCode;
266        }
267    }