/****************************************************************************** * Copyright (c) 2002 - 2014 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *****************************************************************************/ /* * Position.java * * Created on 20. Juni 2005, 10:32 */ package com.ibm.wala.sourcepos; /** * Represents a source file position. Source file positions are integers in the * format: {@code line-number << LINESHIFT + column-number} * * @author Siegfried Weber * @author Juergen Graf <juergen.graf@gmail.com> */ public final class Position { /** Represents the undefined position. */ private static final int NOPOS = 0; /** bits to shift to get the line number */ private static final int LINE_SHIFT = 10; /** the bit mask of the column number */ private static final int COLUMN_MASK = 1023; /** Stores the position as unsigned integer. */ private int position; /** * Creates the undefined position. */ Position() { position = NOPOS; } /** * Creates a new instance of Position. * * @param position * the position as unsigned integer * @throws InvalidPositionException * if the position is not undefined and the line or the column * number is 0 */ Position(int position) throws InvalidPositionException { this.position = position; if (!isUndefined() && getLine() == 0) throw new InvalidPositionException(InvalidPositionException.Cause.LINE_NUMBER_ZERO); if (!isUndefined() && getColumn() == 0) throw new InvalidPositionException(InvalidPositionException.Cause.COLUMN_NUMBER_ZERO); } /** * Creates a new instance of Position. * * @param line * the line number * @param column * the column number * @throws InvalidPositionException * if the line or the column number is out of range or if the * position is not undefined and the line or the column number is 0. * The maximum line number is 4194303. The maximum column number is * 1023. */ Position(int line, int column) throws InvalidPositionException { if (line < 0 || line >= 4194304) // 4194304 = 2^32 >>> LINE_SHIFT throw new InvalidPositionException(InvalidPositionException.Cause.LINE_NUMBER_OUT_OF_RANGE); if (column < 0 || column > COLUMN_MASK) throw new InvalidPositionException(InvalidPositionException.Cause.COLUMN_NUMBER_OUT_OF_RANGE); if (line == 0 && column != 0) throw new InvalidPositionException(InvalidPositionException.Cause.LINE_NUMBER_ZERO); if (line != 0 && column == 0) throw new InvalidPositionException(InvalidPositionException.Cause.COLUMN_NUMBER_ZERO); position = (line << LINE_SHIFT) + column; } /** * Returns the line number. * * @return the line number */ public final int getLine() { return position >>> LINE_SHIFT; } /** * Returns the column number. * * @return the column number */ public final int getColumn() { return position & COLUMN_MASK; } /** * Tests whether this position is undefined. * * @return true if this position is undefined */ public final boolean isUndefined() { return position == NOPOS; } /** * Tests whether this position is before the given position. If one of the * positions is undefined or {@code p} is null then false is returned. * * @param p * the position to test with * @return true if this position is greater */ boolean isBefore(Position p) { return (p != null) && !isUndefined() && !p.isUndefined() && toLong() < p.toLong(); } /** * Converts this position to a signed long variable. * * @return this position as signed long */ private long toLong() { return position & 0xFFFFFFFFL; } /** * Returns this position as an unsigned integer. * * @return this position as unsigned integer */ int toUnsignedInt() { return position; } @Override public String toString() { return getLine() + ":" + getColumn(); } }