summaryrefslogtreecommitdiff
path: root/sources/ch/epfl/lamp/util/Position.java
blob: 91c9d702a38ff22eb510ca013a7936b8feb91252 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
\*                                                                      */

// $Id$

package ch.epfl.lamp.util;

public class Position {

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

    /** Number of bits used to encode the file */
    public static final int FILE_BITS   = 6;
    /** Number of bits used to encode the line number */
    public static final int LINE_BITS   = 16;
    /** Number of bits used to encode the column number */
    public static final int COLUMN_BITS = 32 - LINE_BITS - FILE_BITS;

    /** Mask to decode the file */
    public static final int FILE_MASK   = (1 << FILE_BITS) - 1;
    /** 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(null, 1, 1);

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

    /** Encodes a position into a single int. */
    public static int encode(SourceFile file, int line, int column) {
        int fileId = file == null ? 0 : file.id() & FILE_MASK;
        if (fileId < 0 || FILE_MASK < fileId) fileId = 0;
        if (line < 0  || LINE_MASK < line) line = 0;
        if (column < 0 || COLUMN_MASK < column) column = 0;
        return (((fileId << LINE_BITS) | line) << COLUMN_BITS) | column;
    }

    /** Returns the file of the encoded position. */
    public static SourceFile file(int position) {
        int fileId = (position >> (COLUMN_BITS + LINE_BITS)) & FILE_MASK;
        return SourceFile.fromId(fileId);
    }

    /** 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(int position) {
        this(file(position), line(position), column(position));
    }

    /** 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 line, int column) {
        this.file = file;
        this.line = line;
        this.column = column;
    }

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

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

    /** 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 a string representation of this position. */
    public String toString() {
        return file.name() + ":" + line + ":" + column;
    }

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

    /** 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;
    }

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