src/share/classes/com/sun/tools/javac/util/Position.java

Thu, 10 Jun 2010 16:08:01 -0700

author
jjg
date
Thu, 10 Jun 2010 16:08:01 -0700
changeset 581
f2fdd52e4e87
parent 554
9d9f26857129
child 1326
30c36e23f154
permissions
-rw-r--r--

6944312: Potential rebranding issues in openjdk/langtools repository sources
Reviewed-by: darcy

duke@1 1 /*
ohair@554 2 * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
duke@1 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@1 4 *
duke@1 5 * This code is free software; you can redistribute it and/or modify it
duke@1 6 * under the terms of the GNU General Public License version 2 only, as
ohair@554 7 * published by the Free Software Foundation. Oracle designates this
duke@1 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
duke@1 10 *
duke@1 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@1 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@1 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@1 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@1 15 * accompanied this code).
duke@1 16 *
duke@1 17 * You should have received a copy of the GNU General Public License version
duke@1 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@1 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@1 20 *
ohair@554 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554 22 * or visit www.oracle.com if you need additional information or have any
ohair@554 23 * questions.
duke@1 24 */
duke@1 25
duke@1 26 package com.sun.tools.javac.util;
duke@1 27
duke@1 28 import java.util.BitSet;
duke@1 29 import static com.sun.tools.javac.util.LayoutCharacters.*;
duke@1 30
duke@1 31 /** A class that defines source code positions as simple character
duke@1 32 * offsets from the beginning of the file. The first character
duke@1 33 * is at position 0.
duke@1 34 *
duke@1 35 * Support is also provided for (line,column) coordinates, but tab
duke@1 36 * expansion is optional and no Unicode excape translation is considered.
duke@1 37 * The first character is at location (1,1).
duke@1 38 *
jjg@581 39 * <p><b>This is NOT part of any supported API.
jjg@581 40 * If you write code that depends on this, you do so at your own risk.
duke@1 41 * This code and its internal interfaces are subject to change or
duke@1 42 * deletion without notice.</b>
duke@1 43 */
duke@1 44 public class Position {
duke@1 45 public static final int NOPOS = -1;
duke@1 46
duke@1 47 public static final int FIRSTPOS = 0;
duke@1 48 public static final int FIRSTLINE = 1;
duke@1 49 public static final int FIRSTCOLUMN = 1;
duke@1 50
duke@1 51 public static final int LINESHIFT = 10;
duke@1 52 public static final int MAXCOLUMN = (1<<LINESHIFT) - 1;
duke@1 53 public static final int MAXLINE = (1<<(Integer.SIZE-LINESHIFT)) - 1;
duke@1 54
duke@1 55 public static final int MAXPOS = Integer.MAX_VALUE;
duke@1 56
duke@1 57 /**
duke@1 58 * This is class is not supposed to be instantiated.
duke@1 59 */
duke@1 60 private Position() {}
duke@1 61
duke@1 62 /** A two-way map between line/column numbers and positions,
duke@1 63 * derived from a scan done at creation time. Tab expansion is
duke@1 64 * optionally supported via a character map. Text content
duke@1 65 * is not retained.
duke@1 66 *<p>
duke@1 67 * Notes: The first character position FIRSTPOS is at
duke@1 68 * (FIRSTLINE,FIRSTCOLUMN). No account is taken of Unicode escapes.
duke@1 69 *
duke@1 70 * @param src Source characters
duke@1 71 * @param max Number of characters to read
duke@1 72 * @param expandTabs If true, expand tabs when calculating columns
duke@1 73 */
duke@1 74 public static LineMap makeLineMap(char[] src, int max, boolean expandTabs) {
duke@1 75 LineMapImpl lineMap = expandTabs ?
duke@1 76 new LineTabMapImpl(max) : new LineMapImpl();
duke@1 77 lineMap.build(src, max);
duke@1 78 return lineMap;
duke@1 79 }
duke@1 80
duke@1 81 /** Encode line and column numbers in an integer as:
duke@1 82 * line-number << LINESHIFT + column-number
duke@1 83 * {@link Position.NOPOS represents an undefined position.
duke@1 84 *
duke@1 85 * @param line number of line (first is 1)
duke@1 86 * @param col number of character on line (first is 1)
duke@1 87 * @return an encoded position or {@link Position.NOPOS
duke@1 88 * if the line or column number is too big to
duke@1 89 * represent in the encoded format
duke@1 90 * @throws IllegalArgumentException if line or col is less than 1
duke@1 91 */
duke@1 92 public static int encodePosition(int line, int col) {
duke@1 93 if (line < 1)
duke@1 94 throw new IllegalArgumentException("line must be greater than 0");
duke@1 95 if (col < 1)
duke@1 96 throw new IllegalArgumentException("column must be greater than 0");
duke@1 97
duke@1 98 if (line > MAXLINE || col > MAXCOLUMN) {
duke@1 99 return NOPOS;
duke@1 100 }
duke@1 101 return (line << LINESHIFT) + col;
duke@1 102 }
duke@1 103
duke@1 104 public static interface LineMap extends com.sun.source.tree.LineMap {
duke@1 105 /** Find the start position of a line.
duke@1 106 *
duke@1 107 * @param line number of line (first is 1)
duke@1 108 * @return position of first character in line
duke@1 109 * @throws ArrayIndexOutOfBoundsException
duke@1 110 * if <tt>lineNumber < 1</tt>
duke@1 111 * if <tt>lineNumber > no. of lines</tt>
duke@1 112 */
duke@1 113 int getStartPosition(int line);
duke@1 114
duke@1 115 /** Find the position corresponding to a (line,column).
duke@1 116 *
duke@1 117 * @param line number of line (first is 1)
duke@1 118 * @param column number of character on line (first is 1)
duke@1 119 *
duke@1 120 * @return position of character
duke@1 121 * @throws ArrayIndexOutOfBoundsException
duke@1 122 * if <tt>line < 1</tt>
duke@1 123 * if <tt>line > no. of lines</tt>
duke@1 124 */
duke@1 125 int getPosition(int line, int column);
duke@1 126
duke@1 127 /** Find the line containing a position; a line termination
duke@1 128 * character is on the line it terminates.
duke@1 129 *
duke@1 130 * @param pos character offset of the position
duke@1 131 * @return the line number on which pos occurs (first line is 1)
duke@1 132 */
duke@1 133 int getLineNumber(int pos);
duke@1 134
duke@1 135 /** Find the column for a character position.
duke@1 136 * Note: this method does not handle tab expansion.
duke@1 137 * If tab expansion is needed, use a LineTabMap instead.
duke@1 138 *
duke@1 139 * @param pos character offset of the position
duke@1 140 * @return the column number at which pos occurs
duke@1 141 */
duke@1 142 int getColumnNumber(int pos);
duke@1 143 }
duke@1 144
duke@1 145 static class LineMapImpl implements LineMap {
duke@1 146 protected int[] startPosition; // start position of each line
duke@1 147
duke@1 148 protected LineMapImpl() {}
duke@1 149
duke@1 150 protected void build(char[] src, int max) {
duke@1 151 int c = 0;
duke@1 152 int i = 0;
duke@1 153 int[] linebuf = new int[max];
duke@1 154 while (i < max) {
duke@1 155 linebuf[c++] = i;
duke@1 156 do {
duke@1 157 char ch = src[i];
duke@1 158 if (ch == '\r' || ch == '\n') {
duke@1 159 if (ch == '\r' && (i+1) < max && src[i+1] == '\n')
duke@1 160 i += 2;
duke@1 161 else
duke@1 162 ++i;
duke@1 163 break;
duke@1 164 }
duke@1 165 else if (ch == '\t')
duke@1 166 setTabPosition(i);
duke@1 167 } while (++i < max);
duke@1 168 }
duke@1 169 this.startPosition = new int[c];
duke@1 170 System.arraycopy(linebuf, 0, startPosition, 0, c);
duke@1 171 }
duke@1 172
duke@1 173 public int getStartPosition(int line) {
duke@1 174 return startPosition[line - FIRSTLINE];
duke@1 175 }
duke@1 176
duke@1 177 public long getStartPosition(long line) {
duke@1 178 return getStartPosition(longToInt(line));
duke@1 179 }
duke@1 180
duke@1 181 public int getPosition(int line, int column) {
duke@1 182 return startPosition[line - FIRSTLINE] + column - FIRSTCOLUMN;
duke@1 183 }
duke@1 184
duke@1 185 public long getPosition(long line, long column) {
duke@1 186 return getPosition(longToInt(line), longToInt(column));
duke@1 187 }
duke@1 188
duke@1 189 // Cache of last line number lookup
duke@1 190 private int lastPosition = Position.FIRSTPOS;
duke@1 191 private int lastLine = Position.FIRSTLINE;
duke@1 192
duke@1 193 public int getLineNumber(int pos) {
duke@1 194 if (pos == lastPosition) {
duke@1 195 return lastLine;
duke@1 196 }
duke@1 197 lastPosition = pos;
duke@1 198
duke@1 199 int low = 0;
duke@1 200 int high = startPosition.length-1;
duke@1 201 while (low <= high) {
duke@1 202 int mid = (low + high) >> 1;
duke@1 203 int midVal = startPosition[mid];
duke@1 204
duke@1 205 if (midVal < pos)
duke@1 206 low = mid + 1;
duke@1 207 else if (midVal > pos)
duke@1 208 high = mid - 1;
duke@1 209 else {
duke@1 210 lastLine = mid + 1; // pos is at beginning of this line
duke@1 211 return lastLine;
duke@1 212 }
duke@1 213 }
duke@1 214 lastLine = low;
duke@1 215 return lastLine; // pos is on this line
duke@1 216 }
duke@1 217
duke@1 218 public long getLineNumber(long pos) {
duke@1 219 return getLineNumber(longToInt(pos));
duke@1 220 }
duke@1 221
duke@1 222 public int getColumnNumber(int pos) {
duke@1 223 return pos - startPosition[getLineNumber(pos) - FIRSTLINE] + FIRSTCOLUMN;
duke@1 224 }
duke@1 225
duke@1 226 public long getColumnNumber(long pos) {
duke@1 227 return getColumnNumber(longToInt(pos));
duke@1 228 }
duke@1 229
duke@1 230 private static int longToInt(long longValue) {
duke@1 231 int intValue = (int)longValue;
duke@1 232 if (intValue != longValue)
duke@1 233 throw new IndexOutOfBoundsException();
duke@1 234 return intValue;
duke@1 235 }
duke@1 236
duke@1 237 protected void setTabPosition(int offset) {}
duke@1 238 }
duke@1 239
duke@1 240 /**
duke@1 241 * A LineMap that handles tab expansion correctly. The cost is
duke@1 242 * an additional bit per character in the source array.
duke@1 243 */
duke@1 244 public static class LineTabMapImpl extends LineMapImpl {
duke@1 245 private BitSet tabMap; // bits set for tab positions.
duke@1 246
duke@1 247 public LineTabMapImpl(int max) {
duke@1 248 super();
duke@1 249 tabMap = new BitSet(max);
duke@1 250 }
duke@1 251
duke@1 252 protected void setTabPosition(int offset) {
duke@1 253 tabMap.set(offset);
duke@1 254 }
duke@1 255
duke@1 256 public int getColumnNumber(int pos) {
duke@1 257 int lineStart = startPosition[getLineNumber(pos) - FIRSTLINE];
duke@1 258 int column = 0;
duke@1 259 for (int bp = lineStart; bp < pos; bp++) {
duke@1 260 if (tabMap.get(bp))
duke@1 261 column = (column / TabInc * TabInc) + TabInc;
duke@1 262 else
duke@1 263 column++;
duke@1 264 }
duke@1 265 return column + FIRSTCOLUMN;
duke@1 266 }
duke@1 267
duke@1 268 public int getPosition(int line, int column) {
duke@1 269 int pos = startPosition[line - FIRSTLINE];
duke@1 270 column -= FIRSTCOLUMN;
duke@1 271 int col = 0;
duke@1 272 while (col < column) {
duke@1 273 pos++;
duke@1 274 if (tabMap.get(pos))
duke@1 275 col = (col / TabInc * TabInc) + TabInc;
duke@1 276 else
duke@1 277 col++;
duke@1 278 }
duke@1 279 return pos;
duke@1 280 }
duke@1 281 }
duke@1 282 }

mercurial