| /*=============================================================================# |
| # Copyright (c) 2015, 2021 Stephan Wahlbrink 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, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.jcommons.text.core.input; |
| |
| import org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| |
| |
| @NonNullByDefault |
| public abstract class FilterParserInput extends TextParserInput { |
| |
| |
| private final TextParserInput source; |
| |
| private int[] bufferBeginIndexes; |
| private int[] bufferEndIndexes; |
| |
| |
| protected FilterParserInput(final TextParserInput source, final int defaultBufferSize) { |
| super(defaultBufferSize); |
| |
| if (source == null) { |
| throw new NullPointerException("source"); //$NON-NLS-1$ |
| } |
| this.source= source; |
| |
| this.bufferBeginIndexes= new int[1]; |
| this.bufferEndIndexes= new int[0]; |
| } |
| |
| |
| @Override |
| protected void reset() { |
| super.reset(); |
| |
| this.bufferBeginIndexes[0]= 0; |
| } |
| |
| |
| @Override |
| public FilterParserInput init() { |
| super.init(); |
| |
| return this; |
| } |
| |
| @Override |
| public FilterParserInput init(final int startIndex, final int stopIndex) { |
| this.source.init(startIndex, stopIndex); |
| |
| this.bufferBeginIndexes[0]= this.source.getStartIndex(); |
| |
| super.init(this.source.getStartIndex(), this.source.getStopIndex()); |
| |
| return this; |
| } |
| |
| |
| public final TextParserInput getSource() { |
| return this.source; |
| } |
| |
| @Override |
| protected int getSourceStartIndex() { |
| return this.source.getSourceStartIndex(); |
| } |
| |
| @Override |
| protected int getSourceLength() { |
| return this.source.getSourceLength(); |
| } |
| |
| @Override |
| protected @Nullable String getSourceString() { |
| return this.source.getSourceString(); |
| } |
| |
| @Override |
| protected int getSourceStringIndex() { |
| return this.source.getSourceStringIndex(); |
| } |
| |
| |
| @Override |
| public final int getIndex(final int offset) { |
| final int currentIdx= getIndexIdx(); |
| return this.bufferBeginIndexes[currentIdx + offset]; |
| } |
| |
| @Override |
| public final int getLengthInSource(final int offset) { |
| if (offset == 0) { |
| return 0; |
| } |
| final int currentIdx= getIndexIdx(); |
| return this.bufferEndIndexes[currentIdx + offset - 1] - this.bufferBeginIndexes[currentIdx]; |
| } |
| |
| @Override |
| public void consume(int offset) { |
| if (offset == 0) { |
| return; |
| } |
| int currentIdx= getIndexIdx(); |
| { // we need bufferIndex for offset |
| final int lastOffset= getEndIdx() - currentIdx - 1; |
| if (offset > lastOffset) { |
| if (lastOffset > 0x10) { |
| setConsume(lastOffset, this.bufferBeginIndexes[currentIdx + lastOffset]); |
| currentIdx= getIndexIdx(); |
| offset-= lastOffset; |
| } |
| if (!updateBuffer(offset + 1)) { |
| checkOffset(offset); |
| int index= getStopIndex(); |
| if (index == NA_INDEX) { |
| index= this.bufferBeginIndexes[getEndIdx()]; |
| } |
| setConsume(offset, index); |
| return; |
| } |
| } |
| } |
| setConsume(offset, this.bufferBeginIndexes[currentIdx + offset]); |
| } |
| |
| |
| @Override |
| protected void doUpdateBuffer(final int index, final char[] buffer, |
| final int requiredLength, final int recommendLength) { |
| final int reused= copyBuffer0(buffer); |
| final int[] begins= (buffer == getBuffer()) ? this.bufferBeginIndexes : new int[buffer.length + 1]; |
| final int[] ends= (buffer == getBuffer()) ? this.bufferEndIndexes : new int[buffer.length]; |
| final int currentIdx= getIndexIdx(); |
| if (reused > 0) { |
| System.arraycopy(this.bufferBeginIndexes, currentIdx, begins, 0, reused + 1); |
| System.arraycopy(this.bufferEndIndexes, currentIdx, ends, 0, reused); |
| } |
| else { |
| begins[0]= this.bufferBeginIndexes[currentIdx]; |
| } |
| |
| final int end= read(this.source, buffer, begins, ends, reused, requiredLength, recommendLength); |
| |
| setBuffer(buffer, 0, end); |
| this.bufferBeginIndexes= begins; |
| this.bufferEndIndexes= ends; |
| setConsume(0, this.bufferBeginIndexes[0]); |
| } |
| |
| protected abstract int read(TextParserInput in, char[] buffer, |
| int[] beginIndexes, int[] endIndexes, |
| int beginIdx, int requiredEnd, int recommendEnd); |
| |
| } |