1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/*
2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2007 The Android Open Source Project
3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License.
6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at
7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software
11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and
14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License.
15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */
16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.rop.code;
18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.CstString;
20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.Hex;
21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/**
23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Information about a source position for code, which includes both a
24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * line number and original bytecode address.
25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */
26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic final class SourcePosition {
27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} convenient "no information known" instance */
28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final SourcePosition NO_INFO =
29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        new SourcePosition(null, -1, -1);
30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code null-ok;} name of the file of origin or {@code null} if unknown */
32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private final CstString sourceFile;
33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code >= -1;} the bytecode address, or {@code -1} if that
36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * information is unknown
37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private final int address;
39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code >= -1;} the line number, or {@code -1} if that
42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * information is unknown
43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private final int line;
45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Constructs an instance.
48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param sourceFile {@code null-ok;} name of the file of origin or
50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code null} if unknown
51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param address {@code >= -1;} original bytecode address or {@code -1}
52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * if unknown
53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param line {@code >= -1;} original line number or {@code -1} if
54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * unknown
55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public SourcePosition(CstString sourceFile, int address, int line) {
57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (address < -1) {
58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IllegalArgumentException("address < -1");
59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (line < -1) {
62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IllegalArgumentException("line < -1");
63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.sourceFile = sourceFile;
66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.address = address;
67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.line = line;
68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public String toString() {
73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        StringBuffer sb = new StringBuffer(50);
74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (sourceFile != null) {
76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            sb.append(sourceFile.toHuman());
77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            sb.append(":");
78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (line >= 0) {
81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            sb.append(line);
82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        sb.append('@');
85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (address < 0) {
87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            sb.append("????");
88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } else {
89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            sb.append(Hex.u2(address));
90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return sb.toString();
93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean equals(Object other) {
98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (!(other instanceof SourcePosition)) {
99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return false;
100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (this == other) {
103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return true;
104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        SourcePosition pos = (SourcePosition) other;
107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return (address == pos.address) && sameLineAndFile(pos);
109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int hashCode() {
114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return sourceFile.hashCode() + address + line;
115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Returns whether the lines match between this instance and
119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * the one given.
120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param other {@code non-null;} the instance to compare to
122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code true} iff the lines match
123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean sameLine(SourcePosition other) {
125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return (line == other.line);
126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Returns whether the lines and files match between this instance and
130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * the one given.
131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param other {@code non-null;} the instance to compare to
133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code true} iff the lines and files match
134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean sameLineAndFile(SourcePosition other) {
136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return (line == other.line) &&
137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            ((sourceFile == other.sourceFile) ||
138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             ((sourceFile != null) && sourceFile.equals(other.sourceFile)));
139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the source file, if known.
143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code null-ok;} the source file or {@code null} if unknown
145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public CstString getSourceFile() {
147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return sourceFile;
148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the original bytecode address.
152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code >= -1;} the address or {@code -1} if unknown
154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int getAddress() {
156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return address;
157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the original line number.
161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code >= -1;} the original line number or {@code -1} if
163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * unknown
164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int getLine() {
166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return line;
167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson}
169