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 */
21package proguard.classfile.attribute.preverification;
22
23import proguard.classfile.*;
24import proguard.classfile.attribute.CodeAttribute;
25import proguard.classfile.attribute.preverification.visitor.*;
26
27/**
28 * This StackMapFrame represents a "full frame".
29 *
30 * @author Eric Lafortune
31 */
32public class FullFrame extends StackMapFrame
33{
34    public int                variablesCount;
35    public VerificationType[] variables;
36    public int                stackCount;
37    public VerificationType[] stack;
38
39
40    /**
41     * Creates an uninitialized FullFrame.
42     */
43    public FullFrame()
44    {
45    }
46
47
48    /**
49     * Creates a FullFrame with the given variables and stack.
50     */
51    public FullFrame(int                offsetDelta,
52                     VerificationType[] variables,
53                     VerificationType[] stack)
54    {
55        this(offsetDelta,
56             variables.length,
57             variables,
58             stack.length,
59             stack);
60    }
61
62
63    /**
64     * Creates a FullFrame with the given variables and stack.
65     */
66    public FullFrame(int                offsetDelta,
67                     int                variablesCount,
68                     VerificationType[] variables,
69                     int                stackCount,
70                     VerificationType[] stack)
71    {
72        this.u2offsetDelta  = offsetDelta;
73        this.variablesCount = variablesCount;
74        this.variables      = variables;
75        this.stackCount     = stackCount;
76        this.stack          = stack;
77    }
78
79
80    /**
81     * Applies the given verification type visitor to all variables.
82     */
83    public void variablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationTypeVisitor verificationTypeVisitor)
84    {
85        for (int index = 0; index < variablesCount; index++)
86        {
87            variables[index].variablesAccept(clazz, method, codeAttribute, offset, index, verificationTypeVisitor);
88        }
89    }
90
91
92    /**
93     * Applies the given verification type visitor to all stack.
94     */
95    public void stackAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationTypeVisitor verificationTypeVisitor)
96    {
97        for (int index = 0; index < stackCount; index++)
98        {
99            stack[index].stackAccept(clazz, method, codeAttribute, offset, index, verificationTypeVisitor);
100        }
101    }
102
103
104    // Implementations for StackMapFrame.
105
106    public int getTag()
107    {
108        return FULL_FRAME;
109    }
110
111
112    public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrameVisitor stackMapFrameVisitor)
113    {
114        stackMapFrameVisitor.visitFullFrame(clazz, method, codeAttribute, offset, this);
115    }
116
117
118    // Implementations for Object.
119
120    public boolean equals(Object object)
121    {
122        if (!super.equals(object))
123        {
124            return false;
125        }
126
127        FullFrame other = (FullFrame)object;
128
129        if (this.u2offsetDelta  != other.u2offsetDelta  ||
130            this.variablesCount != other.variablesCount ||
131            this.stackCount     != other.stackCount)
132        {
133            return false;
134        }
135
136        for (int index = 0; index < variablesCount; index++)
137        {
138            VerificationType thisType  = this.variables[index];
139            VerificationType otherType = other.variables[index];
140
141            if (!thisType.equals(otherType))
142            {
143                return false;
144            }
145        }
146
147        for (int index = 0; index < stackCount; index++)
148        {
149            VerificationType thisType  = this.stack[index];
150            VerificationType otherType = other.stack[index];
151
152            if (!thisType.equals(otherType))
153            {
154                return false;
155            }
156        }
157
158        return true;
159    }
160
161
162    public int hashCode()
163    {
164        int hashCode = super.hashCode();
165
166        for (int index = 0; index < variablesCount; index++)
167        {
168            hashCode ^= variables[index].hashCode();
169        }
170
171        for (int index = 0; index < stackCount; index++)
172        {
173            hashCode ^= stack[index].hashCode();
174        }
175
176        return hashCode;
177    }
178
179
180    public String toString()
181    {
182        StringBuffer buffer = new StringBuffer(super.toString()).append("Var: ");
183
184        for (int index = 0; index < variablesCount; index++)
185        {
186            buffer = buffer.append('[')
187                           .append(variables[index].toString())
188                           .append(']');
189        }
190
191        buffer.append(", Stack: ");
192
193        for (int index = 0; index < stackCount; index++)
194        {
195            buffer = buffer.append('[')
196                           .append(stack[index].toString())
197                           .append(']');
198        }
199
200        return buffer.toString();
201    }
202}
203