Clover icon

Coverage Report

  1. Project Clover database Fri Nov 15 2024 13:56:46 GMT
  2. Package org.json.simple.parser

File JSONParser.java

 

Coverage histogram

../../../../img/srcFileCovDistChart4.png
48% of files have more coverage

Code metrics

68
321
15
1
611
499
100
0.31
21.4
15
6.67

Classes

Class Line # Actions
JSONParser 22 321 100
0.3712871437.1%
 

Contributing tests

This file is covered by 93 tests. .

Source view

1    /*
2    * $Id: JSONParser.java,v 1.1 2006/04/15 14:10:48 platform Exp $
3    * Created on 2006-4-15
4    */
5    package org.json.simple.parser;
6   
7    import java.io.IOException;
8    import java.io.Reader;
9    import java.io.StringReader;
10    import java.util.LinkedList;
11    import java.util.List;
12    import java.util.Map;
13   
14    import org.json.simple.JSONArray;
15    import org.json.simple.JSONObject;
16   
17    /**
18    * Parser for JSON text. Please note that JSONParser is NOT thread-safe.
19    *
20    * @author FangYidong<fangyidong@yahoo.com.cn>
21    */
 
22    public class JSONParser
23    {
24    public static final int S_INIT = 0;
25   
26    public static final int S_IN_FINISHED_VALUE = 1;// string,number,boolean,null,object,array
27   
28    public static final int S_IN_OBJECT = 2;
29   
30    public static final int S_IN_ARRAY = 3;
31   
32    public static final int S_PASSED_PAIR_KEY = 4;
33   
34    public static final int S_IN_PAIR_VALUE = 5;
35   
36    public static final int S_END = 6;
37   
38    public static final int S_IN_ERROR = -1;
39   
40    private LinkedList handlerStatusStack;
41   
42    private Yylex lexer = new Yylex((Reader) null);
43   
44    private Yytoken token = null;
45   
46    private int status = S_INIT;
47   
 
48  388976 toggle private int peekStatus(LinkedList statusStack)
49    {
50  388976 if (statusStack.size() == 0)
51  0 return -1;
52  388976 Integer status = (Integer) statusStack.getFirst();
53  388976 return status.intValue();
54    }
55   
56    /**
57    * Reset the parser to the initial state without resetting the underlying
58    * reader.
59    *
60    */
 
61  238 toggle public void reset()
62    {
63  238 token = null;
64  238 status = S_INIT;
65  238 handlerStatusStack = null;
66    }
67   
68    /**
69    * Reset the parser to the initial state with a new character reader.
70    *
71    * @param in
72    * - The new character reader.
73    * @throws IOException
74    * @throws ParseException
75    */
 
76  238 toggle public void reset(Reader in)
77    {
78  238 lexer.yyreset(in);
79  238 reset();
80    }
81   
82    /**
83    * @return The position of the beginning of the current token.
84    */
 
85  0 toggle public int getPosition()
86    {
87  0 return lexer.getPosition();
88    }
89   
 
90  121 toggle public Object parse(String s) throws ParseException
91    {
92  121 return parse(s, (ContainerFactory) null);
93    }
94   
 
95  121 toggle public Object parse(String s, ContainerFactory containerFactory)
96    throws ParseException
97    {
98  121 StringReader in = new StringReader(s);
99  121 try
100    {
101  121 return parse(in, containerFactory);
102    } catch (IOException ie)
103    {
104    /*
105    * Actually it will never happen.
106    */
107  0 throw new ParseException(-1,
108    ParseException.ERROR_UNEXPECTED_EXCEPTION, ie);
109    }
110    }
111   
 
112  117 toggle public Object parse(Reader in) throws IOException, ParseException
113    {
114  117 return parse(in, (ContainerFactory) null);
115    }
116   
117    /**
118    * Parse JSON text into java object from the input source.
119    *
120    * @param in
121    * @param containerFactory
122    * - Use this factory to createyour own JSON object and JSON array
123    * containers.
124    * @return Instance of the following: org.json.simple.JSONObject,
125    * org.json.simple.JSONArray, java.lang.String, java.lang.Number,
126    * java.lang.Boolean, null
127    *
128    * @throws IOException
129    * @throws ParseException
130    */
 
131  238 toggle public Object parse(Reader in, ContainerFactory containerFactory)
132    throws IOException, ParseException
133    {
134  238 reset(in);
135  238 LinkedList statusStack = new LinkedList();
136  238 LinkedList valueStack = new LinkedList();
137   
138  238 try
139    {
140  238 do
141    {
142  9814025 nextToken();
143  9814025 switch (status)
144    {
145  238 case S_INIT:
146  238 switch (token.type)
147    {
148  0 case Yytoken.TYPE_VALUE:
149  0 status = S_IN_FINISHED_VALUE;
150  0 statusStack.addFirst(new Integer(status));
151  0 valueStack.addFirst(token.value);
152  0 break;
153  193 case Yytoken.TYPE_LEFT_BRACE:
154  193 status = S_IN_OBJECT;
155  193 statusStack.addFirst(new Integer(status));
156  193 valueStack.addFirst(createObjectContainer(containerFactory));
157  193 break;
158  45 case Yytoken.TYPE_LEFT_SQUARE:
159  45 status = S_IN_ARRAY;
160  45 statusStack.addFirst(new Integer(status));
161  45 valueStack.addFirst(createArrayContainer(containerFactory));
162  45 break;
163  0 default:
164  0 status = S_IN_ERROR;
165    }// inner switch
166  238 break;
167   
168  238 case S_IN_FINISHED_VALUE:
169  238 if (token.type == Yytoken.TYPE_EOF)
170  238 return valueStack.removeFirst();
171    else
172  0 throw new ParseException(getPosition(),
173    ParseException.ERROR_UNEXPECTED_TOKEN, token);
174   
175  660945 case S_IN_OBJECT:
176  660945 switch (token.type)
177    {
178  276906 case Yytoken.TYPE_COMMA:
179  276906 break;
180  330481 case Yytoken.TYPE_VALUE:
181  330481 if (token.value instanceof String)
182    {
183  330481 String key = (String) token.value;
184  330481 valueStack.addFirst(key);
185  330481 status = S_PASSED_PAIR_KEY;
186  330481 statusStack.addFirst(new Integer(status));
187    }
188    else
189    {
190  0 status = S_IN_ERROR;
191    }
192  330481 break;
193  53558 case Yytoken.TYPE_RIGHT_BRACE:
194  53558 if (valueStack.size() > 1)
195    {
196  53365 statusStack.removeFirst();
197  53365 valueStack.removeFirst();
198  53365 status = peekStatus(statusStack);
199    }
200    else
201    {
202  193 status = S_IN_FINISHED_VALUE;
203    }
204  53558 break;
205  0 default:
206  0 status = S_IN_ERROR;
207  0 break;
208    }// inner switch
209  660945 break;
210   
211  660962 case S_PASSED_PAIR_KEY:
212  660962 switch (token.type)
213    {
214  330481 case Yytoken.TYPE_COLON:
215  330481 break;
216  292579 case Yytoken.TYPE_VALUE:
217  292579 statusStack.removeFirst();
218  292579 String key = (String) valueStack.removeFirst();
219  292579 Map parent = (Map) valueStack.getFirst();
220  292579 parent.put(key, token.value);
221  292579 status = peekStatus(statusStack);
222  292579 break;
223  32678 case Yytoken.TYPE_LEFT_SQUARE:
224  32678 statusStack.removeFirst();
225  32678 key = (String) valueStack.removeFirst();
226  32678 parent = (Map) valueStack.getFirst();
227  32678 List newArray = createArrayContainer(containerFactory);
228  32678 parent.put(key, newArray);
229  32678 status = S_IN_ARRAY;
230  32678 statusStack.addFirst(new Integer(status));
231  32678 valueStack.addFirst(newArray);
232  32678 break;
233  5224 case Yytoken.TYPE_LEFT_BRACE:
234  5224 statusStack.removeFirst();
235  5224 key = (String) valueStack.removeFirst();
236  5224 parent = (Map) valueStack.getFirst();
237  5224 Map newObject = createObjectContainer(containerFactory);
238  5224 parent.put(key, newObject);
239  5224 status = S_IN_OBJECT;
240  5224 statusStack.addFirst(new Integer(status));
241  5224 valueStack.addFirst(newObject);
242  5224 break;
243  0 default:
244  0 status = S_IN_ERROR;
245    }
246  660962 break;
247   
248  8491642 case S_IN_ARRAY:
249  8491642 switch (token.type)
250    {
251  4202746 case Yytoken.TYPE_COMMA:
252  4202746 break;
253  4187324 case Yytoken.TYPE_VALUE:
254  4187324 List val = (List) valueStack.getFirst();
255  4187324 val.add(token.value);
256  4187324 break;
257  43077 case Yytoken.TYPE_RIGHT_SQUARE:
258  43077 if (valueStack.size() > 1)
259    {
260  43032 statusStack.removeFirst();
261  43032 valueStack.removeFirst();
262  43032 status = peekStatus(statusStack);
263    }
264    else
265    {
266  45 status = S_IN_FINISHED_VALUE;
267    }
268  43077 break;
269  48141 case Yytoken.TYPE_LEFT_BRACE:
270  48141 val = (List) valueStack.getFirst();
271  48141 Map newObject = createObjectContainer(containerFactory);
272  48141 val.add(newObject);
273  48141 status = S_IN_OBJECT;
274  48141 statusStack.addFirst(new Integer(status));
275  48141 valueStack.addFirst(newObject);
276  48141 break;
277  10354 case Yytoken.TYPE_LEFT_SQUARE:
278  10354 val = (List) valueStack.getFirst();
279  10354 List newArray = createArrayContainer(containerFactory);
280  10354 val.add(newArray);
281  10354 status = S_IN_ARRAY;
282  10354 statusStack.addFirst(new Integer(status));
283  10354 valueStack.addFirst(newArray);
284  10354 break;
285  0 default:
286  0 status = S_IN_ERROR;
287    }// inner switch
288  8491642 break;
289  0 case S_IN_ERROR:
290  0 throw new ParseException(getPosition(),
291    ParseException.ERROR_UNEXPECTED_TOKEN, token);
292    }// switch
293  9813787 if (status == S_IN_ERROR)
294    {
295  0 throw new ParseException(getPosition(),
296    ParseException.ERROR_UNEXPECTED_TOKEN, token);
297    }
298  9813787 } while (token.type != Yytoken.TYPE_EOF);
299    } catch (IOException ie)
300    {
301  0 throw ie;
302    }
303   
304  0 throw new ParseException(getPosition(),
305    ParseException.ERROR_UNEXPECTED_TOKEN, token);
306    }
307   
 
308  9814025 toggle private void nextToken() throws ParseException, IOException
309    {
310  9814025 token = lexer.yylex();
311  9814025 if (token == null)
312  238 token = new Yytoken(Yytoken.TYPE_EOF, null);
313    }
314   
 
315  53558 toggle private Map createObjectContainer(ContainerFactory containerFactory)
316    {
317  53558 if (containerFactory == null)
318  53558 return new JSONObject();
319  0 Map m = containerFactory.createObjectContainer();
320   
321  0 if (m == null)
322  0 return new JSONObject();
323  0 return m;
324    }
325   
 
326  43077 toggle private List createArrayContainer(ContainerFactory containerFactory)
327    {
328  43077 if (containerFactory == null)
329  43077 return new JSONArray();
330  0 List l = containerFactory.creatArrayContainer();
331   
332  0 if (l == null)
333  0 return new JSONArray();
334  0 return l;
335    }
336   
 
337  0 toggle public void parse(String s, ContentHandler contentHandler)
338    throws ParseException
339    {
340  0 parse(s, contentHandler, false);
341    }
342   
 
343  0 toggle public void parse(String s, ContentHandler contentHandler,
344    boolean isResume) throws ParseException
345    {
346  0 StringReader in = new StringReader(s);
347  0 try
348    {
349  0 parse(in, contentHandler, isResume);
350    } catch (IOException ie)
351    {
352    /*
353    * Actually it will never happen.
354    */
355  0 throw new ParseException(-1,
356    ParseException.ERROR_UNEXPECTED_EXCEPTION, ie);
357    }
358    }
359   
 
360  0 toggle public void parse(Reader in, ContentHandler contentHandler)
361    throws IOException, ParseException
362    {
363  0 parse(in, contentHandler, false);
364    }
365   
366    /**
367    * Stream processing of JSON text.
368    *
369    * @see ContentHandler
370    *
371    * @param in
372    * @param contentHandler
373    * @param isResume
374    * - Indicates if it continues previous parsing operation. If set to
375    * true, resume parsing the old stream, and parameter 'in' will be
376    * ignored. If this method is called for the first time in this
377    * instance, isResume will be ignored.
378    *
379    * @throws IOException
380    * @throws ParseException
381    */
 
382  0 toggle public void parse(Reader in, ContentHandler contentHandler,
383    boolean isResume) throws IOException, ParseException
384    {
385  0 if (!isResume)
386    {
387  0 reset(in);
388  0 handlerStatusStack = new LinkedList();
389    }
390    else
391    {
392  0 if (handlerStatusStack == null)
393    {
394  0 isResume = false;
395  0 reset(in);
396  0 handlerStatusStack = new LinkedList();
397    }
398    }
399   
400  0 LinkedList statusStack = handlerStatusStack;
401   
402  0 try
403    {
404  0 do
405    {
406  0 switch (status)
407    {
408  0 case S_INIT:
409  0 contentHandler.startJSON();
410  0 nextToken();
411  0 switch (token.type)
412    {
413  0 case Yytoken.TYPE_VALUE:
414  0 status = S_IN_FINISHED_VALUE;
415  0 statusStack.addFirst(new Integer(status));
416  0 if (!contentHandler.primitive(token.value))
417  0 return;
418  0 break;
419  0 case Yytoken.TYPE_LEFT_BRACE:
420  0 status = S_IN_OBJECT;
421  0 statusStack.addFirst(new Integer(status));
422  0 if (!contentHandler.startObject())
423  0 return;
424  0 break;
425  0 case Yytoken.TYPE_LEFT_SQUARE:
426  0 status = S_IN_ARRAY;
427  0 statusStack.addFirst(new Integer(status));
428  0 if (!contentHandler.startArray())
429  0 return;
430  0 break;
431  0 default:
432  0 status = S_IN_ERROR;
433    }// inner switch
434  0 break;
435   
436  0 case S_IN_FINISHED_VALUE:
437  0 nextToken();
438  0 if (token.type == Yytoken.TYPE_EOF)
439    {
440  0 contentHandler.endJSON();
441  0 status = S_END;
442  0 return;
443    }
444    else
445    {
446  0 status = S_IN_ERROR;
447  0 throw new ParseException(getPosition(),
448    ParseException.ERROR_UNEXPECTED_TOKEN, token);
449    }
450   
451  0 case S_IN_OBJECT:
452  0 nextToken();
453  0 switch (token.type)
454    {
455  0 case Yytoken.TYPE_COMMA:
456  0 break;
457  0 case Yytoken.TYPE_VALUE:
458  0 if (token.value instanceof String)
459    {
460  0 String key = (String) token.value;
461  0 status = S_PASSED_PAIR_KEY;
462  0 statusStack.addFirst(new Integer(status));
463  0 if (!contentHandler.startObjectEntry(key))
464  0 return;
465    }
466    else
467    {
468  0 status = S_IN_ERROR;
469    }
470  0 break;
471  0 case Yytoken.TYPE_RIGHT_BRACE:
472  0 if (statusStack.size() > 1)
473    {
474  0 statusStack.removeFirst();
475  0 status = peekStatus(statusStack);
476    }
477    else
478    {
479  0 status = S_IN_FINISHED_VALUE;
480    }
481  0 if (!contentHandler.endObject())
482  0 return;
483  0 break;
484  0 default:
485  0 status = S_IN_ERROR;
486  0 break;
487    }// inner switch
488  0 break;
489   
490  0 case S_PASSED_PAIR_KEY:
491  0 nextToken();
492  0 switch (token.type)
493    {
494  0 case Yytoken.TYPE_COLON:
495  0 break;
496  0 case Yytoken.TYPE_VALUE:
497  0 statusStack.removeFirst();
498  0 status = peekStatus(statusStack);
499  0 if (!contentHandler.primitive(token.value))
500  0 return;
501  0 if (!contentHandler.endObjectEntry())
502  0 return;
503  0 break;
504  0 case Yytoken.TYPE_LEFT_SQUARE:
505  0 statusStack.removeFirst();
506  0 statusStack.addFirst(new Integer(S_IN_PAIR_VALUE));
507  0 status = S_IN_ARRAY;
508  0 statusStack.addFirst(new Integer(status));
509  0 if (!contentHandler.startArray())
510  0 return;
511  0 break;
512  0 case Yytoken.TYPE_LEFT_BRACE:
513  0 statusStack.removeFirst();
514  0 statusStack.addFirst(new Integer(S_IN_PAIR_VALUE));
515  0 status = S_IN_OBJECT;
516  0 statusStack.addFirst(new Integer(status));
517  0 if (!contentHandler.startObject())
518  0 return;
519  0 break;
520  0 default:
521  0 status = S_IN_ERROR;
522    }
523  0 break;
524   
525  0 case S_IN_PAIR_VALUE:
526    /*
527    * S_IN_PAIR_VALUE is just a marker to indicate the end of an object entry, it doesn't proccess any token,
528    * therefore delay consuming token until next round.
529    */
530  0 statusStack.removeFirst();
531  0 status = peekStatus(statusStack);
532  0 if (!contentHandler.endObjectEntry())
533  0 return;
534  0 break;
535   
536  0 case S_IN_ARRAY:
537  0 nextToken();
538  0 switch (token.type)
539    {
540  0 case Yytoken.TYPE_COMMA:
541  0 break;
542  0 case Yytoken.TYPE_VALUE:
543  0 if (!contentHandler.primitive(token.value))
544  0 return;
545  0 break;
546  0 case Yytoken.TYPE_RIGHT_SQUARE:
547  0 if (statusStack.size() > 1)
548    {
549  0 statusStack.removeFirst();
550  0 status = peekStatus(statusStack);
551    }
552    else
553    {
554  0 status = S_IN_FINISHED_VALUE;
555    }
556  0 if (!contentHandler.endArray())
557  0 return;
558  0 break;
559  0 case Yytoken.TYPE_LEFT_BRACE:
560  0 status = S_IN_OBJECT;
561  0 statusStack.addFirst(new Integer(status));
562  0 if (!contentHandler.startObject())
563  0 return;
564  0 break;
565  0 case Yytoken.TYPE_LEFT_SQUARE:
566  0 status = S_IN_ARRAY;
567  0 statusStack.addFirst(new Integer(status));
568  0 if (!contentHandler.startArray())
569  0 return;
570  0 break;
571  0 default:
572  0 status = S_IN_ERROR;
573    }// inner switch
574  0 break;
575   
576  0 case S_END:
577  0 return;
578   
579  0 case S_IN_ERROR:
580  0 throw new ParseException(getPosition(),
581    ParseException.ERROR_UNEXPECTED_TOKEN, token);
582    }// switch
583  0 if (status == S_IN_ERROR)
584    {
585  0 throw new ParseException(getPosition(),
586    ParseException.ERROR_UNEXPECTED_TOKEN, token);
587    }
588  0 } while (token.type != Yytoken.TYPE_EOF);
589    } catch (IOException ie)
590    {
591  0 status = S_IN_ERROR;
592  0 throw ie;
593    } catch (ParseException pe)
594    {
595  0 status = S_IN_ERROR;
596  0 throw pe;
597    } catch (RuntimeException re)
598    {
599  0 status = S_IN_ERROR;
600  0 throw re;
601    } catch (Error e)
602    {
603  0 status = S_IN_ERROR;
604  0 throw e;
605    }
606   
607  0 status = S_IN_ERROR;
608  0 throw new ParseException(getPosition(),
609    ParseException.ERROR_UNEXPECTED_TOKEN, token);
610    }
611    }