package com.jsoniter; import com.jsoniter.any.Any; import java.io.IOException; class IterImpl { public static final int readObjectFieldAsHash(JsonIterator iter) throws IOException { if (nextToken(iter) != '"') { throw iter.reportError("readObjectFieldAsHash", "expect \""); } long hash = 0x811c9dc5; for (int i = iter.head; i < iter.tail; i++) { byte c = iter.buf[i]; if (c == '"') { iter.head = i + 1; if (nextToken(iter) != ':') { throw iter.reportError("readObjectFieldAsHash", "expect :"); } return (int) hash; } hash ^= c; hash *= 0x1000193; } throw iter.reportError("readObjectFieldAsHash", "unmatched quote"); } 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(JsonIterator iter) throws IOException { int i = iter.head; try { for (; ; ) { byte c = iter.buf[i++]; switch (c) { case ' ': case '\n': case '\r': case '\t': continue; default: if (i > iter.tail) { iter.head = iter.tail; return 0; } iter.head = i; return c; } } } catch (IndexOutOfBoundsException e) { iter.head = iter.tail; return 0; } } final static byte readByte(JsonIterator iter) throws IOException { if (iter.head == iter.tail) { return 0; } 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 String readStringSlowPath(JsonIterator iter, int j) throws IOException { try { for (int i = iter.head; i < iter.tail; ) { int bc = iter.buf[i++]; if (bc == '"') { return new String(iter.reusableChars, 0, 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; iter.reusableChars[j++] = (char) ((sup >>> 10) + 0xd800); iter.reusableChars[j++] = (char) ((sup & 0x3ff) + 0xdc00); continue; } } } } iter.reusableChars[j++] = (char) bc; } throw iter.reportError("readStringSlowPath", "incomplete string"); } catch (IndexOutOfBoundsException e) { throw iter.reportError("readString", "incomplete string"); } } }