1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * https://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.bcel.classfile;
20
21 import java.io.DataInput;
22 import java.io.DataOutputStream;
23 import java.io.IOException;
24
25 import org.apache.bcel.util.Args;
26
27 /**
28 * This class represents a (PC offset, line number) pair, that is, a line number in the source that corresponds to a
29 * relative address in the byte code. This is used for debugging purposes.
30 *
31 * @see LineNumberTable
32 */
33 public final class LineNumber implements Cloneable, Node {
34
35 static final LineNumber[] EMPTY_ARRAY = {};
36
37 /** Program Counter (PC) corresponds to line. */
38 private int startPc;
39
40 /** Number in source file. */
41 private int lineNumber;
42
43 /**
44 * Constructs object from file stream.
45 *
46 * @param file Input stream.
47 * @throws IOException Thrown if an I/O Exception occurs in readUnsignedShort.
48 */
49 LineNumber(final DataInput file) throws IOException {
50 this(file.readUnsignedShort(), file.readUnsignedShort());
51 }
52
53 /**
54 * Constructs a LineNumber.
55 *
56 * @param startPc Program Counter (PC) corresponds to.
57 * @param lineNumber line number in source file.
58 */
59 public LineNumber(final int startPc, final int lineNumber) {
60 this.startPc = Args.requireU2(startPc, "startPc");
61 this.lineNumber = Args.requireU2(lineNumber, "lineNumber");
62 }
63
64 /**
65 * Initialize from another object.
66 *
67 * @param c The object to copy.
68 */
69 public LineNumber(final LineNumber c) {
70 this(c.getStartPC(), c.getLineNumber());
71 }
72
73 /**
74 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
75 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
76 *
77 * @param v Visitor object.
78 */
79 @Override
80 public void accept(final Visitor v) {
81 v.visitLineNumber(this);
82 }
83
84 /**
85 * Creates a deep copy of this object.
86 *
87 * @return deep copy of this object.
88 */
89 public LineNumber copy() {
90 try {
91 return (LineNumber) clone();
92 } catch (final CloneNotSupportedException e) {
93 // TODO should this throw?
94 }
95 return null;
96 }
97
98 /**
99 * Dumps line number/pc pair to file stream in binary format.
100 *
101 * @param file Output file stream.
102 * @throws IOException Thrown if an I/O Exception occurs in writeShort.
103 */
104 public void dump(final DataOutputStream file) throws IOException {
105 file.writeShort(startPc);
106 file.writeShort(lineNumber);
107 }
108
109 /**
110 * Gets the line number.
111 *
112 * @return Corresponding source line.
113 */
114 public int getLineNumber() {
115 return lineNumber & 0xffff;
116 }
117
118 /**
119 * Gets the program counter.
120 *
121 * @return PC in code.
122 */
123 public int getStartPC() {
124 return startPc & 0xffff;
125 }
126
127 /**
128 * Sets the line number.
129 *
130 * @param lineNumber The source line number.
131 */
132 public void setLineNumber(final int lineNumber) {
133 this.lineNumber = (short) lineNumber;
134 }
135
136 /**
137 * Sets the program counter.
138 *
139 * @param startPc The pc for this line number.
140 */
141 public void setStartPC(final int startPc) {
142 this.startPc = (short) startPc;
143 }
144
145 /**
146 * @return String representation.
147 */
148 @Override
149 public String toString() {
150 return "LineNumber(" + getStartPC() + ", " + getLineNumber() + ")";
151 }
152 }