| /*=============================================================================# |
| # Copyright (c) 2000, 2020 IBM Corporation and others. |
| # |
| # 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: |
| # IBM Corporation - org.eclipse.jdt: initial API and implementation |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.ecommons.text.core.rules; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.rules.ICharacterScanner; |
| |
| |
| /** |
| * A buffered document scanner. The buffer always contains a section of a fixed size of the |
| * document to be scanned. |
| */ |
| public final class BufferedDocumentScanner implements ICharacterScanner { |
| |
| /** The document being scanned. */ |
| private IDocument fDocument; |
| /** The offset of the document range to scan. */ |
| private int fRangeOffset; |
| /** The length of the document range to scan. */ |
| private int fRangeLength; |
| /** The delimiters of the document. */ |
| private char[][] fDelimiters; |
| |
| /** The buffer. */ |
| private final char[] fBuffer; |
| /** The offset of the buffer within the document. */ |
| private int fBufferOffset; |
| /** The valid length of the buffer for access. */ |
| private int fBufferLength; |
| /** The offset of the scanner within the buffer. */ |
| private int fOffset; |
| |
| |
| /** |
| * Creates a new buffered document scanner. |
| * The buffer size is set to the given number of characters. |
| * |
| * @param size the buffer size |
| */ |
| public BufferedDocumentScanner(final int size) { |
| Assert.isTrue(size >= 1); |
| this.fBuffer= new char[size]; |
| } |
| |
| /** |
| * Fills the buffer with the contens of the document starting at the given offset. |
| * |
| * @param offset the document offset at which the buffer starts |
| */ |
| private final void updateBuffer(final int offset) { |
| this.fBufferOffset= offset; |
| |
| if (this.fBufferOffset + this.fBuffer.length > this.fRangeOffset + this.fRangeLength) { |
| this.fBufferLength= this.fRangeLength - (this.fBufferOffset - this.fRangeOffset); |
| } else { |
| this.fBufferLength= this.fBuffer.length; |
| } |
| |
| try { |
| final String content= this.fDocument.get(this.fBufferOffset, this.fBufferLength); |
| content.getChars(0, this.fBufferLength, this.fBuffer, 0); |
| } catch (final BadLocationException e) { |
| } |
| } |
| |
| /** |
| * Configures the scanner by providing access to the document range over which to scan. |
| * |
| * @param document the document to scan |
| * @param offset the offset of the document range to scan |
| * @param length the length of the document range to scan |
| */ |
| public final void setRange(final IDocument document, final int offset, final int length) { |
| this.fDocument= document; |
| this.fRangeOffset= offset; |
| this.fRangeLength= length; |
| |
| final String[] delimiters= document.getLegalLineDelimiters(); |
| this.fDelimiters= new char[delimiters.length][]; |
| for (int i= 0; i < delimiters.length; i++) { |
| this.fDelimiters[i]= delimiters[i].toCharArray(); |
| } |
| |
| updateBuffer(offset); |
| this.fOffset= 0; |
| } |
| |
| @Override |
| public final int read() { |
| if (this.fOffset >= this.fBufferLength) { |
| if (this.fBufferOffset + this.fBufferLength >= this.fRangeOffset + this.fRangeLength) { |
| return EOF; |
| } else { |
| updateBuffer(this.fBufferOffset + this.fBufferLength); |
| this.fOffset= 0; |
| } |
| } |
| return this.fBuffer[this.fOffset++]; |
| } |
| |
| @Override |
| public final void unread() { |
| if (this.fOffset <= 0) { |
| if (this.fBufferOffset <= this.fRangeOffset) { |
| // error: BOF |
| } else { |
| updateBuffer(this.fBufferOffset - this.fBuffer.length); |
| this.fOffset= this.fBuffer.length - 1; |
| } |
| } else { |
| --this.fOffset; |
| } |
| } |
| |
| @Override |
| public final int getColumn() { |
| try { |
| final int offset= this.fBufferOffset + this.fOffset; |
| final int line= this.fDocument.getLineOfOffset(offset); |
| final int start= this.fDocument.getLineOffset(line); |
| return offset - start; |
| } catch (final BadLocationException e) { |
| } |
| |
| return -1; |
| } |
| |
| @Override |
| public final char[][] getLegalLineDelimiters() { |
| return this.fDelimiters; |
| } |
| |
| } |