1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.rop.code;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport com.android.dx.rop.cst.CstString;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Information about a source position for code, which includes both a
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * line number and original bytecode address.
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class SourcePosition {
2799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} convenient "no information known" instance */
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final SourcePosition NO_INFO =
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        new SourcePosition(null, -1, -1);
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code null-ok;} name of the file of origin or {@code null} if unknown */
32333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson    private final CstString sourceFile;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
3599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code >= -1;} the bytecode address, or {@code -1} if that
36de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * information is unknown
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int address;
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
4199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code >= -1;} the line number, or {@code -1} if that
42de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * information is unknown
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int line;
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance.
48de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
4999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param sourceFile {@code null-ok;} name of the file of origin or
5099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code null} if unknown
5199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param address {@code >= -1;} original bytecode address or {@code -1}
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * if unknown
5399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param line {@code >= -1;} original line number or {@code -1} if
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * unknown
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
56333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson    public SourcePosition(CstString sourceFile, int address, int line) {
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (address < -1) {
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("address < -1");
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (line < -1) {
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("line < -1");
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.sourceFile = sourceFile;
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.address = address;
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.line = line;
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String toString() {
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuffer sb = new StringBuffer(50);
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sourceFile != null) {
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(sourceFile.toHuman());
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(":");
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (line >= 0) {
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(line);
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append('@');
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (address < 0) {
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append("????");
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(Hex.u2(address));
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sb.toString();
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean equals(Object other) {
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!(other instanceof SourcePosition)) {
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (this == other) {
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        SourcePosition pos = (SourcePosition) other;
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (address == pos.address) && sameLineAndFile(pos);
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int hashCode() {
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sourceFile.hashCode() + address + line;
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns whether the lines match between this instance and
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the one given.
120de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
12199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param other {@code non-null;} the instance to compare to
12299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code true} iff the lines match
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean sameLine(SourcePosition other) {
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (line == other.line);
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns whether the lines and files match between this instance and
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the one given.
131de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
13299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param other {@code non-null;} the instance to compare to
13399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code true} iff the lines and files match
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean sameLineAndFile(SourcePosition other) {
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (line == other.line) &&
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ((sourceFile == other.sourceFile) ||
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             ((sourceFile != null) && sourceFile.equals(other.sourceFile)));
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the source file, if known.
143de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
14499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code null-ok;} the source file or {@code null} if unknown
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
146333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson    public CstString getSourceFile() {
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sourceFile;
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the original bytecode address.
152de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
15399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= -1;} the address or {@code -1} if unknown
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getAddress() {
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return address;
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the original line number.
161de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
16299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= -1;} the original line number or {@code -1} if
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * unknown
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getLine() {
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return line;
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
169