1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.cf.code;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.IntList;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.MutabilityControl;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * List of (value, target) mappings representing the choices of a
2499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code tableswitch} or {@code lookupswitch} instruction. It
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * also holds the default target for the switch.
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class SwitchList extends MutabilityControl {
2899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} list of test values */
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final IntList values;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
3299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code non-null;} list of targets corresponding to the test values; there
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is always one extra element in the target list, to hold the
34de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * default target
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final IntList targets;
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** ultimate size of the list */
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int size;
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance.
43de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
4499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param size {@code >= 0;} the number of elements to be in the table
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public SwitchList(int size) {
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super(true);
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.values = new IntList(size);
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.targets = new IntList(size + 1);
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.size = size;
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void setImmutable() {
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        values.setImmutable();
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        targets.setImmutable();
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super.setImmutable();
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the size of the list.
63de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
6499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= 0;} the list size
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int size() {
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return size;
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the indicated test value.
72de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
7399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param n {@code >= 0;}, < size(); which index
74de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * @return the test value
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getValue(int n) {
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return values.get(n);
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
8199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets the indicated target. Asking for the target at {@code size()}
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * returns the default target.
83de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
8499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param n {@code >= 0, <= size();} which index
8599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= 0;} the target
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getTarget(int n) {
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return targets.get(n);
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the default target. This is just a shorthand for
9399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code getTarget(size())}.
94de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
9599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= 0;} the default target
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getDefaultTarget() {
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return targets.get(size);
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the list of all targets. This includes one extra element at the
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * end of the list, which holds the default target.
104de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
10599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the target list
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public IntList getTargets() {
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return targets;
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the list of all case values.
113de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
11499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the case value list
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public IntList getValues() {
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return values;
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Sets the default target. It is only valid to call this method
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * when all the non-default elements have been set.
123de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
12499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param target {@code >= 0;} the absolute (not relative) default target
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * address
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void setDefaultTarget(int target) {
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwIfImmutable();
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (target < 0) {
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("target < 0");
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (targets.size() != size) {
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new RuntimeException("non-default elements not all set");
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        targets.add(target);
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Adds the given item.
143de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param value the test value
14599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param target {@code >= 0;} the absolute (not relative) target address
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void add(int value, int target) {
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwIfImmutable();
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (target < 0) {
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("target < 0");
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        values.add(value);
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        targets.add(target);
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Shrinks this instance if possible, removing test elements that
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * refer to the default target. This is only valid after the instance
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is fully populated, including the default target (naturally).
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void removeSuperfluousDefaults() {
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwIfImmutable();
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sz = size;
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sz != (targets.size() - 1)) {
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("incomplete instance");
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int defaultTarget = targets.get(sz);
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int at = 0;
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < sz; i++) {
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int target = targets.get(i);
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (target != defaultTarget) {
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (i != at) {
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    targets.set(at, target);
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    values.set(at, values.get(i));
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                at++;
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (at != sz) {
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            values.shrink(at);
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            targets.set(at, defaultTarget);
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            targets.shrink(at + 1);
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            size = at;
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
194