KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > cojen > classfile > attribute > LineNumberTableAttr


1 /*
2  * Copyright 2004 Brian S O'Neill
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 org.cojen.classfile.attribute;
18
19 import java.util.ArrayList JavaDoc;
20 import java.util.Collections JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Set JavaDoc;
23 import java.util.TreeSet JavaDoc;
24 import java.io.DataInput JavaDoc;
25 import java.io.DataOutput JavaDoc;
26 import java.io.IOException JavaDoc;
27 import org.cojen.classfile.Attribute;
28 import org.cojen.classfile.ConstantPool;
29 import org.cojen.classfile.FixedLocation;
30 import org.cojen.classfile.Location;
31
32 /**
33  * This class corresponds to the LineNumberTable_attribute structure as
34  * defined in section 4.7.6 of <i>The Java Virtual Machine Specification</i>.
35  *
36  * @author Brian S O'Neill
37  */

38 public class LineNumberTableAttr extends Attribute {
39
40     private List JavaDoc mEntries = new ArrayList JavaDoc();
41     private boolean mClean = false;
42     
43     public LineNumberTableAttr(ConstantPool cp) {
44         super(cp, LINE_NUMBER_TABLE);
45     }
46     
47     public LineNumberTableAttr(ConstantPool cp, String JavaDoc name) {
48         super(cp, name);
49     }
50     
51     public LineNumberTableAttr(ConstantPool cp, String JavaDoc name, int length, DataInput JavaDoc din)
52         throws IOException JavaDoc
53     {
54         super(cp, name);
55
56         int size = din.readUnsignedShort();
57         for (int i=0; i<size; i++) {
58             int start_pc = din.readUnsignedShort();
59             int line_number = din.readUnsignedShort();
60
61             try {
62                 addEntry(new FixedLocation(start_pc), line_number);
63             } catch (IllegalArgumentException JavaDoc e) {
64             }
65         }
66     }
67
68     public int getLineNumber(Location start) {
69         clean();
70         int index = Collections.binarySearch(mEntries, new Entry(start, 0));
71         if (index < 0) {
72             if ((index = -index - 2) < 0) {
73                 return -1;
74             }
75         }
76         return ((Entry)mEntries.get(index)).mLineNumber;
77     }
78
79     public void addEntry(Location start, int line_number) throws IllegalArgumentException JavaDoc {
80         if (line_number < 0 || line_number > 65535) {
81             throw new IllegalArgumentException JavaDoc("Value for line number out of " +
82                                                "valid range: " + line_number);
83         }
84         mEntries.add(new Entry(start, line_number));
85         mClean = false;
86     }
87     
88     public int getLength() {
89         clean();
90         return 2 + 4 * mEntries.size();
91     }
92     
93     public void writeDataTo(DataOutput JavaDoc dout) throws IOException JavaDoc {
94         int size = mEntries.size();
95         dout.writeShort(size);
96         for (int i=0; i<size; i++) {
97             Entry entry = (Entry)mEntries.get(i);
98             
99             int start_pc = entry.mStart.getLocation();
100
101             if (start_pc < 0 || start_pc > 65535) {
102                 throw new IllegalStateException JavaDoc
103                     ("Value for line number table entry start PC out of " +
104                      "valid range: " + start_pc);
105             }
106
107             dout.writeShort(start_pc);
108             dout.writeShort(entry.mLineNumber);
109         }
110     }
111
112     private void clean() {
113         if (!mClean) {
114             mClean = true;
115
116             // Clean things up by removing multiple mappings of the same
117
// start_pc to line numbers. Only keep the last one.
118
// This has to be performed now because the Labels should have
119
// a pc location, but before they did not. Since entries must be
120
// sorted ascending by start_pc, use a sorted set.
121

122             Set JavaDoc reduced = new TreeSet JavaDoc();
123             for (int i = mEntries.size(); --i >= 0; ) {
124                 reduced.add(mEntries.get(i));
125             }
126
127             mEntries = new ArrayList JavaDoc(reduced);
128         }
129     }
130
131     private static class Entry implements Comparable JavaDoc {
132         public final Location mStart;
133         public final int mLineNumber;
134         
135         public Entry(Location start, int line_number) {
136             mStart = start;
137             mLineNumber = line_number;
138         }
139
140         public int compareTo(Object JavaDoc other) {
141             int thisLoc = mStart.getLocation();
142             int thatLoc = ((Entry)other).mStart.getLocation();
143             
144             if (thisLoc < thatLoc) {
145                 return -1;
146             } else if (thisLoc > thatLoc) {
147                 return 1;
148             } else {
149                 return 0;
150             }
151         }
152
153         public boolean equals(Object JavaDoc other) {
154             if (other instanceof Entry) {
155                 return mStart.getLocation() ==
156                     ((Entry)other).mStart.getLocation();
157             }
158             return false;
159         }
160
161         public String JavaDoc toString() {
162             return "start_pc=" + mStart.getLocation() + " => " +
163                 "line_number=" + mLineNumber;
164         }
165     }
166 }
167
Popular Tags