package com.jsoniter;
import com.jsoniter.any.Any;
import com.jsoniter.spi.JsonException;
import com.jsoniter.spi.Slice;
import java.io.IOException;
import java.math.BigInteger;
class IterImpl {
private static BigInteger maxLong = BigInteger.valueOf(Long.MAX_VALUE);
private static BigInteger minLong = BigInteger.valueOf(Long.MIN_VALUE);
private static BigInteger maxInt = BigInteger.valueOf(Integer.MAX_VALUE);
private static BigInteger minInt = BigInteger.valueOf(Integer.MIN_VALUE);
public static final int readObjectFieldAsHash(JsonIterator iter) throws IOException {
if (readByte(iter) != '"') {
if (nextToken(iter) != '"') {
throw iter.reportError("readObjectFieldAsHash", "expect \"");
}
}
long hash = 0x811c9dc5;
int i = iter.head;
for (; i < iter.tail; i++) {
byte c = iter.buf[i];
if (c == '"') {
break;
}
hash ^= c;
hash *= 0x1000193;
}
iter.head = i + 1;
if (readByte(iter) != ':') {
if (nextToken(iter) != ':') {
throw iter.reportError("readObjectFieldAsHash", "expect :");
}
}
return (int) hash;
}
public static final Slice readObjectFieldAsSlice(JsonIterator iter) throws IOException {
Slice field = readSlice(iter);
if (nextToken(iter) != ':') {
throw iter.reportError("readObjectFieldAsSlice", "expect : after object field");
}
return field;
}
final static void skipArray(JsonIterator iter) throws IOException {
int level = 1;
for (int i = iter.head; i < iter.tail; i++) {
switch (iter.buf[i]) {
case '"': // If inside string, skip it
iter.head = i + 1;
skipString(iter);
i = iter.head - 1; // it will be i++ soon
break;
case '[': // If open symbol, increase level
level++;
break;
case ']': // If close symbol, increase level
level--;
// If we have returned to the original level, we're done
if (level == 0) {
iter.head = i + 1;
return;
}
break;
}
}
throw iter.reportError("skipArray", "incomplete array");
}
final static void skipObject(JsonIterator iter) throws IOException {
int level = 1;
for (int i = iter.head; i < iter.tail; i++) {
switch (iter.buf[i]) {
case '"': // If inside string, skip it
iter.head = i + 1;
skipString(iter);
i = iter.head - 1; // it will be i++ soon
break;
case '{': // If open symbol, increase level
level++;
break;
case '}': // If close symbol, increase level
level--;
// If we have returned to the original level, we're done
if (level == 0) {
iter.head = i + 1;
return;
}
break;
}
}
throw iter.reportError("skipObject", "incomplete object");
}
final static void skipString(JsonIterator iter) throws IOException {
int end = IterImplSkip.findStringEnd(iter);
if (end == -1) {
throw iter.reportError("skipString", "incomplete string");
} else {
iter.head = end;
}
}
final static void skipUntilBreak(JsonIterator iter) throws IOException {
// true, false, null, number
for (int i = iter.head; i < iter.tail; i++) {
byte c = iter.buf[i];
if (IterImplSkip.breaks[c]) {
iter.head = i;
return;
}
}
iter.head = iter.tail;
}
final static boolean skipNumber(JsonIterator iter) throws IOException {
// true, false, null, number
boolean dotFound = false;
for (int i = iter.head; i < iter.tail; i++) {
byte c = iter.buf[i];
if (c == '.' || c == 'e' || c == 'E') {
dotFound = true;
continue;
}
if (IterImplSkip.breaks[c]) {
iter.head = i;
return dotFound;
}
}
iter.head = iter.tail;
return dotFound;
}
// read the bytes between " "
public final static Slice readSlice(JsonIterator iter) throws IOException {
if (IterImpl.nextToken(iter) != '"') {
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;
}
}
final static byte nextToken(final JsonIterator iter) throws IOException {
int i = iter.head;
for (; ; ) {
byte c = iter.buf[i++];
switch (c) {
case ' ':
case '\n':
case '\r':
case '\t':
continue;
default:
iter.head = i;
return c;
}
}
}
final static byte readByte(JsonIterator iter) throws IOException {
return iter.buf[iter.head++];
}
public static Any readAny(JsonIterator iter) throws IOException {
int start = iter.head;
byte c = nextToken(iter);
switch (c) {
case '"':
skipString(iter);
return Any.lazyString(iter.buf, start, iter.head);
case 't':
skipFixedBytes(iter, 3);
return Any.wrap(true);
case 'f':
skipFixedBytes(iter, 4);
return Any.wrap(false);
case 'n':
skipFixedBytes(iter, 3);
return Any.wrap((Object) null);
case '[':
skipArray(iter);
return Any.lazyArray(iter.buf, start, iter.head);
case '{':
skipObject(iter);
return Any.lazyObject(iter.buf, start, iter.head);
default:
if (skipNumber(iter)) {
return Any.lazyDouble(iter.buf, start, iter.head);
} else {
return Any.lazyLong(iter.buf, start, iter.head);
}
}
}
public static void skipFixedBytes(JsonIterator iter, int n) throws IOException {
iter.head += n;
}
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++])