/*******************************************************************************
* Copyright (c) 2009, 2013 Wind River Systems, Inc. and others.
* 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:
* Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
/**
* Abstract class for providing input to the lexer.
* @since 5.2
*/
public abstract class AbstractCharArray {
/**
* Returns the length of this array or -1 if it is yet, unknown. This method may be called
* before the array has been traversed.
*/
public abstract int tryGetLength();
/**
* Returns the length of the array. This method is called only after the lexer has worked its
* way through the array. Therefore for subclasses it is efficient enough to read through to
* the end of the array and provide the length.
*/
public abstract int getLength();
/**
* Checks whether the given offset is valid for this array. Subclasses may assume
* that offset is non-negative.
*/
public abstract boolean isValidOffset(int offset);
/**
* Computes 64-bit hash value of the character array. This method doesn't cause any I/O if
* called after the array has been traversed.
* @return The hash value of the contents of the array.
*/
public abstract long getContentsHash();
/**
* Returns the character at the given position, subclasses do not have to do range checks.
*/
public abstract char get(int offset);
/**
* Copies a range of characters to the given destination. Subclasses do not have to do any
* range checks.
*/
public abstract void arraycopy(int offset, char[] destination, int destinationPos, int length);
/**
* Returns the {@link CharSequence} representing a range in the character array.
*/
public CharSequence subSequence(int start, int end) {
return new SubArray(start, end);
}
/**
* Returns {@code true} if there were I/O errors while retrieving contents of this array.
*/
public abstract boolean hasError();
/**
* This method is slow. Use only for debugging.
*/
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
for (int pos = 0; isValidOffset(pos); pos++) {
buf.append(get(pos));
}
return buf.toString();
}
private class SubArray implements CharSequence {
private final int start;
private final int end;
SubArray(int start, int end) {
checkStartEnd(start, end);
this.start = start;
this.end = end;
}
@Override
public int length() {
return end - start;
}
@Override
public char charAt(int index) {
return get(start + index);
}
@Override
public CharSequence subSequence(int start, int end) {
checkStartEnd(start, end);
if (end > this.end - this.start)
throw new IndexOutOfBoundsException(String.valueOf(end));
return new SubArray(this.start + start, this.start + end);
}
private void checkStartEnd(int start, int end) {
if (start < 0)
throw new IndexOutOfBoundsException(String.valueOf(start));
if (end < start)
throw new IndexOutOfBoundsException(String.valueOf(end) + " < " + String.valueOf(start)); //$NON-NLS-1$
}
}
}