/*=============================================================================#
# Copyright (c) 2015-2016 David Green and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# David Green - initial API and implementation in Mylyn
# Stephan Wahlbrink (WalWare.de) - revised API and implementation
#=============================================================================*/
package de.walware.docmlet.wikitext.internal.commonmark.core;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.regex.Matcher;
public class Cursor {
private final TextSegment segment;
private final String text;
private int textOffset;
public Cursor(final TextSegment segment) {
this.segment = checkNotNull(segment);
this.text = segment.getText();
this.textOffset = 0;
}
/**
* Provides the offset of the current cursor position relative to the document.
*
* @return the current cursor position offset
*/
public int getOffset() {
return this.segment.offsetOf(this.textOffset);
}
/**
* Provides the offset of the given cursor position relative to the document.
*
* @param offset
* the position relative to the cursor
* @return the current cursor position offset
*/
public int getOffset(final int offset) {
return this.segment.offsetOf(this.textOffset + offset);
}
public int toCursorOffset(final int documentOffset) {
return this.segment.toTextOffset(documentOffset);
}
public char getChar() {
return this.text.charAt(this.textOffset);
}
/**
* Provides the character at the cursor's 0-based offset, where the given offset is not affected by the position of
* the cursor.
*
* @param offset
* the absolute offset of the character relative to this cursor
* @return the character
*/
public char getChar(final int offset) {
return this.text.charAt(offset);
}
public boolean hasChar() {
return (this.textOffset < this.text.length());
}
/**
* Provides the string at the cursor's 0-based offset, where the given offset is not affected by the position of the
* cursor.
*
* @param offset
* the absolute offset of the character relative to this cursor
* @param endIndex
* the end index of the string to provide, exclusive
* @return the string
*/
public String getText(final int offset, final int endIndex) {
return this.text.substring(offset, endIndex);
}
public char getPrevious() {
return getPrevious(1);
}
public boolean hasPrevious() {
return hasPrevious(1);
}
public boolean hasPrevious(final int offset) {
return this.textOffset - offset >= 0;
}
public char getPrevious(final int offset) {
final int charOffset = this.textOffset - offset;
checkArgument(charOffset >= 0);
return this.text.charAt(charOffset);
}
public char getNext() {
return getNext(1);
}
public char getNext(final int offset) {
checkArgument(offset >= 0);
return this.text.charAt(this.textOffset + offset);
}
public String getTextAtOffset() {
return this.text.substring(this.textOffset, this.text.length());
}
public String getTextAtOffset(final int length) {
checkArgument(length > 0);
return this.text.substring(this.textOffset, this.textOffset + length);
}
public boolean hasNext() {
return hasNext(1);
}
public boolean hasNext(final int offset) {
checkArgument(offset > 0);
return (this.textOffset + offset < this.text.length());
}
public void advance() {
if (this.textOffset < this.text.length()) {
++this.textOffset;
}
}
public void advance(final int count) {
checkArgument(count >= 0);
for (int x = 0; x < count; ++x) {
advance();
}
}
public void rewind(final int count) {
checkArgument(count >= 0);
for (int x = 0; x < count; ++x) {
rewind();
}
}
public void rewind() {
if (this.textOffset > 0) {
--this.textOffset;
}
}
public Line getLineAtOffset() {
return this.segment.getLineAtOffset(this.textOffset);
}
public Matcher setup(final Matcher matcher) {
matcher.reset(this.text);
matcher.region(this.textOffset, this.text.length());
return matcher;
}
public Matcher setup(final Matcher matcher, final int offset) {
matcher.reset(this.text);
matcher.region(this.textOffset + offset, this.text.length());
return matcher;
}
public int getMatcherOffset(final int matchOffset) {
return this.segment.offsetOf(matchOffset);
}
}