• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.dx.cf.code;
18 
19 import com.android.dx.util.FixedSizeList;
20 
21 /**
22  * List of "line number" entries, which are the contents of
23  * {@code LineNumberTable} attributes.
24  */
25 public final class LineNumberList extends FixedSizeList {
26     /** {@code non-null;} zero-size instance */
27     public static final LineNumberList EMPTY = new LineNumberList(0);
28 
29     /**
30      * Returns an instance which is the concatenation of the two given
31      * instances.
32      *
33      * @param list1 {@code non-null;} first instance
34      * @param list2 {@code non-null;} second instance
35      * @return {@code non-null;} combined instance
36      */
concat(LineNumberList list1, LineNumberList list2)37     public static LineNumberList concat(LineNumberList list1,
38                                         LineNumberList list2) {
39         if (list1 == EMPTY) {
40             // easy case
41             return list2;
42         }
43 
44         int sz1 = list1.size();
45         int sz2 = list2.size();
46         LineNumberList result = new LineNumberList(sz1 + sz2);
47 
48         for (int i = 0; i < sz1; i++) {
49             result.set(i, list1.get(i));
50         }
51 
52         for (int i = 0; i < sz2; i++) {
53             result.set(sz1 + i, list2.get(i));
54         }
55 
56         return result;
57     }
58 
59     /**
60      * Constructs an instance.
61      *
62      * @param count the number of elements to be in the list
63      */
LineNumberList(int count)64     public LineNumberList(int count) {
65         super(count);
66     }
67 
68     /**
69      * Gets the indicated item.
70      *
71      * @param n {@code >= 0;} which item
72      * @return {@code null-ok;} the indicated item
73      */
get(int n)74     public Item get(int n) {
75         return (Item) get0(n);
76     }
77 
78     /**
79      * Sets the item at the given index.
80      *
81      * @param n {@code >= 0, < size();} which element
82      * @param item {@code non-null;} the item
83      */
set(int n, Item item)84     public void set(int n, Item item) {
85         if (item == null) {
86             throw new NullPointerException("item == null");
87         }
88 
89         set0(n, item);
90     }
91 
92     /**
93      * Sets the item at the given index.
94      *
95      * @param n {@code >= 0, < size();} which element
96      * @param startPc {@code >= 0;} start pc of this item
97      * @param lineNumber {@code >= 0;} corresponding line number
98      */
set(int n, int startPc, int lineNumber)99     public void set(int n, int startPc, int lineNumber) {
100         set0(n, new Item(startPc, lineNumber));
101     }
102 
103     /**
104      * Gets the line number associated with the given address.
105      *
106      * @param pc {@code >= 0;} the address to look up
107      * @return {@code >= -1;} the associated line number, or {@code -1} if
108      * none is known
109      */
pcToLine(int pc)110     public int pcToLine(int pc) {
111         /*
112          * Line number entries don't have to appear in any particular
113          * order, so we have to do a linear search. TODO: If
114          * this turns out to be a bottleneck, consider sorting the
115          * list prior to use.
116          */
117         int sz = size();
118         int bestPc = -1;
119         int bestLine = -1;
120 
121         for (int i = 0; i < sz; i++) {
122             Item one = get(i);
123             int onePc = one.getStartPc();
124             if ((onePc <= pc) && (onePc > bestPc)) {
125                 bestPc = onePc;
126                 bestLine = one.getLineNumber();
127                 if (bestPc == pc) {
128                     // We can't do better than this
129                     break;
130                 }
131             }
132         }
133 
134         return bestLine;
135     }
136 
137     /**
138      * Item in a line number table.
139      */
140     public static class Item {
141         /** {@code >= 0;} start pc of this item */
142         private final int startPc;
143 
144         /** {@code >= 0;} corresponding line number */
145         private final int lineNumber;
146 
147         /**
148          * Constructs an instance.
149          *
150          * @param startPc {@code >= 0;} start pc of this item
151          * @param lineNumber {@code >= 0;} corresponding line number
152          */
Item(int startPc, int lineNumber)153         public Item(int startPc, int lineNumber) {
154             if (startPc < 0) {
155                 throw new IllegalArgumentException("startPc < 0");
156             }
157 
158             if (lineNumber < 0) {
159                 throw new IllegalArgumentException("lineNumber < 0");
160             }
161 
162             this.startPc = startPc;
163             this.lineNumber = lineNumber;
164         }
165 
166         /**
167          * Gets the start pc of this item.
168          *
169          * @return the start pc
170          */
getStartPc()171         public int getStartPc() {
172             return startPc;
173         }
174 
175         /**
176          * Gets the line number of this item.
177          *
178          * @return the line number
179          */
getLineNumber()180         public int getLineNumber() {
181             return lineNumber;
182         }
183     }
184 }
185