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

[WIP] Fully-functional Slices #166

Open
wants to merge 4 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
1 change: 1 addition & 0 deletions src/main/java/com/jsoniter/CodegenAccess.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.jsoniter;

import com.jsoniter.slice.Slice;
import com.jsoniter.spi.*;

import java.io.IOException;
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/jsoniter/CodegenImplEnum.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ class CodegenImplEnum {
public static String genEnum(ClassInfo classInfo) {
StringBuilder lines = new StringBuilder();
append(lines, "if (iter.readNull()) { return null; }");
append(lines, "com.jsoniter.spi.Slice field = com.jsoniter.CodegenAccess.readSlice(iter);");
append(lines, "switch (field.len()) {");
append(lines, "com.jsoniter.slice.Slice field = com.jsoniter.CodegenAccess.readSlice(iter);");
append(lines, "switch (field.size()) {");
append(lines, renderTriTree(buildTriTree(Arrays.asList(classInfo.clazz.getEnumConstants()))));
append(lines, "}"); // end of switch
append(lines, String.format("throw iter.reportError(\"decode enum\", field + \" is not valid enum for %s\");", classInfo.clazz.getName()));
Expand Down
12 changes: 6 additions & 6 deletions src/main/java/com/jsoniter/CodegenImplObjectStrict.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public static String genObjectUsingStrict(ClassDescriptor desc) {
if (desc.onExtraProperties != null || !desc.keyValueTypeWrappers.isEmpty()) {
append(lines, "java.util.Map extra = null;");
}
append(lines, "com.jsoniter.spi.Slice field = com.jsoniter.CodegenAccess.readObjectFieldAsSlice(iter);");
append(lines, "com.jsoniter.slice.Slice field = com.jsoniter.CodegenAccess.readObjectFieldAsSlice(iter);");
append(lines, "boolean once = true;");
append(lines, "while (once) {");
append(lines, "once = false;");
Expand All @@ -104,7 +104,7 @@ public static String genObjectUsingStrict(ClassDescriptor desc) {
}
}
if (hasAnythingToBindFrom(allBindings)) {
append(lines, "switch (field.len()) {");
append(lines, "switch (field.size()) {");
append(lines, rendered);
append(lines, "}"); // end of switch
}
Expand All @@ -114,7 +114,7 @@ public static String genObjectUsingStrict(ClassDescriptor desc) {
append(lines, "while (com.jsoniter.CodegenAccess.nextToken(iter) == ',') {");
append(lines, "field = com.jsoniter.CodegenAccess.readObjectFieldAsSlice(iter);");
if (hasAnythingToBindFrom(allBindings)) {
append(lines, "switch (field.len()) {");
append(lines, "switch (field.size()) {");
append(lines, rendered);
append(lines, "}"); // end of switch
}
Expand Down Expand Up @@ -155,7 +155,7 @@ private static void appendSetExtraToKeyValueTypeWrappers(StringBuilder lines, Cl
append(lines, "while(extraIter.hasNext()) {");
for (Method wrapper : desc.keyValueTypeWrappers) {
append(lines, "java.util.Map.Entry entry = (java.util.Map.Entry)extraIter.next();");
append(lines, "String key = entry.getKey().toString();");
append(lines, "String key = ((Slice) entry.getKey()).string();");
append(lines, "com.jsoniter.any.Any value = (com.jsoniter.any.Any)entry.getValue();");
append(lines, String.format("obj.%s(key, value.object());", wrapper.getName()));
}
Expand Down Expand Up @@ -259,11 +259,11 @@ private static void appendMissingRequiredProperties(StringBuilder lines, ClassDe

private static void appendOnUnknownField(StringBuilder lines, ClassDescriptor desc) {
if (desc.asExtraForUnknownProperties && desc.onExtraProperties == null) {
append(lines, "throw new com.jsoniter.spi.JsonException('extra property: ' + field.toString());".replace('\'', '"'));
append(lines, "throw new com.jsoniter.spi.JsonException('extra property: ' + ((Slice) field).string());".replace('\'', '"'));
} else {
if (desc.asExtraForUnknownProperties || !desc.keyValueTypeWrappers.isEmpty()) {
append(lines, "if (extra == null) { extra = new java.util.HashMap(); }");
append(lines, "extra.put(field.toString(), iter.readAny());");
append(lines, "extra.put(((Slice) field).string(), iter.readAny());");
} else {
append(lines, "iter.skip();");
}
Expand Down
126 changes: 4 additions & 122 deletions src/main/java/com/jsoniter/IterImpl.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.jsoniter;

import com.jsoniter.any.Any;
import com.jsoniter.slice.Slice;
import com.jsoniter.spi.JsonException;
import com.jsoniter.spi.Slice;

import java.io.IOException;
import java.math.BigInteger;
Expand Down Expand Up @@ -140,18 +140,11 @@ final static boolean skipNumber(JsonIterator iter) throws IOException {

// read the bytes between " "
public final static Slice readSlice(JsonIterator iter) throws IOException {
if (IterImpl.nextToken(iter) != '"') {
Slice slice = IterImplString.readSlice(iter);
if (slice == null) {
throw iter.reportError("readSlice", "expect \" for string");
}
int end = IterImplString.findSliceEnd(iter);
if (end == -1) {
throw iter.reportError("readSlice", "incomplete string");
} else {
// reuse current buffer
iter.reusableSlice.reset(iter.buf, iter.head, end - 1);
iter.head = end;
return iter.reusableSlice;
}
return slice;
}

final static byte nextToken(final JsonIterator iter) throws IOException {
Expand Down Expand Up @@ -214,117 +207,6 @@ public final static boolean loadMore(JsonIterator iter) throws IOException {
return false;
}

public final static int readStringSlowPath(JsonIterator iter, int j) throws IOException {
try {
boolean isExpectingLowSurrogate = false;
for (int i = iter.head; i < iter.tail; ) {
int bc = iter.buf[i++];
if (bc == '"') {
iter.head = i;
return j;
}
if (bc == '\\') {
bc = iter.buf[i++];
switch (bc) {
case 'b':
bc = '\b';
break;
case 't':
bc = '\t';
break;
case 'n':
bc = '\n';
break;
case 'f':
bc = '\f';
break;
case 'r':
bc = '\r';
break;
case '"':
case '/':
case '\\':
break;
case 'u':
bc = (IterImplString.translateHex(iter.buf[i++]) << 12) +
(IterImplString.translateHex(iter.buf[i++]) << 8) +
(IterImplString.translateHex(iter.buf[i++]) << 4) +
IterImplString.translateHex(iter.buf[i++]);
if (Character.isHighSurrogate((char) bc)) {
if (isExpectingLowSurrogate) {
throw new JsonException("invalid surrogate");
} else {
isExpectingLowSurrogate = true;
}
} else if (Character.isLowSurrogate((char) bc)) {
if (isExpectingLowSurrogate) {
isExpectingLowSurrogate = false;
} else {
throw new JsonException("invalid surrogate");
}
} else {
if (isExpectingLowSurrogate) {
throw new JsonException("invalid surrogate");
}
}
break;

default:
throw iter.reportError("readStringSlowPath", "invalid escape character: " + bc);
}
} else if ((bc & 0x80) != 0) {
final int u2 = iter.buf[i++];
if ((bc & 0xE0) == 0xC0) {
bc = ((bc & 0x1F) << 6) + (u2 & 0x3F);
} else {
final int u3 = iter.buf[i++];
if ((bc & 0xF0) == 0xE0) {
bc = ((bc & 0x0F) << 12) + ((u2 & 0x3F) << 6) + (u3 & 0x3F);
} else {
final int u4 = iter.buf[i++];
if ((bc & 0xF8) == 0xF0) {
bc = ((bc & 0x07) << 18) + ((u2 & 0x3F) << 12) + ((u3 & 0x3F) << 6) + (u4 & 0x3F);
} else {
throw iter.reportError("readStringSlowPath", "invalid unicode character");
}

if (bc >= 0x10000) {
// check if valid unicode
if (bc >= 0x110000)
throw iter.reportError("readStringSlowPath", "invalid unicode character");

// split surrogates
final int sup = bc - 0x10000;
if (iter.reusableChars.length == j) {
char[] newBuf = new char[iter.reusableChars.length * 2];
System.arraycopy(iter.reusableChars, 0, newBuf, 0, iter.reusableChars.length);
iter.reusableChars = newBuf;
}
iter.reusableChars[j++] = (char) ((sup >>> 10) + 0xd800);
if (iter.reusableChars.length == j) {
char[] newBuf = new char[iter.reusableChars.length * 2];
System.arraycopy(iter.reusableChars, 0, newBuf, 0, iter.reusableChars.length);
iter.reusableChars = newBuf;
}
iter.reusableChars[j++] = (char) ((sup & 0x3ff) + 0xdc00);
continue;
}
}
}
}
if (iter.reusableChars.length == j) {
char[] newBuf = new char[iter.reusableChars.length * 2];
System.arraycopy(iter.reusableChars, 0, newBuf, 0, iter.reusableChars.length);
iter.reusableChars = newBuf;
}
iter.reusableChars[j++] = (char) bc;
}
throw iter.reportError("readStringSlowPath", "incomplete string");
} catch (IndexOutOfBoundsException e) {
throw iter.reportError("readString", "incomplete string");
}
}

public static int updateStringCopyBound(final JsonIterator iter, final int bound) {
return bound;
}
Expand Down
17 changes: 11 additions & 6 deletions src/main/java/com/jsoniter/IterImplForStreaming.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.jsoniter;

import com.jsoniter.any.Any;
import com.jsoniter.slice.DirectSlice;
import com.jsoniter.slice.Slice;
import com.jsoniter.spi.JsonException;
import com.jsoniter.spi.Slice;

import java.io.IOException;

Expand Down Expand Up @@ -45,7 +46,9 @@ public static final Slice readObjectFieldAsSlice(JsonIterator iter) throws IOExc
int len = field.tail() - field.head();
byte[] newBuf = new byte[len];
System.arraycopy(field.data(), field.head(), newBuf, 0, len);
field.reset(newBuf, 0, newBuf.length);
DirectSlice ds = iter.rDirectSlice;
ds.reset(newBuf, 0, newBuf.length);
field = ds;
}
if (!loadMore(iter)) {
throw iter.reportError("readObjectFieldAsSlice", "expect : after object field");
Expand Down Expand Up @@ -203,9 +206,10 @@ final static Slice readSlice(JsonIterator iter) throws IOException {
int end = IterImplString.findSliceEnd(iter);
if (end != -1) {
// reuse current buffer
iter.reusableSlice.reset(iter.buf, iter.head, end - 1);
DirectSlice slice = iter.rDirectSlice;
slice.reset(iter.buf, iter.head, end - 1);
iter.head = end;
return iter.reusableSlice;
return slice;
}
// TODO: avoid small memory allocation
byte[] part1 = new byte[iter.tail - iter.head];
Expand All @@ -225,8 +229,9 @@ final static Slice readSlice(JsonIterator iter) throws IOException {
System.arraycopy(part1, 0, part2, 0, part1.length);
System.arraycopy(iter.buf, 0, part2, part1.length, end - 1);
iter.head = end;
iter.reusableSlice.reset(part2, 0, part2.length);
return iter.reusableSlice;
DirectSlice slice = iter.rDirectSlice;
slice.reset(part2, 0, part2.length);
return slice;
}
}
}
Expand Down
Loading