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