commit d65cf1822b908124a29d0b37e11a9f64a7627dfb Author: fangyidong Date: Tue Nov 25 13:25:49 2008 +0000 init diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..bddcb9d --- /dev/null +++ b/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..6715d34 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + json.simple + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/AUTHORS.txt b/AUTHORS.txt new file mode 100644 index 0000000..f5ff495 --- /dev/null +++ b/AUTHORS.txt @@ -0,0 +1 @@ +Fang Yidong \ No newline at end of file diff --git a/ChangeLog.txt b/ChangeLog.txt new file mode 100644 index 0000000..1030c68 --- /dev/null +++ b/ChangeLog.txt @@ -0,0 +1,11 @@ +ChangeLog + +Version 1.01 (2008/08/26) +* License changed to a more commerce friendly and clear one, Apache License 2.0 +* Use JFlex to generate a faster Yylex.java +* Added Rope.java to get faster string operations +* Separate test codes from source codes +* Added ant build file build.xml + +Version 1.0 (2006/04/15) +* Initial version diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..ec4d4ca --- /dev/null +++ b/README.txt @@ -0,0 +1,153 @@ +Simple Java toolkit for JSON (JSON.simple) +========================================== + +http://www.JSON.org/java/json_simple.zip + +1.Why the Simple Java toolkit (also named as JSON.simple) for JSON? + + When I use JSON as the data exchange format between the AJAX client and JSP + for the first time, what worry me mostly is how to encode Java strings and + numbers correctly in the server side so the AJAX client will receive a well + formed JSON data. When I looked into the 'JSON in Java' directory in JSON + website,I found that wrappers to JSONObject and JSONArray can be simpler, + due to the simplicity of JSON itself. So I wrote the JSON.simple package. + +2.Is it simple,really? + + I think so. Take an example: + + import org.json.simple.JSONObject; + + JSONObject obj=new JSONObject(); + obj.put("name","foo"); + obj.put("num",new Integer(100)); + obj.put("balance",new Double(1000.21)); + obj.put("is_vip",new Boolean(true)); + obj.put("nickname",null); + System.out.print(obj); + + Result: + {"nickname":null,"num":100,"balance":1000.21,"is_vip":true,"name":"foo"} + + The JSONObject.toString() will escape controls and specials correctly. + +3.How to use JSON.simple in JSP? + + Take an example in JSP: + + <%@page contentType="text/html; charset=UTF-8"%> + <%@page import="org.json.simple.JSONObject"%> + <% + JSONObject obj=new JSONObject(); + obj.put("name","foo"); + obj.put("num",new Integer(100)); + obj.put("balance",new Double(1000.21)); + obj.put("is_vip",new Boolean(true)); + obj.put("nickname",null); + out.print(obj); + out.flush(); + %> + + So the AJAX client will get the responseText. + +4.Some details about JSONObject? + + JSONObject inherits java.util.HashMap,so it don't have to worry about the + mapping things between keys and values. Feel free to use the Map methods + like get(), put(), and remove() and others. JSONObject.toString() will + combine key value pairs to get the JSON data string. Values will be escaped + into JSON quote string format if it's an instance of java.lang.String. Other + type of instance like java.lang.Number,java.lang.Boolean,null,JSONObject and + JSONArray will NOT escape, just take their java.lang.String.valueOf() result. + null value will be the JSON 'null' in the result. + + It's still correct if you put an instance of JSONObject or JSONArray into an + instance of JSONObject or JSONArray. Take the example about: + + JSONObject obj2=new JSONObject(); + obj2.put("phone","123456"); + obj2.put("zip","7890"); + obj.put("contact",obj2); + System.out.print(obj); + + Result: + {"nickname":null,"num":100,"contact":{"phone":"123456","zip":"7890"},"balance":1000.21,"is_vip":true,"name":"foo"} + + The method JSONObject.escape() is used to escape Java string into JSON quote + string. Controls and specials will be escaped correctly into \b,\f,\r,\n,\t, + \",\\,\/,\uhhhh. + +5.Some detail about JSONArray? + + org.json.simple.JSONArray inherits java.util.ArrayList. Feel free to use the + List methods like get(),add(),remove(),iterator() and so on. The rules of + JSONArray.toString() is similar to JSONObject.toString(). Here's the example: + + import org.json.simple.JSONArray; + + JSONArray array=new JSONArray(); + array.add("hello"); + array.add(new Integer(123)); + array.add(new Boolean(false)); + array.add(null); + array.add(new Double(123.45)); + array.add(obj2);//see above + System.out.print(array); + + Result: + ["hello",123,false,null,123.45,{"phone":"123456","zip":"7890"}] + +6.What is JSONValue for? + + org.json.simple.JSONValue is use to parse JSON data into Java Object. + In JSON, the topmost entity is JSON value, not the JSON object. But + it's not necessary to wrap JSON string,boolean,number and null again, + for the Java has already had the according classes: java.lang.String, + java.lang.Boolean,java.lang.Number and null. The mapping is: + + JSON Java + ------------------------------------------------ + string <=> java.lang.String + number <=> java.lang.Number + true|false <=> java.lang.Boolean + null <=> null + array <=> org.json.simple.JSONArray + object <=> org.json.simple.JSONObject + ------------------------------------------------ + + JSONValue has only one kind of method, JSONValue.parse(), which receives + a java.io.Reader or java.lang.String. Return type of JSONValue.parse() + is according to the mapping above. If the input is incorrect in syntax or + there's exceptions during the parsing, I choose to return null, ignoring + the exception: I have no idea if it's a serious implementaion, but I think + it's convenient to the user. + + Here's the example: + + String s="[0,{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}]"; + Object obj=JSONValue.parse(s); + JSONArray array=(JSONArray)obj; + System.out.println(array.get(1)); + JSONObject obj2=(JSONObject)array.get(1); + System.out.println(obj2.get("1")); + + Result: + {"1":{"2":{"3":{"4":[5,{"6":7}]}}}} + {"2":{"3":{"4":[5,{"6":7}]}}} + +7.About the author. + + I'm a Java EE developer on Linux. + I'm working on web systems and information retrieval systems. + I also develop 3D games and Flash games. + + You can contact me through: + Fang Yidong + Fang Yidong + +8.Project home. + + http://code.google.com/p/json-simple/ + + +http://www.JSON.org/java/json_simple.zip \ No newline at end of file diff --git a/VERSION.txt b/VERSION.txt new file mode 100644 index 0000000..7f20734 --- /dev/null +++ b/VERSION.txt @@ -0,0 +1 @@ +1.0.1 \ No newline at end of file diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..b7acbc7 --- /dev/null +++ b/build.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/json.lex b/doc/json.lex new file mode 100644 index 0000000..ec5f05c --- /dev/null +++ b/doc/json.lex @@ -0,0 +1,47 @@ +package org.json.simple.parser; + +import org.json.simple.rope.Rope; + +%% + +%{ +private Rope sb=new Rope(); + +%} + +%switch +%unicode +%state STRING_BEGIN + +HEX_D = [a-fA-F0-9] +INT = [-]?[0-9]+ +DOUBLE = {INT}((\.[0-9]+)?([eE][-+]?[0-9]+)?) +WS = [ \t\r\n] +%% + + \\\" {sb.append('"');} + \\\\ {sb.append('\\');} + \\\/ {sb.append('/');} + \\b {sb.append('\b');} + \\f {sb.append('\f');} + \\n {sb.append('\n');} + \\r {sb.append('\r');} + \\t {sb.append('\t');} + \\u{HEX_D}{HEX_D}{HEX_D}{HEX_D} { int ch=Integer.parseInt(yytext().substring(2),16); + sb.append((char)ch); + } + + \" { yybegin(YYINITIAL);return new Yytoken(Yytoken.TYPE_VALUE,sb.toString());} + . { sb.append(yytext());} + \" { sb.clear();yybegin(STRING_BEGIN);} + {INT} { Long val=Long.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);} + {DOUBLE} { Double val=Double.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);} + "true"|"false" { Boolean val=Boolean.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);} + "null" { return new Yytoken(Yytoken.TYPE_VALUE,null);} + "{" { return new Yytoken(Yytoken.TYPE_LEFT_BRACE,null);} + "}" { return new Yytoken(Yytoken.TYPE_RIGHT_BRACE,null);} + "[" { return new Yytoken(Yytoken.TYPE_LEFT_SQUARE,null);} + "]" { return new Yytoken(Yytoken.TYPE_RIGHT_SQUARE,null);} + "," { return new Yytoken(Yytoken.TYPE_COMMA,null);} + ":" { return new Yytoken(Yytoken.TYPE_COLON,null);} + {WS} {} diff --git a/lib/json_simple-1.0.1.jar b/lib/json_simple-1.0.1.jar new file mode 100644 index 0000000..e856c14 Binary files /dev/null and b/lib/json_simple-1.0.1.jar differ diff --git a/src/org/json/simple/ItemList.java b/src/org/json/simple/ItemList.java new file mode 100644 index 0000000..07231e6 --- /dev/null +++ b/src/org/json/simple/ItemList.java @@ -0,0 +1,147 @@ +/* + * $Id: ItemList.java,v 1.1 2006/04/15 14:10:48 platform Exp $ + * Created on 2006-3-24 + */ +package org.json.simple; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +/** + * |a:b:c| => |a|,|b|,|c| + * |:| => ||,|| + * |a:| => |a|,|| + * @author FangYidong + */ +public class ItemList { + private String sp=","; + List items=new ArrayList(); + + + public ItemList(){} + + + public ItemList(String s){ + this.split(s,sp,items); + } + + public ItemList(String s,String sp){ + this.sp=s; + this.split(s,sp,items); + } + + public ItemList(String s,String sp,boolean isMultiToken){ + split(s,sp,items,isMultiToken); + } + + public List getItems(){ + return this.items; + } + + public String[] getArray(){ + return (String[])this.items.toArray(); + } + + public void split(String s,String sp,List append,boolean isMultiToken){ + if(s==null || sp==null) + return; + if(isMultiToken){ + StringTokenizer tokens=new StringTokenizer(s,sp); + while(tokens.hasMoreTokens()){ + append.add(tokens.nextToken().trim()); + } + } + else{ + this.split(s,sp,append); + } + } + + public void split(String s,String sp,List append){ + if(s==null || sp==null) + return; + int pos=0; + int prevPos=0; + do{ + prevPos=pos; + pos=s.indexOf(sp,pos); + if(pos==-1) + break; + append.add(s.substring(prevPos,pos).trim()); + pos+=sp.length(); + }while(pos!=-1); + append.add(s.substring(prevPos).trim()); + } + + public void setSP(String sp){ + this.sp=sp; + } + + public void add(int i,String item){ + if(item==null) + return; + items.add(i,item.trim()); + } + + public void add(String item){ + if(item==null) + return; + items.add(item.trim()); + } + + public void addAll(ItemList list){ + items.addAll(list.items); + } + + public void addAll(String s){ + this.split(s,sp,items); + } + + public void addAll(String s,String sp){ + this.split(s,sp,items); + } + + public void addAll(String s,String sp,boolean isMultiToken){ + this.split(s,sp,items,isMultiToken); + } + + /** + * @param i 0-based + * @return + */ + public String get(int i){ + return (String)items.get(i); + } + + public int size(){ + return items.size(); + } + + public String toString(){ + return toString(sp); + } + + public String toString(String sp){ + StringBuffer sb=new StringBuffer(); + + for(int i=0;i + */ +public class JSONArray extends ArrayList { + public String toString(){ + ItemList list=new ItemList(); + + Iterator iter=iterator(); + + while(iter.hasNext()){ + Object value=iter.next(); + if(value instanceof String){ + list.add("\""+JSONObject.escape((String)value)+"\""); + } + else + list.add(String.valueOf(value)); + } + return "["+list.toString()+"]"; + } + +} diff --git a/src/org/json/simple/JSONObject.java b/src/org/json/simple/JSONObject.java new file mode 100644 index 0000000..387411a --- /dev/null +++ b/src/org/json/simple/JSONObject.java @@ -0,0 +1,100 @@ +/* + * $Id: JSONObject.java,v 1.1 2006/04/15 14:10:48 platform Exp $ + * Created on 2006-4-10 + */ +package org.json.simple; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * @author FangYidong + */ +public class JSONObject extends HashMap{ + + public String toString(){ + ItemList list=new ItemList(); + Iterator iter=entrySet().iterator(); + + while(iter.hasNext()){ + Map.Entry entry=(Map.Entry)iter.next(); + list.add(toString(entry.getKey().toString(),entry.getValue())); + } + return "{"+list.toString()+"}"; + } + + public static String toString(String key,Object value){ + StringBuffer sb=new StringBuffer(); + + sb.append("\""); + sb.append(escape(key)); + sb.append("\":"); + if(value==null){ + sb.append("null"); + return sb.toString(); + } + + if(value instanceof String){ + sb.append("\""); + sb.append(escape((String)value)); + sb.append("\""); + } + else + sb.append(value); + return sb.toString(); + } + + /** + * " => \" , \ => \\ + * @param s + * @return + */ + public static String escape(String s){ + if(s==null) + return null; + StringBuffer sb=new StringBuffer(); + for(int i=0;i='\u0000' && ch<='\u001F'){ + String ss=Integer.toHexString(ch); + sb.append("\\u"); + for(int k=0;k<4-ss.length();k++){ + sb.append('0'); + } + sb.append(ss.toUpperCase()); + } + else{ + sb.append(ch); + } + } + }//for + return sb.toString(); + } +} diff --git a/src/org/json/simple/JSONValue.java b/src/org/json/simple/JSONValue.java new file mode 100644 index 0000000..662a1b9 --- /dev/null +++ b/src/org/json/simple/JSONValue.java @@ -0,0 +1,36 @@ +/* + * $Id: JSONValue.java,v 1.1 2006/04/15 14:37:04 platform Exp $ + * Created on 2006-4-15 + */ +package org.json.simple; + +import java.io.Reader; +import java.io.StringReader; + +import org.json.simple.parser.JSONParser; + + +/** + * @author FangYidong + */ +public class JSONValue { + /** + * parse into java object from input source. + * @param in + * @return instance of : JSONObject,JSONArray,String,Boolean,Long,Double or null + */ + public static Object parse(Reader in){ + try{ + JSONParser parser=new JSONParser(); + return parser.parse(in); + } + catch(Exception e){ + return null; + } + } + + public static Object parse(String s){ + StringReader in=new StringReader(s); + return parse(in); + } +} diff --git a/src/org/json/simple/parser/JSONParser.java b/src/org/json/simple/parser/JSONParser.java new file mode 100644 index 0000000..e58d276 --- /dev/null +++ b/src/org/json/simple/parser/JSONParser.java @@ -0,0 +1,190 @@ +/* + * $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.Reader; +import java.util.LinkedList; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + + +/** + * @author FangYidong + */ +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_ERROR=-1; + + private int peekStatus(LinkedList statusStack){ + if(statusStack.size()==0) + return -1; + Integer status=(Integer)statusStack.getFirst(); + return status.intValue(); + } + + public Object parse(Reader in) throws Exception{ + LinkedList statusStack=new LinkedList(); + LinkedList valueStack=new LinkedList(); + Yylex lexer=new Yylex(in); + Yytoken token=null; + int status=S_INIT; + + try{ + do{ + token=lexer.yylex(); + if(token==null) + token=new Yytoken(Yytoken.TYPE_EOF,null); + 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(new JSONObject()); + break; + case Yytoken.TYPE_LEFT_SQUARE: + status=S_IN_ARRAY; + statusStack.addFirst(new Integer(status)); + valueStack.addFirst(new JSONArray()); + break; + default: + status=S_IN_ERROR; + }//inner switch + break; + + case S_IN_FINISHED_VALUE: + if(token.type==Yytoken.TYPE_EOF) + return valueStack.removeFirst(); + else + return null; + + 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(); + JSONObject parent=(JSONObject)valueStack.getFirst(); + parent.put(key,token.value); + status=peekStatus(statusStack); + break; + case Yytoken.TYPE_LEFT_SQUARE: + statusStack.removeFirst(); + key=(String)valueStack.removeFirst(); + parent=(JSONObject)valueStack.getFirst(); + JSONArray newArray=new JSONArray(); + 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=(JSONObject)valueStack.getFirst(); + JSONObject newObject=new JSONObject(); + 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: + JSONArray val=(JSONArray)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=(JSONArray)valueStack.getFirst(); + JSONObject newObject=new JSONObject(); + val.add(newObject); + status=S_IN_OBJECT; + statusStack.addFirst(new Integer(status)); + valueStack.addFirst(newObject); + break; + case Yytoken.TYPE_LEFT_SQUARE: + val=(JSONArray)valueStack.getFirst(); + JSONArray newArray=new JSONArray(); + 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: + return null; + }//switch + if(status==S_IN_ERROR) + return null; + }while(token.type!=Yytoken.TYPE_EOF); + } + catch(Exception e){ + throw e; + } + return null; + } +} diff --git a/src/org/json/simple/parser/Yylex.java b/src/org/json/simple/parser/Yylex.java new file mode 100644 index 0000000..229670d --- /dev/null +++ b/src/org/json/simple/parser/Yylex.java @@ -0,0 +1,736 @@ +/* The following code was generated by JFlex 1.4.2 on 2008-11-25 */ + +package org.json.simple.parser; + +import org.json.simple.rope.Rope; + +class Yylex { + + /** This character denotes the end of file */ + public static final int YYEOF = -1; + + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** lexical states */ + public static final int YYINITIAL = 0; + public static final int STRING_BEGIN = 2; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\0\1\7\1\21\2\0\1\7\22\0\1\7\1\0\1\11\10\0"+ + "\1\6\1\32\1\2\1\4\1\12\12\3\1\33\6\0\4\1\1\5"+ + "\1\1\24\0\1\30\1\10\1\31\3\0\1\23\1\13\2\1\1\22"+ + "\1\14\5\0\1\24\1\0\1\15\3\0\1\16\1\25\1\17\1\20"+ + "\5\0\1\26\1\0\1\27\uff82\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\3\0\1\1\1\2\1\3\3\0\1\4\1\5\1\6"+ + "\1\7\1\10\1\11\2\12\1\13\5\0\1\14\1\15"+ + "\1\16\1\17\1\20\1\21\1\22\1\23\1\0\1\24"+ + "\1\0\1\24\4\0\1\25\1\26\2\0\1\27"; + + private static int [] zzUnpackAction() { + int [] result = new int[44]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** the input device */ + private java.io.Reader zzReader; + + /** the current state of the DFA */ + private int zzState; + + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; + + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; + + /** the textposition at the last accepting state */ + private int zzMarkedPos; + + /** the current text position in the buffer */ + private int zzCurrentPos; + + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; + + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; + + /** number of newlines encountered up to the start of the matched text */ + private int yyline; + + /** the number of characters up to the start of the matched text */ + private int yychar; + + /** + * the number of characters from the last newline up to the start of the + * matched text + */ + private int yycolumn; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; + + /* user code: */ +private Rope sb=new Rope(); + + + + /** + * Creates a new scanner + * There is also a java.io.InputStream version of this constructor. + * + * @param in the java.io.Reader to read input from. + */ + Yylex(java.io.Reader in) { + this.zzReader = in; + } + + /** + * Creates a new scanner. + * There is also java.io.Reader version of this constructor. + * + * @param in the java.io.Inputstream to read input from. + */ + Yylex(java.io.InputStream in) { + this(new java.io.InputStreamReader(in)); + } + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 90) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; while (--count > 0); + } + return map; + } + + + /** + * Refills the input buffer. + * + * @return false, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + + /* first: make room (if you can) */ + if (zzStartRead > 0) { + System.arraycopy(zzBuffer, zzStartRead, + zzBuffer, 0, + zzEndRead-zzStartRead); + + /* translate stored positions */ + zzEndRead-= zzStartRead; + zzCurrentPos-= zzStartRead; + zzMarkedPos-= zzStartRead; + zzStartRead = 0; + } + + /* is the buffer big enough? */ + if (zzCurrentPos >= zzBuffer.length) { + /* if not: blow it up */ + char newBuffer[] = new char[zzCurrentPos*2]; + System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); + zzBuffer = newBuffer; + } + + /* finally: fill the buffer with new input */ + int numRead = zzReader.read(zzBuffer, zzEndRead, + zzBuffer.length-zzEndRead); + + if (numRead > 0) { + zzEndRead+= numRead; + return false; + } + // unlikely but not impossible: read 0 characters, but not at end of stream + if (numRead == 0) { + int c = zzReader.read(); + if (c == -1) { + return true; + } else { + zzBuffer[zzEndRead++] = (char) c; + return false; + } + } + + // numRead < 0 + return true; + } + + + /** + * Closes the input stream. + */ + public final void yyclose() throws java.io.IOException { + zzAtEOF = true; /* indicate end of file */ + zzEndRead = zzStartRead; /* invalidate buffer */ + + if (zzReader != null) + zzReader.close(); + } + + + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * cannot be reused (internal buffer is discarded and lost). + * Lexical state is set to ZZ_INITIAL. + * + * @param reader the new input stream + */ + public final void yyreset(java.io.Reader reader) { + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + zzEndRead = zzStartRead = 0; + zzCurrentPos = zzMarkedPos = 0; + yyline = yychar = yycolumn = 0; + zzLexicalState = YYINITIAL; + } + + + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } + + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final String yytext() { + return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); + } + + + /** + * Returns the character at position pos from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer[zzStartRead+pos]; + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos-zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); + + zzMarkedPos -= number; + } + + + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public Yytoken yylex() throws java.io.IOException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char [] zzBufferL = zzBuffer; + char [] zzCMapL = ZZ_CMAP; + + + while (true) { + zzMarkedPosL = zzMarkedPos; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) + zzInput = zzBufferL[zzCurrentPosL++]; + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = zzBufferL[zzCurrentPosL++]; + } + } + zzInput = zzCMapL[zzInput]; + + boolean zzIsFinal = false; + boolean zzNoLookAhead = false; + + zzForNext: { switch (zzState) { + case 0: + switch (zzInput) { + case 2: zzState = 2; break zzForNext; + case 3: zzIsFinal = true; zzState = 3; break zzForNext; + case 7: + case 17: zzIsFinal = true; zzNoLookAhead = true; zzState = 4; break zzForNext; + case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 5; break zzForNext; + case 12: zzState = 6; break zzForNext; + case 13: zzState = 7; break zzForNext; + case 15: zzState = 8; break zzForNext; + case 22: zzIsFinal = true; zzNoLookAhead = true; zzState = 9; break zzForNext; + case 23: zzIsFinal = true; zzNoLookAhead = true; zzState = 10; break zzForNext; + case 24: zzIsFinal = true; zzNoLookAhead = true; zzState = 11; break zzForNext; + case 25: zzIsFinal = true; zzNoLookAhead = true; zzState = 12; break zzForNext; + case 26: zzIsFinal = true; zzNoLookAhead = true; zzState = 13; break zzForNext; + case 27: zzIsFinal = true; zzNoLookAhead = true; zzState = 14; break zzForNext; + default: break zzForAction; + } + + case 1: + switch (zzInput) { + case 8: zzIsFinal = true; zzState = 16; break zzForNext; + case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 17; break zzForNext; + case 17: break zzForAction; + default: zzIsFinal = true; zzNoLookAhead = true; zzState = 15; break zzForNext; + } + + case 2: + switch (zzInput) { + case 3: zzIsFinal = true; zzState = 3; break zzForNext; + default: break zzForAction; + } + + case 3: + switch (zzInput) { + case 3: zzIsFinal = true; break zzForNext; + case 4: zzState = 18; break zzForNext; + case 5: + case 18: zzState = 19; break zzForNext; + default: break zzForAction; + } + + case 6: + switch (zzInput) { + case 19: zzState = 20; break zzForNext; + default: break zzForAction; + } + + case 7: + switch (zzInput) { + case 16: zzState = 21; break zzForNext; + default: break zzForAction; + } + + case 8: + switch (zzInput) { + case 14: zzState = 22; break zzForNext; + default: break zzForAction; + } + + case 16: + switch (zzInput) { + case 8: zzIsFinal = true; zzNoLookAhead = true; zzState = 23; break zzForNext; + case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 24; break zzForNext; + case 10: zzIsFinal = true; zzNoLookAhead = true; zzState = 25; break zzForNext; + case 11: zzIsFinal = true; zzNoLookAhead = true; zzState = 26; break zzForNext; + case 12: zzIsFinal = true; zzNoLookAhead = true; zzState = 27; break zzForNext; + case 13: zzIsFinal = true; zzNoLookAhead = true; zzState = 28; break zzForNext; + case 14: zzIsFinal = true; zzNoLookAhead = true; zzState = 29; break zzForNext; + case 15: zzIsFinal = true; zzNoLookAhead = true; zzState = 30; break zzForNext; + case 16: zzState = 31; break zzForNext; + default: break zzForAction; + } + + case 18: + switch (zzInput) { + case 3: zzIsFinal = true; zzState = 32; break zzForNext; + default: break zzForAction; + } + + case 19: + switch (zzInput) { + case 2: + case 6: zzState = 33; break zzForNext; + case 3: zzIsFinal = true; zzState = 34; break zzForNext; + default: break zzForAction; + } + + case 20: + switch (zzInput) { + case 20: zzState = 35; break zzForNext; + default: break zzForAction; + } + + case 21: + switch (zzInput) { + case 20: zzState = 36; break zzForNext; + default: break zzForAction; + } + + case 22: + switch (zzInput) { + case 16: zzState = 37; break zzForNext; + default: break zzForAction; + } + + case 31: + switch (zzInput) { + case 1: + case 3: + case 5: + case 11: + case 12: + case 18: + case 19: zzState = 38; break zzForNext; + default: break zzForAction; + } + + case 32: + switch (zzInput) { + case 5: + case 18: zzState = 19; break zzForNext; + case 3: zzIsFinal = true; break zzForNext; + default: break zzForAction; + } + + case 33: + switch (zzInput) { + case 3: zzIsFinal = true; zzState = 34; break zzForNext; + default: break zzForAction; + } + + case 34: + switch (zzInput) { + case 3: zzIsFinal = true; break zzForNext; + default: break zzForAction; + } + + case 35: + switch (zzInput) { + case 21: zzState = 37; break zzForNext; + default: break zzForAction; + } + + case 36: + switch (zzInput) { + case 20: zzIsFinal = true; zzNoLookAhead = true; zzState = 39; break zzForNext; + default: break zzForAction; + } + + case 37: + switch (zzInput) { + case 18: zzIsFinal = true; zzNoLookAhead = true; zzState = 40; break zzForNext; + default: break zzForAction; + } + + case 38: + switch (zzInput) { + case 1: + case 3: + case 5: + case 11: + case 12: + case 18: + case 19: zzState = 41; break zzForNext; + default: break zzForAction; + } + + case 41: + switch (zzInput) { + case 1: + case 3: + case 5: + case 11: + case 12: + case 18: + case 19: zzState = 42; break zzForNext; + default: break zzForAction; + } + + case 42: + switch (zzInput) { + case 1: + case 3: + case 5: + case 11: + case 12: + case 18: + case 19: zzIsFinal = true; zzNoLookAhead = true; zzState = 43; break zzForNext; + default: break zzForAction; + } + + default: + // if this is ever reached, there is a serious bug in JFlex + zzScanError(ZZ_UNKNOWN_ERROR); + break; + } } + + if ( zzIsFinal ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( zzNoLookAhead ) break zzForAction; + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 10: + { sb.append(yytext()); + } + case 24: break; + case 3: + { sb.clear();yybegin(STRING_BEGIN); + } + case 25: break; + case 15: + { sb.append('\b'); + } + case 26: break; + case 5: + { return new Yytoken(Yytoken.TYPE_RIGHT_BRACE,null); + } + case 27: break; + case 12: + { sb.append('\\'); + } + case 28: break; + case 20: + { Double val=Double.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val); + } + case 29: break; + case 1: + { Long val=Long.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val); + } + case 30: break; + case 7: + { return new Yytoken(Yytoken.TYPE_RIGHT_SQUARE,null); + } + case 31: break; + case 18: + { sb.append('\r'); + } + case 32: break; + case 21: + { return new Yytoken(Yytoken.TYPE_VALUE,null); + } + case 33: break; + case 14: + { sb.append('/'); + } + case 34: break; + case 9: + { return new Yytoken(Yytoken.TYPE_COLON,null); + } + case 35: break; + case 11: + { yybegin(YYINITIAL);return new Yytoken(Yytoken.TYPE_VALUE,sb.toString()); + } + case 36: break; + case 13: + { sb.append('"'); + } + case 37: break; + case 4: + { return new Yytoken(Yytoken.TYPE_LEFT_BRACE,null); + } + case 38: break; + case 16: + { sb.append('\f'); + } + case 39: break; + case 19: + { sb.append('\t'); + } + case 40: break; + case 6: + { return new Yytoken(Yytoken.TYPE_LEFT_SQUARE,null); + } + case 41: break; + case 23: + { int ch=Integer.parseInt(yytext().substring(2),16); + sb.append((char)ch); + } + case 42: break; + case 22: + { Boolean val=Boolean.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val); + } + case 43: break; + case 17: + { sb.append('\n'); + } + case 44: break; + case 8: + { return new Yytoken(Yytoken.TYPE_COMMA,null); + } + case 45: break; + case 2: + { + } + case 46: break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + return null; + } + else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/src/org/json/simple/parser/Yytoken.java b/src/org/json/simple/parser/Yytoken.java new file mode 100644 index 0000000..46bfe64 --- /dev/null +++ b/src/org/json/simple/parser/Yytoken.java @@ -0,0 +1,31 @@ +/* + * $Id: Yytoken.java,v 1.1 2006/04/15 14:10:48 platform Exp $ + * Created on 2006-4-15 + */ +package org.json.simple.parser; + +/** + * @author FangYidong + */ +public class Yytoken { + public static final int TYPE_VALUE=0;//JSON primitive value: string,number,boolean,null + public static final int TYPE_LEFT_BRACE=1; + public static final int TYPE_RIGHT_BRACE=2; + public static final int TYPE_LEFT_SQUARE=3; + public static final int TYPE_RIGHT_SQUARE=4; + public static final int TYPE_COMMA=5; + public static final int TYPE_COLON=6; + public static final int TYPE_EOF=-1;//end of file + + public int type=0; + public Object value=null; + + public Yytoken(int type,Object value){ + this.type=type; + this.value=value; + } + + public String toString(){ + return String.valueOf(type+"=>|"+value+"|"); + } +} diff --git a/src/org/json/simple/rope/Node.java b/src/org/json/simple/rope/Node.java new file mode 100644 index 0000000..a172ef2 --- /dev/null +++ b/src/org/json/simple/rope/Node.java @@ -0,0 +1,12 @@ +package org.json.simple.rope; + +class Node { + static final int TYPE_STR = 0; + static final int TYPE_CH = 1; + static final int TYPE_UNKNOWN = -1; + + int type = TYPE_UNKNOWN; + Node next; + char content_ch; + String content_str; +} diff --git a/src/org/json/simple/rope/Rope.java b/src/org/json/simple/rope/Rope.java new file mode 100644 index 0000000..8c23496 --- /dev/null +++ b/src/org/json/simple/rope/Rope.java @@ -0,0 +1,68 @@ +package org.json.simple.rope; + +public class Rope { + private Node first; + private Node current; + private int count = 0; + + public void clear(){ + count = 0; + first = null; + current = null; + } + + public int length(){ + return count; + } + + public String toString(){ + if(count == 0) + return ""; + + char[] chs = new char[count]; + int pos = 0; + + Node p = first; + do{ + if(p.type == Node.TYPE_CH){ + chs[pos] = p.content_ch; + pos++; + } + else{ + int len = p.content_str.length(); + p.content_str.getChars(0, len, chs, pos); + pos += len; + } + p = p.next; + }while(p != null); + + return new String(chs); + } + + public void append(char ch){ + Node node = new Node(); + node.type = Node.TYPE_CH; + node.content_ch = ch; + if(first == null) + first = node; + if(current != null) + current.next = node; + current = node; + count++; + } + + public void append(String s){ + if(s == null || s.equals("")) + return; + + Node node = new Node(); + node.type = Node.TYPE_STR; + node.content_str = s; + if(first == null) + first = node; + if(current != null) + current.next = node; + current = node; + count += s.length(); + } +} diff --git a/svn-commit.tmp b/svn-commit.tmp new file mode 100644 index 0000000..8cae831 --- /dev/null +++ b/svn-commit.tmp @@ -0,0 +1 @@ +init diff --git a/test.xml b/test.xml new file mode 100644 index 0000000..2265e9f --- /dev/null +++ b/test.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/org/json/simple/Test.java b/test/org/json/simple/Test.java new file mode 100644 index 0000000..be2ed57 --- /dev/null +++ b/test/org/json/simple/Test.java @@ -0,0 +1,75 @@ +/* + * $Id: Test.java,v 1.1 2006/04/15 14:40:06 platform Exp $ + * Created on 2006-4-15 + */ +package org.json.simple; + +import junit.framework.TestCase; + + +/** + * @author FangYidong + */ +public class Test extends TestCase{ + + public void testDecode() throws Exception{ + System.out.println("=======decode======="); + + String s="[0,{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}]"; + Object obj=JSONValue.parse(s); + JSONArray array=(JSONArray)obj; + System.out.println("======the 2nd element of array======"); + System.out.println(array.get(1)); + System.out.println(); + assertEquals("{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}",array.get(1).toString()); + + JSONObject obj2=(JSONObject)array.get(1); + System.out.println("======field \"1\"=========="); + System.out.println(obj2.get("1")); + assertEquals("{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}",obj2.get("1").toString()); + + s="{}"; + obj=JSONValue.parse(s); + assertEquals("{}",obj.toString()); + + s="[5,]"; + obj=JSONValue.parse(s); + assertEquals("[5]",obj.toString()); + + s="[5,,2]"; + obj=JSONValue.parse(s); + assertEquals("[5,2]",obj.toString()); + } + + public void testEncode() throws Exception{ + System.out.println("=======encode======="); + + JSONArray array1=new JSONArray(); + array1.add("abc\u0010a/"); + array1.add(new Integer(123)); + array1.add(new Double(222.123)); + array1.add(new Boolean(true)); + System.out.println("======array1=========="); + System.out.println(array1); + System.out.println(); + assertEquals("[\"abc\\u0010a\\/\",123,222.123,true]",array1.toString()); + + JSONObject obj1=new JSONObject(); + obj1.put("name","fang"); + obj1.put("age",new Integer(27)); + obj1.put("is_developer",new Boolean(true)); + obj1.put("weight",new Double(60.21)); + obj1.put("array1",array1); + System.out.println("======obj1 with array1==========="); + System.out.println(obj1); + System.out.println(); + assertEquals("{\"array1\":[\"abc\\u0010a\\/\",123,222.123,true],\"weight\":60.21,\"age\":27,\"name\":\"fang\",\"is_developer\":true}",obj1.toString()); + + obj1.remove("array1"); + array1.add(obj1); + System.out.println("======array1 with obj1========"); + System.out.println(array1); + System.out.println(); + assertEquals("[\"abc\\u0010a\\/\",123,222.123,true,{\"weight\":60.21,\"age\":27,\"name\":\"fang\",\"is_developer\":true}]",array1.toString()); + } +} diff --git a/test/org/json/simple/parser/YylexTest.java b/test/org/json/simple/parser/YylexTest.java new file mode 100644 index 0000000..d0eaf40 --- /dev/null +++ b/test/org/json/simple/parser/YylexTest.java @@ -0,0 +1,52 @@ +package org.json.simple.parser; + +import java.io.StringReader; + +import junit.framework.TestCase; + +public class YylexTest extends TestCase { + + public void testYylex() throws Exception{ + String s="\"\\/\""; + System.out.println(s); + StringReader in = new StringReader(s); + Yylex lexer=new Yylex(in); + Yytoken token=lexer.yylex(); + assertEquals(Yytoken.TYPE_VALUE,token.type); + assertEquals("/",token.value); + + s="\"abc\\/\\r\\b\\n\\t\\f\\\\\""; + System.out.println(s); + in = new StringReader(s); + lexer=new Yylex(in); + token=lexer.yylex(); + assertEquals(Yytoken.TYPE_VALUE,token.type); + assertEquals("abc/\r\b\n\t\f\\",token.value); + + s="[\t \n\r\n{ \t \t\n\r}"; + System.out.println(s); + in = new StringReader(s); + lexer=new Yylex(in); + token=lexer.yylex(); + assertEquals(Yytoken.TYPE_LEFT_SQUARE,token.type); + token=lexer.yylex(); + assertEquals(Yytoken.TYPE_LEFT_BRACE,token.type); + token=lexer.yylex(); + assertEquals(Yytoken.TYPE_RIGHT_BRACE,token.type); + + s="\b\f{"; + System.out.println(s); + in = new StringReader(s); + lexer=new Yylex(in); + Error err=null; + try{ + token=lexer.yylex(); + } + catch(Error e){ + err=e; + System.out.println("error:"+err); + } + assertTrue(err!=null); + } + +} diff --git a/test/org/json/simple/rope/RopeTest.java b/test/org/json/simple/rope/RopeTest.java new file mode 100644 index 0000000..da58c3b --- /dev/null +++ b/test/org/json/simple/rope/RopeTest.java @@ -0,0 +1,44 @@ +package org.json.simple.rope; + +import junit.framework.TestCase; + +public class RopeTest extends TestCase { + public void testOpts(){ + Rope rope = new Rope(); + + assertEquals("",rope.toString()); + assertEquals(0,rope.length()); + + rope.append('c'); + assertEquals("c",rope.toString()); + assertEquals(1,rope.length()); + + rope.append("fang"); + assertEquals("cfang",rope.toString()); + assertEquals(5,rope.length()); + + rope.append('1'); + assertEquals("cfang1",rope.toString()); + assertEquals(6,rope.length()); + + rope.append("你好"); + assertEquals("cfang1你好",rope.toString()); + assertEquals(8,rope.length()); + + rope.append('世'); + assertEquals("cfang1你好世",rope.toString()); + assertEquals(9,rope.length()); + + rope.append("界"); + assertEquals("cfang1你好世界",rope.toString()); + assertEquals(10,rope.length()); + + rope.append(""); + assertEquals("cfang1你好世界",rope.toString()); + assertEquals(10,rope.length()); + + rope.clear(); + assertEquals("",rope.toString()); + assertEquals(0,rope.length()); + } +}