/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* 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:
* * Arnold Lankamp - Arnold.Lankamp@cwi.nl
*******************************************************************************/
package org.rascalmpl.parser.gtd.location;
public class PositionStore{
private final static int LINE_FEED_CHAR = '\n';
private final static int CARRIAGE_RETURN_CHAR = '\r';
private final static int DEFAULT_SIZE = 8;
private int[] offsets;
private int endOfFile;
private int size;
private int cursor;
public PositionStore(){
super();
offsets = new int[DEFAULT_SIZE];
}
public void enlarge(){
int[] oldOffsets = offsets;
offsets = new int[size << 1];
System.arraycopy(oldOffsets, 0, offsets, 0, size);
}
public void index(int[] input){
add(0);
endOfFile = input.length;
boolean encounteredCarriageReturn = false;
for(int i = 0; i < endOfFile; ++i){
int character = input[i];
if(character == CARRIAGE_RETURN_CHAR){
encounteredCarriageReturn = true;
}else if(character == LINE_FEED_CHAR){
add(i + 1);
encounteredCarriageReturn = false;
}else if(encounteredCarriageReturn){
add(i);
encounteredCarriageReturn = false;
}
}
}
private void add(int offset){
if(size == offsets.length){
enlarge();
}
offsets[size++] = offset;
}
public void resetCursor(){
cursor = 0;
}
public void setCursorTo(int index){
cursor = index;
}
public int findLine(int offset){
int line = cursor;
if(offsets[line] <= offset){
++line;
while(line < size && offsets[line] <= offset){
++line;
}
cursor = line - 1;
}else{
while(line > 0 && offsets[line] > offset){
--line;
}
cursor = line;
}
return cursor;
}
public int getColumn(int offset, int line){
return (offset - offsets[line]);
}
public boolean startsLine(int offset){
return (isAtColumn(offset, 0));
}
public boolean endsLine(int offset){
return (offset == endOfFile) || (isAtColumn(offset+1, 0));
}
public boolean isAtColumn(int offset, int column){
return (offset - offsets[findLine(offset)]) == column;
}
public void clear(){
int length = offsets.length;
offsets = new int[length];
size = 0;
}
public void dirtyClear(){
size = 0;
}
}