mirror of https://github.com/Minestom/Minestom.git
CommandReader with tests
This commit is contained in:
parent
079439896f
commit
899a8e02d8
|
@ -1,15 +1,17 @@
|
|||
package net.minestom.server.command;
|
||||
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
//TODO IMPLEMENT METHODS
|
||||
public final class CommandReader {
|
||||
static final char SPACE = ' ';
|
||||
static final char QUOTE = '"';
|
||||
static final char ESCAPE = '\\';
|
||||
private final CharSequence input;
|
||||
private int cursor = 0;
|
||||
private int pendingData = 0;
|
||||
|
||||
public CommandReader(CharSequence input) {
|
||||
this.input = input;
|
||||
|
@ -20,19 +22,22 @@ public final class CommandReader {
|
|||
}
|
||||
|
||||
public String getWord() {
|
||||
final int i = nextIndexOf(SPACE);
|
||||
return get(i == -1 ? input.length() : i);
|
||||
final int i = nextIndexOf(SPACE, 0);
|
||||
final String s = get(i == -1 ? input.length() : i);
|
||||
pendingData = s.length()+1;
|
||||
return s;
|
||||
}
|
||||
|
||||
public String getQuotedString() {
|
||||
if (getNextChar() != QUOTE) throw new RuntimeException("Tried to read an unquoted string as quoted.");
|
||||
int end;
|
||||
int end = cursor;
|
||||
do {
|
||||
if (!hasRemaining()) throw new RuntimeException("Reached end of input before finding a closing quote");
|
||||
end = nextIndexOf(QUOTE);
|
||||
end = nextIndexOf(QUOTE, end-cursor+1);
|
||||
if (end == -1) throw new RuntimeException("Quoted string doesn't have a closing quote.");
|
||||
} while (getCharAt(end - 1) != ESCAPE);
|
||||
return get(end);
|
||||
} while (getCharAt(end - 1) == ESCAPE);
|
||||
final String s = get(end+1);
|
||||
pendingData = s.length()+1;
|
||||
return s.substring(1, s.length()-1).replaceAll("\\\\\"", "\"");
|
||||
}
|
||||
|
||||
public String getRemaining() {
|
||||
|
@ -44,32 +49,59 @@ public final class CommandReader {
|
|||
}
|
||||
|
||||
public char getCharAt(int position) {
|
||||
pendingData = 1;
|
||||
return input.charAt(position);
|
||||
}
|
||||
|
||||
public void moveCursor(int amount) {
|
||||
cursor += amount;
|
||||
}
|
||||
|
||||
public void consume() {
|
||||
|
||||
cursor += pendingData;
|
||||
}
|
||||
|
||||
public void consume(int amount) {
|
||||
|
||||
cursor += amount;
|
||||
}
|
||||
|
||||
public int getClosingIndexOfJsonObject() {
|
||||
public int getClosingIndexOfJsonObject(int fromOffset) {
|
||||
int count = 1;
|
||||
boolean insideString = false;
|
||||
boolean lastWasEscape = false;
|
||||
final int start = nextIndexOf('{', fromOffset);
|
||||
if (start == -1) return -1;
|
||||
for (int i = start+1; i < input.length(); i++) {
|
||||
final char current = getCharAt(i);
|
||||
if (insideString) {
|
||||
if (current == '"')
|
||||
if (lastWasEscape)
|
||||
lastWasEscape = false;
|
||||
else
|
||||
insideString = false;
|
||||
else if (current == '\\')
|
||||
lastWasEscape = !lastWasEscape;
|
||||
else
|
||||
lastWasEscape = false;
|
||||
} else {
|
||||
if (current == '{')
|
||||
count++;
|
||||
else if (current == '}' && --count == 0)
|
||||
return i;
|
||||
else if (current == '"')
|
||||
insideString = true;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private String get(int end) {
|
||||
@VisibleForTesting
|
||||
String get(int exclusiveAbsoluteEnd) {
|
||||
if (!hasRemaining()) throw new BufferUnderflowException();
|
||||
return input.subSequence(cursor, end).toString();
|
||||
final String s = input.subSequence(cursor, exclusiveAbsoluteEnd).toString();
|
||||
pendingData = s.length();
|
||||
return s;
|
||||
}
|
||||
|
||||
private int nextIndexOf(char c) {
|
||||
return IntStream.range(cursor, input.length()).filter(x -> input.charAt(x) == c).findFirst().orElse(-1);
|
||||
@VisibleForTesting
|
||||
int nextIndexOf(char c, int offset) {
|
||||
return IntStream.range(cursor+offset, input.length()).filter(x -> input.charAt(x) == c).findFirst().orElse(-1);
|
||||
}
|
||||
|
||||
public int remaining() {
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
package net.minestom.server.command;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
public class CommandReaderTest {
|
||||
@Test
|
||||
public void searchTest() {
|
||||
final CommandReader reader = new CommandReader("0123456789ABCDEF0123456789ABCDEF");
|
||||
assertEquals(3, reader.nextIndexOf('3', 0));
|
||||
assertEquals(1, reader.nextIndexOf('1', 0));
|
||||
assertEquals(12, reader.nextIndexOf('C', 0));
|
||||
assertEquals(19, reader.nextIndexOf('3', 15));
|
||||
assertEquals(17, reader.nextIndexOf('1', 15));
|
||||
assertEquals(28, reader.nextIndexOf('C', 15));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readRaw() {
|
||||
final CommandReader reader = new CommandReader("0123456789ABCDEF");
|
||||
assertEquals("01", reader.get(2));
|
||||
reader.consume();
|
||||
assertEquals("23456", reader.get(7));
|
||||
reader.consume();
|
||||
assertEquals("7", reader.get(8));
|
||||
reader.consume();
|
||||
assertEquals("89ABCD", reader.get(14));
|
||||
reader.consume();
|
||||
assertEquals("EF", reader.get(16));
|
||||
reader.consume();
|
||||
assertFalse(reader.hasRemaining());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readWords() {
|
||||
final CommandReader reader = new CommandReader("test 15 foo bar a");
|
||||
assertEquals("test", reader.getWord());
|
||||
reader.consume();
|
||||
assertEquals("15", reader.getWord());
|
||||
reader.consume();
|
||||
assertEquals("foo", reader.getWord());
|
||||
reader.consume();
|
||||
assertEquals("bar", reader.getWord());
|
||||
reader.consume();
|
||||
assertEquals("a", reader.getWord());
|
||||
reader.consume();
|
||||
assertFalse(reader.hasRemaining());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readQuotedStrings() {
|
||||
final CommandReader reader = new CommandReader("\"test 15\" \"foo \\\\\"bar\" \"a\"");
|
||||
assertEquals("test 15", reader.getQuotedString());
|
||||
reader.consume();
|
||||
assertEquals("foo \\\"bar", reader.getQuotedString());
|
||||
reader.consume();
|
||||
assertEquals("a", reader.getQuotedString());
|
||||
reader.consume();
|
||||
assertFalse(reader.hasRemaining());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readWordsAndQuotedStringsMixed() {
|
||||
final CommandReader reader = new CommandReader("\"te\\\"st\" 15 foo \"bar\" \"\\\"a\\\"\"");
|
||||
assertEquals("te\"st", reader.getQuotedString());
|
||||
reader.consume();
|
||||
assertEquals("15", reader.getWord());
|
||||
reader.consume();
|
||||
assertEquals("foo", reader.getWord());
|
||||
reader.consume();
|
||||
assertEquals("bar", reader.getQuotedString());
|
||||
reader.consume();
|
||||
assertEquals("\"a\"", reader.getQuotedString());
|
||||
reader.consume();
|
||||
assertFalse(reader.hasRemaining());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getJsonObjectClosingIndex() {
|
||||
assertEquals(-1, jsonTest("no json here"));
|
||||
assertEquals(-1, jsonTest("no valid {json here"));
|
||||
assertEquals(1, jsonTest("{}"));
|
||||
assertEquals(8, jsonTest("0123456{}9A"));
|
||||
assertEquals(11, jsonTest("012{\"foo\":5}+"));
|
||||
assertEquals(76, jsonTest("{\"foo\":1,\"bar\":\"S9 M M\",\"baz\":false,\"array\":[],\"obj\":{\"foo\":\"fq h{q}{{{r}\"}}"));
|
||||
assertEquals(82, jsonTest("012345{\"foo\":1,\"bar\":\"S9 M M\",\"baz\":false,\"array\":[],\"obj\":{\"foo\":\"fq h{q}{{{r}\"}}789"));
|
||||
}
|
||||
|
||||
private int jsonTest(String input) {
|
||||
return new CommandReader(input).getClosingIndexOfJsonObject(0);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue