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

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

mercurial