17c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetpackage com.google.polo.json; 27c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 37c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport java.io.BufferedReader; 47c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport java.io.IOException; 57c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport java.io.Reader; 67c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport java.io.StringReader; 77c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 87c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet/* 97c9978567a202d6aa98beac5da5e1b3b34792862Jerome PoichetCopyright (c) 2002 JSON.org 107c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 117c9978567a202d6aa98beac5da5e1b3b34792862Jerome PoichetPermission is hereby granted, free of charge, to any person obtaining a copy 127c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetof this software and associated documentation files (the "Software"), to deal 137c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetin the Software without restriction, including without limitation the rights 147c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetto use, copy, modify, merge, publish, distribute, sublicense, and/or sell 157c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetcopies of the Software, and to permit persons to whom the Software is 167c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetfurnished to do so, subject to the following conditions: 177c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 187c9978567a202d6aa98beac5da5e1b3b34792862Jerome PoichetThe above copyright notice and this permission notice shall be included in all 197c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetcopies or substantial portions of the Software. 207c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 217c9978567a202d6aa98beac5da5e1b3b34792862Jerome PoichetThe Software shall be used for Good, not Evil. 227c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 237c9978567a202d6aa98beac5da5e1b3b34792862Jerome PoichetTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 247c9978567a202d6aa98beac5da5e1b3b34792862Jerome PoichetIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 257c9978567a202d6aa98beac5da5e1b3b34792862Jerome PoichetFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 267c9978567a202d6aa98beac5da5e1b3b34792862Jerome PoichetAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 277c9978567a202d6aa98beac5da5e1b3b34792862Jerome PoichetLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 287c9978567a202d6aa98beac5da5e1b3b34792862Jerome PoichetOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 297c9978567a202d6aa98beac5da5e1b3b34792862Jerome PoichetSOFTWARE. 307c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet*/ 317c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 327c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet/** 337c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * A JSONTokener takes a source string and extracts characters and tokens from 347c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * it. It is used by the JSONObject and JSONArray constructors to parse 357c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * JSON source strings. 367c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @author JSON.org 377c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @version 2008-09-18 387c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 397c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetpublic class JSONTokener { 407c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 417c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet private int index; 427c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet private Reader reader; 437c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet private char lastChar; 447c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet private boolean useLastChar; 457c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 467c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 477c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 487c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Construct a JSONTokener from a string. 497c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 507c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param reader A reader. 517c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 527c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public JSONTokener(Reader reader) { 537c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet this.reader = reader.markSupported() ? 547c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet reader : new BufferedReader(reader); 557c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet this.useLastChar = false; 567c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet this.index = 0; 577c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 587c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 597c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 607c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 617c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Construct a JSONTokener from a string. 627c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 637c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param s A source string. 647c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 657c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public JSONTokener(String s) { 667c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet this(new StringReader(s)); 677c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 687c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 697c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 707c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 717c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Back up one character. This provides a sort of lookahead capability, 727c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * so that you can test for a digit or letter before attempting to parse 737c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * the next number or identifier. 747c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 757c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public void back() throws JSONException { 767c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (useLastChar || index <= 0) { 777c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw new JSONException("Stepping back two steps is not supported"); 787c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 797c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet index -= 1; 807c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet useLastChar = true; 817c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 827c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 837c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 847c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 857c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 867c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Get the hex value of a character (base16). 877c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param c A character between '0' and '9' or between 'A' and 'F' or 887c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * between 'a' and 'f'. 897c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return An int between 0 and 15, or -1 if c was not a hex digit. 907c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 917c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public static int dehexchar(char c) { 927c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (c >= '0' && c <= '9') { 937c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return c - '0'; 947c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 957c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (c >= 'A' && c <= 'F') { 967c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return c - ('A' - 10); 977c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 987c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (c >= 'a' && c <= 'f') { 997c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return c - ('a' - 10); 1007c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1017c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return -1; 1027c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1037c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1047c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1057c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 1067c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Determine if the source string still contains characters that next() 1077c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * can consume. 1087c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return true if not yet at the end of the source. 1097c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 1107c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public boolean more() throws JSONException { 1117c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet char nextChar = next(); 1127c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (nextChar == 0) { 1137c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return false; 1147c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1157c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet back(); 1167c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return true; 1177c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1187c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1197c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1207c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 1217c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Get the next character in the source string. 1227c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 1237c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return The next character, or 0 if past the end of the source string. 1247c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 1257c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public char next() throws JSONException { 1267c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (this.useLastChar) { 1277c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet this.useLastChar = false; 1287c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (this.lastChar != 0) { 1297c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet this.index += 1; 1307c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1317c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return this.lastChar; 1327c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1337c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet int c; 1347c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet try { 1357c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet c = this.reader.read(); 1367c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } catch (IOException exc) { 1377c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw new JSONException(exc); 1387c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1397c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1407c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (c <= 0) { // End of stream 1417c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet this.lastChar = 0; 1427c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return 0; 1437c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1447c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet this.index += 1; 1457c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet this.lastChar = (char) c; 1467c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return this.lastChar; 1477c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1487c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1497c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1507c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 1517c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Consume the next character, and check that it matches a specified 1527c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * character. 1537c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param c The character to match. 1547c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return The character. 1557c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @throws JSONException if the character does not match. 1567c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 1577c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public char next(char c) throws JSONException { 1587c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet char n = next(); 1597c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (n != c) { 1607c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw syntaxError("Expected '" + c + "' and instead saw '" + 1617c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet n + "'"); 1627c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1637c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return n; 1647c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1657c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1667c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1677c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 1687c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Get the next n characters. 1697c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 1707c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param n The number of characters to take. 1717c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return A string of n characters. 1727c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @throws JSONException 1737c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Substring bounds error if there are not 1747c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * n characters remaining in the source string. 1757c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 1767c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public String next(int n) throws JSONException { 1777c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (n == 0) { 1787c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return ""; 1797c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1807c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1817c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet char[] buffer = new char[n]; 1827c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet int pos = 0; 1837c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1847c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (this.useLastChar) { 1857c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet this.useLastChar = false; 1867c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet buffer[0] = this.lastChar; 1877c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet pos = 1; 1887c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1897c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1907c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet try { 1917c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet int len; 1927c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet while ((pos < n) && ((len = reader.read(buffer, pos, n - pos)) != -1)) { 1937c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet pos += len; 1947c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1957c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } catch (IOException exc) { 1967c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw new JSONException(exc); 1977c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1987c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet this.index += pos; 1997c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 2007c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (pos < n) { 2017c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw syntaxError("Substring bounds error"); 2027c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 2037c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 2047c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet this.lastChar = buffer[n - 1]; 2057c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return new String(buffer); 2067c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 2077c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 2087c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 2097c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 2107c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Get the next char in the string, skipping whitespace. 2117c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @throws JSONException 2127c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return A character, or 0 if there are no more characters. 2137c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 2147c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public char nextClean() throws JSONException { 2157c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet for (;;) { 2167c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet char c = next(); 2177c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (c == 0 || c > ' ') { 2187c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return c; 2197c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 2207c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 2217c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 2227c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 2237c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 2247c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 2257c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Return the characters up to the next close quote character. 2267c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Backslash processing is done. The formal JSON format does not 2277c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * allow strings in single quotes, but an implementation is allowed to 2287c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * accept them. 2297c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param quote The quoting character, either 2307c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * <code>"</code> <small>(double quote)</small> or 2317c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * <code>'</code> <small>(single quote)</small>. 2327c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return A String. 2337c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @throws JSONException Unterminated string. 2347c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 2357c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public String nextString(char quote) throws JSONException { 2367c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet char c; 2377c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet StringBuffer sb = new StringBuffer(); 2387c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet for (;;) { 2397c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet c = next(); 2407c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet switch (c) { 2417c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case 0: 2427c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case '\n': 2437c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case '\r': 2447c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw syntaxError("Unterminated string"); 2457c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case '\\': 2467c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet c = next(); 2477c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet switch (c) { 2487c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case 'b': 2497c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet sb.append('\b'); 2507c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet break; 2517c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case 't': 2527c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet sb.append('\t'); 2537c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet break; 2547c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case 'n': 2557c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet sb.append('\n'); 2567c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet break; 2577c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case 'f': 2587c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet sb.append('\f'); 2597c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet break; 2607c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case 'r': 2617c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet sb.append('\r'); 2627c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet break; 2637c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case 'u': 2647c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet sb.append((char)Integer.parseInt(next(4), 16)); 2657c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet break; 2667c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case 'x' : 2677c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet sb.append((char) Integer.parseInt(next(2), 16)); 2687c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet break; 2697c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet default: 2707c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet sb.append(c); 2717c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 2727c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet break; 2737c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet default: 2747c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (c == quote) { 2757c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return sb.toString(); 2767c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 2777c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet sb.append(c); 2787c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 2797c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 2807c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 2817c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 2827c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 2837c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 2847c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Get the text up but not including the specified character or the 2857c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * end of line, whichever comes first. 2867c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param d A delimiter character. 2877c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return A string. 2887c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 2897c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public String nextTo(char d) throws JSONException { 2907c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet StringBuffer sb = new StringBuffer(); 2917c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet for (;;) { 2927c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet char c = next(); 2937c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (c == d || c == 0 || c == '\n' || c == '\r') { 2947c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (c != 0) { 2957c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet back(); 2967c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 2977c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return sb.toString().trim(); 2987c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 2997c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet sb.append(c); 3007c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 3017c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 3027c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 3037c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 3047c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 3057c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Get the text up but not including one of the specified delimiter 3067c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * characters or the end of line, whichever comes first. 3077c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param delimiters A set of delimiter characters. 3087c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return A string, trimmed. 3097c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 3107c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public String nextTo(String delimiters) throws JSONException { 3117c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet char c; 3127c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet StringBuffer sb = new StringBuffer(); 3137c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet for (;;) { 3147c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet c = next(); 3157c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (delimiters.indexOf(c) >= 0 || c == 0 || 3167c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet c == '\n' || c == '\r') { 3177c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (c != 0) { 3187c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet back(); 3197c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 3207c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return sb.toString().trim(); 3217c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 3227c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet sb.append(c); 3237c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 3247c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 3257c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 3267c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 3277c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 3287c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Get the next value. The value can be a Boolean, Double, Integer, 3297c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. 3307c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @throws JSONException If syntax error. 3317c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 3327c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return An object. 3337c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 3347c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public Object nextValue() throws JSONException { 3357c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet char c = nextClean(); 3367c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet String s; 3377c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 3387c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet switch (c) { 3397c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case '"': 3407c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case '\'': 3417c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return nextString(c); 3427c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case '{': 3437c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet back(); 3447c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return new JSONObject(this); 3457c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case '[': 3467c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet case '(': 3477c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet back(); 3487c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return new JSONArray(this); 3497c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 3507c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 3517c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /* 3527c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Handle unquoted text. This could be the values true, false, or 3537c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * null, or it can be a number. An implementation (such as this one) 3547c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * is allowed to also accept non-standard forms. 3557c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 3567c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Accumulate characters until we reach the end of the text or a 3577c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * formatting character. 3587c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 3597c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 3607c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet StringBuffer sb = new StringBuffer(); 3617c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { 3627c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet sb.append(c); 3637c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet c = next(); 3647c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 3657c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet back(); 3667c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 3677c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet s = sb.toString().trim(); 3687c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (s.equals("")) { 3697c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw syntaxError("Missing value"); 3707c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 3717c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return JSONObject.stringToValue(s); 3727c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 3737c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 3747c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 3757c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 3767c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Skip characters until the next character is the requested character. 3777c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * If the requested character is not found, no characters are skipped. 3787c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param to A character to skip to. 3797c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return The requested character, or zero if the requested character 3807c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * is not found. 3817c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 3827c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public char skipTo(char to) throws JSONException { 3837c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet char c; 3847c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet try { 3857c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet int startIndex = this.index; 3867c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet reader.mark(Integer.MAX_VALUE); 3877c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet do { 3887c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet c = next(); 3897c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (c == 0) { 3907c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet reader.reset(); 3917c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet this.index = startIndex; 3927c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return c; 3937c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 3947c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } while (c != to); 3957c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } catch (IOException exc) { 3967c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw new JSONException(exc); 3977c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 3987c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 3997c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet back(); 4007c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return c; 4017c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 4027c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 4037c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 4047c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Make a JSONException to signal a syntax error. 4057c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 4067c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param message The error message. 4077c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return A JSONException object, suitable for throwing 4087c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 4097c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public JSONException syntaxError(String message) { 4107c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return new JSONException(message + toString()); 4117c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 4127c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 4137c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 4147c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 4157c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Make a printable string of this JSONTokener. 4167c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 4177c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return " at character [this.index]" 4187c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 4197c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public String toString() { 4207c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return " at character " + index; 4217c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 4227c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}