Merge pull request #147 from square/jwilson_0406_small_optimizations

Small optimizations to JSON parsing.
This commit is contained in:
Jake Wharton 2016-04-06 00:54:57 -04:00
commit 40e323c805
2 changed files with 25 additions and 29 deletions

View file

@ -304,7 +304,7 @@ final class BufferedSourceJsonReader extends JsonReader {
break;
case '=':
checkLenient();
if (fillBuffer(1) && buffer.getByte(0) == '>') {
if (source.request(1) && buffer.getByte(0) == '>') {
buffer.readByte(); // Consume '>'.
}
break;
@ -400,7 +400,7 @@ final class BufferedSourceJsonReader extends JsonReader {
// Confirm that chars [1..length) match the keyword.
int length = keyword.length();
for (int i = 1; i < length; i++) {
if (!fillBuffer(i + 1)) {
if (!source.request(i + 1)) {
return PEEKED_NONE;
}
c = buffer.getByte(i);
@ -409,7 +409,7 @@ final class BufferedSourceJsonReader extends JsonReader {
}
}
if (fillBuffer(length + 1) && isLiteral(buffer.getByte(length))) {
if (source.request(length + 1) && isLiteral(buffer.getByte(length))) {
return PEEKED_NONE; // Don't match trues, falsey or nullsoft!
}
@ -428,7 +428,7 @@ final class BufferedSourceJsonReader extends JsonReader {
charactersOfNumber:
for (; true; i++) {
if (!fillBuffer(i + 1)) {
if (!source.request(i + 1)) {
break;
}
@ -880,15 +880,6 @@ final class BufferedSourceJsonReader extends JsonReader {
stack[stackSize++] = newTop;
}
/**
* Returns true once {@code limit - pos >= minimum}. If the data is
* exhausted before that many characters are available, this returns
* false.
*/
private boolean fillBuffer(int minimum) throws IOException {
return source.request(minimum);
}
/**
* Returns the next character in the stream that is neither whitespace nor a
* part of a comment. When this returns, the returned character is always at
@ -905,7 +896,7 @@ final class BufferedSourceJsonReader extends JsonReader {
* 'p' and 'l' after any (potentially indirect) call to the same method.
*/
int p = 0;
while (fillBuffer(p + 1)) {
while (source.request(p + 1)) {
int c = buffer.getByte(p++);
if (c == '\n' || c == ' ' || c == '\r' || c == '\t') {
continue;
@ -913,7 +904,7 @@ final class BufferedSourceJsonReader extends JsonReader {
buffer.skip(p - 1);
if (c == '/') {
if (!fillBuffer(2)) {
if (!source.request(2)) {
return c;
}
@ -981,7 +972,7 @@ final class BufferedSourceJsonReader extends JsonReader {
*/
private boolean skipTo(String toFind) throws IOException {
outer:
for (; fillBuffer(toFind.length());) {
for (; source.request(toFind.length());) {
for (int c = 0; c < toFind.length(); c++) {
if (buffer.getByte(c) != toFind.charAt(c)) {
buffer.readByte();
@ -1009,14 +1000,14 @@ final class BufferedSourceJsonReader extends JsonReader {
* @throws IOException if any unicode escape sequences are malformed.
*/
private char readEscapeCharacter() throws IOException {
if (!fillBuffer(1)) {
if (!source.request(1)) {
throw syntaxError("Unterminated escape sequence");
}
byte escaped = buffer.readByte();
switch (escaped) {
case 'u':
if (!fillBuffer(4)) {
if (!source.request(4)) {
throw new EOFException("Unterminated escape sequence at path " + getPath());
}
// Equivalent to Integer.parseInt(stringPool.get(buffer, pos, 4), 16);

View file

@ -21,6 +21,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
@ -81,11 +82,11 @@ final class ClassJsonAdapter<T> extends JsonAdapter<T> {
// Create the binding between field and JSON.
field.setAccessible(true);
FieldBinding<Object> fieldBinding = new FieldBinding<>(field, adapter);
// Store it using the field's name. If there was already a field with this name, fail!
Json jsonAnnotation = field.getAnnotation(Json.class);
String name = jsonAnnotation != null ? jsonAnnotation.name() : field.getName();
FieldBinding<Object> fieldBinding = new FieldBinding<>(name, field, adapter);
FieldBinding<?> replaced = fieldBindings.put(name, fieldBinding);
if (replaced != null) {
throw new IllegalArgumentException("Conflicting fields:\n"
@ -113,11 +114,13 @@ final class ClassJsonAdapter<T> extends JsonAdapter<T> {
};
private final ClassFactory<T> classFactory;
private final Map<String, FieldBinding<?>> jsonFields;
private final Map<String, FieldBinding<?>> fieldsMap;
private final FieldBinding<?>[] fieldsArray;
ClassJsonAdapter(ClassFactory<T> classFactory, Map<String, FieldBinding<?>> jsonFields) {
ClassJsonAdapter(ClassFactory<T> classFactory, Map<String, FieldBinding<?>> fieldsMap) {
this.classFactory = classFactory;
this.jsonFields = jsonFields;
this.fieldsMap = new LinkedHashMap<>(fieldsMap);
this.fieldsArray = fieldsMap.values().toArray(new FieldBinding[fieldsMap.size()]);
}
@Override public T fromJson(JsonReader reader) throws IOException {
@ -139,7 +142,7 @@ final class ClassJsonAdapter<T> extends JsonAdapter<T> {
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
FieldBinding<?> fieldBinding = jsonFields.get(name);
FieldBinding<?> fieldBinding = fieldsMap.get(name);
if (fieldBinding != null) {
fieldBinding.read(reader, result);
} else {
@ -156,9 +159,9 @@ final class ClassJsonAdapter<T> extends JsonAdapter<T> {
@Override public void toJson(JsonWriter writer, T value) throws IOException {
try {
writer.beginObject();
for (Map.Entry<String, FieldBinding<?>> entry : jsonFields.entrySet()) {
writer.name(entry.getKey());
entry.getValue().write(writer, value);
for (FieldBinding<?> fieldBinding : fieldsArray) {
writer.name(fieldBinding.name);
fieldBinding.write(writer, value);
}
writer.endObject();
} catch (IllegalAccessException e) {
@ -171,10 +174,12 @@ final class ClassJsonAdapter<T> extends JsonAdapter<T> {
}
static class FieldBinding<T> {
private final Field field;
private final JsonAdapter<T> adapter;
final String name;
final Field field;
final JsonAdapter<T> adapter;
public FieldBinding(Field field, JsonAdapter<T> adapter) {
public FieldBinding(String name, Field field, JsonAdapter<T> adapter) {
this.name = name;
this.field = field;
this.adapter = adapter;
}