package com.jsoniter; import com.jsoniter.any.Any; import com.jsoniter.spi.JsonException; import java.io.IOException; class IterImpl { 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 == '.') { 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 { 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++]); 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; } static final int readPositiveInt(final JsonIterator iter, byte c) throws IOException { int ind = IterImplNumber.intDigits[c]; if (ind == 0) { return 0; } if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { throw iter.reportError("readPositiveInt", "expect 0~9"); } if (iter.tail - iter.head > 9) { int i = iter.head; int ind2 = IterImplNumber.intDigits[iter.buf[i]]; if (ind2 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; return ind; } int ind3 = IterImplNumber.intDigits[iter.buf[++i]]; if (ind3 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; return ind * 10 + ind2; } int ind4 = IterImplNumber.intDigits[iter.buf[++i]]; if (ind4 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; return ind * 100 + ind2 * 10 + ind3; } int ind5 = IterImplNumber.intDigits[iter.buf[++i]]; if (ind5 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; return ind * 1000 + ind2 * 100 + ind3 * 10 + ind4; } int ind6 = IterImplNumber.intDigits[iter.buf[++i]]; if (ind6 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; return ind * 10000 + ind2 * 1000 + ind3 * 100 + ind4 * 10 + ind5; } int ind7 = IterImplNumber.intDigits[iter.buf[++i]]; if (ind7 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; return ind * 100000 + ind2 * 10000 + ind3 * 1000 + ind4 * 100 + ind5 * 10 + ind6; } int ind8 = IterImplNumber.intDigits[iter.buf[++i]]; if (ind8 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; return ind * 1000000 + ind2 * 100000 + ind3 * 10000 + ind4 * 1000 + ind5 * 100 + ind6 * 10 + ind7; } int ind9 = IterImplNumber.intDigits[iter.buf[++i]]; ind = ind * 10000000 + ind2 * 1000000 + ind3 * 100000 + ind4 * 10000 + ind5 * 1000 + ind6 * 100 + ind7 * 10 + ind8; iter.head = i; if (ind9 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { return ind; } } return IterImplForStreaming.readIntSlowPath(iter, ind); } static final long readPositiveLong(final JsonIterator iter, byte c) throws IOException { long ind = IterImplNumber.intDigits[c]; if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { throw iter.reportError("readPositiveLong", "expect 0~9"); } if (iter.tail - iter.head > 9) { int i = iter.head; int ind2 = IterImplNumber.intDigits[iter.buf[i]]; if (ind2 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; return ind; } int ind3 = IterImplNumber.intDigits[iter.buf[++i]]; if (ind3 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; return ind * 10 + ind2; } int ind4 = IterImplNumber.intDigits[iter.buf[++i]]; if (ind4 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; return ind * 100 + ind2 * 10 + ind3; } int ind5 = IterImplNumber.intDigits[iter.buf[++i]]; if (ind5 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; return ind * 1000 + ind2 * 100 + ind3 * 10 + ind4; } int ind6 = IterImplNumber.intDigits[iter.buf[++i]]; if (ind6 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; return ind * 10000 + ind2 * 1000 + ind3 * 100 + ind4 * 10 + ind5; } int ind7 = IterImplNumber.intDigits[iter.buf[++i]]; if (ind7 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; return ind * 100000 + ind2 * 10000 + ind3 * 1000 + ind4 * 100 + ind5 * 10 + ind6; } int ind8 = IterImplNumber.intDigits[iter.buf[++i]]; if (ind8 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; return ind * 1000000 + ind2 * 100000 + ind3 * 10000 + ind4 * 1000 + ind5 * 100 + ind6 * 10 + ind7; } int ind9 = IterImplNumber.intDigits[iter.buf[++i]]; ind = ind * 10000000 + ind2 * 1000000 + ind3 * 100000 + ind4 * 10000 + ind5 * 1000 + ind6 * 100 + ind7 * 10 + ind8; iter.head = i; if (ind9 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { return ind; } } return IterImplForStreaming.readLongSlowPath(iter, ind); } static final double readPositiveDouble(final JsonIterator iter) throws IOException { int oldHead = iter.head; try { long value = IterImplNumber.readLong(iter); // without the dot if (iter.head == iter.tail) { return value; } byte c = iter.buf[iter.head]; if (c == '.') { iter.head++; int start = iter.head; c = iter.buf[iter.head++]; long decimalPart = readPositiveLong(iter, c); int decimalPlaces = iter.head - start; if (decimalPlaces > 0 && decimalPlaces < IterImplNumber.POW10.length && (iter.head - oldHead) < 10) { value = value * IterImplNumber.POW10[decimalPlaces] + decimalPart; return value / (double) IterImplNumber.POW10[decimalPlaces]; } else { iter.head = oldHead; return IterImplForStreaming.readDoubleSlowPath(iter); } } else { if (iter.head < iter.tail && iter.buf[iter.head] == 'e') { iter.head = oldHead; return IterImplForStreaming.readDoubleSlowPath(iter); } else { return value; } } } catch (JsonException e) { iter.head = oldHead; return IterImplForStreaming.readDoubleSlowPath(iter); } } }