| /******************************************************************************* |
| * 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(); |
| } |
| } |
| |
| } |