Clover icon

Coverage Report

  1. Project Clover database Mon Sep 2 2024 17:57:51 BST
  2. Package org.json.simple.parser

File JSONParser.java

 

Coverage histogram

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