mobile/android/thirdparty/org/json/simple/parser/JSONParser.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

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

mercurial