package com.jsoniter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import static java.lang.Character.MIN_HIGH_SURROGATE;
import static java.lang.Character.MIN_LOW_SURROGATE;
import static java.lang.Character.MIN_SUPPLEMENTARY_CODE_POINT;
class IterImplString {
static int[] base64Tbl = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2,
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
public static final String readString(JsonIterator iter) throws IOException {
byte c = iter.nextToken();
if (c == 'n') {
IterImplSkip.skipUntilBreak(iter);
return null;
}
if (c != '"') {
throw iter.reportError("readString", "expect n or \"");
}
// try fast path first
for (int i = iter.head, j = 0; i < iter.tail && j < iter.reusableChars.length; i++, j++) {
c = iter.buf[i];
if (c == '"') {
iter.head = i + 1;
return new String(iter.reusableChars, 0, j);
}
// If we encounter a backslash, which is a beginning of an escape sequence
// or a high bit was set - indicating an UTF-8 encoded multibyte character,
// there is no chance that we can decode the string without instantiating
// a temporary buffer, so quit this loop
if ((c ^ '\\') < 1) break;
iter.reusableChars[j] = (char) c;
}
return readStringSlowPath(iter);
}
final static String readStringSlowPath(JsonIterator iter) throws IOException {
// http://grepcode.com/file_/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/sun/nio/cs/UTF_8.java/?v=source
// byte => char with support of escape in one pass
int j = 0;
int minimumCapacity = iter.reusableChars.length - 2;
for (; ; ) {
if (j == minimumCapacity) {
char[] newBuf = new char[iter.reusableChars.length * 2];
System.arraycopy(iter.reusableChars, 0, newBuf, 0, iter.reusableChars.length);
iter.reusableChars = newBuf;
minimumCapacity = iter.reusableChars.length - 2;
}
int b1 = iter.readByte();
if (b1 >= 0) {
if (b1 == '"') {
return new String(iter.reusableChars, 0, j);
} else if (b1 == '\\') {
int b2 = iter.readByte();
switch (b2) {
case '"':
iter.reusableChars[j++] = '"';
break;
case '\\':
iter.reusableChars[j++] = '\\';
break;
case '/':
iter.reusableChars[j++] = '/';
break;
case 'b':
iter.reusableChars[j++] = '\b';
break;
case 'f':
iter.reusableChars[j++] = '\f';
break;
case 'n':
iter.reusableChars[j++] = '\n';
break;
case 'r':
iter.reusableChars[j++] = '\r';
break;
case 't':
iter.reusableChars[j++] = '\t';
break;
case 'u':
iter.reusableChars[j++] = IterImplNumber.readU4(iter);
break;
default:
throw iter.reportError("readStringSlowPath", "unexpected escape char: " + b2);
}
} else {
// 1 byte, 7 bits: 0xxxxxxx
iter.reusableChars[j++] = (char) b1;
}
} else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) {
// 2 bytes, 11 bits: 110xxxxx 10xxxxxx
int b2 = iter.readByte();
iter.reusableChars[j++] = (char) (((b1