You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2013/01/22 02:57:59 UTC
[20/52] [partial] support for 2.4.0rc1. "vendored" the platform libs
in. added Gord and Braden as contributors. removed dependency on unzip and
axed the old download-cordova code.
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/JSON4JStringReader.java
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/JSON4JStringReader.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/JSON4JStringReader.java
new file mode 100644
index 0000000..5c3583a
--- /dev/null
+++ b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/JSON4JStringReader.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.cordova.json4j.internal;
+
+import java.io.IOException;
+import java.io.Reader;
+
+public class JSON4JStringReader extends Reader {
+
+ private char[] _buf = null;
+ private int _mark = 0;
+ private int maxLength = 0;
+
+ public JSON4JStringReader(String str) {
+ _buf = str.toCharArray();
+ maxLength = str.length();
+ _mark = 0;
+ }
+
+ public void close() throws IOException {
+ return;
+ }
+
+ public int read(char[] cbuf, int off, int len) throws IOException {
+ if (_mark == (maxLength))
+ return -1;
+
+ int read = 0;
+ for (int x=0; x<len; x++) {
+ cbuf[x+off] = _buf[_mark];
+ read++;
+ _mark++;
+ if (_mark == (maxLength))
+ return read;
+ }
+ return read;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/JSON4JStringWriter.java
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/JSON4JStringWriter.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/JSON4JStringWriter.java
new file mode 100644
index 0000000..ce1d2cc
--- /dev/null
+++ b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/JSON4JStringWriter.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.cordova.json4j.internal;
+
+import java.io.IOException;
+import java.io.Writer;
+
+public class JSON4JStringWriter extends Writer {
+
+ public static int BUF_SIZE = 10000;
+
+ private char[] _buffer = null;
+
+ private int _mark = 0;
+
+ public JSON4JStringWriter() {
+ _buffer = new char[BUF_SIZE];
+ _mark = 0;
+ }
+
+ // Resizes an array; doubles up every time.
+ public static char[] resizeArray(char[] expandMe) {
+ int newSize = expandMe.length * 2;
+ char[] newArray = new char[newSize];
+ System.arraycopy(expandMe, 0, newArray, 0, expandMe.length);
+ return newArray;
+ }
+
+
+ public void close() throws IOException {
+ return;
+ }
+
+ public void flush() throws IOException {
+ return;
+ }
+
+ public void write(char[] cbuf, int off, int len) throws IOException {
+ if (((len - off) + _mark) >= _buffer.length) {
+ // Resize the array first.
+ _buffer = JSON4JStringWriter.resizeArray(_buffer);
+ }
+ for (int x=0; x < len; x++) {
+ _buffer[_mark] = cbuf[off+x];
+ _mark++;
+ }
+ }
+
+ public String toString() {
+ return new String(_buffer, 0, _mark);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/NumberUtil.java
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/NumberUtil.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/NumberUtil.java
new file mode 100644
index 0000000..d63d4db
--- /dev/null
+++ b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/NumberUtil.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.cordova.json4j.internal;
+
+public class NumberUtil {
+
+ public static boolean isNumber(Class clazz) {
+ if ( (clazz == Integer.class) || (clazz == Long.class) || (clazz == Double.class) || (clazz == Short.class) || (clazz == Float.class)) {
+ return true;
+ }
+ return false;
+ }
+
+ public static double getDouble(Object val) {
+ if (val instanceof Double) {
+ return ((Double)val).doubleValue();
+ }
+ else if (val instanceof Long) {
+ return ((Long)val).doubleValue();
+ }
+ else if (val instanceof Short) {
+ Integer i = new Integer( ((Short)val).shortValue() );
+ return i.doubleValue();
+ }
+ else if (val instanceof Float) {
+ return ((Float)val).doubleValue();
+ }
+ else if (val instanceof Integer) {
+ return ((Integer)val).doubleValue();
+ }
+ throw new IllegalArgumentException("Not a number");
+ }
+
+ public static short getShort(Object val) {
+ if (val instanceof Double) {
+ return ((Double)val).shortValue();
+ }
+ else if (val instanceof Long) {
+ Double dg = new Double(((Long)val).longValue());
+ return dg.shortValue();
+ }
+ else if (val instanceof Short) {
+ return ((Short)val).shortValue();
+ }
+ else if (val instanceof Float) {
+ return ((Float)val).shortValue();
+ } else if (val instanceof Integer) {
+ return ((Integer)val).shortValue();
+ }
+ throw new IllegalArgumentException("Not a number");
+ }
+
+ public static int getInt(Object val) {
+ if (val instanceof Double) {
+ return ((Double)val).intValue();
+ }
+ else if (val instanceof Long) {
+ Double dg = new Double(((Long)val).longValue());
+ return dg.intValue();
+ }
+ else if (val instanceof Short) {
+ Double dg = new Double(((Short)val).shortValue());
+ return dg.intValue();
+ }
+ else if (val instanceof Float) {
+ return ((Float)val).intValue();
+ }
+ else if (val instanceof Integer) {
+ return ((Integer)val).intValue();
+ }
+ throw new IllegalArgumentException("Not a number");
+ }
+
+ public static long getLong(Object val) {
+ if (val instanceof Double) {
+ return ((Double)val).longValue();
+ }
+ else if (val instanceof Long) {
+ return ((Long)val).longValue();
+ }
+ else if (val instanceof Short) {
+ Long lg = new Long(((Short)val).shortValue());
+ return lg.longValue();
+ }
+ else if (val instanceof Float) {
+ return ((Float)val).longValue();
+ }
+ else if (val instanceof Integer) {
+ return ((Integer)val).longValue();
+ }
+ throw new IllegalArgumentException("Not a number");
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Parser.java
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Parser.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Parser.java
new file mode 100644
index 0000000..39ddf98
--- /dev/null
+++ b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Parser.java
@@ -0,0 +1,338 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.cordova.json4j.internal;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.apache.cordova.json4j.JSONArray;
+import org.apache.cordova.json4j.JSONException;
+import org.apache.cordova.json4j.JSONObject;
+
+/**
+ * Private parser class which handles doing the parsing of the JSON string into tokens.
+ */
+public class Parser {
+
+ private Tokenizer tokenizer;
+ private Token lastToken;
+
+ /**
+ * Contructor
+ * @param reader The Reader to use when reading in the JSON stream/string.
+ *
+ * @throws JSONException Thrown if an error occurs in tokenizing the JSON string.
+ */
+ public Parser(Reader reader) throws JSONException {
+ super();
+ try {
+ this.tokenizer = new Tokenizer(reader, false);
+ } catch (IOException iox) {
+ JSONException jex = new JSONException("Error occurred during input read.");
+ jex.setCause(iox);
+ throw jex;
+ }
+ }
+
+ /**
+ * Contructor
+ * @param reader The Reader to use when reading in the JSON stream/string.
+ * @param strict Boolean indicating if the parser should parse in strict mode, meaning unqoted strings and comments are not allowed.
+ *
+ * @throws JSONException Thrown if an error occurs in tokenizing the JSON string.
+ */
+ public Parser(Reader reader, boolean strict) throws JSONException {
+ super();
+ try {
+ this.tokenizer = new Tokenizer(reader, strict);
+ } catch (IOException iox) {
+ JSONException jex = new JSONException("Error occurred during input read.");
+ jex.setCause(iox);
+ throw jex;
+ }
+ }
+
+ /**
+ * Method to initiate the parse of the toplevel JSON object, which will in turn parse all child JSON objects contained within.
+ * Same as calling parse(false);
+ *
+ * @throws JSONException Thrown if an IO error occurd during parse of the JSON object(s).
+ */
+ public JSONObject parse() throws JSONException {
+ return parse(false, (JSONObject)null);
+ }
+
+ /**
+ * Method to initiate the parse of the toplevel JSON object, which will in turn parse all child JSON objects contained within.
+ * Same as calling parse(false);
+ *
+ * @throws JSONException Thrown if an IO error occurd during parse of the JSON object(s).
+ */
+ public JSONObject parse(JSONObject jObj) throws JSONException {
+ return parse(false, jObj);
+ }
+
+ /**
+ * Method to initiate the parse of the toplevel JSON object, which will in turn parse all child JSON objects contained within.
+ * @param ordered Flag to denote if the parse should contruct a JSON object which maintains serialization order of the attributes.
+ *
+ * @throws JSONException Thrown if an IO error occurd during parse of the JSON object(s).
+ */
+ public JSONObject parse(boolean ordered) throws JSONException {
+ try {
+ lastToken = tokenizer.next();
+ } catch (IOException iox) {
+ JSONException jex = new JSONException("Error occurred during input read.");
+ jex.setCause(iox);
+ throw jex;
+ }
+ return parseObject(ordered, null);
+ }
+
+ /**
+ * Method to initiate the parse of the toplevel JSON object, which will in turn parse all child JSON objects contained within.
+ * @param ordered Flag to denote if the parse should contruct a JSON object which maintains serialization order of the attributes.
+ * @param jObj The JSONObjetc to fill out from the parsing. If null, create a new one.
+ *
+ * @throws JSONException Thrown if an IO error occurd during parse of the JSON object(s).
+ */
+ public JSONObject parse(boolean ordered, JSONObject jObj) throws JSONException {
+ try {
+ lastToken = tokenizer.next();
+ } catch (IOException iox) {
+ JSONException jex = new JSONException("Error occurred during input read.");
+ jex.setCause(iox);
+ throw jex;
+ }
+ return parseObject(ordered, jObj);
+ }
+
+ /**
+ * Method to initiate the parse of the toplevel JSON object, which will in turn parse all child JSON objects contained within.
+ * @param jObj The JSONArray to fill out from the parsing. If null, create a new one.
+ *
+ * @throws JSONException Thrown if an IO error occurd during parse of the JSON object(s).
+ */
+ public JSONArray parse(JSONArray jObj) throws JSONException {
+ return parse(false, jObj);
+ }
+
+ /**
+ * Method to initiate the parse of the toplevel JSON object, which will in turn parse all child JSON objects contained within.
+ * @param ordered Flag to denote if the parse should contruct for all JSON objects encounted, a JSON object which maintains serialization order of the attributes.
+ * @param jObj The JSONArray to fill out from the parsing. If null, create a new one.
+ *
+ * @throws JSONException Thrown if an IO error occurd during parse of the JSON object(s).
+ */
+ public JSONArray parse(boolean ordered, JSONArray jObj) throws JSONException {
+ try {
+ lastToken = tokenizer.next();
+ } catch (IOException iox) {
+ JSONException jex = new JSONException("Error occurred during input read.");
+ jex.setCause(iox);
+ throw jex;
+ }
+ return parseArray(ordered, jObj);
+ }
+
+ /**
+ * Method to parse a JSON object out of the current JSON string position.
+ * @return JSONObject Returns the parsed out JSON object.
+ *
+ * @throws JSONException Thrown if an IO error occurs during parse, such as a malformed JSON object.
+ */
+ public JSONObject parseObject() throws JSONException {
+ return parseObject(false, null);
+ }
+
+ /**
+ * Method to parse a JSON object out of the current JSON string position.
+ * @param ordered Flag to denote if the parse should contruct a JSON object which maintains serialization order of the attributes.
+ * @return JSONObject Returns the parsed out JSON object.
+ *
+ * @throws JSONException Thrown if an IO error occurs during parse, such as a malformed JSON object.
+ */
+ public JSONObject parseObject(boolean ordered, JSONObject rootObject) throws JSONException {
+
+ try {
+ JSONObject result = null;
+ if (rootObject != null) {
+ result = rootObject;
+ } else {
+ if (!ordered) {
+ result = new JSONObject();
+ } else {
+ //MSN NO ORDERED
+ result = new JSONObject();
+ }
+ }
+
+ if (lastToken != Token.TokenBraceL) throw new JSONException("Expecting '{' " + tokenizer.onLineCol() + " instead, obtained token: '" + lastToken + "'");
+ lastToken = tokenizer.next();
+
+ while (true) {
+ if (lastToken == Token.TokenEOF) throw new JSONException("Unterminated object " + tokenizer.onLineCol());
+
+ if (lastToken == Token.TokenBraceR) {
+ lastToken = tokenizer.next();
+ break;
+ }
+
+ if (!lastToken.isString()) throw new JSONException("Expecting string key " + tokenizer.onLineCol());
+ String key = lastToken.getString();
+
+ lastToken = tokenizer.next();
+ if (lastToken != Token.TokenColon) throw new JSONException("Expecting colon " + tokenizer.onLineCol());
+
+ lastToken = tokenizer.next();
+ Object val = parseValue(ordered);
+
+ result.put(key, val);
+
+ if (lastToken == Token.TokenComma) {
+ lastToken = tokenizer.next();
+ }
+
+ else if (lastToken != Token.TokenBraceR) {
+ throw new JSONException("expecting either ',' or '}' " + tokenizer.onLineCol());
+ }
+ }
+ return result;
+ } catch (IOException iox) {
+ JSONException jex = new JSONException("Error occurred during object input read.");
+ jex.setCause(iox);
+ throw jex;
+ }
+ }
+
+ /**
+ * Method to parse out a JSON array from a JSON string
+ * Same as calling parseArray(false, null)
+ *
+ * @throws JSONException Thrown if a parse error occurs, such as a malformed JSON array.
+ */
+ public JSONArray parseArray() throws JSONException {
+ return parseArray(false, null);
+ }
+
+ /**
+ * Method to parse out a JSON array from a JSON string
+ * @param ordered Flag to denote if the parse should contruct JSON objects which maintain serialization order of the attributes for all JSONOjects in the array.
+ * *param array An array instance to populate instead of creating a new one.
+ *
+ * @throws JSONException Thrown if a parse error occurs, such as a malformed JSON array.
+ */
+ public JSONArray parseArray(boolean ordered, JSONArray array) throws JSONException {
+ JSONArray result = null;
+ if(array != null){
+ result = array;
+ } else {
+ result = new JSONArray();
+ }
+
+ try {
+ if (lastToken != Token.TokenBrackL) throw new JSONException("Expecting '[' " + tokenizer.onLineCol());
+ lastToken = tokenizer.next();
+ while (true) {
+ if (lastToken == Token.TokenEOF) throw new JSONException("Unterminated array " + tokenizer.onLineCol());
+
+ /**
+ * End of the array.
+ */
+ if (lastToken == Token.TokenBrackR) {
+ lastToken = tokenizer.next();
+ break;
+ }
+
+ Object val = parseValue(ordered);
+ result.add(val);
+
+ if (lastToken == Token.TokenComma) {
+ lastToken = tokenizer.next();
+ } else if (lastToken != Token.TokenBrackR) {
+ throw new JSONException("expecting either ',' or ']' " + tokenizer.onLineCol());
+ }
+ }
+ } catch (IOException iox) {
+ JSONException jex = new JSONException("Error occurred during array input read.");
+ jex.setCause(iox);
+ throw jex;
+ }
+ return result;
+ }
+
+ /**
+ * Method to parse the current JSON property value from the last token.
+ * @return The java object type that represents the JSON value.
+ *
+ * @throws JSONException Thrown if an IO error (read incomplete token) occurs.
+ */
+ public Object parseValue() throws JSONException {
+ return parseValue(false);
+ }
+
+ /**
+ * Method to parse the current JSON property value from the last token.
+ * @return The java object type that represents the JSON value.
+ * @param ordered Flag to denote if the parse should contruct JSON objects and arrays which maintain serialization order of the attributes.
+ *
+ * @throws JSONException Thrown if an IO error (read incomplete token) occurs.
+ */
+ public Object parseValue(boolean ordered) throws JSONException {
+ if (lastToken == Token.TokenEOF) throw new JSONException("Expecting property value " + tokenizer.onLineCol());
+
+ try {
+ if (lastToken.isNumber()) {
+ Object result = lastToken.getNumber();
+ lastToken = tokenizer.next();
+ return result;
+ }
+
+ if (lastToken.isString()) {
+ Object result = lastToken.getString();
+ lastToken = tokenizer.next();
+ return result;
+ }
+
+ if (lastToken == Token.TokenFalse) {
+ lastToken = tokenizer.next();
+ return Boolean.FALSE;
+ }
+
+ if (lastToken == Token.TokenTrue) {
+ lastToken = tokenizer.next();
+ return Boolean.TRUE;
+ }
+
+ if (lastToken == Token.TokenNull) {
+ lastToken = tokenizer.next();
+ return JSONObject.NULL;
+ }
+
+ if (lastToken == Token.TokenBrackL) return parseArray(ordered, null);
+ if (lastToken == Token.TokenBraceL) return parseObject(ordered, null);
+
+ } catch (IOException iox) {
+ JSONException jex = new JSONException("Error occurred during value input read.");
+ jex.setCause(iox);
+ throw jex;
+ }
+ throw new JSONException("Invalid token " + tokenizer.onLineCol());
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Serializer.java
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Serializer.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Serializer.java
new file mode 100644
index 0000000..50f34d3
--- /dev/null
+++ b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Serializer.java
@@ -0,0 +1,353 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.cordova.json4j.internal;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.apache.cordova.json4j.JSONArray;
+import org.apache.cordova.json4j.JSONObject;
+import org.apache.cordova.json4j.JSONString;
+
+/**
+ * Class to handle serialization of a JSON object to a JSON string.
+ */
+public class Serializer {
+
+ /**
+ * The writer to use when writing this JSON object.
+ */
+ private Writer writer;
+
+ /**
+ * Create a serializer on the specified output stream writer.
+ */
+ public Serializer(Writer writer) {
+ super();
+ this.writer = writer;
+ }
+
+ /**
+ * Method to flush the current writer.
+ * @throws IOException Thrown if an error occurs during writer flush.
+ */
+ public void flush() throws IOException {
+ writer.flush();
+ }
+
+ /**
+ * Method to close the current writer.
+ * @throws IOException Thrown if an error occurs during writer close.
+ */
+ public void close() throws IOException {
+ writer.close();
+ }
+
+ /**
+ * Method to write a raw string to the writer.
+ * @param s The String to write.
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public Serializer writeRawString(String s) throws IOException {
+ writer.write(s);
+ return this;
+ }
+
+ /**
+ * Method to write the text string 'null' to the output stream (null JSON object).
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public Serializer writeNull() throws IOException {
+ writeRawString("null");
+ return this;
+ }
+
+ /**
+ * Method to write a number to the current writer.
+ * @param value The number to write to the JSON output string.
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public Serializer writeNumber(Object value) throws IOException {
+ if (null == value) return writeNull();
+
+ if (value instanceof Float) {
+ if (((Float)value).isNaN()) return writeNull();
+ if (Float.NEGATIVE_INFINITY == ((Float)value).floatValue()) return writeNull();
+ if (Float.POSITIVE_INFINITY == ((Float)value).floatValue()) return writeNull();
+ }
+
+ if (value instanceof Double) {
+ if (((Double)value).isNaN()) return writeNull();
+ if (Double.NEGATIVE_INFINITY == ((Double)value).doubleValue()) return writeNull();
+ if (Double.POSITIVE_INFINITY == ((Double)value).doubleValue()) return writeNull();
+ }
+
+ writeRawString(value.toString());
+
+ return this;
+ }
+
+ /**
+ * Method to write a boolean value to the output stream.
+ * @param value The Boolean object to write out as a JSON boolean.
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public Serializer writeBoolean(Boolean value) throws IOException {
+ if (null == value) return writeNull();
+
+ writeRawString(value.toString());
+
+ return this;
+ }
+
+ /**
+ * Method to generate a string with a particular width. Alignment is done using zeroes if it does not meet the width requirements.
+ * @param s The string to write
+ * @param len The minimum length it should be, and to align with zeroes if length is smaller.
+ * @return A string properly aligned/correct width.
+ */
+ private static String rightAlignedZero(String s, int len) {
+ if (len == s.length()) return s;
+
+ StringBuffer sb = new StringBuffer(s);
+
+ while (sb.length() < len) {
+ sb.insert(0, '0');
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Method to write a String out to the writer, encoding special characters and unicode characters properly.
+ * @param value The string to write out.
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public Serializer writeString(String value) throws IOException {
+ if (null == value) return writeNull();
+
+ writer.write('"');
+
+ char[] chars = value.toCharArray();
+
+ for (int i=0; i<chars.length; i++) {
+ char c = chars[i];
+ switch (c) {
+ case '"': writer.write("\\\""); break;
+ case '\\': writer.write("\\\\"); break;
+ case 0: writer.write("\\0"); break;
+ case '\b': writer.write("\\b"); break;
+ case '\t': writer.write("\\t"); break;
+ case '\n': writer.write("\\n"); break;
+ case '\f': writer.write("\\f"); break;
+ case '\r': writer.write("\\r"); break;
+ case '/': writer.write("\\/"); break;
+ default:
+ if ((c >= 32) && (c <= 126)) {
+ writer.write(c);
+ } else {
+ writer.write("\\u");
+ writer.write(rightAlignedZero(Integer.toHexString(c),4));
+ }
+ }
+ }
+
+ writer.write('"');
+
+ return this;
+ }
+
+ /**
+ * Method to write out a generic JSON type.
+ * @param object The JSON compatible object to serialize.
+ * @throws IOException Thrown if an error occurs during write, or if a nonJSON compatible Java object is passed..
+ */
+ private Serializer write(Object object) throws IOException {
+ if (null == object) return writeNull();
+
+ // Serialize the various types!
+ Class clazz = object.getClass();
+ if (NumberUtil.isNumber(clazz)) return writeNumber(object);
+ if (Boolean.class.isAssignableFrom(clazz)) return writeBoolean((Boolean) object);
+ if (JSONObject.class.isAssignableFrom(clazz)) return writeObject((JSONObject) object);
+ if (JSONArray.class.isAssignableFrom(clazz)) return writeArray((JSONArray) object);
+ if (JSONString.class.isAssignableFrom(clazz)) return writeRawString(((JSONString) object).toJSONString());
+ if (String.class.isAssignableFrom(clazz)) return writeString((String) object);
+
+ throw new IOException("Attempting to serialize unserializable object: '" + object + "'");
+ }
+
+ /**
+ * Method to write a complete JSON object to the stream.
+ * @param object The JSON object to write out.
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public Serializer writeObject(JSONObject object) throws IOException {
+ if (null == object) return writeNull();
+
+ // write header
+ writeRawString("{");
+ indentPush();
+
+ Enumeration iter = getPropertyNames(object);
+
+ while ( iter.hasMoreElements() ) {
+ Object key = iter.nextElement();
+ if (!(key instanceof String)) throw new IOException("attempting to serialize object with an invalid property name: '" + key + "'" );
+
+ Object value = object.get(key);
+ if (!JSONObject.isValidObject(value)) throw new IOException("attempting to serialize object with an invalid property value: '" + value + "'");
+
+ newLine();
+ indent();
+ writeString((String)key);
+ writeRawString(":");
+ space();
+ write(value);
+
+ if (iter.hasMoreElements()) writeRawString(",");
+ }
+
+ // write trailer
+ indentPop();
+ newLine();
+ indent();
+ writeRawString("}");
+
+ return this;
+ }
+
+ /**
+ * Method to write a JSON array out to the stream.
+ * @param value The JSON array to write out.
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public Serializer writeArray(JSONArray value) throws IOException {
+ if (null == value) return writeNull();
+
+ // write header
+ writeRawString("[");
+ indentPush();
+
+ for (Enumeration iter=value.elements(); iter.hasMoreElements(); ) {
+ Object element = iter.nextElement();
+ if (!JSONObject.isValidObject(element)) throw new IOException("attempting to serialize array with an invalid element: '" + value + "'");
+
+ newLine();
+ indent();
+ write(element);
+
+ if (iter.hasMoreElements()) writeRawString(",");
+ }
+
+ // write trailer
+ indentPop();
+ newLine();
+ indent();
+ writeRawString("]");
+
+ return this;
+ }
+
+ //---------------------------------------------------------------
+ // pretty printing overridables
+ //---------------------------------------------------------------
+
+ /**
+ * Method to write a space to the output writer.
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public void space() throws IOException {
+ }
+
+ /**
+ * Method to write a newline to the output writer.
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public void newLine() throws IOException {
+ }
+
+ /**
+ * Method to write an indent to the output writer.
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public void indent() throws IOException {
+ }
+
+ /**
+ * Method to increase the indent depth of the output writer.
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public void indentPush() {
+ }
+
+ /**
+ * Method to reduce the indent depth of the output writer.
+ */
+ public void indentPop() {
+ }
+
+ /**
+ * Method to get a list of all the property names stored in a map.
+ */
+ public Enumeration getPropertyNames(Hashtable map) {
+ return map.keys();
+ }
+
+ /**
+ * Method to write a String out to the writer, encoding special characters and unicode characters properly.
+ * @param value The string to write out.
+ */
+ public static String quote(String value) {
+ if (value == null || value.length() == 0) {
+ return "\"\"";
+ }
+
+ StringBuffer buf = new StringBuffer();
+ char[] chars = value.toCharArray();
+
+ buf.append('"');
+ for (int i=0; i<chars.length; i++) {
+ char c = chars[i];
+ switch (c) {
+ case '"': buf.append("\\\""); break;
+ case '\\': buf.append("\\\\"); break;
+ case 0: buf.append("\\0"); break;
+ case '\b': buf.append("\\b"); break;
+ case '\t': buf.append("\\t"); break;
+ case '\n': buf.append("\\n"); break;
+ case '\f': buf.append("\\f"); break;
+ case '\r': buf.append("\\r"); break;
+ case '/': buf.append("\\/"); break;
+ default:
+ if ((c >= 32) && (c <= 126)) {
+ buf.append(c);
+ } else {
+ buf.append("\\u");
+ buf.append(rightAlignedZero(Integer.toHexString(c),4));
+ }
+ }
+ }
+ buf.append('"');
+
+ return buf.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/SerializerVerbose.java
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/SerializerVerbose.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/SerializerVerbose.java
new file mode 100644
index 0000000..5132591
--- /dev/null
+++ b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/SerializerVerbose.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.cordova.json4j.internal;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * Internaql class for handling the serialization of JSON objects in a verbose
+ * format, meaning newlines and indention.
+ */
+public class SerializerVerbose extends Serializer {
+
+ /**
+ * Internal tracker keeping indent position.
+ */
+ private int indent = 0;
+
+ /**
+ * The indent string to use when serializing.
+ */
+ private String indentStr = "\t";
+
+ /**
+ * Constructor.
+ */
+ public SerializerVerbose(Writer writer) {
+ super(writer);
+ }
+
+ /**
+ * Constructor.
+ * @param Writer The writer to serialize JSON to.
+ * @param indentSpaces: How many spaces to indent by (0 to 8).
+ * The default indent is the TAB character.
+ */
+ public SerializerVerbose(Writer writer, int indentSpaces) {
+ super(writer);
+ if(indentSpaces > 0 && indentSpaces < 8){
+ this.indentStr = "";
+ for(int i = 0; i < indentSpaces; i++){
+ this.indentStr += " ";
+ }
+ }
+ }
+
+ /**
+ * Method to write a space to the output writer.
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public void space() throws IOException {
+ writeRawString(" ");
+ }
+
+ /**
+ * Method to write a newline to the output writer.
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public void newLine() throws IOException {
+ writeRawString("\n");
+ }
+
+ /**
+ * Method to write an indent to the output writer.
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public void indent() throws IOException {
+ for (int i=0; i<indent; i++) writeRawString(this.indentStr);
+ }
+
+ /**
+ * Method to increase the indent depth of the output writer.
+ * @throws IOException Thrown if an error occurs during write.
+ */
+ public void indentPush() {
+ indent++;
+ }
+
+ /**
+ * Method to reduce the indent depth of the output writer.
+ */
+ public void indentPop() {
+ indent--;
+ if (indent < 0) throw new IllegalStateException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Token.java
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Token.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Token.java
new file mode 100644
index 0000000..1c635e9
--- /dev/null
+++ b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Token.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.cordova.json4j.internal;
+
+/**
+ * Class representing a JSON token.
+ */
+public class Token {
+
+ static final public Token TokenEOF = new Token();
+ static final public Token TokenBraceL = new Token();
+ static final public Token TokenBraceR = new Token();
+ static final public Token TokenBrackL = new Token();
+ static final public Token TokenBrackR = new Token();
+ static final public Token TokenColon = new Token();
+ static final public Token TokenComma = new Token();
+ static final public Token TokenTrue = new Token();
+ static final public Token TokenFalse = new Token();
+ static final public Token TokenNull = new Token();
+
+ private String valueString;
+ private Object valueNumber;
+ private boolean isConstant;
+
+ /**
+ * Constructor
+ */
+ public Token() {
+ super();
+ }
+
+ /**
+ * Constructor
+ * @param value The value of the token as a string
+ */
+ public Token(String value) {
+ super();
+ valueString = value;
+ }
+
+ /**
+ * Constructor
+ * @param value The value of the token as a number
+ */
+ public Token(Object value) {
+ super();
+
+ valueNumber = value;
+ }
+
+ /**
+ * Method to obtain the string value of this token
+ */
+ public String getString() {
+ return valueString;
+ }
+
+ /**
+ * Method to obtain the number value of this token
+ */
+ public Object getNumber() {
+ return valueNumber;
+ }
+
+ /**
+ * Method to indicate if this token is string based or not.
+ */
+ public boolean isString() {
+ return (null != valueString) && !isConstant;
+ }
+
+ /**
+ * Method to indicate if this token is number based or not.
+ */
+ public boolean isNumber() {
+ return null != valueNumber;
+ }
+
+ /**
+ * Method to convert the token to a string representation.
+ */
+ public String toString() {
+ if (this == TokenEOF) return "Token: EOF";
+ if (this == TokenBraceL) return "Token: {";
+ if (this == TokenBraceR) return "Token: }";
+ if (this == TokenBrackL) return "Token: [";
+ if (this == TokenBrackR) return "Token: ]";
+ if (this == TokenColon) return "Token: :";
+ if (this == TokenComma) return "Token: ,";
+ if (this == TokenTrue) return "Token: true";
+ if (this == TokenFalse) return "Token: false";
+ if (this == TokenNull) return "Token: null";
+
+ if (this.isNumber()) return "Token: Number - " + getNumber();
+ if (this.isString()) return "Token: String - '" + getString() + "'";
+
+ return "Token: unknown.";
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Tokenizer.java
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Tokenizer.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Tokenizer.java
new file mode 100644
index 0000000..652106e
--- /dev/null
+++ b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/json4j/internal/Tokenizer.java
@@ -0,0 +1,619 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.cordova.json4j.internal;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * Tokenizes a stream into JSON tokens.
+ */
+public class Tokenizer {
+
+ /**
+ * The reader from which the JSON string is being read.
+ */
+ private Reader reader;
+
+ /**
+ * The current line position in the JSON string.
+ */
+ private int lineNo;
+
+ /**
+ * The current column position in the JSON string.
+ */
+ private int colNo;
+
+ /**
+ * The last character read from the JSON string.
+ */
+ private int lastChar;
+
+ /**
+ * Whether or not the parser should be spec strict, or allow unquoted strings and comments
+ */
+ private boolean strict = false;
+
+ /**
+ * Constructor.
+ * @param reader The reader from which the JSON string is read. Same as Tokenizer(reader, false);
+ *
+ * @throws IOException Thrown on IOErrors such as invalid JSON or sudden reader closures.
+ */
+ public Tokenizer(Reader reader) throws IOException {
+ super();
+
+// Class readerClass= reader.getClass();
+ //In-memory readers don't need to be buffered. Also, skip PushbackReaders
+ //because they probably already wrap a buffered stream. And lastly, anything
+ //that extends from a BufferedReader also doesn't need buffering!
+// if (!StringReader.class.isAssignableFrom(readerClass) &&
+// !CharArrayReader.class.isAssignableFrom(readerClass) &&
+// !PushbackReader.class.isAssignableFrom(readerClass) &&
+// !BufferedReader.class.isAssignableFrom(readerClass)) {
+// reader = new BufferedReader(reader);
+// }
+ this.reader = reader;
+ this.lineNo = 0;
+ this.colNo = 0;
+ this.lastChar = '\n';
+ readChar();
+ }
+
+ /**
+ * Constructor.
+ * @param reader The reader from which the JSON string is read.
+ * @param strict Whether or not the parser should be spec strict, or allow unquoted strings and comments.
+ *
+ * @throws IOException Thrown on IOErrors such as invalid JSON or sudden reader closures.
+ */
+ public Tokenizer(Reader reader, boolean strict) throws IOException {
+ super();
+
+// Class readerClass= reader.getClass();
+ //In-memory readers don't need to be buffered. Also, skip PushbackReaders
+ //because they probably already wrap a buffered stream. And lastly, anything
+ //that extends from a BufferedReader also doesn't need buffering!
+// if (!StringReader.class.isAssignableFrom(readerClass) &&
+// !CharArrayReader.class.isAssignableFrom(readerClass) &&
+// !PushbackReader.class.isAssignableFrom(readerClass) &&
+// !BufferedReader.class.isAssignableFrom(readerClass)) {
+// reader = new BufferedReader(reader);
+// }
+ this.reader = reader;
+ this.lineNo = 0;
+ this.colNo = 0;
+ this.lastChar = '\n';
+ this.strict = strict;
+
+ readChar();
+ }
+
+ /**
+ * Method to get the next JSON token from the JSON String
+ * @return The next token in the stream, returning Token.TokenEOF when finished.
+ *
+ * @throws IOException Thrown if unexpected read error occurs or invalid character encountered in JSON string.
+ */
+ public Token next() throws IOException {
+
+ // skip whitespace, use our own checker, it seems
+ // a bit faster than Java's default.
+ //while (Character.isWhitespace((char)lastChar)) {
+ while (isWhitespace((char)lastChar)) {
+ readChar();
+ }
+
+ // handle punctuation
+ switch (lastChar) {
+ case -1: readChar(); return Token.TokenEOF;
+ case '{': readChar(); return Token.TokenBraceL;
+ case '}': readChar(); return Token.TokenBraceR;
+ case '[': readChar(); return Token.TokenBrackL;
+ case ']': readChar(); return Token.TokenBrackR;
+ case ':': readChar(); return Token.TokenColon;
+ case ',': readChar(); return Token.TokenComma;
+
+ case '"':
+ case '\'':
+ String stringValue = readString();
+ return new Token(stringValue);
+
+ case '-':
+ case '.':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ Object numberValue = readNumber();
+ return new Token(numberValue);
+
+ case 'n':
+ case 't':
+ case 'f':
+ String ident = readIdentifier();
+
+ if (ident.equals("null")) return Token.TokenNull;
+ if (ident.equals("true")) return Token.TokenTrue;
+ if (ident.equals("false")) return Token.TokenFalse;
+
+ // Okay, this was some sort of unquoted string, may be okay
+ if (!this.strict) {
+ //Unquoted string. Non-strict mode allows this. It's still bad input
+ //from a spec perspective, but allowable in non-strict mode.
+ return new Token(ident);
+ } else {
+ throw new IOException("Unexpected unquoted string literal: [" + ident + "]. Unquoted strings are not allowed in strict mode");
+ }
+ case '/':
+ if (!this.strict) {
+ // Comment mode and not strict. Lets just devour the comment.
+ readComment();
+ return next();
+ } else {
+ throw new IOException("Unexpected character / encountered " + onLineCol() + ". Comments are not allowed in strict mode");
+ }
+
+ default:
+ if (!this.strict && isValidUnquotedChar((char)lastChar)) {
+ // Unquoted string. Bad form, but ... okay, lets accept it.
+ // some other parsers do.
+ String unquotedStr = readIdentifier();
+ return new Token(unquotedStr);
+ } else {
+ if (this.strict) {
+ throw new IOException("Unexpected character '" + (char)lastChar + "' " + onLineCol() + ". Unquoted strings are not allowed in strict mode.");
+ } else {
+ throw new IOException("Unexpected character '" + (char)lastChar + "' " + onLineCol());
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Method to read out comments in the 'JSON'. JSON normally should not
+ * have comments, but I guess we need to be more permissive to make some Crockford code
+ * happy.
+ */
+ private void readComment() throws IOException {
+ readChar();
+ if ((char)lastChar == '/') {
+ // Okay, // comment,so just read to \n or end of line
+ while ((char)lastChar != '\n' && lastChar != -1) {
+ readChar();
+ }
+ } else if ((char)lastChar == '*') {
+ // /* comment, so read past it.
+ char[] chars = new char[2];
+ readChar();
+ if (lastChar != -1) {
+ chars[0] = (char)lastChar;
+ } else {
+ return;
+ }
+ readChar();
+ if (lastChar != -1) {
+ chars[1] = (char)lastChar;
+ } else {
+ return;
+ }
+
+ while (chars[0] != '*' || chars[1] != '/') {
+ readChar();
+ if (lastChar != -1) {
+ chars[0] = chars[1];
+ chars[1] = (char)lastChar;
+
+ } else {
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * Method to read a string from the JSON string, converting escapes accordingly.
+ * @return The parsed JSON string with all escapes properly converyed.
+ *
+ * @throws IOException Thrown on unterminated strings, invalid characters, bad escapes, and so on. Basically, invalid JSON.
+ */
+ private String readString() throws IOException {
+ StringBuffer sb = new StringBuffer();
+ int delim = lastChar;
+ int l = lineNo;
+ int c = colNo;
+
+ readChar();
+ while ((-1 != lastChar) && (delim != lastChar)) {
+ StringBuffer digitBuffer;
+
+ if (lastChar != '\\') {
+ sb.append((char)lastChar);
+ readChar();
+ continue;
+ }
+
+ readChar();
+
+ switch (lastChar) {
+ case 'b': readChar(); sb.append('\b'); continue;
+ case 'f': readChar(); sb.append('\f'); continue;
+ case 'n': readChar(); sb.append('\n'); continue;
+ case 'r': readChar(); sb.append('\r'); continue;
+ case 't': readChar(); sb.append('\t'); continue;
+ case '\'': readChar(); sb.append('\''); continue;
+ case '"': readChar(); sb.append('"'); continue;
+ case '\\': readChar(); sb.append('\\'); continue;
+ case '/': readChar(); sb.append('/'); continue;
+
+ // hex constant
+ // unicode constant
+ case 'x':
+ case 'u':
+ digitBuffer = new StringBuffer();
+
+ int toRead = 2;
+ if (lastChar == 'u') toRead = 4;
+
+ for (int i=0; i<toRead; i++) {
+ readChar();
+ if (!isHexDigit(lastChar)) throw new IOException("non-hex digit " + onLineCol());
+ digitBuffer.append((char) lastChar);
+ }
+ readChar();
+
+ try {
+ int digitValue = Integer.parseInt(digitBuffer.toString(), 16);
+ sb.append((char) digitValue);
+ } catch (NumberFormatException e) {
+ throw new IOException("non-hex digit " + onLineCol());
+ }
+
+ break;
+
+ // octal constant
+ default:
+ if (!isOctalDigit(lastChar)) throw new IOException("non-hex digit " + onLineCol());
+
+ digitBuffer = new StringBuffer();
+ digitBuffer.append((char) lastChar);
+
+ for (int i=0; i<2; i++) {
+ readChar();
+ if (!isOctalDigit(lastChar)) break;
+
+ digitBuffer.append((char) lastChar);
+ }
+
+ try {
+ int digitValue = Integer.parseInt(digitBuffer.toString(), 8);
+ sb.append((char) digitValue);
+ } catch (NumberFormatException e) {
+ throw new IOException("non-hex digit " + onLineCol());
+ }
+ }
+ }
+
+ if (-1 == lastChar) {
+ throw new IOException("String not terminated " + onLineCol(l,c));
+ }
+
+ readChar();
+
+ return sb.toString();
+ }
+
+ /**
+ * Method to read a number from the JSON string.
+ *
+ * (-)(1-9)(0-9)* : decimal
+ * (-)0(0-7)* : octal
+ * (-)0(x|X)(0-9|a-f|A-F)* : hex
+ * [digits][.digits][(E|e)[(+|-)]digits]
+ *
+ * @returns The number as the wrapper Java Number type.
+ *
+ * @throws IOException Thrown in invalid numbers or unexpected end of JSON string
+ * */
+ private Object readNumber() throws IOException {
+ StringBuffer sb = new StringBuffer();
+ int l = lineNo;
+ int c = colNo;
+
+ boolean isHex = false;
+
+ if (lastChar == '-') {
+ sb.append((char)lastChar);
+ readChar();
+ }
+ if (lastChar == '0') {
+ sb.append((char)lastChar);
+ readChar();
+ if (lastChar == 'x' || lastChar == 'X') {
+ sb.append((char)lastChar);
+ readChar();
+ isHex = true;
+ }
+ }
+
+ if (isHex) {
+ while (isDigitChar(lastChar) || isHexDigit(lastChar)) {
+ sb.append((char)lastChar);
+ readChar();
+ }
+ }
+ else {
+ while (isDigitChar(lastChar)) {
+ sb.append((char)lastChar);
+ readChar();
+ }
+ }
+
+ // convert it!
+ String string = sb.toString();
+
+ try {
+ if (-1 != string.indexOf('.')) {
+ return Double.valueOf(string);
+ }
+
+ String sign = "";
+ if (string.startsWith("-")) {
+ sign = "-";
+ string = string.substring(1);
+ }
+
+// if (isHex) {
+// Long value = Long.valueOf(sign + string.substring(2),16);
+// if (value.longValue() <= Integer.MAX_VALUE && (value.longValue() >= Integer.MIN_VALUE)) {
+// return new Integer(value.intValue());
+// }
+// else {
+// return value;
+// }
+// }
+
+ if (string.equals("0")) {
+ return new Integer(0);
+// } else if (string.startsWith("0") && string.length() > 1) {
+// Long value = Long.valueOf(sign + string.substring(1),8);
+// if (value.longValue() <= Integer.MAX_VALUE && (value.longValue() >= Integer.MIN_VALUE)) {
+// return new Integer(value.intValue());
+// }
+// else {
+// return value;
+// }
+ }
+
+ /**
+ * We have to check for the exponential and treat appropriately
+ * Exponentials should be treated as Doubles.
+ */
+ if (string.indexOf("e") != -1 || string.indexOf("E") != -1) {
+ return Double.valueOf(sign + string);
+ } else {
+ Long value = new Long(Long.parseLong(sign+ string, 10));
+ //Long value = Long.valueOf(sign + string);
+ if (value.longValue() <= Integer.MAX_VALUE && (value.longValue() >= Integer.MIN_VALUE)) {
+ return new Integer(Integer.parseInt(sign + string, 10));
+ }
+ else {
+ return value;
+ }
+ }
+ // else return new Integer(0); //MSN
+ } catch (NumberFormatException e) {
+ IOException iox = new IOException("Invalid number literal " + onLineCol(l,c));
+ //MSNiox.setCause(e);
+ throw iox;
+ }
+ }
+
+ /**
+ * Method to indicate if the character read is a HEX digit or not.
+ * @param c The character to check for being a HEX digit.
+ */
+ private boolean isHexDigit(int c) {
+ switch (c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Method to indicate if the character read is an OCTAL digit or not.
+ * @param c The character to check for being a OCTAL digit.
+ */
+ private boolean isOctalDigit(int c) {
+ switch (c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Method to indicate if the character read is a digit or not.
+ * @param c The character to check for being a digit.
+ */
+ private boolean isDigitChar(int c) {
+ switch (c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '.':
+ case 'e':
+ case 'E':
+ case 'x':
+ case 'X':
+ case '+':
+ case '-':
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Method to read a partular character string.
+ * only really need to handle 'null', 'true', and 'false'
+ */
+ private String readIdentifier() throws IOException {
+ StringBuffer sb = new StringBuffer();
+
+ if (this.strict) {
+ while ((-1 != lastChar) && ( (Character.isUpperCase((char)lastChar)) || (Character.isLowerCase((char)lastChar)) ) ){
+ sb.append((char)lastChar);
+ readChar();
+ }
+ }
+ else {
+ while ((-1 != lastChar) && isValidUnquotedChar((char)lastChar)) {
+ sb.append((char)lastChar);
+ readChar();
+ }
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Method to read the next character from the string, keeping track of line/column position.
+ *
+ * @throws IOEXception Thrown when underlying reader throws an error.
+ */
+ private void readChar() throws IOException {
+ if ('\n' == lastChar) {
+ this.colNo = 0;
+ this.lineNo++;
+ }
+ lastChar = reader.read();
+ if (-1 == lastChar) return ;
+ colNo++;
+ }
+
+ /**
+ * Method to generate a String indicationg the current line and column position in the JSON string.
+ */
+ private String onLineCol(int line, int col) {
+ return "on line " + line + ", column " + col;
+ }
+
+ /**
+ * Method to generate a String indicationg the current line and column position in the JSON string.
+ */
+ public String onLineCol() {
+ return onLineCol(lineNo,colNo);
+ }
+
+ /**
+ * High speed test for whitespace! Faster than the java one (from some testing).
+ * @return if the indicated character is whitespace.
+ */
+ public boolean isWhitespace(char c) {
+ switch (c) {
+ case 9: //'unicode: 0009
+ case 10: //'unicode: 000A'
+ case 11: //'unicode: 000B'
+ case 12: //'unicode: 000C'
+ case 13: //'unicode: 000D'
+ case 28: //'unicode: 001C'
+ case 29: //'unicode: 001D'
+ case 30: //'unicode: 001E'
+ case 31: //'unicode: 001F'
+ case ' ': // Space
+ //case Character.SPACE_SEPARATOR:
+ //case Character.LINE_SEPARATOR:
+ //MSN case Character.PARAGRAPH_SEPARATOR:
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * For non strict mode, check if char is valid when not quoted.
+ * @param c
+ * @return if character is valid unquoted character.
+ */
+ public boolean isValidUnquotedChar(char c) {
+
+ if ( (Character.isDigit(c)) || (Character.isLowerCase(c)) || (Character.isUpperCase(c)) ) {
+ return true;
+ }
+
+ switch (c) {
+ case '@':
+ case '-':
+ case '.':
+ case '$':
+ case '+':
+ case '!':
+ case '_':
+ return true;
+ }
+ return false;
+ }
+
+}