1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/*
2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project
3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License");
5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License.
6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at
7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *      http://www.apache.org/licenses/LICENSE-2.0
9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software
11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS,
12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and
14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License.
15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.rop;
18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.FixedSizeList;
20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * List of "line number" entries, which are the contents of
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code LineNumberTable} attributes.
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class LineNumberList extends FixedSizeList {
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} zero-size instance */
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static final LineNumberList EMPTY = new LineNumberList(0);
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance which is the concatenation of the two given
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * instances.
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param list1 {@code non-null;} first instance
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param list2 {@code non-null;} second instance
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} combined instance
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static LineNumberList concat(LineNumberList list1,
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                                        LineNumberList list2) {
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (list1 == EMPTY) {
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            // easy case
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return list2;
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int sz1 = list1.size();
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int sz2 = list2.size();
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        LineNumberList result = new LineNumberList(sz1 + sz2);
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < sz1; i++) {
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result.set(i, list1.get(i));
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < sz2; i++) {
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result.set(sz1 + i, list2.get(i));
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return result;
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs an instance.
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param count the number of elements to be in the list
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public LineNumberList(int count) {
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        super(count);
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the indicated item.
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param n {@code >= 0;} which item
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code null-ok;} the indicated item
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public Item get(int n) {
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return (Item) get0(n);
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Sets the item at the given index.
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param n {@code >= 0, < size();} which element
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param item {@code non-null;} the item
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void set(int n, Item item) {
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (item == null) {
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("item == null");
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        set0(n, item);
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Sets the item at the given index.
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param n {@code >= 0, < size();} which element
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param startPc {@code >= 0;} start pc of this item
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param lineNumber {@code >= 0;} corresponding line number
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void set(int n, int startPc, int lineNumber) {
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        set0(n, new Item(startPc, lineNumber));
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the line number associated with the given address.
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param pc {@code >= 0;} the address to look up
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code >= -1;} the associated line number, or {@code -1} if
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * none is known
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public int pcToLine(int pc) {
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /*
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Line number entries don't have to appear in any particular
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * order, so we have to do a linear search. TODO: If
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * this turns out to be a bottleneck, consider sorting the
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * list prior to use.
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int sz = size();
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int bestPc = -1;
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int bestLine = -1;
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < sz; i++) {
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            Item one = get(i);
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            int onePc = one.getStartPc();
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if ((onePc <= pc) && (onePc > bestPc)) {
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                bestPc = onePc;
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                bestLine = one.getLineNumber();
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                if (bestPc == pc) {
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    // We can't do better than this
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    break;
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                }
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return bestLine;
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Item in a line number table.
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static class Item {
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code >= 0;} start pc of this item */
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private final int startPc;
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code >= 0;} corresponding line number */
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private final int lineNumber;
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Constructs an instance.
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param startPc {@code >= 0;} start pc of this item
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param lineNumber {@code >= 0;} corresponding line number
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public Item(int startPc, int lineNumber) {
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (startPc < 0) {
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                throw new IllegalArgumentException("startPc < 0");
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (lineNumber < 0) {
159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                throw new IllegalArgumentException("lineNumber < 0");
160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.startPc = startPc;
163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.lineNumber = lineNumber;
164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Gets the start pc of this item.
168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @return the start pc
170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public int getStartPc() {
172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return startPc;
173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Gets the line number of this item.
177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @return the line number
179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public int getLineNumber() {
181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return lineNumber;
182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
185