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, i.e., 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 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 * @param startPc Program Counter (PC) corresponds to
55 * @param lineNumber line number in source file
56 */
57 public LineNumber(final int startPc, final int lineNumber) {
58 this.startPc = Args.requireU2(startPc, "startPc");
59 this.lineNumber = Args.requireU2(lineNumber, "lineNumber");
60 }
61
62 /**
63 * Initialize from another object.
64 *
65 * @param c the object to copy
66 */
67 public LineNumber(final LineNumber c) {
68 this(c.getStartPC(), c.getLineNumber());
69 }
70
71 /**
72 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
73 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
74 *
75 * @param v Visitor object
76 */
77 @Override
78 public void accept(final Visitor v) {
79 v.visitLineNumber(this);
80 }
81
82 /**
83 * @return deep copy of this object
84 */
85 public LineNumber copy() {
86 try {
87 return (LineNumber) clone();
88 } catch (final CloneNotSupportedException e) {
89 // TODO should this throw?
90 }
91 return null;
92 }
93
94 /**
95 * Dump line number/pc pair to file stream in binary format.
96 *
97 * @param file Output file stream
98 * @throws IOException if an I/O Exception occurs in writeShort
99 */
100 public void dump(final DataOutputStream file) throws IOException {
101 file.writeShort(startPc);
102 file.writeShort(lineNumber);
103 }
104
105 /**
106 * @return Corresponding source line
107 */
108 public int getLineNumber() {
109 return lineNumber & 0xffff;
110 }
111
112 /**
113 * @return PC in code
114 */
115 public int getStartPC() {
116 return startPc & 0xffff;
117 }
118
119 /**
120 * @param lineNumber the source line number
121 */
122 public void setLineNumber(final int lineNumber) {
123 this.lineNumber = (short) lineNumber;
124 }
125
126 /**
127 * @param startPc the pc for this line number
128 */
129 public void setStartPC(final int startPc) {
130 this.startPc = (short) startPc;
131 }
132
133 /**
134 * @return String representation
135 */
136 @Override
137 public String toString() {
138 return "LineNumber(" + getStartPC() + ", " + getLineNumber() + ")";
139 }
140 }