1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2014 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;
22
23import proguard.classfile.*;
24import proguard.classfile.attribute.visitor.*;
25
26/**
27 * This Attribute represents a line number table attribute.
28 *
29 * @author Eric Lafortune
30 */
31public class LineNumberTableAttribute extends Attribute
32{
33    public int              u2lineNumberTableLength;
34    public LineNumberInfo[] lineNumberTable;
35
36
37    /**
38     * Creates an uninitialized LineNumberTableAttribute.
39     */
40    public LineNumberTableAttribute()
41    {
42    }
43
44
45    /**
46     * Creates an initialized LineNumberTableAttribute.
47     */
48    public LineNumberTableAttribute(int              u2attributeNameIndex,
49                                    int              u2lineNumberTableLength,
50                                    LineNumberInfo[] lineNumberTable)
51    {
52        super(u2attributeNameIndex);
53
54        this.u2lineNumberTableLength = u2lineNumberTableLength;
55        this.lineNumberTable         = lineNumberTable;
56    }
57
58
59    /**
60     * Returns the line number corresponding to the given byte code program
61     * counter.
62     */
63    public int getLineNumber(int pc)
64    {
65        for (int index = u2lineNumberTableLength-1 ; index >= 0 ; index--)
66        {
67            LineNumberInfo info = lineNumberTable[index];
68            if (pc >= info.u2startPC)
69            {
70                return info.u2lineNumber;
71            }
72        }
73
74        return u2lineNumberTableLength > 0 ?
75            lineNumberTable[0].u2lineNumber :
76            0;
77    }
78
79
80    /**
81     * Returns the lowest line number, or 0 if there aren't any line numbers.
82     */
83    public int getLowestLineNumber()
84    {
85        if (u2lineNumberTableLength == 0)
86        {
87            return 0;
88        }
89
90        int lowestLineNumber = Integer.MAX_VALUE;
91
92        for (int index = 0; index < u2lineNumberTableLength; index++)
93        {
94            int lineNumber = lineNumberTable[index].u2lineNumber;
95            if (lineNumber < lowestLineNumber)
96            {
97                lowestLineNumber = lineNumber;
98            }
99        }
100
101        return lowestLineNumber;
102    }
103
104
105    /**
106     * Returns the highest line number, or 0 if there aren't any line numbers.
107     */
108    public int getHighestLineNumber()
109    {
110        if (u2lineNumberTableLength == 0)
111        {
112            return 0;
113        }
114
115        int highestLineNumber = Integer.MIN_VALUE;
116
117        for (int index = 0; index < u2lineNumberTableLength; index++)
118        {
119            int lineNumber = lineNumberTable[index].u2lineNumber;
120            if (lineNumber > highestLineNumber)
121            {
122                highestLineNumber = lineNumber;
123            }
124        }
125
126        return highestLineNumber;
127    }
128
129
130    // Implementations for Attribute.
131
132    public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor)
133    {
134        attributeVisitor.visitLineNumberTableAttribute(clazz, method, codeAttribute, this);
135    }
136
137
138    /**
139     * Applies the given visitor to all line numbers.
140     */
141    public void lineNumbersAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfoVisitor lineNumberInfoVisitor)
142    {
143        for (int index = 0; index < u2lineNumberTableLength; index++)
144        {
145            // We don't need double dispatching here, since there is only one
146            // type of LineNumberInfo.
147            lineNumberInfoVisitor.visitLineNumberInfo(clazz, method, codeAttribute, lineNumberTable[index]);
148        }
149    }
150}
151