• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 package proguard.classfile.editor;
22 
23 import proguard.classfile.*;
24 import proguard.classfile.constant.*;
25 import proguard.classfile.constant.visitor.ConstantVisitor;
26 import proguard.classfile.util.SimplifiedVisitor;
27 
28 
29 /**
30  * This class is a <code>Comparable</code> wrapper of <code>Constant</code>
31  * objects. It can store an index, in order to identify the constant   pool
32  * entry after it has been sorted. The comparison is primarily based   on the
33  * types of the constant pool entries, and secondarily on the contents of
34  * the constant pool entries.
35  *
36  * @author Eric Lafortune
37  */
38 class      ComparableConstant
39 extends    SimplifiedVisitor
40 implements Comparable, ConstantVisitor
41 {
42     private static final int[] PRIORITIES = new int[13];
43     static
44     {
45         PRIORITIES[ClassConstants.CONSTANT_Integer]            = 0; // Possibly byte index (ldc).
46         PRIORITIES[ClassConstants.CONSTANT_Float]              = 1;
47         PRIORITIES[ClassConstants.CONSTANT_String]             = 2;
48         PRIORITIES[ClassConstants.CONSTANT_Class]              = 3;
49         PRIORITIES[ClassConstants.CONSTANT_Long]               = 4; // Always wide index (ldc2_w).
50         PRIORITIES[ClassConstants.CONSTANT_Double]             = 5;
51         PRIORITIES[ClassConstants.CONSTANT_Fieldref]           = 6; // Always wide index.
52         PRIORITIES[ClassConstants.CONSTANT_Methodref]          = 7;
53         PRIORITIES[ClassConstants.CONSTANT_InterfaceMethodref] = 8;
54         PRIORITIES[ClassConstants.CONSTANT_NameAndType]        = 9;
55         PRIORITIES[ClassConstants.CONSTANT_Utf8]               = 10;
56     }
57 
58     private final Clazz    clazz;
59     private final int      thisIndex;
60     private final Constant thisConstant;
61 
62     private Constant otherConstant;
63     private int      result;
64 
65 
ComparableConstant(Clazz clazz, int index, Constant constant)66     public ComparableConstant(Clazz clazz, int index, Constant constant)
67     {
68         this.clazz        = clazz;
69         this.thisIndex    = index;
70         this.thisConstant = constant;
71     }
72 
73 
getIndex()74     public int getIndex()
75     {
76         return thisIndex;
77     }
78 
79 
getConstant()80     public Constant getConstant()
81     {
82         return thisConstant;
83     }
84 
85 
86     // Implementations for Comparable.
87 
compareTo(Object other)88     public int compareTo(Object other)
89     {
90         ComparableConstant otherComparableConstant = (ComparableConstant)other;
91 
92         otherConstant = otherComparableConstant.thisConstant;
93 
94         // Compare based on the original indices, if the actual constant pool
95         // entries are the same.
96         if (thisConstant == otherConstant)
97         {
98             int otherIndex = otherComparableConstant.thisIndex;
99 
100             return thisIndex <  otherIndex ? -1 :
101                    thisIndex == otherIndex ?  0 :
102                                               1;
103         }
104 
105         // Compare based on the tags, if they are different.
106         int thisTag  = thisConstant.getTag();
107         int otherTag = otherConstant.getTag();
108 
109         if (thisTag != otherTag)
110         {
111             return PRIORITIES[thisTag] < PRIORITIES[otherTag] ? -1 : 1;
112         }
113 
114         // Otherwise compare based on the contents of the Constant objects.
115         thisConstant.accept(clazz, this);
116 
117         return result;
118     }
119 
120 
121     // Implementations for ConstantVisitor.
122 
visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)123     public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
124     {
125         // In JDK 1.4, we can use Integer.compare(a,b).
126         result = new Integer(integerConstant.getValue()).compareTo(new Integer(((IntegerConstant)otherConstant).getValue()));
127     }
128 
visitLongConstant(Clazz clazz, LongConstant longConstant)129     public void visitLongConstant(Clazz clazz, LongConstant longConstant)
130     {
131         // In JDK 1.4, we can use Long.compare(a,b).
132         result = new Long(longConstant.getValue()).compareTo(new Long(((LongConstant)otherConstant).getValue()));
133     }
134 
visitFloatConstant(Clazz clazz, FloatConstant floatConstant)135     public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
136     {
137         // In JDK 1.4, we can use Float.compare(a,b).
138         result = new Float(floatConstant.getValue()).compareTo(new Float(((FloatConstant)otherConstant).getValue()));
139     }
140 
visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)141     public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
142     {
143         // In JDK 1.4, we can use Double.compare(a,b).
144         result = new Double(doubleConstant.getValue()).compareTo(new Double(((DoubleConstant)otherConstant).getValue()));
145     }
146 
visitStringConstant(Clazz clazz, StringConstant stringConstant)147     public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
148     {
149         result = stringConstant.getString(clazz).compareTo(((StringConstant)otherConstant).getString(clazz));
150     }
151 
visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)152     public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
153     {
154         result = utf8Constant.getString().compareTo(((Utf8Constant)otherConstant).getString());
155     }
156 
visitAnyRefConstant(Clazz clazz, RefConstant refConstant)157     public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
158     {
159         RefConstant otherRefConstant = (RefConstant)otherConstant;
160         result = (refConstant.getClassName(clazz) + ' ' +
161                   refConstant.getName(clazz)      + ' ' +
162                   refConstant.getType(clazz))
163                  .compareTo
164                  (otherRefConstant.getClassName(clazz) + ' ' +
165                   otherRefConstant.getName(clazz)      + ' ' +
166                   otherRefConstant.getType(clazz));
167     }
168 
visitClassConstant(Clazz clazz, ClassConstant classConstant)169     public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
170     {
171         result = classConstant.getName(clazz).compareTo(((ClassConstant)otherConstant).getName(clazz));
172     }
173 
visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)174     public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
175     {
176         NameAndTypeConstant otherNameAndTypeConstant = (NameAndTypeConstant)otherConstant;
177         result = (nameAndTypeConstant.getName(clazz) + ' ' +
178                   nameAndTypeConstant.getType(clazz))
179                  .compareTo
180                  (otherNameAndTypeConstant.getName(clazz) + ' ' +
181                   otherNameAndTypeConstant.getType(clazz));
182     }
183 
184 
185     // Implementations for Object.
186 
equals(Object other)187     public boolean equals(Object other)
188     {
189         return other != null &&
190                this.getClass().equals(other.getClass()) &&
191                this.getConstant().getClass().equals(((ComparableConstant)other).getConstant().getClass()) &&
192                this.compareTo(other) == 0;
193     }
194 
195 
hashCode()196     public int hashCode()
197     {
198         return this.getClass().hashCode();
199     }
200 }
201