/*******************************************************************************
* Copyright Technophobia Ltd 2012
*
* This file is part of the Substeps Eclipse Plugin.
*
* The Substeps Eclipse Plugin is free software: you can redistribute it and/or modify
* it under the terms of the Eclipse Public License v1.0.
*
* The Substeps Eclipse Plugin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Eclipse Public License for more details.
*
* You should have received a copy of the Eclipse Public License
* along with the Substeps Eclipse Plugin. If not, see <http://www.eclipse.org/legal/epl-v10.html>.
******************************************************************************/
package com.technophobia.substeps.document.text.rule;
import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.MultiLineRule;
/**
* Extention of {@link MultiLineRule} in which the end sequence may contain
* whitespace that should be discounted when scanning for it
*
* @author sforbes
*
*/
public class MultiLineFragmentedSequenceRule extends MultiLineRule {
private static final char[] WHITESPACE_CHARS = new char[] { ' ', '\r', '\n', '\t' };
public MultiLineFragmentedSequenceRule(final String startString, final String endSequence, final IToken token) {
super(startString, endSequence, token, (char) 0, true);
}
@Override
protected boolean sequenceDetected(final ICharacterScanner scanner, final char[] sequence, final boolean eofAllowed) {
int i = 1;
while (i < sequence.length) {
final int c = scanner.read();
if (c == ICharacterScanner.EOF && eofAllowed) {
return true;
} else if (c == sequence[i]) {
i++;
} else if (whitespaceChar(c)) {
// no-op - don't fail yet, but likewise don't increment i
} else {
// Non-matching character detected, rewind the scanner back to
// the start.
// Do not unread the first character.
scanner.unread();
for (int j = i - 1; j > 0; j--)
scanner.unread();
return false;
}
}
return true;
}
/**
* Determine if character is a whitespace character
*
* @param c
* the character under test
* @return true if c is whitespace, false otherwise
*/
private boolean whitespaceChar(final int c) {
for (final char whitespaceChar : WHITESPACE_CHARS) {
if (whitespaceChar == c)
return true;
}
return false;
}
}