summaryrefslogblamecommitdiff
path: root/sources/ch/epfl/lamp/util/Position.java
blob: 486ef7add65c40e310d044b38891a03f6d3f8eee (plain) (tree)
1
2
3
4
5
6
7
8
9
10









                                                                          


























                                                                      




                                                                              
                                                        
                                             
                                                          
                                                                               
 








                                                                 
                                                       



                                                                              






                                                                           



























                                                                              









                                                  




                                                     



                                                            


                                                                           




                                                                              














                                                      




                                                                        

                                                            



                                                                      



                                                  
                                                     










                                                                               
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
\*                                                                      */

// $Id$

package ch.epfl.lamp.util;

/**
 * This class represents a position in a source file. Such a position
 * is defined by a source file (mandatory), a line number (optional)
 * and a column number (optional, may be specified only if the line
 * number is defined).
 *
 * Line (Column) numbers range from 0 to Integer.MAX_VALUE. A value of
 * 0 indicates that the line (column) is undefined, 1 represents the
 * first line (column). Negative values are prohibited.
 *
 * The class provides also functions to encode a line number and a
 * column number into one single integer. The encode line (column)
 * numbers range from 0 to LINE_MASK (COLUMN_MASK), where 0 indicates
 * that the line (column) is the undefined and 1 represents the first
 * line (column). Line (Column) numbers greater than LINE_MASK
 * (COLUMN_MASK) are replaced by LINE_MASK (COLUMN_MASK). Furthermore,
 * if the encoded line number is LINE_MASK, the column number is
 * always set to 0.
 *
 * The following properties hold:
 * - the undefined position is 0: encode(0,0) == 0
 * - encodings are non-negative : encode(line,column) >= 0
 * - position order is preserved:
 *   (line1 < line2) || (line1 == line2 && column1 < column2)
 * implies
 *   encode(line1,column1) <= encode(line2,column2)
 */
public class Position {

    //########################################################################
    // Public Constants

    /** Number of bits used to encode the line number */
    public static final int LINE_BITS   = 20;
    /** Number of bits used to encode the column number */
    public static final int COLUMN_BITS = 31 - LINE_BITS; // no negatives => 31

    /** Mask to decode the line number */
    public static final int LINE_MASK   = (1 << LINE_BITS) - 1;
    /** Mask to decode the column number */
    public static final int COLUMN_MASK = (1 << COLUMN_BITS) - 1;

    /** The undefined position */
    public static final int NOPOS       = 0;

    /** The first position in a source file */
    public static final int FIRSTPOS    = encode(1, 1);

    //########################################################################
    // Public Functions

    /** Encodes a position into a single integer. */
    public static int encode(int line, int column) {
        assert line >= 0 : line;
        assert line == 0 ? column == 0 : column >= 0 : line + "," + column;
        if (line >= LINE_MASK) { line = LINE_MASK; column = 0; }
        if (column > COLUMN_MASK) column = COLUMN_MASK;
        return (line << COLUMN_BITS) | column;
    }

    /** Returns the line number of the encoded position. */
    public static int line(int position) {
        return (position >> COLUMN_BITS) & LINE_MASK;
    }

    /** Returns the column number of the encoded position. */
    public static int column(int position) {
        return position & COLUMN_MASK;
    }

    //########################################################################
    // Private Fields

    /** The position's file */
    private final SourceFile file;

    /** The position's line number */
    private final int line;

    /** The position's column number */
    private final int column;

    //########################################################################
    // Public Constructors

    /** Initializes a new instance. */
    public Position(String source) {
        this(new SourceFile(source, new byte[0]));
    }

    /** Initializes a new instance. */
    public Position(SourceFile file) {
        this(file, 0, 0);
    }

    /** Initializes a new instance. */
    public Position(SourceFile file, int position) {
        this(file, line(position), column(position));
    }

    /** Initializes a new instance. */
    public Position(SourceFile file, int line, int column) {
        this.file = file;
        this.line = line;
        this.column = column;
        assert file != null;
        assert line >= 0 : line;
        assert line == 0 ? column == 0 : column >= 0 : line + "," + column;
    }

    //########################################################################
    // Public Methods

    /** Returns the file of this position. */
    public SourceFile file() {
        return file;
    }

    /** Returns the line number of this position. */
    public int line() {
        return line;
    }

    /** Returns the column number of this position. */
    public int column() {
        return column;
    }

    /** Returns an int encoding the line and column of this position. */
    public int encodedLineColumn() {
        return encode(line, column);
    }

    /** Returns a string representation of this position. */
    public String toString() {
        StringBuffer buffer = new StringBuffer(file.name());
        if (line > 0) buffer.append(":").append(line);
        if (line > 0 && column > 0) buffer.append(":").append(column);
        return buffer.toString();
    }

    /** Returns the hash code of this position. */
    public int hashCode() {
        return file.hashCode() ^ encodedLineColumn();
    }

    /** Returns true iff the given object represents the same position. */
    public boolean equals(Object object) {
        if (!(object instanceof Position)) return false;
        Position that = (Position)object;
        return file == that.file && line == that.line && column == that.column;
    }

    //########################################################################
}