summaryrefslogtreecommitdiffstats
path: root/mobile/android/thirdparty/org/json/simple/parser/JSONParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/thirdparty/org/json/simple/parser/JSONParser.java')
-rw-r--r--mobile/android/thirdparty/org/json/simple/parser/JSONParser.java533
1 files changed, 533 insertions, 0 deletions
diff --git a/mobile/android/thirdparty/org/json/simple/parser/JSONParser.java b/mobile/android/thirdparty/org/json/simple/parser/JSONParser.java
new file mode 100644
index 000000000..9acaa377f
--- /dev/null
+++ b/mobile/android/thirdparty/org/json/simple/parser/JSONParser.java
@@ -0,0 +1,533 @@
+/*
+ * $Id: JSONParser.java,v 1.1 2006/04/15 14:10:48 platform Exp $
+ * Created on 2006-4-15
+ */
+package org.json.simple.parser;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+
+
+/**
+ * Parser for JSON text. Please note that JSONParser is NOT thread-safe.
+ *
+ * @author FangYidong<fangyidong@yahoo.com.cn>
+ */
+public class JSONParser {
+ public static final int S_INIT=0;
+ public static final int S_IN_FINISHED_VALUE=1;//string,number,boolean,null,object,array
+ public static final int S_IN_OBJECT=2;
+ public static final int S_IN_ARRAY=3;
+ public static final int S_PASSED_PAIR_KEY=4;
+ public static final int S_IN_PAIR_VALUE=5;
+ public static final int S_END=6;
+ public static final int S_IN_ERROR=-1;
+
+ private LinkedList handlerStatusStack;
+ private Yylex lexer = new Yylex((Reader)null);
+ private Yytoken token = null;
+ private int status = S_INIT;
+
+ private int peekStatus(LinkedList statusStack){
+ if(statusStack.size()==0)
+ return -1;
+ Integer status=(Integer)statusStack.getFirst();
+ return status.intValue();
+ }
+
+ /**
+ * Reset the parser to the initial state without resetting the underlying reader.
+ *
+ */
+ public void reset(){
+ token = null;
+ status = S_INIT;
+ handlerStatusStack = null;
+ }
+
+ /**
+ * Reset the parser to the initial state with a new character reader.
+ *
+ * @param in - The new character reader.
+ * @throws IOException
+ * @throws ParseException
+ */
+ public void reset(Reader in){
+ lexer.yyreset(in);
+ reset();
+ }
+
+ /**
+ * @return The position of the beginning of the current token.
+ */
+ public int getPosition(){
+ return lexer.getPosition();
+ }
+
+ public Object parse(String s) throws ParseException{
+ return parse(s, (ContainerFactory)null);
+ }
+
+ public Object parse(String s, ContainerFactory containerFactory) throws ParseException{
+ StringReader in=new StringReader(s);
+ try{
+ return parse(in, containerFactory);
+ }
+ catch(IOException ie){
+ /*
+ * Actually it will never happen.
+ */
+ throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, ie);
+ }
+ }
+
+ public Object parse(Reader in) throws IOException, ParseException{
+ return parse(in, (ContainerFactory)null);
+ }
+
+ /**
+ * Parse JSON text into java object from the input source.
+ *
+ * @param in
+ * @param containerFactory - Use this factory to createyour own JSON object and JSON array containers.
+ * @return Instance of the following:
+ * org.json.simple.JSONObject,
+ * org.json.simple.JSONArray,
+ * java.lang.String,
+ * java.lang.Number,
+ * java.lang.Boolean,
+ * null
+ *
+ * @throws IOException
+ * @throws ParseException
+ */
+ public Object parse(Reader in, ContainerFactory containerFactory) throws IOException, ParseException{
+ reset(in);
+ LinkedList statusStack = new LinkedList();
+ LinkedList valueStack = new LinkedList();
+
+ try{
+ do{
+ nextToken();
+ switch(status){
+ case S_INIT:
+ switch(token.type){
+ case Yytoken.TYPE_VALUE:
+ status=S_IN_FINISHED_VALUE;
+ statusStack.addFirst(new Integer(status));
+ valueStack.addFirst(token.value);
+ break;
+ case Yytoken.TYPE_LEFT_BRACE:
+ status=S_IN_OBJECT;
+ statusStack.addFirst(new Integer(status));
+ valueStack.addFirst(createObjectContainer(containerFactory));
+ break;
+ case Yytoken.TYPE_LEFT_SQUARE:
+ status=S_IN_ARRAY;
+ statusStack.addFirst(new Integer(status));
+ valueStack.addFirst(createArrayContainer(containerFactory));
+ break;
+ default:
+ status=S_IN_ERROR;
+ }//inner switch
+ break;
+
+ case S_IN_FINISHED_VALUE:
+ if(token.type==Yytoken.TYPE_EOF)
+ return valueStack.removeFirst();
+ else
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+
+ case S_IN_OBJECT:
+ switch(token.type){
+ case Yytoken.TYPE_COMMA:
+ break;
+ case Yytoken.TYPE_VALUE:
+ if(token.value instanceof String){
+ String key=(String)token.value;
+ valueStack.addFirst(key);
+ status=S_PASSED_PAIR_KEY;
+ statusStack.addFirst(new Integer(status));
+ }
+ else{
+ status=S_IN_ERROR;
+ }
+ break;
+ case Yytoken.TYPE_RIGHT_BRACE:
+ if(valueStack.size()>1){
+ statusStack.removeFirst();
+ valueStack.removeFirst();
+ status=peekStatus(statusStack);
+ }
+ else{
+ status=S_IN_FINISHED_VALUE;
+ }
+ break;
+ default:
+ status=S_IN_ERROR;
+ break;
+ }//inner switch
+ break;
+
+ case S_PASSED_PAIR_KEY:
+ switch(token.type){
+ case Yytoken.TYPE_COLON:
+ break;
+ case Yytoken.TYPE_VALUE:
+ statusStack.removeFirst();
+ String key=(String)valueStack.removeFirst();
+ Map parent=(Map)valueStack.getFirst();
+ parent.put(key,token.value);
+ status=peekStatus(statusStack);
+ break;
+ case Yytoken.TYPE_LEFT_SQUARE:
+ statusStack.removeFirst();
+ key=(String)valueStack.removeFirst();
+ parent=(Map)valueStack.getFirst();
+ List newArray=createArrayContainer(containerFactory);
+ parent.put(key,newArray);
+ status=S_IN_ARRAY;
+ statusStack.addFirst(new Integer(status));
+ valueStack.addFirst(newArray);
+ break;
+ case Yytoken.TYPE_LEFT_BRACE:
+ statusStack.removeFirst();
+ key=(String)valueStack.removeFirst();
+ parent=(Map)valueStack.getFirst();
+ Map newObject=createObjectContainer(containerFactory);
+ parent.put(key,newObject);
+ status=S_IN_OBJECT;
+ statusStack.addFirst(new Integer(status));
+ valueStack.addFirst(newObject);
+ break;
+ default:
+ status=S_IN_ERROR;
+ }
+ break;
+
+ case S_IN_ARRAY:
+ switch(token.type){
+ case Yytoken.TYPE_COMMA:
+ break;
+ case Yytoken.TYPE_VALUE:
+ List val=(List)valueStack.getFirst();
+ val.add(token.value);
+ break;
+ case Yytoken.TYPE_RIGHT_SQUARE:
+ if(valueStack.size()>1){
+ statusStack.removeFirst();
+ valueStack.removeFirst();
+ status=peekStatus(statusStack);
+ }
+ else{
+ status=S_IN_FINISHED_VALUE;
+ }
+ break;
+ case Yytoken.TYPE_LEFT_BRACE:
+ val=(List)valueStack.getFirst();
+ Map newObject=createObjectContainer(containerFactory);
+ val.add(newObject);
+ status=S_IN_OBJECT;
+ statusStack.addFirst(new Integer(status));
+ valueStack.addFirst(newObject);
+ break;
+ case Yytoken.TYPE_LEFT_SQUARE:
+ val=(List)valueStack.getFirst();
+ List newArray=createArrayContainer(containerFactory);
+ val.add(newArray);
+ status=S_IN_ARRAY;
+ statusStack.addFirst(new Integer(status));
+ valueStack.addFirst(newArray);
+ break;
+ default:
+ status=S_IN_ERROR;
+ }//inner switch
+ break;
+ case S_IN_ERROR:
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+ }//switch
+ if(status==S_IN_ERROR){
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+ }
+ }while(token.type!=Yytoken.TYPE_EOF);
+ }
+ catch(IOException ie){
+ throw ie;
+ }
+
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+ }
+
+ private void nextToken() throws ParseException, IOException{
+ token = lexer.yylex();
+ if(token == null)
+ token = new Yytoken(Yytoken.TYPE_EOF, null);
+ }
+
+ private Map createObjectContainer(ContainerFactory containerFactory){
+ if(containerFactory == null)
+ return new JSONObject();
+ Map m = containerFactory.createObjectContainer();
+
+ if(m == null)
+ return new JSONObject();
+ return m;
+ }
+
+ private List createArrayContainer(ContainerFactory containerFactory){
+ if(containerFactory == null)
+ return new JSONArray();
+ List l = containerFactory.creatArrayContainer();
+
+ if(l == null)
+ return new JSONArray();
+ return l;
+ }
+
+ public void parse(String s, ContentHandler contentHandler) throws ParseException{
+ parse(s, contentHandler, false);
+ }
+
+ public void parse(String s, ContentHandler contentHandler, boolean isResume) throws ParseException{
+ StringReader in=new StringReader(s);
+ try{
+ parse(in, contentHandler, isResume);
+ }
+ catch(IOException ie){
+ /*
+ * Actually it will never happen.
+ */
+ throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, ie);
+ }
+ }
+
+ public void parse(Reader in, ContentHandler contentHandler) throws IOException, ParseException{
+ parse(in, contentHandler, false);
+ }
+
+ /**
+ * Stream processing of JSON text.
+ *
+ * @see ContentHandler
+ *
+ * @param in
+ * @param contentHandler
+ * @param isResume - Indicates if it continues previous parsing operation.
+ * If set to true, resume parsing the old stream, and parameter 'in' will be ignored.
+ * If this method is called for the first time in this instance, isResume will be ignored.
+ *
+ * @throws IOException
+ * @throws ParseException
+ */
+ public void parse(Reader in, ContentHandler contentHandler, boolean isResume) throws IOException, ParseException{
+ if(!isResume){
+ reset(in);
+ handlerStatusStack = new LinkedList();
+ }
+ else{
+ if(handlerStatusStack == null){
+ isResume = false;
+ reset(in);
+ handlerStatusStack = new LinkedList();
+ }
+ }
+
+ LinkedList statusStack = handlerStatusStack;
+
+ try{
+ do{
+ switch(status){
+ case S_INIT:
+ contentHandler.startJSON();
+ nextToken();
+ switch(token.type){
+ case Yytoken.TYPE_VALUE:
+ status=S_IN_FINISHED_VALUE;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.primitive(token.value))
+ return;
+ break;
+ case Yytoken.TYPE_LEFT_BRACE:
+ status=S_IN_OBJECT;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.startObject())
+ return;
+ break;
+ case Yytoken.TYPE_LEFT_SQUARE:
+ status=S_IN_ARRAY;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.startArray())
+ return;
+ break;
+ default:
+ status=S_IN_ERROR;
+ }//inner switch
+ break;
+
+ case S_IN_FINISHED_VALUE:
+ nextToken();
+ if(token.type==Yytoken.TYPE_EOF){
+ contentHandler.endJSON();
+ status = S_END;
+ return;
+ }
+ else{
+ status = S_IN_ERROR;
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+ }
+
+ case S_IN_OBJECT:
+ nextToken();
+ switch(token.type){
+ case Yytoken.TYPE_COMMA:
+ break;
+ case Yytoken.TYPE_VALUE:
+ if(token.value instanceof String){
+ String key=(String)token.value;
+ status=S_PASSED_PAIR_KEY;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.startObjectEntry(key))
+ return;
+ }
+ else{
+ status=S_IN_ERROR;
+ }
+ break;
+ case Yytoken.TYPE_RIGHT_BRACE:
+ if(statusStack.size()>1){
+ statusStack.removeFirst();
+ status=peekStatus(statusStack);
+ }
+ else{
+ status=S_IN_FINISHED_VALUE;
+ }
+ if(!contentHandler.endObject())
+ return;
+ break;
+ default:
+ status=S_IN_ERROR;
+ break;
+ }//inner switch
+ break;
+
+ case S_PASSED_PAIR_KEY:
+ nextToken();
+ switch(token.type){
+ case Yytoken.TYPE_COLON:
+ break;
+ case Yytoken.TYPE_VALUE:
+ statusStack.removeFirst();
+ status=peekStatus(statusStack);
+ if(!contentHandler.primitive(token.value))
+ return;
+ if(!contentHandler.endObjectEntry())
+ return;
+ break;
+ case Yytoken.TYPE_LEFT_SQUARE:
+ statusStack.removeFirst();
+ statusStack.addFirst(new Integer(S_IN_PAIR_VALUE));
+ status=S_IN_ARRAY;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.startArray())
+ return;
+ break;
+ case Yytoken.TYPE_LEFT_BRACE:
+ statusStack.removeFirst();
+ statusStack.addFirst(new Integer(S_IN_PAIR_VALUE));
+ status=S_IN_OBJECT;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.startObject())
+ return;
+ break;
+ default:
+ status=S_IN_ERROR;
+ }
+ break;
+
+ case S_IN_PAIR_VALUE:
+ /*
+ * S_IN_PAIR_VALUE is just a marker to indicate the end of an object entry, it doesn't proccess any token,
+ * therefore delay consuming token until next round.
+ */
+ statusStack.removeFirst();
+ status = peekStatus(statusStack);
+ if(!contentHandler.endObjectEntry())
+ return;
+ break;
+
+ case S_IN_ARRAY:
+ nextToken();
+ switch(token.type){
+ case Yytoken.TYPE_COMMA:
+ break;
+ case Yytoken.TYPE_VALUE:
+ if(!contentHandler.primitive(token.value))
+ return;
+ break;
+ case Yytoken.TYPE_RIGHT_SQUARE:
+ if(statusStack.size()>1){
+ statusStack.removeFirst();
+ status=peekStatus(statusStack);
+ }
+ else{
+ status=S_IN_FINISHED_VALUE;
+ }
+ if(!contentHandler.endArray())
+ return;
+ break;
+ case Yytoken.TYPE_LEFT_BRACE:
+ status=S_IN_OBJECT;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.startObject())
+ return;
+ break;
+ case Yytoken.TYPE_LEFT_SQUARE:
+ status=S_IN_ARRAY;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.startArray())
+ return;
+ break;
+ default:
+ status=S_IN_ERROR;
+ }//inner switch
+ break;
+
+ case S_END:
+ return;
+
+ case S_IN_ERROR:
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+ }//switch
+ if(status==S_IN_ERROR){
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+ }
+ }while(token.type!=Yytoken.TYPE_EOF);
+ }
+ catch(IOException ie){
+ status = S_IN_ERROR;
+ throw ie;
+ }
+ catch(ParseException pe){
+ status = S_IN_ERROR;
+ throw pe;
+ }
+ catch(RuntimeException re){
+ status = S_IN_ERROR;
+ throw re;
+ }
+ catch(Error e){
+ status = S_IN_ERROR;
+ throw e;
+ }
+
+ status = S_IN_ERROR;
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+ }
+}