Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add isNext(char) and isNext(Predicate<Character>) methods to ImmutableStringReader and StringReader #98

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/main/java/com/mojang/brigadier/ImmutableStringReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

package com.mojang.brigadier;

import java.util.function.Predicate;

public interface ImmutableStringReader {
String getString();

Expand All @@ -23,4 +25,8 @@ public interface ImmutableStringReader {
char peek();

char peek(int offset);

boolean isNext(char c);

boolean isNext(Predicate<Character> predicate);
Copy link

@Marcono1234 Marcono1234 Nov 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about using IntPredicate here? This would avoid boxing and unboxing. But maybe it does not matter much. And it might cause confusion, making users believe this handles code points (including > Character.MAX_VALUE), so this would require renaming the parameter to for example charPredicate.

}
26 changes: 19 additions & 7 deletions src/main/java/com/mojang/brigadier/StringReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import com.mojang.brigadier.exceptions.CommandSyntaxException;

import java.util.function.Predicate;

public class StringReader implements ImmutableStringReader {
private static final char SYNTAX_ESCAPE = '\\';
private static final char SYNTAX_DOUBLE_QUOTE = '"';
Expand Down Expand Up @@ -76,6 +78,16 @@ public char peek(final int offset) {
return string.charAt(cursor + offset);
}

@Override
public boolean isNext(char c) {
return canRead() && peek() == c;
}

@Override
public boolean isNext(Predicate<Character> predicate) {
return canRead() && predicate.test(peek());
}
Comment on lines +81 to +89

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to implement these as default methods of the interface instead?
(Though assuming no or only a few users implement their own ImmutableStringReader it likely makes no difference)


public char read() {
return string.charAt(cursor++);
}
Expand All @@ -93,14 +105,14 @@ public static boolean isQuotedStringStart(char c) {
}

public void skipWhitespace() {
while (canRead() && Character.isWhitespace(peek())) {
while (isNext(Character::isWhitespace)) {
skip();
}
}

public int readInt() throws CommandSyntaxException {
final int start = cursor;
while (canRead() && isAllowedNumber(peek())) {
while (isNext(StringReader::isAllowedNumber)) {
skip();
}
final String number = string.substring(start, cursor);
Expand All @@ -117,7 +129,7 @@ public int readInt() throws CommandSyntaxException {

public long readLong() throws CommandSyntaxException {
final int start = cursor;
while (canRead() && isAllowedNumber(peek())) {
while (isNext(StringReader::isAllowedNumber)) {
skip();
}
final String number = string.substring(start, cursor);
Expand All @@ -134,7 +146,7 @@ public long readLong() throws CommandSyntaxException {

public double readDouble() throws CommandSyntaxException {
final int start = cursor;
while (canRead() && isAllowedNumber(peek())) {
while (isNext(StringReader::isAllowedNumber)) {
skip();
}
final String number = string.substring(start, cursor);
Expand All @@ -151,7 +163,7 @@ public double readDouble() throws CommandSyntaxException {

public float readFloat() throws CommandSyntaxException {
final int start = cursor;
while (canRead() && isAllowedNumber(peek())) {
while (isNext(StringReader::isAllowedNumber)) {
skip();
}
final String number = string.substring(start, cursor);
Expand All @@ -176,7 +188,7 @@ public static boolean isAllowedInUnquotedString(final char c) {

public String readUnquotedString() {
final int start = cursor;
while (canRead() && isAllowedInUnquotedString(peek())) {
while (isNext(StringReader::isAllowedInUnquotedString)) {
skip();
}
return string.substring(start, cursor);
Expand Down Expand Up @@ -249,7 +261,7 @@ public boolean readBoolean() throws CommandSyntaxException {
}

public void expect(final char c) throws CommandSyntaxException {
if (!canRead() || peek() != c) {
if (!isNext(c)) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.readerExpectedSymbol().createWithContext(this, String.valueOf(c));
}
skip();
Expand Down
24 changes: 24 additions & 0 deletions src/test/java/com/mojang/brigadier/StringReaderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import org.junit.Test;

import java.util.function.Predicate;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
Expand Down Expand Up @@ -585,4 +587,26 @@ public void readBoolean_none() throws Exception {
assertThat(ex.getCursor(), is(0));
}
}

@Test
public void isNext() {
final StringReader reader = new StringReader("abc");
assertThat(reader.isNext('a'), is(true));
assertThat(reader.isNext('x'), is(false));
reader.setCursor(2);
assertThat(reader.isNext('c'), is(true));
reader.skip();
assertThat(reader.isNext('c'), is(false));
}

@Test
public void isNext_predicate() {
final StringReader reader = new StringReader("abc");
final Predicate<Character> predicate = c -> (c == 'a' || c == 'b');
assertThat(reader.isNext(predicate), is(true));
reader.setCursor(1);
assertThat(reader.isNext(predicate), is(true));
reader.setCursor(2);
assertThat(reader.isNext(predicate), is(false));
}
}