private void continueNumber(CharArr arr) throws IOException { if (arr != out) arr.write(out); if ((nstate & HAS_EXPONENT) != 0) { readExpDigits(arr, Integer.MAX_VALUE); return; } if (nstate != 0) { readFrac(arr, Integer.MAX_VALUE); return; } for (; ; ) { int ch = getChar(); if (ch >= '0' && ch <= '9') { arr.write(ch); } else if (ch == '.') { arr.write(ch); readFrac(arr, Integer.MAX_VALUE); return; } else if (ch == 'e' || ch == 'E') { arr.write(ch); readExp(arr, Integer.MAX_VALUE); return; } else { if (ch != -1) start--; return; } } }
public static void unicodeEscape(int ch, CharArr out) { out.write('\\'); out.write('u'); out.write(HEX_CHARS[ch >>> 12]); out.write(HEX_CHARS[(ch >>> 8) & 0xf]); out.write(HEX_CHARS[(ch >>> 4) & 0xf]); out.write(HEX_CHARS[ch & 0xf]); }
// read digits right of decimal point private int readFrac(CharArr arr, int lim) throws IOException { nstate = HAS_FRACTION; // deliberate set instead of '|' while (--lim >= 0) { int ch = getChar(); if (ch >= '0' && ch <= '9') { arr.write(ch); } else if (ch == 'e' || ch == 'E') { arr.write(ch); return readExp(arr, lim); } else { if (ch != -1) start--; // back up return NUMBER; } } return BIGNUMBER; }
// call after 'e' or 'E' has been seen to read the rest of the exponent private int readExp(CharArr arr, int lim) throws IOException { nstate |= HAS_EXPONENT; int ch = getChar(); lim--; if (ch == '+' || ch == '-') { arr.write(ch); ch = getChar(); lim--; } // make sure at least one digit is read. if (ch < '0' || ch > '9') { throw err("missing exponent number"); } arr.write(ch); return readExpDigits(arr, lim); }
/** Reads a JSON numeric value into the output. */ public void getNumberChars(CharArr output) throws IOException { int ev = 0; if (valstate == 0) ev = nextEvent(); if (valstate == LONG || valstate == NUMBER) output.write(this.out); else if (valstate == BIGNUMBER) { continueNumber(output); } else { throw err("Unexpected " + ev); } valstate = 0; }
// continuation of readExpStart private int readExpDigits(CharArr arr, int lim) throws IOException { while (--lim >= 0) { int ch = getChar(); if (ch >= '0' && ch <= '9') { arr.write(ch); } else { if (ch != -1) start--; // back up return NUMBER; } } return BIGNUMBER; }
// middle is the pointer to the middle of a buffer to start scanning for a non-string // character ('"' or "/"). start<=middle<end // this should be faster for strings with fewer escapes, but probably slower for many escapes. private void readStringChars2(CharArr arr, int middle) throws IOException { for (; ; ) { if (middle >= end) { arr.write(buf, start, middle - start); start = middle; getMore(); middle = start; } int ch = buf[middle++]; if (ch == '"') { int len = middle - start - 1; if (len > 0) arr.write(buf, start, len); start = middle; return; } else if (ch == '\\') { int len = middle - start - 1; if (len > 0) arr.write(buf, start, len); start = middle; arr.write(readEscapedChar()); middle = start; } } }
public static void writeStringPart(char[] val, int start, int end, CharArr out) { for (int i = start; i < end; i++) { char ch = val[i]; switch (ch) { case '"': case '\\': out.write('\\'); out.write(ch); break; case '\r': out.write('\\'); out.write('r'); break; case '\n': out.write('\\'); out.write('n'); break; case '\t': out.write('\\'); out.write('t'); break; case '\b': out.write('\\'); out.write('b'); break; case '\f': out.write('\\'); out.write('f'); break; // case '/': default: if (ch <= 0x1F) { unicodeEscape(ch, out); } else { // These characters are valid JSON, but not valid JavaScript if (ch == '\u2028' || ch == '\u2029') { unicodeEscape(ch, out); } else { out.write(ch); } } } } }
public static void writeString(CharSequence val, int start, int end, CharArr out) { out.write('"'); writeStringPart(val, start, end, out); out.write('"'); }
public static void writeNumber(double number, CharArr out) { out.write(Double.toString(number)); }
public static void writeNumber(float number, CharArr out) { out.write(Float.toString(number)); }
public static void writeNumber(long number, CharArr out) { out.write(Long.toString(number)); }
public static void writeNumber(int number, CharArr out) { out.write(Integer.toString(number)); }
public static void writeBoolean(boolean val, CharArr out) { out.write(val ? TRUE_CHARS : FALSE_CHARS); }
public static void writeNull(CharArr out) { out.write(NULL_CHARS); }