Clover icon

Coverage Report

  1. Project Clover database Mon Nov 18 2024 09:38:20 GMT
  2. Package org.json.simple.parser

File JSONParser.java

 

Coverage histogram

../../../../img/srcFileCovDistChart4.png
40% 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 55 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  365446 toggle private int peekStatus(LinkedList statusStack)
49    {
50  365446 if (statusStack.size() == 0)
51  0 return -1;
52  365446 Integer status = (Integer) statusStack.getFirst();
53  365446 return status.intValue();
54    }
55   
56    /**
57    * Reset the parser to the initial state without resetting the underlying
58    * reader.
59    *
60    */
 
61  147 toggle public void reset()
62    {
63  147 token = null;
64  147 status = S_INIT;
65  147 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  147 toggle public void reset(Reader in)
77    {
78  147 lexer.yyreset(in);
79  147 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  92 toggle public Object parse(String s) throws ParseException
91    {
92  92 return parse(s, (ContainerFactory) null);
93    }
94   
 
95  92 toggle public Object parse(String s, ContainerFactory containerFactory)
96    throws ParseException
97    {
98  92 StringReader in = new StringReader(s);
99  92 try
100    {
101  92 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  55 toggle public Object parse(Reader in) throws IOException, ParseException
113    {
114  55 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  147 toggle public Object parse(Reader in, ContainerFactory containerFactory)
132    throws IOException, ParseException
133    {
134  147 reset(in);
135  147 LinkedList statusStack = new LinkedList();
136  147 LinkedList valueStack = new LinkedList();
137   
138  147 try
139    {
140  147 do
141    {
142  8220855 nextToken();
143  8220855 switch (status)
144    {
145  147 case S_INIT:
146  147 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  134 case Yytoken.TYPE_LEFT_BRACE:
154  134 status = S_IN_OBJECT;
155  134 statusStack.addFirst(new Integer(status));
156  134 valueStack.addFirst(createObjectContainer(containerFactory));
157  134 break;
158  13 case Yytoken.TYPE_LEFT_SQUARE:
159  13 status = S_IN_ARRAY;
160  13 statusStack.addFirst(new Integer(status));
161  13 valueStack.addFirst(createArrayContainer(containerFactory));
162  13 break;
163  0 default:
164  0 status = S_IN_ERROR;
165    }// inner switch
166  147 break;
167   
168  147 case S_IN_FINISHED_VALUE:
169  147 if (token.type == Yytoken.TYPE_EOF)
170  147 return valueStack.removeFirst();
171    else
172  0 throw new ParseException(getPosition(),
173    ParseException.ERROR_UNEXPECTED_TOKEN, token);
174   
175  632561 case S_IN_OBJECT:
176  632561 switch (token.type)
177    {
178  266298 case Yytoken.TYPE_COMMA:
179  266298 break;
180  316289 case Yytoken.TYPE_VALUE:
181  316289 if (token.value instanceof String)
182    {
183  316289 String key = (String) token.value;
184  316289 valueStack.addFirst(key);
185  316289 status = S_PASSED_PAIR_KEY;
186  316289 statusStack.addFirst(new Integer(status));
187    }
188    else
189    {
190  0 status = S_IN_ERROR;
191    }
192  316289 break;
193  49974 case Yytoken.TYPE_RIGHT_BRACE:
194  49974 if (valueStack.size() > 1)
195    {
196  49840 statusStack.removeFirst();
197  49840 valueStack.removeFirst();
198  49840 status = peekStatus(statusStack);
199    }
200    else
201    {
202  134 status = S_IN_FINISHED_VALUE;
203    }
204  49974 break;
205  0 default:
206  0 status = S_IN_ERROR;
207  0 break;
208    }// inner switch
209  632561 break;
210   
211  632578 case S_PASSED_PAIR_KEY:
212  632578 switch (token.type)
213    {
214  316289 case Yytoken.TYPE_COLON:
215  316289 break;
216  278539 case Yytoken.TYPE_VALUE:
217  278539 statusStack.removeFirst();
218  278539 String key = (String) valueStack.removeFirst();
219  278539 Map parent = (Map) valueStack.getFirst();
220  278539 parent.put(key, token.value);
221  278539 status = peekStatus(statusStack);
222  278539 break;
223  32538 case Yytoken.TYPE_LEFT_SQUARE:
224  32538 statusStack.removeFirst();
225  32538 key = (String) valueStack.removeFirst();
226  32538 parent = (Map) valueStack.getFirst();
227  32538 List newArray = createArrayContainer(containerFactory);
228  32538 parent.put(key, newArray);
229  32538 status = S_IN_ARRAY;
230  32538 statusStack.addFirst(new Integer(status));
231  32538 valueStack.addFirst(newArray);
232  32538 break;
233  5212 case Yytoken.TYPE_LEFT_BRACE:
234  5212 statusStack.removeFirst();
235  5212 key = (String) valueStack.removeFirst();
236  5212 parent = (Map) valueStack.getFirst();
237  5212 Map newObject = createObjectContainer(containerFactory);
238  5212 parent.put(key, newObject);
239  5212 status = S_IN_OBJECT;
240  5212 statusStack.addFirst(new Integer(status));
241  5212 valueStack.addFirst(newObject);
242  5212 break;
243  0 default:
244  0 status = S_IN_ERROR;
245    }
246  632578 break;
247   
248  6955422 case S_IN_ARRAY:
249  6955422 switch (token.type)
250    {
251  3440633 case Yytoken.TYPE_COMMA:
252  3440633 break;
253  3428552 case Yytoken.TYPE_VALUE:
254  3428552 List val = (List) valueStack.getFirst();
255  3428552 val.add(token.value);
256  3428552 break;
257  37080 case Yytoken.TYPE_RIGHT_SQUARE:
258  37080 if (valueStack.size() > 1)
259    {
260  37067 statusStack.removeFirst();
261  37067 valueStack.removeFirst();
262  37067 status = peekStatus(statusStack);
263    }
264    else
265    {
266  13 status = S_IN_FINISHED_VALUE;
267    }
268  37080 break;
269  44628 case Yytoken.TYPE_LEFT_BRACE:
270  44628 val = (List) valueStack.getFirst();
271  44628 Map newObject = createObjectContainer(containerFactory);
272  44628 val.add(newObject);
273  44628 status = S_IN_OBJECT;
274  44628 statusStack.addFirst(new Integer(status));
275  44628 valueStack.addFirst(newObject);
276  44628 break;
277  4529 case Yytoken.TYPE_LEFT_SQUARE:
278  4529 val = (List) valueStack.getFirst();
279  4529 List newArray = createArrayContainer(containerFactory);
280  4529 val.add(newArray);
281  4529 status = S_IN_ARRAY;
282  4529 statusStack.addFirst(new Integer(status));
283  4529 valueStack.addFirst(newArray);
284  4529 break;
285  0 default:
286  0 status = S_IN_ERROR;
287    }// inner switch
288  6955422 break;
289  0 case S_IN_ERROR:
290  0 throw new ParseException(getPosition(),
291    ParseException.ERROR_UNEXPECTED_TOKEN, token);
292    }// switch
293  8220708 if (status == S_IN_ERROR)
294    {
295  0 throw new ParseException(getPosition(),
296    ParseException.ERROR_UNEXPECTED_TOKEN, token);
297    }
298  8220708 } 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  8220855 toggle private void nextToken() throws ParseException, IOException
309    {
310  8220855 token = lexer.yylex();
311  8220855 if (token == null)
312  147 token = new Yytoken(Yytoken.TYPE_EOF, null);
313    }
314   
 
315  49974 toggle private Map createObjectContainer(ContainerFactory containerFactory)
316    {
317  49974 if (containerFactory == null)
318  49974 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  37080 toggle private List createArrayContainer(ContainerFactory containerFactory)
327    {
328  37080 if (containerFactory == null)
329  37080 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    }