blob: 5fa719e0534169c5c8b657f39b3a097123fe0ff7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2018 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat - initial API and implementation
*******************************************************************************/
package org.eclipse.linuxtools.internal.rpm.ui.editor.rules;
import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IPredicateRule;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.Token;
public class SectionRule implements IPredicateRule {
/** Buffer used for pattern detection */
private StringBuilder fBuffer = new StringBuilder();
/** Buffer used for pattern detection of next header */
private StringBuilder nextHeaderBuffer = new StringBuilder();
/** The success token */
private IToken token;
/** The beginning token, represents a section of the spec file */
private String startingHeader;
/** A list of possible ending section headers */
private String[] endingHeaders;
public SectionRule(String startingHeader, String[] endingHeaders, IToken token) {
this.startingHeader = startingHeader;
this.endingHeaders = endingHeaders;
this.token = token;
}
@Override
public IToken getSuccessToken() {
return token;
}
@Override
public IToken evaluate(ICharacterScanner scanner, boolean resume) {
/*
* whether we think we're reading the ending sequence, i.e. the next section
* heading
*/
boolean readingEndSequence = false;
fBuffer.setLength(0);
nextHeaderBuffer.setLength(0);
int c = scanner.read();
/*
* if we're starting at the beginning header we check that the partition begins
* with the required header
*/
if (!resume) {
for (int i = 0; i < startingHeader.length(); i++) {
fBuffer.append((char) c);
if (startingHeader.charAt(i) != (char) c) {
unreadBuffer(scanner, fBuffer);
return Token.UNDEFINED;
}
c = scanner.read();
}
}
fBuffer.append((char) c);
do {
// Sections can only begin with a % on a new line
if (c == '\n') {
// if we were readin a %blah, reset because it turned out to
// not be a terminating section header
readingEndSequence = false;
// if we're reading a line beginning with % then it might be
// at terminating sectino header
c = scanner.read();
if (c == '%') {
// Start appending to the we reset the buffer for section
// headers, and indicate that this line can be a terminating
// section header
nextHeaderBuffer.setLength(0);
readingEndSequence = true;
} else if (c == ICharacterScanner.EOF) {
// we allow EOF as a valid ending to a section
break;
} else {
fBuffer.append((char) c);
continue;
}
}
// we're in a line that's a possible terminating section header,
// so we compare it with all terminating headers
if (readingEndSequence) {
nextHeaderBuffer.append((char) c);
for (int i = 0; i < endingHeaders.length; i++) {
String tempSectionheader = endingHeaders[i];
// we've found our terminating header
if (nextHeaderBuffer.toString().equals(tempSectionheader)) {
// exclude the terminating header from the partition
unreadBuffer(scanner, nextHeaderBuffer);
return token;
}
}
}
// read the next char
c = scanner.read();
fBuffer.append((char) c);
} while (c != ICharacterScanner.EOF);
// we've reached EOF and since our section started with the correct
// header, then this is just the current end of the partition, and
// we return the success token
return token;
}
@Override
public IToken evaluate(ICharacterScanner scanner) {
return evaluate(scanner, false);
}
/**
* Returns the characters in the buffer to the scanner.
*
* @param scanner the scanner to be used
*/
protected void unreadBuffer(ICharacterScanner scanner, StringBuilder buffer) {
for (int i = buffer.length() - 1; i >= 0; i--) {
scanner.unread();
}
}
}