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.

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

mercurial