root/tools/routingservice/branches/wrs-2.0/lib/org/json/JSONTokener.java

Revision 290, 11.7 KB (checked in by anton, 20 months ago)

First working version with JSON input and GML output for route service

Line 
1package org.json;
2
3import java.io.BufferedReader;
4import java.io.IOException;
5import java.io.Reader;
6import java.io.StringReader;
7
8/*
9Copyright (c) 2002 JSON.org
10
11Permission is hereby granted, free of charge, to any person obtaining a copy
12of this software and associated documentation files (the "Software"), to deal
13in the Software without restriction, including without limitation the rights
14to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15copies of the Software, and to permit persons to whom the Software is
16furnished to do so, subject to the following conditions:
17
18The above copyright notice and this permission notice shall be included in all
19copies or substantial portions of the Software.
20
21The Software shall be used for Good, not Evil.
22
23THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29SOFTWARE.
30*/
31
32/**
33 * A JSONTokener takes a source string and extracts characters and tokens from
34 * it. It is used by the JSONObject and JSONArray constructors to parse
35 * JSON source strings.
36 * @author JSON.org
37 * @version 2008-09-18
38 */
39public class JSONTokener {
40
41    private int index;
42    private Reader reader;
43    private char lastChar;
44    private boolean useLastChar;
45
46
47    /**
48     * Construct a JSONTokener from a string.
49     *
50     * @param reader     A reader.
51     */
52    public JSONTokener(Reader reader) {
53        this.reader = reader.markSupported() ?
54                        reader : new BufferedReader(reader);
55        this.useLastChar = false;
56        this.index = 0;
57    }
58
59
60    /**
61     * Construct a JSONTokener from a string.
62     *
63     * @param s     A source string.
64     */
65    public JSONTokener(String s) {
66        this(new StringReader(s));
67    }
68
69
70    /**
71     * Back up one character. This provides a sort of lookahead capability,
72     * so that you can test for a digit or letter before attempting to parse
73     * the next number or identifier.
74     */
75    public void back() throws JSONException {
76        if (useLastChar || index <= 0) {
77            throw new JSONException("Stepping back two steps is not supported");
78        }
79        index -= 1;
80        useLastChar = true;
81    }
82
83
84
85    /**
86     * Get the hex value of a character (base16).
87     * @param c A character between '0' and '9' or between 'A' and 'F' or
88     * between 'a' and 'f'.
89     * @return  An int between 0 and 15, or -1 if c was not a hex digit.
90     */
91    public static int dehexchar(char c) {
92        if (c >= '0' && c <= '9') {
93            return c - '0';
94        }
95        if (c >= 'A' && c <= 'F') {
96            return c - ('A' - 10);
97        }
98        if (c >= 'a' && c <= 'f') {
99            return c - ('a' - 10);
100        }
101        return -1;
102    }
103
104
105    /**
106     * Determine if the source string still contains characters that next()
107     * can consume.
108     * @return true if not yet at the end of the source.
109     */
110    public boolean more() throws JSONException {
111        char nextChar = next();
112        if (nextChar == 0) {
113            return false;
114        }
115        back();
116        return true;
117    }
118
119
120    /**
121     * Get the next character in the source string.
122     *
123     * @return The next character, or 0 if past the end of the source string.
124     */
125    public char next() throws JSONException {
126        if (this.useLastChar) {
127                this.useLastChar = false;
128            if (this.lastChar != 0) {
129                this.index += 1;
130            }
131            return this.lastChar;
132        }
133        int c;
134        try {
135            c = this.reader.read();
136        } catch (IOException exc) {
137            throw new JSONException(exc);
138        }
139
140        if (c <= 0) { // End of stream
141                this.lastChar = 0;
142            return 0;
143        }
144        this.index += 1;
145        this.lastChar = (char) c;
146        return this.lastChar;
147    }
148
149
150    /**
151     * Consume the next character, and check that it matches a specified
152     * character.
153     * @param c The character to match.
154     * @return The character.
155     * @throws JSONException if the character does not match.
156     */
157    public char next(char c) throws JSONException {
158        char n = next();
159        if (n != c) {
160            throw syntaxError("Expected '" + c + "' and instead saw '" +
161                    n + "'");
162        }
163        return n;
164    }
165
166
167    /**
168     * Get the next n characters.
169     *
170     * @param n     The number of characters to take.
171     * @return      A string of n characters.
172     * @throws JSONException
173     *   Substring bounds error if there are not
174     *   n characters remaining in the source string.
175     */
176     public String next(int n) throws JSONException {
177         if (n == 0) {
178             return "";
179         }
180
181         char[] buffer = new char[n];
182         int pos = 0;
183
184         if (this.useLastChar) {
185                 this.useLastChar = false;
186             buffer[0] = this.lastChar;
187             pos = 1;
188         }
189
190         try {
191             int len;
192             while ((pos < n) && ((len = reader.read(buffer, pos, n - pos)) != -1)) {
193                 pos += len;
194             }
195         } catch (IOException exc) {
196             throw new JSONException(exc);
197         }
198         this.index += pos;
199
200         if (pos < n) {
201             throw syntaxError("Substring bounds error");
202         }
203
204         this.lastChar = buffer[n - 1];
205         return new String(buffer);
206     }
207
208
209    /**
210     * Get the next char in the string, skipping whitespace.
211     * @throws JSONException
212     * @return  A character, or 0 if there are no more characters.
213     */
214    public char nextClean() throws JSONException {
215        for (;;) {
216            char c = next();
217            if (c == 0 || c > ' ') {
218                return c;
219            }
220        }
221    }
222
223
224    /**
225     * Return the characters up to the next close quote character.
226     * Backslash processing is done. The formal JSON format does not
227     * allow strings in single quotes, but an implementation is allowed to
228     * accept them.
229     * @param quote The quoting character, either
230     *      <code>"</code>&nbsp;<small>(double quote)</small> or
231     *      <code>'</code>&nbsp;<small>(single quote)</small>.
232     * @return      A String.
233     * @throws JSONException Unterminated string.
234     */
235    public String nextString(char quote) throws JSONException {
236        char c;
237        StringBuffer sb = new StringBuffer();
238        for (;;) {
239            c = next();
240            switch (c) {
241            case 0:
242            case '\n':
243            case '\r':
244                throw syntaxError("Unterminated string");
245            case '\\':
246                c = next();
247                switch (c) {
248                case 'b':
249                    sb.append('\b');
250                    break;
251                case 't':
252                    sb.append('\t');
253                    break;
254                case 'n':
255                    sb.append('\n');
256                    break;
257                case 'f':
258                    sb.append('\f');
259                    break;
260                case 'r':
261                    sb.append('\r');
262                    break;
263                case 'u':
264                    sb.append((char)Integer.parseInt(next(4), 16));
265                    break;
266                case 'x' :
267                    sb.append((char) Integer.parseInt(next(2), 16));
268                    break;
269                default:
270                    sb.append(c);
271                }
272                break;
273            default:
274                if (c == quote) {
275                    return sb.toString();
276                }
277                sb.append(c);
278            }
279        }
280    }
281
282
283    /**
284     * Get the text up but not including the specified character or the
285     * end of line, whichever comes first.
286     * @param  d A delimiter character.
287     * @return   A string.
288     */
289    public String nextTo(char d) throws JSONException {
290        StringBuffer sb = new StringBuffer();
291        for (;;) {
292            char c = next();
293            if (c == d || c == 0 || c == '\n' || c == '\r') {
294                if (c != 0) {
295                    back();
296                }
297                return sb.toString().trim();
298            }
299            sb.append(c);
300        }
301    }
302
303
304    /**
305     * Get the text up but not including one of the specified delimiter
306     * characters or the end of line, whichever comes first.
307     * @param delimiters A set of delimiter characters.
308     * @return A string, trimmed.
309     */
310    public String nextTo(String delimiters) throws JSONException {
311        char c;
312        StringBuffer sb = new StringBuffer();
313        for (;;) {
314            c = next();
315            if (delimiters.indexOf(c) >= 0 || c == 0 ||
316                    c == '\n' || c == '\r') {
317                if (c != 0) {
318                    back();
319                }
320                return sb.toString().trim();
321            }
322            sb.append(c);
323        }
324    }
325
326
327    /**
328     * Get the next value. The value can be a Boolean, Double, Integer,
329     * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
330     * @throws JSONException If syntax error.
331     *
332     * @return An object.
333     */
334    public Object nextValue() throws JSONException {
335        char c = nextClean();
336        String s;
337
338        switch (c) {
339            case '"':
340            case '\'':
341                return nextString(c);
342            case '{':
343                back();
344                return new JSONObject(this);
345            case '[':
346            case '(':
347                back();
348                return new JSONArray(this);
349        }
350
351        /*
352         * Handle unquoted text. This could be the values true, false, or
353         * null, or it can be a number. An implementation (such as this one)
354         * is allowed to also accept non-standard forms.
355         *
356         * Accumulate characters until we reach the end of the text or a
357         * formatting character.
358         */
359
360        StringBuffer sb = new StringBuffer();
361        while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
362            sb.append(c);
363            c = next();
364        }
365        back();
366
367        s = sb.toString().trim();
368        if (s.equals("")) {
369            throw syntaxError("Missing value");
370        }
371        return JSONObject.stringToValue(s);
372    }
373
374
375    /**
376     * Skip characters until the next character is the requested character.
377     * If the requested character is not found, no characters are skipped.
378     * @param to A character to skip to.
379     * @return The requested character, or zero if the requested character
380     * is not found.
381     */
382    public char skipTo(char to) throws JSONException {
383        char c;
384        try {
385            int startIndex = this.index;
386            reader.mark(Integer.MAX_VALUE);
387            do {
388                c = next();
389                if (c == 0) {
390                    reader.reset();
391                    this.index = startIndex;
392                    return c;
393                }
394            } while (c != to);
395        } catch (IOException exc) {
396            throw new JSONException(exc);
397        }
398
399        back();
400        return c;
401    }
402
403    /**
404     * Make a JSONException to signal a syntax error.
405     *
406     * @param message The error message.
407     * @return  A JSONException object, suitable for throwing
408     */
409    public JSONException syntaxError(String message) {
410        return new JSONException(message + toString());
411    }
412
413
414    /**
415     * Make a printable string of this JSONTokener.
416     *
417     * @return " at character [this.index]"
418     */
419    public String toString() {
420        return " at character " + index;
421    }
422}
Note: See TracBrowser for help on using the browser.