~ubuntu-branches/ubuntu/maverick/proguard/maverick

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/* $Id: SpecificArrayReferenceValue.java,v 1.5 2005/06/11 13:13:16 eric Exp $
 *
 * ProGuard -- shrinking, optimization, and obfuscation of Java class files.
 *
 * Copyright (c) 2002-2005 Eric Lafortune (eric@graphics.cornell.edu)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package proguard.optimize.evaluation.value;

import proguard.classfile.*;
import proguard.classfile.ClassCpInfo;
import proguard.classfile.util.ClassUtil;

/**
 * This ReferenceValue represents an array reference value of a specific type
 * and dimensionality.
 *
 * @author Eric Lafortune
 */
class SpecificArrayReferenceValue extends SpecificReferenceValue
{
    protected int dimension;


    /**
     * Creates a new specific array reference value. The dimensionality of the
     * value argument alone is ignored.
     */
    public SpecificArrayReferenceValue(ClassFile value, int dimension, boolean mayBeNull)
    {
        super(value, mayBeNull);

        this.dimension = dimension;
    }


    // Implementations for ReferenceValue.

    public int dimension()
    {
        return dimension;
    }


    // Implementations of binary methods of ReferenceValue.

    // Perhaps the other value arguments are more specific than apparent
    // in these methods, so delegate to them.

    public ReferenceValue generalize(ReferenceValue other)
    {
        return other.generalize(this);
    }

    public int equal(ReferenceValue other)
    {
        return other.equal(this);
    }


    // Implementations of unary methods of ReferenceValue.

    public int instanceOf(ClassFile typeClassFile, int typeDimension)
    {
        // If this value is null, it is never an instance of any class.
        if (value == null)
        {
            return NEVER;
        }

        // If the type class is unknown or the type has a higher dimension, we
        // can't tell for sure.
        if (typeClassFile == null ||
            typeDimension > dimension)
        {
            return MAYBE;
        }

        // If the type dimension is less than the value's dimension, the type
        // must be Object, Cloneable, or Serializable.
        if (typeDimension < dimension)
        {
            String typeClassName = typeClassFile.getName();
            return typeClassName.equals(ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT)    ||
                   typeClassName.equals(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLONEABLE) ||
                   typeClassName.equals(ClassConstants.INTERNAL_NAME_JAVA_IO_SERIALIZABLE) ?
                       ALWAYS :
                       NEVER;
        }

        // If the value extends the type, we're sure.
        return value.extends_(typeClassFile) ||
               value.implements_(typeClassFile) ?
                   ALWAYS :
                   MAYBE;
    }


    // Implementations of binary ReferenceValue methods with
    // SpecificArrayReferenceValue arguments.

    public ReferenceValue generalize(SpecificArrayReferenceValue other)
    {
        return this.value     == other.value &&
               this.dimension == other.dimension ?
            this.mayBeNull ? this : other :
            ReferenceValueFactory.create(this.mayBeNull || other.mayBeNull);
    }

    public int equal(SpecificArrayReferenceValue other)
    {
        return this.value  == null &&
               other.value == null ? ALWAYS : MAYBE;
    }


    // Implementations for Object.

    public boolean equals(Object object)
    {
        if (object == null ||
            this.getClass() != object.getClass())
        {
            return false;
        }

        SpecificArrayReferenceValue other = (SpecificArrayReferenceValue)object;
        return this.mayBeNull == other.mayBeNull                     &&
               (this.value == null ? other.value == null :
                                     this.value.equals(other.value)) &&
               this.dimension == other.dimension;
    }


    public int hashCode()
    {
        return this.getClass().hashCode()             ^
               (value == null ? 0 : value.hashCode()) ^
               dimension;
    }


    public String toString()
    {
        return "a:" + (value == null ? "null" : value.getName()+"["+dimension+"]");
    }
}