mirror of
https://github.com/fankes/moshi.git
synced 2025-10-18 23:49:21 +08:00
Merge pull request #3 from square/jwilson_0810_indexOfElement
Use indexOfElement in JsonReader.
This commit is contained in:
@@ -16,7 +16,6 @@
|
||||
<dependency>
|
||||
<groupId>com.squareup.okio</groupId>
|
||||
<artifactId>okio</artifactId>
|
||||
<version>1.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
|
@@ -20,6 +20,7 @@ import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSource;
|
||||
import okio.ByteString;
|
||||
import okio.Source;
|
||||
|
||||
/**
|
||||
@@ -176,6 +177,12 @@ import okio.Source;
|
||||
public class JsonReader implements Closeable {
|
||||
private static final long MIN_INCOMPLETE_INTEGER = Long.MIN_VALUE / 10;
|
||||
|
||||
private static final ByteString SINGLE_QUOTE_OR_SLASH = ByteString.encodeUtf8("'\\");
|
||||
private static final ByteString DOUBLE_QUOTE_OR_SLASH = ByteString.encodeUtf8("\"\\");
|
||||
private static final ByteString UNQUOTED_STRING_TERMINALS
|
||||
= ByteString.encodeUtf8("{}[]:, \n\t\r\f/\\;#=");
|
||||
private static final ByteString LINEFEED_OR_CARRIAGE_RETURN = ByteString.encodeUtf8("\n\r");
|
||||
|
||||
private static final int PEEKED_NONE = 0;
|
||||
private static final int PEEKED_BEGIN_OBJECT = 1;
|
||||
private static final int PEEKED_END_OBJECT = 2;
|
||||
@@ -271,7 +278,7 @@ public class JsonReader implements Closeable {
|
||||
*/
|
||||
public JsonReader(String s) {
|
||||
this.source = new Buffer().writeUtf8(s);
|
||||
this.buffer = new Buffer();
|
||||
this.buffer = source.buffer();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -561,7 +568,7 @@ public class JsonReader implements Closeable {
|
||||
buffer.readByte(); // Consume '['.
|
||||
return peeked = PEEKED_BEGIN_ARRAY;
|
||||
case '{':
|
||||
buffer.readByte(); // Consume ']'.
|
||||
buffer.readByte(); // Consume '{'.
|
||||
return peeked = PEEKED_BEGIN_OBJECT;
|
||||
default:
|
||||
}
|
||||
@@ -760,10 +767,10 @@ public class JsonReader implements Closeable {
|
||||
String result;
|
||||
if (p == PEEKED_UNQUOTED_NAME) {
|
||||
result = nextUnquotedValue();
|
||||
} else if (p == PEEKED_SINGLE_QUOTED_NAME) {
|
||||
result = nextQuotedValue('\'');
|
||||
} else if (p == PEEKED_DOUBLE_QUOTED_NAME) {
|
||||
result = nextQuotedValue('"');
|
||||
result = nextQuotedValue(DOUBLE_QUOTE_OR_SLASH);
|
||||
} else if (p == PEEKED_SINGLE_QUOTED_NAME) {
|
||||
result = nextQuotedValue(SINGLE_QUOTE_OR_SLASH);
|
||||
} else {
|
||||
throw new IllegalStateException("Expected a name but was " + peek()
|
||||
+ " at path " + getPath());
|
||||
@@ -789,10 +796,10 @@ public class JsonReader implements Closeable {
|
||||
String result;
|
||||
if (p == PEEKED_UNQUOTED) {
|
||||
result = nextUnquotedValue();
|
||||
} else if (p == PEEKED_SINGLE_QUOTED) {
|
||||
result = nextQuotedValue('\'');
|
||||
} else if (p == PEEKED_DOUBLE_QUOTED) {
|
||||
result = nextQuotedValue('"');
|
||||
result = nextQuotedValue(DOUBLE_QUOTE_OR_SLASH);
|
||||
} else if (p == PEEKED_SINGLE_QUOTED) {
|
||||
result = nextQuotedValue(SINGLE_QUOTE_OR_SLASH);
|
||||
} else if (p == PEEKED_BUFFERED) {
|
||||
result = peekedString;
|
||||
peekedString = null;
|
||||
@@ -878,8 +885,10 @@ public class JsonReader implements Closeable {
|
||||
|
||||
if (p == PEEKED_NUMBER) {
|
||||
peekedString = buffer.readUtf8(peekedNumberLength);
|
||||
} else if (p == PEEKED_SINGLE_QUOTED || p == PEEKED_DOUBLE_QUOTED) {
|
||||
peekedString = nextQuotedValue(p == PEEKED_SINGLE_QUOTED ? '\'' : '"');
|
||||
} else if (p == PEEKED_DOUBLE_QUOTED) {
|
||||
peekedString = nextQuotedValue(DOUBLE_QUOTE_OR_SLASH);
|
||||
} else if (p == PEEKED_SINGLE_QUOTED) {
|
||||
peekedString = nextQuotedValue(SINGLE_QUOTE_OR_SLASH);
|
||||
} else if (p == PEEKED_UNQUOTED) {
|
||||
peekedString = nextUnquotedValue();
|
||||
} else if (p != PEEKED_BUFFERED) {
|
||||
@@ -923,8 +932,10 @@ public class JsonReader implements Closeable {
|
||||
|
||||
if (p == PEEKED_NUMBER) {
|
||||
peekedString = buffer.readUtf8(peekedNumberLength);
|
||||
} else if (p == PEEKED_SINGLE_QUOTED || p == PEEKED_DOUBLE_QUOTED) {
|
||||
peekedString = nextQuotedValue(p == PEEKED_SINGLE_QUOTED ? '\'' : '"');
|
||||
} else if (p == PEEKED_DOUBLE_QUOTED || p == PEEKED_SINGLE_QUOTED) {
|
||||
peekedString = p == PEEKED_DOUBLE_QUOTED
|
||||
? nextQuotedValue(DOUBLE_QUOTE_OR_SLASH)
|
||||
: nextQuotedValue(SINGLE_QUOTE_OR_SLASH);
|
||||
try {
|
||||
long result = Long.parseLong(peekedString);
|
||||
peeked = PEEKED_NONE;
|
||||
@@ -957,109 +968,61 @@ public class JsonReader implements Closeable {
|
||||
* should have already been read. This consumes the closing quote, but does
|
||||
* not include it in the returned string.
|
||||
*
|
||||
* @param quote either ' or ".
|
||||
* @throws NumberFormatException if any unicode escape sequences are
|
||||
* malformed.
|
||||
*/
|
||||
private String nextQuotedValue(char quote) throws IOException {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int p = 0;
|
||||
while (fillBuffer(p + 1)) {
|
||||
int c = buffer.getByte(p++);
|
||||
private String nextQuotedValue(ByteString runTerminator) throws IOException {
|
||||
StringBuilder builder = null;
|
||||
while (true) {
|
||||
long index = source.indexOfElement(runTerminator);
|
||||
if (index == -1L) throw syntaxError("Unterminated string");
|
||||
|
||||
if (c == quote) {
|
||||
builder.append(buffer.readUtf8(p - 1));
|
||||
buffer.readByte();
|
||||
return builder.toString();
|
||||
} else if (c == '\\') {
|
||||
builder.append(buffer.readUtf8(p - 1));
|
||||
// If we've got an escape character, we're going to need a string builder.
|
||||
if (buffer.getByte(index) == '\\') {
|
||||
if (builder == null) builder = new StringBuilder();
|
||||
builder.append(buffer.readUtf8(index));
|
||||
buffer.readByte(); // '\'
|
||||
builder.append(readEscapeCharacter());
|
||||
p = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If it isn't the escape character, it's the quote. Return the string.
|
||||
if (builder == null) {
|
||||
String result = buffer.readUtf8(index);
|
||||
buffer.readByte(); // Consume the quote character.
|
||||
return result;
|
||||
} else {
|
||||
builder.append(buffer.readUtf8(index));
|
||||
buffer.readByte(); // Consume the quote character.
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
throw syntaxError("Unterminated string");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unquoted value as a string.
|
||||
*/
|
||||
@SuppressWarnings("fallthrough")
|
||||
/** Returns an unquoted value as a string. */
|
||||
private String nextUnquotedValue() throws IOException {
|
||||
int i = 0;
|
||||
|
||||
findNonStringChar:
|
||||
for (; fillBuffer(i + 1); i++) {
|
||||
switch (buffer.getByte(i)) {
|
||||
case '/':
|
||||
case '\\':
|
||||
case ';':
|
||||
case '#':
|
||||
case '=':
|
||||
checkLenient(); // fall-through
|
||||
case '{':
|
||||
case '}':
|
||||
case '[':
|
||||
case ']':
|
||||
case ':':
|
||||
case ',':
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\f':
|
||||
case '\r':
|
||||
case '\n':
|
||||
break findNonStringChar;
|
||||
}
|
||||
}
|
||||
|
||||
return buffer.readUtf8(i);
|
||||
long i = source.indexOfElement(UNQUOTED_STRING_TERMINALS);
|
||||
return i != -1 ? buffer.readUtf8(i) : buffer.readUtf8();
|
||||
}
|
||||
|
||||
private void skipQuotedValue(char quote) throws IOException {
|
||||
int p = 0;
|
||||
while (fillBuffer(p + 1)) {
|
||||
int c = buffer.getByte(p++);
|
||||
if (c == quote) {
|
||||
buffer.skip(p);
|
||||
return;
|
||||
} else if (c == '\\') {
|
||||
buffer.skip(p);
|
||||
private void skipQuotedValue(ByteString runTerminator) throws IOException {
|
||||
while (true) {
|
||||
long index = source.indexOfElement(runTerminator);
|
||||
if (index == -1L) throw syntaxError("Unterminated string");
|
||||
|
||||
if (buffer.getByte(index) == '\\') {
|
||||
buffer.skip(index + 1);
|
||||
readEscapeCharacter();
|
||||
p = 0;
|
||||
} else {
|
||||
buffer.skip(index + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw syntaxError("Unterminated string");
|
||||
}
|
||||
|
||||
private void skipUnquotedValue() throws IOException {
|
||||
int i = 0;
|
||||
|
||||
findNonStringChar:
|
||||
for (; fillBuffer(i + 1); i++) {
|
||||
switch (buffer.getByte(i)) {
|
||||
case '/':
|
||||
case '\\':
|
||||
case ';':
|
||||
case '#':
|
||||
case '=':
|
||||
checkLenient(); // fall-through
|
||||
case '{':
|
||||
case '}':
|
||||
case '[':
|
||||
case ']':
|
||||
case ':':
|
||||
case ',':
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\f':
|
||||
case '\r':
|
||||
case '\n':
|
||||
break findNonStringChar;
|
||||
}
|
||||
}
|
||||
|
||||
buffer.skip(i);
|
||||
long i = source.indexOfElement(UNQUOTED_STRING_TERMINALS);
|
||||
buffer.skip(i != -1L ? i : buffer.size());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1092,8 +1055,10 @@ public class JsonReader implements Closeable {
|
||||
|
||||
if (p == PEEKED_NUMBER) {
|
||||
peekedString = buffer.readUtf8(peekedNumberLength);
|
||||
} else if (p == PEEKED_SINGLE_QUOTED || p == PEEKED_DOUBLE_QUOTED) {
|
||||
peekedString = nextQuotedValue(p == PEEKED_SINGLE_QUOTED ? '\'' : '"');
|
||||
} else if (p == PEEKED_DOUBLE_QUOTED || p == PEEKED_SINGLE_QUOTED) {
|
||||
peekedString = p == PEEKED_DOUBLE_QUOTED
|
||||
? nextQuotedValue(DOUBLE_QUOTE_OR_SLASH)
|
||||
: nextQuotedValue(SINGLE_QUOTE_OR_SLASH);
|
||||
try {
|
||||
result = Integer.parseInt(peekedString);
|
||||
peeked = PEEKED_NONE;
|
||||
@@ -1158,10 +1123,10 @@ public class JsonReader implements Closeable {
|
||||
count--;
|
||||
} else if (p == PEEKED_UNQUOTED_NAME || p == PEEKED_UNQUOTED) {
|
||||
skipUnquotedValue();
|
||||
} else if (p == PEEKED_SINGLE_QUOTED || p == PEEKED_SINGLE_QUOTED_NAME) {
|
||||
skipQuotedValue('\'');
|
||||
} else if (p == PEEKED_DOUBLE_QUOTED || p == PEEKED_DOUBLE_QUOTED_NAME) {
|
||||
skipQuotedValue('"');
|
||||
skipQuotedValue(DOUBLE_QUOTE_OR_SLASH);
|
||||
} else if (p == PEEKED_SINGLE_QUOTED || p == PEEKED_SINGLE_QUOTED_NAME) {
|
||||
skipQuotedValue(SINGLE_QUOTE_OR_SLASH);
|
||||
} else if (p == PEEKED_NUMBER) {
|
||||
buffer.skip(peekedNumberLength);
|
||||
}
|
||||
@@ -1193,10 +1158,7 @@ public class JsonReader implements Closeable {
|
||||
* false.
|
||||
*/
|
||||
private boolean fillBuffer(int minimum) throws IOException {
|
||||
while (buffer.size() < minimum) {
|
||||
if (source.read(buffer, 2048) == -1) return false;
|
||||
}
|
||||
return true;
|
||||
return source.request(minimum);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1285,12 +1247,8 @@ public class JsonReader implements Closeable {
|
||||
* caller.
|
||||
*/
|
||||
private void skipToEndOfLine() throws IOException {
|
||||
while (fillBuffer(1)) {
|
||||
byte c = buffer.readByte();
|
||||
if (c == '\n' || c == '\r') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
long index = source.indexOfElement(LINEFEED_OR_CARRIAGE_RETURN);
|
||||
buffer.skip(index != -1 ? index + 1 : buffer.size());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -17,8 +17,6 @@ package com.squareup.moshi;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.Arrays;
|
||||
import okio.Source;
|
||||
import org.junit.Ignore;
|
||||
@@ -895,6 +893,11 @@ public final class JsonReaderTest {
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
|
||||
reader = new JsonReader("a//");
|
||||
reader.setLenient(true);
|
||||
assertEquals("a", reader.nextString());
|
||||
assertEquals(JsonToken.END_DOCUMENT, reader.peek());
|
||||
}
|
||||
|
||||
@Test public void strictCommentsWithSkipValue() throws IOException {
|
||||
@@ -1011,6 +1014,14 @@ public final class JsonReaderTest {
|
||||
assertEquals("a", reader.nextString());
|
||||
}
|
||||
|
||||
@Test public void lenientUnquotedStringsDelimitedByComment() throws IOException {
|
||||
JsonReader reader = new JsonReader("[a#comment\n]");
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
assertEquals("a", reader.nextString());
|
||||
reader.endArray();
|
||||
}
|
||||
|
||||
@Test public void strictSingleQuotedStrings() throws IOException {
|
||||
JsonReader reader = new JsonReader("['a']");
|
||||
reader.beginArray();
|
||||
|
7
pom.xml
7
pom.xml
@@ -26,7 +26,7 @@
|
||||
<java.version>1.6</java.version>
|
||||
|
||||
<!-- Dependencies -->
|
||||
<okio.version>1.0.1</okio.version>
|
||||
<okio.version>1.0.2-SNAPSHOT</okio.version>
|
||||
|
||||
<!-- Test Dependencies -->
|
||||
<junit.version>4.11</junit.version>
|
||||
@@ -58,6 +58,11 @@
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okio</groupId>
|
||||
<artifactId>okio</artifactId>
|
||||
<version>${okio.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
Reference in New Issue
Block a user