diff --git a/core/src/processing/core/PApplet.java b/core/src/processing/core/PApplet.java
index e4a65e169..622758a4f 100644
--- a/core/src/processing/core/PApplet.java
+++ b/core/src/processing/core/PApplet.java
@@ -6082,11 +6082,17 @@ public class PApplet extends Applet
return saveXML(xml, filename, null);
}
+
public boolean saveXML(XML xml, String filename, String options) {
return xml.save(saveFile(filename), options);
}
+ public JSONObject loadJSONObject(String filename) {
+ JSONTokener tokener = new JSONTokener(createReader(filename));
+ return new JSONObject(tokener);
+ }
+
/**
* @webref input:files
diff --git a/core/src/processing/data/JSONArray.java b/core/src/processing/data/JSONArray.java
index 8f9c17ce8..618c7c60a 100644
--- a/core/src/processing/data/JSONArray.java
+++ b/core/src/processing/data/JSONArray.java
@@ -107,7 +107,7 @@ public class JSONArray {
* @param x A JSONTokener
* @throws JSONException If there is a syntax error.
*/
- private JSONArray(JSONTokener x) {
+ protected JSONArray(JSONTokener x) {
this();
if (x.nextClean() != '[') {
throw new RuntimeException("A JSONArray text must start with '['");
diff --git a/core/src/processing/data/JSONObject.java b/core/src/processing/data/JSONObject.java
index 4f9980b08..78c520cf6 100644
--- a/core/src/processing/data/JSONObject.java
+++ b/core/src/processing/data/JSONObject.java
@@ -34,12 +34,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Method;
@@ -48,6 +43,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
/**
* A JSONObject is an unordered collection of name/value pairs. Its external
@@ -220,7 +216,7 @@ public class JSONObject {
* @throws JSONException If there is a syntax error in the source string
* or a duplicated key.
*/
- protected JSONObject(JSONTokener x) {
+ public JSONObject(JSONTokener x) {
this();
char c;
String key;
@@ -312,7 +308,7 @@ public class JSONObject {
* @param bean An object that has getter methods that should be used
* to make a JSONObject.
*/
- protected JSONObject(Object bean) {
+ public JSONObject(Object bean) {
this();
this.populateMap(bean);
}
@@ -746,14 +742,14 @@ public class JSONObject {
}
-// /**
-// * Get a set of keys of the JSONObject.
-// *
-// * @return A keySet.
-// */
-// public Set keySet() {
-// return this.map.keySet();
-// }
+ /**
+ * Get a set of keys of the JSONObject.
+ *
+ * @return A keySet.
+ */
+ public Set keySet() {
+ return this.map.keySet();
+ }
/**
@@ -1715,379 +1711,379 @@ public class JSONObject {
// }
- static class JSONTokener {
- private long character;
- private boolean eof;
- private long index;
- private long line;
- private char previous;
- private Reader reader;
- private boolean usePrevious;
-
-
- /**
- * Construct a JSONTokener from a Reader.
- *
- * @param reader A reader.
- */
- public JSONTokener(Reader reader) {
- this.reader = reader.markSupported()
- ? reader
- : new BufferedReader(reader);
- this.eof = false;
- this.usePrevious = false;
- this.previous = 0;
- this.index = 0;
- this.character = 1;
- this.line = 1;
- }
-
-
- /**
- * Construct a JSONTokener from an InputStream.
- */
- public JSONTokener(InputStream inputStream) {
- this(new InputStreamReader(inputStream));
- }
-
-
- /**
- * Construct a JSONTokener from a string.
- *
- * @param s A source string.
- */
- public JSONTokener(String s) {
- this(new StringReader(s));
- }
-
-
- /**
- * Back up one character. This provides a sort of lookahead capability,
- * so that you can test for a digit or letter before attempting to parse
- * the next number or identifier.
- */
- public void back() {
- if (this.usePrevious || this.index <= 0) {
- throw new RuntimeException("Stepping back two steps is not supported");
- }
- this.index -= 1;
- this.character -= 1;
- this.usePrevious = true;
- this.eof = false;
- }
-
-
- public boolean end() {
- return this.eof && !this.usePrevious;
- }
-
-
- /**
- * Determine if the source string still contains characters that next()
- * can consume.
- * @return true if not yet at the end of the source.
- */
- public boolean more() {
- this.next();
- if (this.end()) {
- return false;
- }
- this.back();
- return true;
- }
-
-
- /**
- * Get the next character in the source string.
- *
- * @return The next character, or 0 if past the end of the source string.
- */
- public char next() {
- int c;
- if (this.usePrevious) {
- this.usePrevious = false;
- c = this.previous;
- } else {
- try {
- c = this.reader.read();
- } catch (IOException exception) {
- throw new RuntimeException(exception);
- }
-
- if (c <= 0) { // End of stream
- this.eof = true;
- c = 0;
- }
- }
- this.index += 1;
- if (this.previous == '\r') {
- this.line += 1;
- this.character = c == '\n' ? 0 : 1;
- } else if (c == '\n') {
- this.line += 1;
- this.character = 0;
- } else {
- this.character += 1;
- }
- this.previous = (char) c;
- return this.previous;
- }
-
-
- /**
- * Consume the next character, and check that it matches a specified
- * character.
- * @param c The character to match.
- * @return The character.
- * @throws JSONException if the character does not match.
- */
- public char next(char c) {
- char n = this.next();
- if (n != c) {
- throw new RuntimeException("Expected '" + c + "' and instead saw '" + n + "'");
- }
- return n;
- }
-
-
- /**
- * Get the next n characters.
- *
- * @param n The number of characters to take.
- * @return A string of n characters.
- * @throws JSONException
- * Substring bounds error if there are not
- * n characters remaining in the source string.
- */
- public String next(int n) {
- if (n == 0) {
- return "";
- }
-
- char[] chars = new char[n];
- int pos = 0;
-
- while (pos < n) {
- chars[pos] = this.next();
- if (this.end()) {
- throw new RuntimeException("Substring bounds error");
- }
- pos += 1;
- }
- return new String(chars);
- }
-
-
- /**
- * Get the next char in the string, skipping whitespace.
- * @throws JSONException
- * @return A character, or 0 if there are no more characters.
- */
- public char nextClean() {
- for (;;) {
- char c = this.next();
- if (c == 0 || c > ' ') {
- return c;
- }
- }
- }
-
-
- /**
- * Return the characters up to the next close quote character.
- * Backslash processing is done. The formal JSON format does not
- * allow strings in single quotes, but an implementation is allowed to
- * accept them.
- * @param quote The quoting character, either
- * " (double quote) or
- * ' (single quote).
- * @return A String.
- * @throws JSONException Unterminated string.
- */
- public String nextString(char quote) {
- char c;
- StringBuffer sb = new StringBuffer();
- for (;;) {
- c = this.next();
- switch (c) {
- case 0:
- case '\n':
- case '\r':
- throw new RuntimeException("Unterminated string");
- case '\\':
- c = this.next();
- switch (c) {
- case 'b':
- sb.append('\b');
- break;
- case 't':
- sb.append('\t');
- break;
- case 'n':
- sb.append('\n');
- break;
- case 'f':
- sb.append('\f');
- break;
- case 'r':
- sb.append('\r');
- break;
- case 'u':
- sb.append((char)Integer.parseInt(this.next(4), 16));
- break;
- case '"':
- case '\'':
- case '\\':
- case '/':
- sb.append(c);
- break;
- default:
- throw new RuntimeException("Illegal escape.");
- }
- break;
- default:
- if (c == quote) {
- return sb.toString();
- }
- sb.append(c);
- }
- }
- }
-
-
- /**
- * Get the text up but not including the specified character or the
- * end of line, whichever comes first.
- * @param delimiter A delimiter character.
- * @return A string.
- */
- public String nextTo(char delimiter) {
- StringBuffer sb = new StringBuffer();
- for (;;) {
- char c = this.next();
- if (c == delimiter || c == 0 || c == '\n' || c == '\r') {
- if (c != 0) {
- this.back();
- }
- return sb.toString().trim();
- }
- sb.append(c);
- }
- }
-
-
- /**
- * Get the text up but not including one of the specified delimiter
- * characters or the end of line, whichever comes first.
- * @param delimiters A set of delimiter characters.
- * @return A string, trimmed.
- */
- public String nextTo(String delimiters) {
- char c;
- StringBuffer sb = new StringBuffer();
- for (;;) {
- c = this.next();
- if (delimiters.indexOf(c) >= 0 || c == 0 ||
- c == '\n' || c == '\r') {
- if (c != 0) {
- this.back();
- }
- return sb.toString().trim();
- }
- sb.append(c);
- }
- }
-
-
- /**
- * Get the next value. The value can be a Boolean, Double, Integer,
- * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
- * @throws JSONException If syntax error.
- *
- * @return An object.
- */
- public Object nextValue() {
- char c = this.nextClean();
- String string;
-
- switch (c) {
- case '"':
- case '\'':
- return this.nextString(c);
- case '{':
- this.back();
- return new JSONObject(this);
- case '[':
- this.back();
- return new JSONArray(this);
- }
-
- /*
- * Handle unquoted text. This could be the values true, false, or
- * null, or it can be a number. An implementation (such as this one)
- * is allowed to also accept non-standard forms.
- *
- * Accumulate characters until we reach the end of the text or a
- * formatting character.
- */
-
- StringBuffer sb = new StringBuffer();
- while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
- sb.append(c);
- c = this.next();
- }
- this.back();
-
- string = sb.toString().trim();
- if ("".equals(string)) {
- throw new RuntimeException("Missing value");
- }
- return JSONObject.stringToValue(string);
- }
-
-
- /**
- * Skip characters until the next character is the requested character.
- * If the requested character is not found, no characters are skipped.
- * @param to A character to skip to.
- * @return The requested character, or zero if the requested character
- * is not found.
- */
- public char skipTo(char to) {
- char c;
- try {
- long startIndex = this.index;
- long startCharacter = this.character;
- long startLine = this.line;
- this.reader.mark(1000000);
- do {
- c = this.next();
- if (c == 0) {
- this.reader.reset();
- this.index = startIndex;
- this.character = startCharacter;
- this.line = startLine;
- return c;
- }
- } while (c != to);
- } catch (IOException exc) {
- throw new RuntimeException(exc);
- }
-
- this.back();
- return c;
- }
-
-
- /**
- * Make a printable string of this JSONTokener.
- *
- * @return " at {index} [character {character} line {line}]"
- */
- @Override
- public String toString() {
- return " at " + this.index + " [character " + this.character + " line " +
- this.line + "]";
- }
- }
+// static class JSONTokener {
+// private long character;
+// private boolean eof;
+// private long index;
+// private long line;
+// private char previous;
+// private Reader reader;
+// private boolean usePrevious;
+//
+//
+// /**
+// * Construct a JSONTokener from a Reader.
+// *
+// * @param reader A reader.
+// */
+// public JSONTokener(Reader reader) {
+// this.reader = reader.markSupported()
+// ? reader
+// : new BufferedReader(reader);
+// this.eof = false;
+// this.usePrevious = false;
+// this.previous = 0;
+// this.index = 0;
+// this.character = 1;
+// this.line = 1;
+// }
+//
+//
+// /**
+// * Construct a JSONTokener from an InputStream.
+// */
+// public JSONTokener(InputStream inputStream) {
+// this(new InputStreamReader(inputStream));
+// }
+//
+//
+// /**
+// * Construct a JSONTokener from a string.
+// *
+// * @param s A source string.
+// */
+// public JSONTokener(String s) {
+// this(new StringReader(s));
+// }
+//
+//
+// /**
+// * Back up one character. This provides a sort of lookahead capability,
+// * so that you can test for a digit or letter before attempting to parse
+// * the next number or identifier.
+// */
+// public void back() {
+// if (this.usePrevious || this.index <= 0) {
+// throw new RuntimeException("Stepping back two steps is not supported");
+// }
+// this.index -= 1;
+// this.character -= 1;
+// this.usePrevious = true;
+// this.eof = false;
+// }
+//
+//
+// public boolean end() {
+// return this.eof && !this.usePrevious;
+// }
+//
+//
+// /**
+// * Determine if the source string still contains characters that next()
+// * can consume.
+// * @return true if not yet at the end of the source.
+// */
+// public boolean more() {
+// this.next();
+// if (this.end()) {
+// return false;
+// }
+// this.back();
+// return true;
+// }
+//
+//
+// /**
+// * Get the next character in the source string.
+// *
+// * @return The next character, or 0 if past the end of the source string.
+// */
+// public char next() {
+// int c;
+// if (this.usePrevious) {
+// this.usePrevious = false;
+// c = this.previous;
+// } else {
+// try {
+// c = this.reader.read();
+// } catch (IOException exception) {
+// throw new RuntimeException(exception);
+// }
+//
+// if (c <= 0) { // End of stream
+// this.eof = true;
+// c = 0;
+// }
+// }
+// this.index += 1;
+// if (this.previous == '\r') {
+// this.line += 1;
+// this.character = c == '\n' ? 0 : 1;
+// } else if (c == '\n') {
+// this.line += 1;
+// this.character = 0;
+// } else {
+// this.character += 1;
+// }
+// this.previous = (char) c;
+// return this.previous;
+// }
+//
+//
+// /**
+// * Consume the next character, and check that it matches a specified
+// * character.
+// * @param c The character to match.
+// * @return The character.
+// * @throws JSONException if the character does not match.
+// */
+// public char next(char c) {
+// char n = this.next();
+// if (n != c) {
+// throw new RuntimeException("Expected '" + c + "' and instead saw '" + n + "'");
+// }
+// return n;
+// }
+//
+//
+// /**
+// * Get the next n characters.
+// *
+// * @param n The number of characters to take.
+// * @return A string of n characters.
+// * @throws JSONException
+// * Substring bounds error if there are not
+// * n characters remaining in the source string.
+// */
+// public String next(int n) {
+// if (n == 0) {
+// return "";
+// }
+//
+// char[] chars = new char[n];
+// int pos = 0;
+//
+// while (pos < n) {
+// chars[pos] = this.next();
+// if (this.end()) {
+// throw new RuntimeException("Substring bounds error");
+// }
+// pos += 1;
+// }
+// return new String(chars);
+// }
+//
+//
+// /**
+// * Get the next char in the string, skipping whitespace.
+// * @throws JSONException
+// * @return A character, or 0 if there are no more characters.
+// */
+// public char nextClean() {
+// for (;;) {
+// char c = this.next();
+// if (c == 0 || c > ' ') {
+// return c;
+// }
+// }
+// }
+//
+//
+// /**
+// * Return the characters up to the next close quote character.
+// * Backslash processing is done. The formal JSON format does not
+// * allow strings in single quotes, but an implementation is allowed to
+// * accept them.
+// * @param quote The quoting character, either
+// * " (double quote) or
+// * ' (single quote).
+// * @return A String.
+// * @throws JSONException Unterminated string.
+// */
+// public String nextString(char quote) {
+// char c;
+// StringBuffer sb = new StringBuffer();
+// for (;;) {
+// c = this.next();
+// switch (c) {
+// case 0:
+// case '\n':
+// case '\r':
+// throw new RuntimeException("Unterminated string");
+// case '\\':
+// c = this.next();
+// switch (c) {
+// case 'b':
+// sb.append('\b');
+// break;
+// case 't':
+// sb.append('\t');
+// break;
+// case 'n':
+// sb.append('\n');
+// break;
+// case 'f':
+// sb.append('\f');
+// break;
+// case 'r':
+// sb.append('\r');
+// break;
+// case 'u':
+// sb.append((char)Integer.parseInt(this.next(4), 16));
+// break;
+// case '"':
+// case '\'':
+// case '\\':
+// case '/':
+// sb.append(c);
+// break;
+// default:
+// throw new RuntimeException("Illegal escape.");
+// }
+// break;
+// default:
+// if (c == quote) {
+// return sb.toString();
+// }
+// sb.append(c);
+// }
+// }
+// }
+//
+//
+// /**
+// * Get the text up but not including the specified character or the
+// * end of line, whichever comes first.
+// * @param delimiter A delimiter character.
+// * @return A string.
+// */
+// public String nextTo(char delimiter) {
+// StringBuffer sb = new StringBuffer();
+// for (;;) {
+// char c = this.next();
+// if (c == delimiter || c == 0 || c == '\n' || c == '\r') {
+// if (c != 0) {
+// this.back();
+// }
+// return sb.toString().trim();
+// }
+// sb.append(c);
+// }
+// }
+//
+//
+// /**
+// * Get the text up but not including one of the specified delimiter
+// * characters or the end of line, whichever comes first.
+// * @param delimiters A set of delimiter characters.
+// * @return A string, trimmed.
+// */
+// public String nextTo(String delimiters) {
+// char c;
+// StringBuffer sb = new StringBuffer();
+// for (;;) {
+// c = this.next();
+// if (delimiters.indexOf(c) >= 0 || c == 0 ||
+// c == '\n' || c == '\r') {
+// if (c != 0) {
+// this.back();
+// }
+// return sb.toString().trim();
+// }
+// sb.append(c);
+// }
+// }
+//
+//
+// /**
+// * Get the next value. The value can be a Boolean, Double, Integer,
+// * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
+// * @throws JSONException If syntax error.
+// *
+// * @return An object.
+// */
+// public Object nextValue() {
+// char c = this.nextClean();
+// String string;
+//
+// switch (c) {
+// case '"':
+// case '\'':
+// return this.nextString(c);
+// case '{':
+// this.back();
+// return new JSONObject(this);
+// case '[':
+// this.back();
+// return new JSONArray(this);
+// }
+//
+// /*
+// * Handle unquoted text. This could be the values true, false, or
+// * null, or it can be a number. An implementation (such as this one)
+// * is allowed to also accept non-standard forms.
+// *
+// * Accumulate characters until we reach the end of the text or a
+// * formatting character.
+// */
+//
+// StringBuffer sb = new StringBuffer();
+// while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
+// sb.append(c);
+// c = this.next();
+// }
+// this.back();
+//
+// string = sb.toString().trim();
+// if ("".equals(string)) {
+// throw new RuntimeException("Missing value");
+// }
+// return JSONObject.stringToValue(string);
+// }
+//
+//
+// /**
+// * Skip characters until the next character is the requested character.
+// * If the requested character is not found, no characters are skipped.
+// * @param to A character to skip to.
+// * @return The requested character, or zero if the requested character
+// * is not found.
+// */
+// public char skipTo(char to) {
+// char c;
+// try {
+// long startIndex = this.index;
+// long startCharacter = this.character;
+// long startLine = this.line;
+// this.reader.mark(1000000);
+// do {
+// c = this.next();
+// if (c == 0) {
+// this.reader.reset();
+// this.index = startIndex;
+// this.character = startCharacter;
+// this.line = startLine;
+// return c;
+// }
+// } while (c != to);
+// } catch (IOException exc) {
+// throw new RuntimeException(exc);
+// }
+//
+// this.back();
+// return c;
+// }
+//
+//
+// /**
+// * Make a printable string of this JSONTokener.
+// *
+// * @return " at {index} [character {character} line {line}]"
+// */
+// @Override
+// public String toString() {
+// return " at " + this.index + " [character " + this.character + " line " +
+// this.line + "]";
+// }
+// }
}
diff --git a/core/todo.txt b/core/todo.txt
index c7d0de1d1..66b8c1c20 100644
--- a/core/todo.txt
+++ b/core/todo.txt
@@ -1,6 +1,15 @@
0217 core
X improve load/save of .gz files with Table, clear up some .bin issues
+_ implement content specifiers
+getIntContent()
+getFloatContent()
+getContent() or getStringContent()?
+
+_ Dan having trouble with JSON
+_ keys() vs keySet() in JSON..
+_ keys() doesn't iterate, keySet() introduces 'Set' type
+
andres
A lines not properly renderered in P3D when using ortographic projection
A https://github.com/processing/processing/issues/1661