001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS,
013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 *  See the License for the specific language governing permissions and
015 *  limitations under the License.
016 *
017 */
018package org.apache.bcel.classfile;
019
020import java.io.DataInput;
021import java.io.DataOutputStream;
022import java.io.IOException;
023
024/**
025 * This class represents a (PC offset, line number) pair, i.e., a line number in the source that corresponds to a
026 * relative address in the byte code. This is used for debugging purposes.
027 *
028 * @see LineNumberTable
029 */
030public final class LineNumber implements Cloneable, Node {
031
032    /** Program Counter (PC) corresponds to line */
033    private short startPc;
034
035    /** number in source file */
036    private short lineNumber;
037
038    /**
039     * Construct object from file stream.
040     *
041     * @param file Input stream
042     * @throws IOException if an I/O Exception occurs in readUnsignedShort
043     */
044    LineNumber(final DataInput file) throws IOException {
045        this(file.readUnsignedShort(), file.readUnsignedShort());
046    }
047
048    /**
049     * @param startPc Program Counter (PC) corresponds to
050     * @param lineNumber line number in source file
051     */
052    public LineNumber(final int startPc, final int lineNumber) {
053        this.startPc = (short) startPc;
054        this.lineNumber = (short) lineNumber;
055    }
056
057    /**
058     * Initialize from another object.
059     *
060     * @param c the object to copy
061     */
062    public LineNumber(final LineNumber c) {
063        this(c.getStartPC(), c.getLineNumber());
064    }
065
066    /**
067     * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
068     * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
069     *
070     * @param v Visitor object
071     */
072    @Override
073    public void accept(final Visitor v) {
074        v.visitLineNumber(this);
075    }
076
077    /**
078     * @return deep copy of this object
079     */
080    public LineNumber copy() {
081        try {
082            return (LineNumber) clone();
083        } catch (final CloneNotSupportedException e) {
084            // TODO should this throw?
085        }
086        return null;
087    }
088
089    /**
090     * Dump line number/pc pair to file stream in binary format.
091     *
092     * @param file Output file stream
093     * @throws IOException if an I/O Exception occurs in writeShort
094     */
095    public void dump(final DataOutputStream file) throws IOException {
096        file.writeShort(startPc);
097        file.writeShort(lineNumber);
098    }
099
100    /**
101     * @return Corresponding source line
102     */
103    public int getLineNumber() {
104        return lineNumber & 0xffff;
105    }
106
107    /**
108     * @return PC in code
109     */
110    public int getStartPC() {
111        return startPc & 0xffff;
112    }
113
114    /**
115     * @param lineNumber the source line number
116     */
117    public void setLineNumber(final int lineNumber) {
118        this.lineNumber = (short) lineNumber;
119    }
120
121    /**
122     * @param startPc the pc for this line number
123     */
124    public void setStartPC(final int startPc) {
125        this.startPc = (short) startPc;
126    }
127
128    /**
129     * @return String representation
130     */
131    @Override
132    public String toString() {
133        return "LineNumber(" + getStartPC() + ", " + getLineNumber() + ")";
134    }
135}