Skip to content

Commit

Permalink
Allow single quote in strings
Browse files Browse the repository at this point in the history
  • Loading branch information
boq authored and Dinnerbone committed Feb 19, 2019
1 parent 447845b commit 559d8f3
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 8 deletions.
31 changes: 23 additions & 8 deletions src/main/java/com/mojang/brigadier/StringReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

public class StringReader implements ImmutableStringReader {
private static final char SYNTAX_ESCAPE = '\\';
private static final char SYNTAX_QUOTE = '"';
private static final char SYNTAX_DOUBLE_QUOTE = '"';
private static final char SYNTAX_SINGLE_QUOTE = '\'';

private final String string;
private int cursor;
Expand Down Expand Up @@ -87,6 +88,10 @@ public static boolean isAllowedNumber(final char c) {
return c >= '0' && c <= '9' || c == '.' || c == '-';
}

public static boolean isQuotedStringStart(char c) {
return c == SYNTAX_DOUBLE_QUOTE || c == SYNTAX_SINGLE_QUOTE;
}

public void skipWhitespace() {
while (canRead() && Character.isWhitespace(peek())) {
skip();
Expand Down Expand Up @@ -180,16 +185,22 @@ public String readUnquotedString() {
public String readQuotedString() throws CommandSyntaxException {
if (!canRead()) {
return "";
} else if (peek() != SYNTAX_QUOTE) {
}
final char next = peek();
if (!isQuotedStringStart(next)) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.readerExpectedStartOfQuote().createWithContext(this);
}
skip();
return readStringUntil(next);
}

public String readStringUntil(char terminator) throws CommandSyntaxException {
final StringBuilder result = new StringBuilder();
boolean escaped = false;
while (canRead()) {
final char c = read();
if (escaped) {
if (c == SYNTAX_QUOTE || c == SYNTAX_ESCAPE) {
if (c == terminator || c == SYNTAX_ESCAPE) {
result.append(c);
escaped = false;
} else {
Expand All @@ -198,7 +209,7 @@ public String readQuotedString() throws CommandSyntaxException {
}
} else if (c == SYNTAX_ESCAPE) {
escaped = true;
} else if (c == SYNTAX_QUOTE) {
} else if (c == terminator) {
return result.toString();
} else {
result.append(c);
Expand All @@ -209,11 +220,15 @@ public String readQuotedString() throws CommandSyntaxException {
}

public String readString() throws CommandSyntaxException {
if (canRead() && peek() == SYNTAX_QUOTE) {
return readQuotedString();
} else {
return readUnquotedString();
if (!canRead()) {
return "";
}
final char next = peek();
if (isQuotedStringStart(next)) {
skip();
return readStringUntil(next);
}
return readUnquotedString();
}

public boolean readBoolean() throws CommandSyntaxException {
Expand Down
58 changes: 58 additions & 0 deletions src/test/java/com/mojang/brigadier/StringReaderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,30 @@ public void readQuotedString() throws Exception {
assertThat(reader.getRemaining(), equalTo(""));
}

@Test
public void readSingleQuotedString() throws Exception {
final StringReader reader = new StringReader("'hello world'");
assertThat(reader.readQuotedString(), equalTo("hello world"));
assertThat(reader.getRead(), equalTo("'hello world'"));
assertThat(reader.getRemaining(), equalTo(""));
}

@Test
public void readMixedQuotedString_doubleInsideSingle() throws Exception {
final StringReader reader = new StringReader("'hello \"world\"'");
assertThat(reader.readQuotedString(), equalTo("hello \"world\""));
assertThat(reader.getRead(), equalTo("'hello \"world\"'"));
assertThat(reader.getRemaining(), equalTo(""));
}

@Test
public void readMixedQuotedString_singleInsideDouble() throws Exception {
final StringReader reader = new StringReader("\"hello 'world'\"");
assertThat(reader.readQuotedString(), equalTo("hello 'world'"));
assertThat(reader.getRead(), equalTo("\"hello 'world'\""));
assertThat(reader.getRemaining(), equalTo(""));
}

@Test
public void readQuotedString_empty() throws Exception {
final StringReader reader = new StringReader("");
Expand Down Expand Up @@ -242,6 +266,40 @@ public void readQuotedString_invalidEscape() throws Exception {
}
}

@Test
public void readQuotedString_invalidQuoteEscape() throws Exception {
try {
new StringReader("'hello\\\"\'world").readQuotedString();
} catch (final CommandSyntaxException ex) {
assertThat(ex.getType(), is(CommandSyntaxException.BUILT_IN_EXCEPTIONS.readerInvalidEscape()));
assertThat(ex.getCursor(), is(7));
}
}

@Test
public void readString_noQuotes() throws Exception {
final StringReader reader = new StringReader("hello world");
assertThat(reader.readString(), equalTo("hello"));
assertThat(reader.getRead(), equalTo("hello"));
assertThat(reader.getRemaining(), equalTo(" world"));
}

@Test
public void readString_singleQuotes() throws Exception {
final StringReader reader = new StringReader("'hello world'");
assertThat(reader.readString(), equalTo("hello world"));
assertThat(reader.getRead(), equalTo("'hello world'"));
assertThat(reader.getRemaining(), equalTo(""));
}

@Test
public void readString_doubleQuotes() throws Exception {
final StringReader reader = new StringReader("\"hello world\"");
assertThat(reader.readString(), equalTo("hello world"));
assertThat(reader.getRead(), equalTo("\"hello world\""));
assertThat(reader.getRemaining(), equalTo(""));
}

@Test
public void readInt() throws Exception {
final StringReader reader = new StringReader("1234567890");
Expand Down

2 comments on commit 559d8f3

@JochCool
Copy link

Choose a reason for hiding this comment

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

Thank you so much for this change, this makes JSON in text so much cleaner!

@hetavrao9
Copy link

Choose a reason for hiding this comment

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

OK Thank You dear Mojang, Minecraft!
I really love Coding and Minecraft and when they come mix with each other it is like heaven!
Thanks Again!!!!!!!!!
~Hetav_Rao

Please sign in to comment.