mirror of
https://github.com/IntellectualSites/PlotSquared.git
synced 2024-11-22 13:16:45 +01:00
Remove unused classes.
This commit is contained in:
parent
23b9eca4ab
commit
fe12d03916
@ -1,249 +0,0 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
/**
|
||||
* This provides static methods to convert comma delimited text into a JSONArray, and to covert a JSONArray into comma
|
||||
* delimited text. Comma delimited text is a very popular format for data interchange. It is understood by most
|
||||
* database, spreadsheet, and organizer programs.
|
||||
* <p>
|
||||
* Each row of text represents a row in a table or a data record. Each row ends with a NEWLINE character. Each row
|
||||
* contains one or more values. Values are separated by commas. A value can contain any character except for comma,
|
||||
* unless is is wrapped in single quotes or double quotes.
|
||||
* <p>
|
||||
* The first row usually contains the names of the columns.
|
||||
* <p>
|
||||
* A comma delimited list can be converted into a JSONArray of JSONObjects. The names for the elements in the
|
||||
* JSONObjects can be taken from the names in the first row.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class CDL {
|
||||
|
||||
/**
|
||||
* Get the next value. The value can be wrapped in quotes. The value can be empty.
|
||||
*
|
||||
* @param x A JSONTokener of the source text.
|
||||
* @return The value string, or null if empty.
|
||||
* @throws JSONException if the quoted string is badly formed.
|
||||
*/
|
||||
private static String getValue(JSONTokener x) throws JSONException {
|
||||
char c;
|
||||
char q;
|
||||
StringBuffer sb;
|
||||
do {
|
||||
c = x.next();
|
||||
} while ((c == ' ') || (c == '\t'));
|
||||
switch (c) {
|
||||
case 0:
|
||||
return null;
|
||||
case '"':
|
||||
case '\'':
|
||||
q = c;
|
||||
sb = new StringBuffer();
|
||||
for (; ; ) {
|
||||
c = x.next();
|
||||
if (c == q) {
|
||||
break;
|
||||
}
|
||||
if ((c == 0) || (c == '\n') || (c == '\r')) {
|
||||
throw x.syntaxError("Missing close quote '" + q + "'.");
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
return sb.toString();
|
||||
case ',':
|
||||
x.back();
|
||||
return "";
|
||||
default:
|
||||
x.back();
|
||||
return x.nextTo(',');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of strings from a row of comma delimited values.
|
||||
*
|
||||
* @param x A JSONTokener of the source text.
|
||||
* @return A JSONArray of strings.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException {
|
||||
JSONArray ja = new JSONArray();
|
||||
for (; ; ) {
|
||||
String value = getValue(x);
|
||||
char c = x.next();
|
||||
if ((value == null) || ((ja.length() == 0) && value.isEmpty() && (c != ','))) {
|
||||
return null;
|
||||
}
|
||||
ja.put(value);
|
||||
for (; ; ) {
|
||||
if (c == ',') {
|
||||
break;
|
||||
}
|
||||
if (c != ' ') {
|
||||
if ((c == '\n') || (c == '\r') || (c == 0)) {
|
||||
return ja;
|
||||
}
|
||||
throw x.syntaxError("Bad character '" + c + "' (" + (int) c + ").");
|
||||
}
|
||||
c = x.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONObject from a row of comma delimited text, using a parallel JSONArray of strings to provides the
|
||||
* names of the elements.
|
||||
*
|
||||
* @param names A JSONArray of names. This is commonly obtained from the first row of a comma delimited text file
|
||||
* using the rowToJSONArray method.
|
||||
* @param x A JSONTokener of the source text.
|
||||
* @return A JSONObject combining the names and values.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x) throws JSONException {
|
||||
JSONArray ja = rowToJSONArray(x);
|
||||
return ja != null ? ja.toJSONObject(names) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a comma delimited text row from a JSONArray. Values containing the comma character will be quoted.
|
||||
* Troublesome characters may be removed.
|
||||
*
|
||||
* @param ja A JSONArray of strings.
|
||||
* @return A string ending in NEWLINE.
|
||||
*/
|
||||
public static String rowToString(JSONArray ja) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < ja.length(); i += 1) {
|
||||
if (i > 0) {
|
||||
sb.append(',');
|
||||
}
|
||||
Object object = ja.opt(i);
|
||||
if (object != null) {
|
||||
String string = object.toString();
|
||||
if (!string.isEmpty() && ((string.indexOf(',') >= 0) || (string.indexOf('\n') >= 0)
|
||||
|| (string.indexOf('\r') >= 0) || (string.indexOf(0) >= 0) || (string.charAt(0)
|
||||
== '"'))) {
|
||||
sb.append('"');
|
||||
int length = string.length();
|
||||
for (int j = 0; j < length; j += 1) {
|
||||
char c = string.charAt(j);
|
||||
if ((c >= ' ') && (c != '"')) {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
sb.append('"');
|
||||
} else {
|
||||
sb.append(string);
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.append('\n');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string, using the first row as a source of names.
|
||||
*
|
||||
* @param string The comma delimited text.
|
||||
* @return A JSONArray of JSONObjects.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(String string) throws JSONException {
|
||||
return toJSONArray(new JSONTokener(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string, using the first row as a source of names.
|
||||
*
|
||||
* @param x The JSONTokener containing the comma delimited text.
|
||||
* @return A JSONArray of JSONObjects.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(JSONTokener x) throws JSONException {
|
||||
return toJSONArray(rowToJSONArray(x), x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string using a supplied JSONArray as the source of
|
||||
* element names.
|
||||
*
|
||||
* @param names A JSONArray of strings.
|
||||
* @param string The comma delimited text.
|
||||
* @return A JSONArray of JSONObjects.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(JSONArray names, String string) throws JSONException {
|
||||
return toJSONArray(names, new JSONTokener(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string using a supplied JSONArray as the source of
|
||||
* element names.
|
||||
*
|
||||
* @param names A JSONArray of strings.
|
||||
* @param x A JSONTokener of the source text.
|
||||
* @return A JSONArray of JSONObjects.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(JSONArray names, JSONTokener x) throws JSONException {
|
||||
if ((names == null) || (names.length() == 0)) {
|
||||
return null;
|
||||
}
|
||||
JSONArray ja = new JSONArray();
|
||||
for (; ; ) {
|
||||
JSONObject jo = rowToJSONObject(names, x);
|
||||
if (jo == null) {
|
||||
break;
|
||||
}
|
||||
ja.put(jo);
|
||||
}
|
||||
if (ja.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
return ja;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a comma delimited text from a JSONArray of JSONObjects. The first row will be a list of names obtained by
|
||||
* inspecting the first JSONObject.
|
||||
*
|
||||
* @param ja A JSONArray of JSONObjects.
|
||||
* @return A comma delimited text.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONArray ja) throws JSONException {
|
||||
JSONObject jo = ja.optJSONObject(0);
|
||||
if (jo != null) {
|
||||
JSONArray names = jo.names();
|
||||
if (names != null) {
|
||||
return rowToString(names) + toString(names, ja);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a comma delimited text from a JSONArray of JSONObjects using a provided list of names. The list of names
|
||||
* is not included in the output.
|
||||
*
|
||||
* @param names A JSONArray of strings.
|
||||
* @param ja A JSONArray of JSONObjects.
|
||||
* @return A comma delimited text.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONArray names, JSONArray ja) throws JSONException {
|
||||
if ((names == null) || (names.length() == 0)) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < ja.length(); i += 1) {
|
||||
JSONObject jo = ja.optJSONObject(i);
|
||||
if (jo != null) {
|
||||
sb.append(rowToString(jo.toJSONArray(names)));
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,130 +0,0 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
/**
|
||||
* Convert a web browser cookie specification to a JSONObject and back. JSON and Cookies are both notations for
|
||||
* name/value pairs.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class Cookie {
|
||||
/**
|
||||
* Produce a copy of a string in which the characters '+', '%', '=', ';' and control characters are replaced with
|
||||
* "%hh". This is a gentle form of URL encoding, attempting to cause as little distortion to the string as possible.
|
||||
* The characters '=' and ';' are meta characters in cookies. By convention, they are escaped using the
|
||||
* URL-encoding. This is only a convention, not a standard. Often, cookies are expected to have encoded values. We
|
||||
* encode '=' and ';' because we must. We encode '%' and '+' because they are meta characters in URL encoding.
|
||||
*
|
||||
* @param string The source string.
|
||||
* @return The escaped result.
|
||||
*/
|
||||
public static String escape(final String string) {
|
||||
char c;
|
||||
final String s = string.trim();
|
||||
final int length = s.length();
|
||||
final StringBuilder sb = new StringBuilder(length);
|
||||
for (int i = 0; i < length; i += 1) {
|
||||
c = s.charAt(i);
|
||||
if ((c < ' ') || (c == '+') || (c == '%') || (c == '=') || (c == ';')) {
|
||||
sb.append('%');
|
||||
sb.append(Character.forDigit((char) ((c >>> 4) & 0x0f), 16));
|
||||
sb.append(Character.forDigit((char) (c & 0x0f), 16));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a cookie specification string into a JSONObject. The string will contain a name value pair separated by
|
||||
* '='. The name and the value will be unescaped, possibly converting '+' and '%' sequences. The cookie properties
|
||||
* may follow, separated by ';', also represented as name=value (except the secure property, which does not have a
|
||||
* value). The name will be stored under the key "name", and the value will be stored under the key "value". This
|
||||
* method does not do checking or validation of the parameters. It only converts the cookie string into a
|
||||
* JSONObject.
|
||||
*
|
||||
* @param string The cookie specification string.
|
||||
* @return A JSONObject containing "name", "value", and possibly other members.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(final String string) throws JSONException {
|
||||
String name;
|
||||
final JSONObject jo = new JSONObject();
|
||||
Object value;
|
||||
final JSONTokener x = new JSONTokener(string);
|
||||
jo.put("name", x.nextTo('='));
|
||||
x.next('=');
|
||||
jo.put("value", x.nextTo(';'));
|
||||
x.next();
|
||||
while (x.more()) {
|
||||
name = unescape(x.nextTo("=;"));
|
||||
if (x.next() != '=') {
|
||||
if (name.equals("secure")) {
|
||||
value = Boolean.TRUE;
|
||||
} else {
|
||||
throw x.syntaxError("Missing '=' in cookie parameter.");
|
||||
}
|
||||
} else {
|
||||
value = unescape(x.nextTo(';'));
|
||||
x.next();
|
||||
}
|
||||
jo.put(name, value);
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into a cookie specification string. The JSONObject must contain "name" and "value" members.
|
||||
* If the JSONObject contains "expires", "domain", "path", or "secure" members, they will be appended to the cookie
|
||||
* specification string. All other members are ignored.
|
||||
*
|
||||
* @param jo A JSONObject
|
||||
* @return A cookie specification string
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(final JSONObject jo) throws JSONException {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(escape(jo.getString("name"))).append("=").append(escape(jo.getString("value")));
|
||||
if (jo.has("expires")) {
|
||||
sb.append(";expires=").append(jo.getString("expires"));
|
||||
}
|
||||
if (jo.has("domain")) {
|
||||
sb.append(";domain=").append(escape(jo.getString("domain")));
|
||||
}
|
||||
if (jo.has("path")) {
|
||||
sb.append(";path=").append(escape(jo.getString("path")));
|
||||
}
|
||||
if (jo.optBoolean("secure")) {
|
||||
sb.append(";secure");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert {@code %}<i>hh</i> sequences to single characters, and convert plus to space.
|
||||
*
|
||||
* @param string A string that may contain {@code +} <small>(plus)</small> and <code>%</code><i>hh</i>
|
||||
* sequences.
|
||||
* @return The unescaped string.
|
||||
*/
|
||||
public static String unescape(final String string) {
|
||||
final int length = string.length();
|
||||
final StringBuilder sb = new StringBuilder(length);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
char c = string.charAt(i);
|
||||
if (c == '+') {
|
||||
c = ' ';
|
||||
} else if ((c == '%') && ((i + 2) < length)) {
|
||||
final int d = JSONTokener.dehexchar(string.charAt(i + 1));
|
||||
final int e = JSONTokener.dehexchar(string.charAt(i + 2));
|
||||
if ((d >= 0) && (e >= 0)) {
|
||||
c = (char) ((d * 16) + e);
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Convert a web browser cookie list string to a JSONObject and back.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class CookieList {
|
||||
/**
|
||||
* Convert a cookie list into a JSONObject. A cookie list is a sequence of name/value pairs. The names are separated
|
||||
* from the values by '='. The pairs are separated by ';'. The names and the values will be unescaped, possibly
|
||||
* converting '+' and '%' sequences.
|
||||
* <p>
|
||||
* To add a cookie to a cooklist, cookielistJSONObject.put(cookieJSONObject.getString("name"),
|
||||
* cookieJSONObject.getString("value"));
|
||||
*
|
||||
* @param string A cookie list string
|
||||
* @return A JSONObject
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(final String string) throws JSONException {
|
||||
final JSONObject jo = new JSONObject();
|
||||
final JSONTokener x = new JSONTokener(string);
|
||||
while (x.more()) {
|
||||
final String name = Cookie.unescape(x.nextTo('='));
|
||||
x.next('=');
|
||||
jo.put(name, Cookie.unescape(x.nextTo(';')));
|
||||
x.next();
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into a cookie list. A cookie list is a sequence of name/value pairs. The names are separated
|
||||
* from the values by '='. The pairs are separated by ';'. The characters '%', '+', '=', and ';' in the names and
|
||||
* values are replaced by "%hh".
|
||||
*
|
||||
* @param jo A JSONObject
|
||||
* @return A cookie list string
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(final JSONObject jo) throws JSONException {
|
||||
boolean b = false;
|
||||
final Iterator<String> keys = jo.keys();
|
||||
String string;
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
while (keys.hasNext()) {
|
||||
string = keys.next();
|
||||
if (!jo.isNull(string)) {
|
||||
if (b) {
|
||||
sb.append(';');
|
||||
}
|
||||
sb.append(Cookie.escape(string));
|
||||
sb.append("=");
|
||||
sb.append(Cookie.escape(jo.getString(string)));
|
||||
b = true;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Convert an HTTP header to a JSONObject and back.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class HTTP {
|
||||
/**
|
||||
* Carriage return/line feed.
|
||||
*/
|
||||
public static final String CRLF = "\r\n";
|
||||
|
||||
public static JSONObject toJSONObject(final String string) throws JSONException {
|
||||
final JSONObject jo = new JSONObject();
|
||||
final HTTPTokener x = new HTTPTokener(string);
|
||||
String token;
|
||||
token = x.nextToken();
|
||||
if (token.toUpperCase().startsWith("HTTP")) {
|
||||
// Response
|
||||
jo.put("HTTP-Version", token);
|
||||
jo.put("Status-Code", x.nextToken());
|
||||
jo.put("Reason-Phrase", x.nextTo('\0'));
|
||||
x.next();
|
||||
} else {
|
||||
// Request
|
||||
jo.put("Method", token);
|
||||
jo.put("Request-URI", x.nextToken());
|
||||
jo.put("HTTP-Version", x.nextToken());
|
||||
}
|
||||
// Fields
|
||||
while (x.more()) {
|
||||
final String name = x.nextTo(':');
|
||||
x.next(':');
|
||||
jo.put(name, x.nextTo('\0'));
|
||||
x.next();
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into an HTTP header. A request header must contain
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* Method: "POST" (for example),
|
||||
* "Request-URI": "/" (for example),
|
||||
* "HTTP-Version": "HTTP/1.1" (for example)
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* A response header must contain
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* "HTTP-Version": "HTTP/1.1" (for example),
|
||||
* "Status-Code": "200" (for example),
|
||||
* "Reason-Phrase": "OK" (for example)
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* Any other members of the JSONObject will be output as HTTP fields. The result will end with two CRLF pairs.
|
||||
*
|
||||
* @param jo A JSONObject
|
||||
* @return An HTTP header string.
|
||||
* @throws JSONException if the object does not contain enough information.
|
||||
*/
|
||||
public static String toString(final JSONObject jo) throws JSONException {
|
||||
final Iterator<String> keys = jo.keys();
|
||||
String string;
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
if (jo.has("Status-Code") && jo.has("Reason-Phrase")) {
|
||||
sb.append(jo.getString("HTTP-Version"));
|
||||
sb.append(' ');
|
||||
sb.append(jo.getString("Status-Code"));
|
||||
sb.append(' ');
|
||||
sb.append(jo.getString("Reason-Phrase"));
|
||||
} else if (jo.has("Method") && jo.has("Request-URI")) {
|
||||
sb.append(jo.getString("Method"));
|
||||
sb.append(' ');
|
||||
sb.append('"');
|
||||
sb.append(jo.getString("Request-URI"));
|
||||
sb.append('"');
|
||||
sb.append(' ');
|
||||
sb.append(jo.getString("HTTP-Version"));
|
||||
} else {
|
||||
throw new JSONException("Not enough material for an HTTP header.");
|
||||
}
|
||||
sb.append(CRLF);
|
||||
while (keys.hasNext()) {
|
||||
string = keys.next();
|
||||
if (!"HTTP-Version".equals(string) && !"Status-Code".equals(string) && !"Reason-Phrase"
|
||||
.equals(string) && !"Method".equals(string) && !"Request-URI".equals(string) && !jo
|
||||
.isNull(string)) {
|
||||
sb.append(string);
|
||||
sb.append(": ");
|
||||
sb.append(jo.getString(string));
|
||||
sb.append(CRLF);
|
||||
}
|
||||
}
|
||||
sb.append(CRLF);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
/**
|
||||
* The HTTPTokener extends the JSONTokener to provide additional methods for the parsing of HTTP headers.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class HTTPTokener extends JSONTokener {
|
||||
/**
|
||||
* Construct an HTTPTokener from a string.
|
||||
*
|
||||
* @param string A source string.
|
||||
*/
|
||||
public HTTPTokener(final String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next token or string. This is used in parsing HTTP headers.
|
||||
*
|
||||
* @return A String.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public String nextToken() throws JSONException {
|
||||
char c;
|
||||
char q;
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
do {
|
||||
c = next();
|
||||
} while (Character.isWhitespace(c));
|
||||
if ((c == '"') || (c == '\'')) {
|
||||
q = c;
|
||||
for (; ; ) {
|
||||
c = next();
|
||||
if (c < ' ') {
|
||||
throw syntaxError("Unterminated string.");
|
||||
}
|
||||
if (c == q) {
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
for (; ; ) {
|
||||
if ((c == 0) || Character.isWhitespace(c)) {
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append(c);
|
||||
c = next();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,393 +0,0 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* This provides static methods to convert an XML text into a JSONArray or JSONObject, and to covert a JSONArray or
|
||||
* JSONObject into an XML text using the JsonML transform.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONML {
|
||||
/**
|
||||
* Parse XML values and store them in a JSONArray.
|
||||
*
|
||||
* @param x The XMLTokener containing the source string.
|
||||
* @param arrayForm true if array form, false if object form.
|
||||
* @param ja The JSONArray that is containing the current tag or null if we are at the outermost level.
|
||||
* @return A JSONArray if the value is the outermost tag, otherwise null.
|
||||
* @throws JSONException
|
||||
*/
|
||||
private static Object parse(XMLTokener x, boolean arrayForm, JSONArray ja)
|
||||
throws JSONException {
|
||||
String attribute;
|
||||
char c;
|
||||
String closeTag = null;
|
||||
int i;
|
||||
JSONArray newja = null;
|
||||
JSONObject newjo = null;
|
||||
Object token;
|
||||
String tagName = null;
|
||||
// Test for and skip past these forms:
|
||||
// <!-- ... -->
|
||||
// <![ ... ]]>
|
||||
// <! ... >
|
||||
// <? ... ?>
|
||||
while (true) {
|
||||
if (!x.more()) {
|
||||
throw x.syntaxError("Bad XML");
|
||||
}
|
||||
token = x.nextContent();
|
||||
if (token == XML.LT) {
|
||||
token = x.nextToken();
|
||||
if (token instanceof Character) {
|
||||
if (token == XML.SLASH) {
|
||||
// Close tag </
|
||||
token = x.nextToken();
|
||||
if (!(token instanceof String)) {
|
||||
throw new JSONException(
|
||||
"Expected a closing name instead of '" + token + "'.");
|
||||
}
|
||||
if (x.nextToken() != XML.GT) {
|
||||
throw x.syntaxError("Misshaped close tag");
|
||||
}
|
||||
return token;
|
||||
} else if (token == XML.BANG) {
|
||||
// <!
|
||||
c = x.next();
|
||||
if (c == '-') {
|
||||
if (x.next() == '-') {
|
||||
x.skipPast("-->");
|
||||
} else {
|
||||
x.back();
|
||||
}
|
||||
} else if (c == '[') {
|
||||
token = x.nextToken();
|
||||
if (token.equals("CDATA") && (x.next() == '[')) {
|
||||
if (ja != null) {
|
||||
ja.put(x.nextCDATA());
|
||||
}
|
||||
} else {
|
||||
throw x.syntaxError("Expected 'CDATA['");
|
||||
}
|
||||
} else {
|
||||
i = 1;
|
||||
do {
|
||||
token = x.nextMeta();
|
||||
if (token == null) {
|
||||
throw x.syntaxError("Missing '>' after '<!'.");
|
||||
} else if (token == XML.LT) {
|
||||
i += 1;
|
||||
} else if (token == XML.GT) {
|
||||
i -= 1;
|
||||
}
|
||||
} while (i > 0);
|
||||
}
|
||||
} else if (token == XML.QUEST) {
|
||||
// <?
|
||||
x.skipPast("?>");
|
||||
} else {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
// Open tag <
|
||||
} else {
|
||||
if (!(token instanceof String)) {
|
||||
throw x.syntaxError("Bad tagName '" + token + "'.");
|
||||
}
|
||||
tagName = (String) token;
|
||||
newja = new JSONArray();
|
||||
newjo = new JSONObject();
|
||||
if (arrayForm) {
|
||||
newja.put(tagName);
|
||||
if (ja != null) {
|
||||
ja.put(newja);
|
||||
}
|
||||
} else {
|
||||
newjo.put("tagName", tagName);
|
||||
if (ja != null) {
|
||||
ja.put(newjo);
|
||||
}
|
||||
}
|
||||
token = null;
|
||||
for (; ; ) {
|
||||
if (token == null) {
|
||||
token = x.nextToken();
|
||||
}
|
||||
if (!(token instanceof String)) {
|
||||
break;
|
||||
}
|
||||
// attribute = value
|
||||
attribute = (String) token;
|
||||
if (!arrayForm && ("tagName".equals(attribute) || "childNode"
|
||||
.equals(attribute))) {
|
||||
throw x.syntaxError("Reserved attribute.");
|
||||
}
|
||||
token = x.nextToken();
|
||||
if (token == XML.EQ) {
|
||||
token = x.nextToken();
|
||||
if (!(token instanceof String)) {
|
||||
throw x.syntaxError("Missing value");
|
||||
}
|
||||
newjo.accumulate(attribute, XML.stringToValue((String) token));
|
||||
token = null;
|
||||
} else {
|
||||
newjo.accumulate(attribute, "");
|
||||
}
|
||||
}
|
||||
if (arrayForm && (newjo.length() > 0)) {
|
||||
newja.put(newjo);
|
||||
}
|
||||
// Empty tag <.../>
|
||||
if (token == XML.SLASH) {
|
||||
if (x.nextToken() != XML.GT) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
if (ja == null) {
|
||||
if (arrayForm) {
|
||||
return newja;
|
||||
} else {
|
||||
return newjo;
|
||||
}
|
||||
}
|
||||
// Content, between <...> and </...>
|
||||
} else {
|
||||
if (token != XML.GT) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
closeTag = (String) parse(x, arrayForm, newja);
|
||||
if (closeTag != null) {
|
||||
if (!closeTag.equals(tagName)) {
|
||||
throw x.syntaxError(
|
||||
"Mismatched '" + tagName + "' and '" + closeTag + "'");
|
||||
}
|
||||
tagName = null;
|
||||
if (!arrayForm && (newja.length() > 0)) {
|
||||
newjo.put("childNodes", newja);
|
||||
}
|
||||
if (ja == null) {
|
||||
if (arrayForm) {
|
||||
return newja;
|
||||
} else {
|
||||
return newjo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ja != null) {
|
||||
ja.put(token instanceof String ? XML.stringToValue((String) token) : token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a JSONArray using the JsonML transform. Each
|
||||
* XML tag is represented as a JSONArray in which the first element is the tag name. If the tag has attributes, then
|
||||
* the second element will be JSONObject containing the name/value pairs. If the tag contains children, then strings
|
||||
*
|
||||
* @param string The source string.
|
||||
* @return A JSONArray containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(String string) throws JSONException {
|
||||
return toJSONArray(new XMLTokener(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a JSONArray using the JsonML transform. Each
|
||||
* XML tag is represented as a JSONArray in which the first element is the tag name. If the tag has attributes, then
|
||||
* the second element will be JSONObject containing the name/value pairs. If the tag contains children, then strings
|
||||
* and JSONArrays will represent the child content and tags. Comments, prologs, DTDs, and <code><[ [ ]]></code>
|
||||
* are ignored.
|
||||
*
|
||||
* @param x An XMLTokener.
|
||||
* @return A JSONArray containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
|
||||
return (JSONArray) parse(x, true, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a JSONObject using the JsonML transform. Each
|
||||
* XML tag is represented as a JSONObject with a "tagName" property. If the tag has attributes, then the attributes
|
||||
* will be in the JSONObject as properties. If the tag contains children, the object will have a "childNodes"
|
||||
* property which will be an array of strings and JsonML JSONObjects.
|
||||
* <p>
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
*
|
||||
* @param x An XMLTokener of the XML source text.
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
|
||||
return (JSONObject) parse(x, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a JSONObject using the JsonML transform. Each
|
||||
* XML tag is represented as a JSONObject with a "tagName" property. If the tag has attributes, then the attributes
|
||||
* will be in the JSONObject as properties. If the tag contains children, the object will have a "childNodes"
|
||||
* property which will be an array of strings and JsonML JSONObjects.
|
||||
* <p>
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
*
|
||||
* @param string The XML source text.
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||
return toJSONObject(new XMLTokener(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the JSONML transformation, making an XML text from a JSONArray.
|
||||
*
|
||||
* @param ja A JSONArray.
|
||||
* @return An XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONArray ja) throws JSONException {
|
||||
int i;
|
||||
JSONObject jo;
|
||||
String key;
|
||||
Iterator<String> keys;
|
||||
int length;
|
||||
Object object;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String tagName;
|
||||
String value;
|
||||
// Emit <tagName
|
||||
tagName = ja.getString(0);
|
||||
XML.noSpace(tagName);
|
||||
tagName = XML.escape(tagName);
|
||||
sb.append('<');
|
||||
sb.append(tagName);
|
||||
object = ja.opt(1);
|
||||
if (object instanceof JSONObject) {
|
||||
i = 2;
|
||||
jo = (JSONObject) object;
|
||||
// Emit the attributes
|
||||
keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
key = keys.next();
|
||||
XML.noSpace(key);
|
||||
value = jo.optString(key);
|
||||
if (value != null) {
|
||||
sb.append(' ');
|
||||
sb.append(XML.escape(key));
|
||||
sb.append('=');
|
||||
sb.append('"');
|
||||
sb.append(XML.escape(value));
|
||||
sb.append('"');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
i = 1;
|
||||
}
|
||||
// Emit content in body
|
||||
length = ja.length();
|
||||
if (i >= length) {
|
||||
sb.append('/');
|
||||
sb.append('>');
|
||||
} else {
|
||||
sb.append('>');
|
||||
do {
|
||||
object = ja.get(i);
|
||||
i += 1;
|
||||
if (object != null) {
|
||||
if (object instanceof String) {
|
||||
sb.append(XML.escape(object.toString()));
|
||||
} else if (object instanceof JSONObject) {
|
||||
sb.append(toString((JSONObject) object));
|
||||
} else if (object instanceof JSONArray) {
|
||||
sb.append(toString((JSONArray) object));
|
||||
}
|
||||
}
|
||||
} while (i < length);
|
||||
sb.append('<');
|
||||
sb.append('/');
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the JSONML transformation, making an XML text from a JSONObject. The JSONObject must contain a "tagName"
|
||||
* property. If it has children, then it must have a "childNodes" property containing an array of objects. The other
|
||||
* properties are attributes with string values.
|
||||
*
|
||||
* @param jo A JSONObject.
|
||||
* @return An XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONObject jo) throws JSONException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i;
|
||||
JSONArray ja;
|
||||
String key;
|
||||
Iterator<String> keys;
|
||||
int length;
|
||||
Object object;
|
||||
String tagName;
|
||||
String value;
|
||||
// Emit <tagName
|
||||
tagName = jo.optString("tagName");
|
||||
if (tagName == null) {
|
||||
return XML.escape(jo.toString());
|
||||
}
|
||||
XML.noSpace(tagName);
|
||||
tagName = XML.escape(tagName);
|
||||
sb.append('<');
|
||||
sb.append(tagName);
|
||||
// Emit the attributes
|
||||
keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
key = keys.next();
|
||||
if (!"tagName".equals(key) && !"childNodes".equals(key)) {
|
||||
XML.noSpace(key);
|
||||
value = jo.optString(key);
|
||||
if (value != null) {
|
||||
sb.append(' ');
|
||||
sb.append(XML.escape(key));
|
||||
sb.append('=');
|
||||
sb.append('"');
|
||||
sb.append(XML.escape(value));
|
||||
sb.append('"');
|
||||
}
|
||||
}
|
||||
}
|
||||
// Emit content in body
|
||||
ja = jo.optJSONArray("childNodes");
|
||||
if (ja == null) {
|
||||
sb.append('/');
|
||||
sb.append('>');
|
||||
} else {
|
||||
sb.append('>');
|
||||
length = ja.length();
|
||||
for (i = 0; i < length; i += 1) {
|
||||
object = ja.get(i);
|
||||
if (object != null) {
|
||||
if (object instanceof String) {
|
||||
sb.append(XML.escape(object.toString()));
|
||||
} else if (object instanceof JSONObject) {
|
||||
sb.append(toString((JSONObject) object));
|
||||
} else if (object instanceof JSONArray) {
|
||||
sb.append(toString((JSONArray) object));
|
||||
} else {
|
||||
sb.append(object.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.append('<');
|
||||
sb.append('/');
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* JSONStringer provides a quick and convenient way of producing JSON text. The texts produced strictly conform to JSON
|
||||
* syntax rules. No whitespace is added, so the results are ready for transmission or storage. Each instance of
|
||||
* JSONStringer can produce one JSON text.
|
||||
* <p>
|
||||
* A JSONStringer instance provides a <code>value</code> method for appending values to the text, and a <code>key</code>
|
||||
* method for adding keys before values in objects. There are <code>array</code> and <code>endArray</code> methods that
|
||||
* make and bound array values, and <code>object</code> and <code>endObject</code> methods which make and bound object
|
||||
* values. All of these methods return the JSONWriter instance, permitting cascade style. For example,
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* myString = new JSONStringer().object().key("JSON").value("Hello,
|
||||
* World!").endObject().toString();
|
||||
* </pre>
|
||||
* <p>
|
||||
* which produces the string
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* {"JSON":"Hello, World!"}
|
||||
* </pre>
|
||||
* <p>
|
||||
* The first method called must be <code>array</code> or <code>object</code>. There are no methods for adding commas or
|
||||
* colons. JSONStringer adds them for you. Objects and arrays can be nested up to 20 levels deep.
|
||||
* <p>
|
||||
* This can sometimes be easier than using a JSONObject to build a string.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2008-09-18
|
||||
*/
|
||||
public class JSONStringer extends JSONWriter {
|
||||
/**
|
||||
* Make a fresh JSONStringer. It can be used to build one JSON text.
|
||||
*/
|
||||
public JSONStringer() {
|
||||
super(new StringWriter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JSON text. This method is used to obtain the product of the JSONStringer instance. It will return
|
||||
* <code>null</code> if there was a problem in the construction of the JSON text (such as the calls to
|
||||
* <code>array</code> were not properly balanced with calls to <code>endArray</code>).
|
||||
*
|
||||
* @return The JSON text.
|
||||
*/
|
||||
@Override public String toString() {
|
||||
return mode == 'd' ? writer.toString() : null;
|
||||
}
|
||||
}
|
@ -1,288 +0,0 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* JSONWriter provides a quick and convenient way of producing JSON text. The texts produced strictly conform to JSON
|
||||
* syntax rules. No whitespace is added, so the results are ready for transmission or storage. Each instance of
|
||||
* JSONWriter can produce one JSON text.
|
||||
* <p>
|
||||
* A JSONWriter instance provides a <code>value</code> method for appending values to the text, and a <code>key</code>
|
||||
* method for adding keys before values in objects. There are <code>array</code> and <code>endArray</code> methods that
|
||||
* make and bound array values, and <code>object</code> and <code>endObject</code> methods which make and bound object
|
||||
* values. All of these methods return the JSONWriter instance, permitting a cascade style. For example,
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* new JSONWriter(myWriter).object().key("JSON").value("Hello, World!").endObject();
|
||||
* </pre>
|
||||
* <p>
|
||||
* which writes
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* {"JSON":"Hello, World!"}
|
||||
* </pre>
|
||||
* <p>
|
||||
* The first method called must be <code>array</code> or <code>object</code>. There are no methods for adding commas or
|
||||
* colons. JSONWriter adds them for you. Objects and arrays can be nested up to 20 levels deep.
|
||||
* <p>
|
||||
* This can sometimes be easier than using a JSONObject to build a string.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2011-11-24
|
||||
*/
|
||||
public class JSONWriter {
|
||||
private static final int maxdepth = 200;
|
||||
/**
|
||||
* The writer that will receive the output.
|
||||
*/
|
||||
protected final Writer writer;
|
||||
/**
|
||||
* The object/array stack.
|
||||
*/
|
||||
private final JSONObject stack[];
|
||||
/**
|
||||
* The current mode. Values: 'a' (array), 'd' (done), 'i' (initial), 'k' (key), 'o' (object).
|
||||
*/
|
||||
protected char mode;
|
||||
/**
|
||||
* The comma flag determines if a comma should be output before the next value.
|
||||
*/
|
||||
private boolean comma;
|
||||
/**
|
||||
* The stack top index. A value of 0 indicates that the stack is empty.
|
||||
*/
|
||||
private int top;
|
||||
|
||||
/**
|
||||
* Make a fresh JSONWriter. It can be used to build one JSON text.
|
||||
*/
|
||||
public JSONWriter(final Writer w) {
|
||||
comma = false;
|
||||
mode = 'i';
|
||||
stack = new JSONObject[maxdepth];
|
||||
top = 0;
|
||||
writer = w;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a value.
|
||||
*
|
||||
* @param string A string value.
|
||||
* @return this
|
||||
* @throws JSONException If the value is out of sequence.
|
||||
*/
|
||||
private JSONWriter append(final String string) throws JSONException {
|
||||
if (string == null) {
|
||||
throw new JSONException("Null pointer");
|
||||
}
|
||||
if ((mode == 'o') || (mode == 'a')) {
|
||||
try {
|
||||
if (comma && (mode == 'a')) {
|
||||
writer.write(',');
|
||||
}
|
||||
writer.write(string);
|
||||
} catch (final IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
if (mode == 'o') {
|
||||
mode = 'k';
|
||||
}
|
||||
comma = true;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Value out of sequence.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin appending a new array. All values until the balancing <code>endArray</code> will be appended to this array.
|
||||
* The <code>endArray</code> method must be called to mark the array's end.
|
||||
*
|
||||
* @return this
|
||||
* @throws JSONException If the nesting is too deep, or if the object is started in the wrong place (for example as
|
||||
* a key or after the end of the outermost array or object).
|
||||
*/
|
||||
public JSONWriter array() throws JSONException {
|
||||
if ((mode == 'i') || (mode == 'o') || (mode == 'a')) {
|
||||
push(null);
|
||||
append("[");
|
||||
comma = false;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Misplaced array.");
|
||||
}
|
||||
|
||||
/**
|
||||
* End something.
|
||||
*
|
||||
* @param mode Mode
|
||||
* @param c Closing character
|
||||
* @return this
|
||||
* @throws JSONException If unbalanced.
|
||||
*/
|
||||
private JSONWriter end(final char mode, final char c) throws JSONException {
|
||||
if (this.mode != mode) {
|
||||
throw new JSONException(mode == 'a' ? "Misplaced endArray." : "Misplaced endObject.");
|
||||
}
|
||||
pop(mode);
|
||||
try {
|
||||
writer.write(c);
|
||||
} catch (final IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
comma = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* End an array. This method most be called to balance calls to <code>array</code>.
|
||||
*
|
||||
* @return this
|
||||
* @throws JSONException If incorrectly nested.
|
||||
*/
|
||||
public JSONWriter endArray() throws JSONException {
|
||||
return end('a', ']');
|
||||
}
|
||||
|
||||
/**
|
||||
* End an object. This method most be called to balance calls to <code>object</code>.
|
||||
*
|
||||
* @return this
|
||||
* @throws JSONException If incorrectly nested.
|
||||
*/
|
||||
public JSONWriter endObject() throws JSONException {
|
||||
return end('k', '}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a key. The key will be associated with the next value. In an object, every value must be preceded by a
|
||||
* key.
|
||||
*
|
||||
* @param string A key string.
|
||||
* @return this
|
||||
* @throws JSONException If the key is out of place. For example, keys do not belong in arrays or if the key is
|
||||
* null.
|
||||
*/
|
||||
public JSONWriter key(final String string) throws JSONException {
|
||||
if (string == null) {
|
||||
throw new JSONException("Null key.");
|
||||
}
|
||||
if (mode == 'k') {
|
||||
try {
|
||||
stack[top - 1].putOnce(string, Boolean.TRUE);
|
||||
if (comma) {
|
||||
writer.write(',');
|
||||
}
|
||||
writer.write(JSONObject.quote(string));
|
||||
writer.write(':');
|
||||
comma = false;
|
||||
mode = 'o';
|
||||
return this;
|
||||
} catch (final IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
}
|
||||
throw new JSONException("Misplaced key.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin appending a new object. All keys and values until the balancing <code>endObject</code> will be appended to
|
||||
* this object. The <code>endObject</code> method must be called to mark the object's end.
|
||||
*
|
||||
* @return this
|
||||
* @throws JSONException If the nesting is too deep, or if the object is started in the wrong place (for example as
|
||||
* a key or after the end of the outermost array or object).
|
||||
*/
|
||||
public JSONWriter object() throws JSONException {
|
||||
if (mode == 'i') {
|
||||
mode = 'o';
|
||||
}
|
||||
if ((mode == 'o') || (mode == 'a')) {
|
||||
append("{");
|
||||
push(new JSONObject());
|
||||
comma = false;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Misplaced object.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop an array or object scope.
|
||||
*
|
||||
* @param c The scope to close.
|
||||
* @throws JSONException If nesting is wrong.
|
||||
*/
|
||||
private void pop(final char c) throws JSONException {
|
||||
if (top <= 0) {
|
||||
throw new JSONException("Nesting error.");
|
||||
}
|
||||
final char m = stack[top - 1] == null ? 'a' : 'k';
|
||||
if (m != c) {
|
||||
throw new JSONException("Nesting error.");
|
||||
}
|
||||
top -= 1;
|
||||
mode = top == 0 ? 'd' : stack[top - 1] == null ? 'a' : 'k';
|
||||
}
|
||||
|
||||
/**
|
||||
* Push an array or object scope.
|
||||
*
|
||||
* @param jo The scope to open.
|
||||
* @throws JSONException If nesting is too deep.
|
||||
*/
|
||||
private void push(final JSONObject jo) throws JSONException {
|
||||
if (top >= maxdepth) {
|
||||
throw new JSONException("Nesting too deep.");
|
||||
}
|
||||
stack[top] = jo;
|
||||
mode = jo == null ? 'a' : 'k';
|
||||
top += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append either the value <code>true</code> or the value <code>false</code> .
|
||||
*
|
||||
* @param b A boolean.
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
*/
|
||||
public JSONWriter value(final boolean b) throws JSONException {
|
||||
return append(b ? "true" : "false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a double value.
|
||||
*
|
||||
* @param d A double.
|
||||
* @return this
|
||||
* @throws JSONException If the number is not finite.
|
||||
*/
|
||||
public JSONWriter value(final double d) throws JSONException {
|
||||
return this.value(new Double(d));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a long value.
|
||||
*
|
||||
* @param l A long.
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
*/
|
||||
public JSONWriter value(final long l) throws JSONException {
|
||||
return append(Long.toString(l));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an object value.
|
||||
*
|
||||
* @param object The object to append. It can be null, or a Boolean, Number, String, JSONObject, or JSONArray, or an
|
||||
* object that implements JSONString.
|
||||
* @return this
|
||||
* @throws JSONException If the value is out of sequence.
|
||||
*/
|
||||
public JSONWriter value(final Object object) throws JSONException {
|
||||
return append(JSONObject.valueToString(object));
|
||||
}
|
||||
}
|
@ -1,303 +0,0 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
/**
|
||||
* Kim makes immutable eight bit Unicode strings. If the MSB of a byte is set, then the next byte is a continuation
|
||||
* byte. The last byte of a character never has the MSB reset. Every byte that is not the last byte has the MSB set. Kim
|
||||
* stands for "Keep it minimal". A Unicode character is never longer than 3 bytes. Every byte contributes 7 bits to the
|
||||
* character. ASCII is unmodified.
|
||||
* <p>
|
||||
* Kim UTF-8 one byte U+007F U+007F two bytes U+3FFF U+07FF three bytes U+10FFF U+FFFF four bytes U+10FFFF
|
||||
* <p>
|
||||
* Characters in the ranges U+0800..U+3FFF and U+10000..U+10FFFF will be one byte smaller when encoded in Kim compared
|
||||
* to UTF-8.
|
||||
* <p>
|
||||
* Kim is beneficial when using scripts such as Old South Arabian, Aramaic, Avestan, Balinese, Batak, Bopomofo,
|
||||
* Buginese, Buhid, Carian, Cherokee, Coptic, Cyrillic, Deseret, Egyptian Hieroglyphs, Ethiopic, Georgian, Glagolitic,
|
||||
* Gothic, Hangul Jamo, Hanunoo, Hiragana, Kanbun, Kaithi, Kannada, Katakana, Kharoshthi, Khmer, Lao, Lepcha, Limbu,
|
||||
* Lycian, Lydian, Malayalam, Mandaic, Meroitic, Miao, Mongolian, Myanmar, New Tai Lue, Ol Chiki, Old Turkic, Oriya,
|
||||
* Osmanya, Pahlavi, Parthian, Phags-Pa, Phoenician, Samaritan, Sharada, Sinhala, Sora Sompeng, Tagalog, Tagbanwa,
|
||||
* Takri, Tai Le, Tai Tham, Tamil, Telugu, Thai, Tibetan, Tifinagh, UCAS.
|
||||
* <p>
|
||||
* A kim object can be constructed from an ordinary UTF-16 string, or from a byte array. A kim object can produce a
|
||||
* UTF-16 string.
|
||||
* <p>
|
||||
* As with UTF-8, it is possible to detect character boundaries within a byte sequence. UTF-8 is one of the world's
|
||||
* great inventions. While Kim is more efficient, it is not clear that it is worth the expense of transition.
|
||||
*
|
||||
* @version 2013-04-18
|
||||
*/
|
||||
public class Kim {
|
||||
/**
|
||||
* The number of bytes in the kim. The number of bytes can be as much as three times the number of characters.
|
||||
*/
|
||||
public int length = 0;
|
||||
/**
|
||||
* The byte array containing the kim's content.
|
||||
*/
|
||||
private byte[] bytes = null;
|
||||
/**
|
||||
* The kim's hashcode, conforming to Java's hashcode conventions.
|
||||
*/
|
||||
private int hashcode = 0;
|
||||
/**
|
||||
* The memoization of toString().
|
||||
*/
|
||||
private String string = null;
|
||||
|
||||
/**
|
||||
* Make a kim from a portion of a byte array.
|
||||
*
|
||||
* @param bytes A byte array.
|
||||
* @param from The index of the first byte.
|
||||
* @param thru The index of the last byte plus one.
|
||||
*/
|
||||
public Kim(final byte[] bytes, final int from, final int thru) {
|
||||
// As the bytes are copied into the new kim, a hashcode is computed
|
||||
// using a
|
||||
// modified Fletcher code.
|
||||
int sum = 1;
|
||||
int value;
|
||||
hashcode = 0;
|
||||
length = thru - from;
|
||||
if (length > 0) {
|
||||
this.bytes = new byte[length];
|
||||
for (int at = 0; at < length; at += 1) {
|
||||
value = bytes[at + from] & 0xFF;
|
||||
sum += value;
|
||||
hashcode += sum;
|
||||
this.bytes[at] = (byte) value;
|
||||
}
|
||||
hashcode += sum << 16;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a kim from a byte array.
|
||||
*
|
||||
* @param bytes The byte array.
|
||||
* @param length The number of bytes.
|
||||
*/
|
||||
public Kim(final byte[] bytes, final int length) {
|
||||
this(bytes, 0, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new kim from a substring of an existing kim. The coordinates are in byte units, not character units.
|
||||
*
|
||||
* @param kim The source of bytes.
|
||||
* @param from The point at which to take bytes.
|
||||
* @param thru The point at which to stop taking bytes.
|
||||
*/
|
||||
public Kim(final Kim kim, final int from, final int thru) {
|
||||
this(kim.bytes, from, thru);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a kim from a string.
|
||||
*
|
||||
* @param string The string.
|
||||
* @throws JSONException if surrogate pair mismatch.
|
||||
*/
|
||||
public Kim(final String string) throws JSONException {
|
||||
final int stringLength = string.length();
|
||||
hashcode = 0;
|
||||
length = 0;
|
||||
// First pass: Determine the length of the kim, allowing for the UTF-16
|
||||
// to UTF-32 conversion, and then the UTF-32 to Kim conversion.
|
||||
if (stringLength > 0) {
|
||||
for (int i = 0; i < stringLength; i += 1) {
|
||||
final int c = string.charAt(i);
|
||||
if (c <= 0x7F) {
|
||||
length += 1;
|
||||
} else if (c <= 0x3FFF) {
|
||||
length += 2;
|
||||
} else {
|
||||
if ((c >= 0xD800) && (c <= 0xDFFF)) {
|
||||
i += 1;
|
||||
final int d = string.charAt(i);
|
||||
if ((c > 0xDBFF) || (d < 0xDC00) || (d > 0xDFFF)) {
|
||||
throw new JSONException("Bad UTF16");
|
||||
}
|
||||
}
|
||||
length += 3;
|
||||
}
|
||||
}
|
||||
// Second pass: Allocate a byte array and fill that array with the
|
||||
// conversion
|
||||
// while computing the hashcode.
|
||||
bytes = new byte[length];
|
||||
int at = 0;
|
||||
int b;
|
||||
int sum = 1;
|
||||
for (int i = 0; i < stringLength; i += 1) {
|
||||
int character = string.charAt(i);
|
||||
if (character <= 0x7F) {
|
||||
bytes[at] = (byte) character;
|
||||
sum += character;
|
||||
hashcode += sum;
|
||||
at += 1;
|
||||
} else if (character <= 0x3FFF) {
|
||||
b = 0x80 | (character >>> 7);
|
||||
bytes[at] = (byte) b;
|
||||
sum += b;
|
||||
hashcode += sum;
|
||||
at += 1;
|
||||
b = character & 0x7F;
|
||||
bytes[at] = (byte) b;
|
||||
sum += b;
|
||||
hashcode += sum;
|
||||
at += 1;
|
||||
} else {
|
||||
if ((character >= 0xD800) && (character <= 0xDBFF)) {
|
||||
i += 1;
|
||||
character =
|
||||
(((character & 0x3FF) << 10) | (string.charAt(i) & 0x3FF)) + 65536;
|
||||
}
|
||||
b = 0x80 | (character >>> 14);
|
||||
bytes[at] = (byte) b;
|
||||
sum += b;
|
||||
hashcode += sum;
|
||||
at += 1;
|
||||
b = 0x80 | ((character >>> 7) & 0xFF);
|
||||
bytes[at] = (byte) b;
|
||||
sum += b;
|
||||
hashcode += sum;
|
||||
at += 1;
|
||||
b = character & 0x7F;
|
||||
bytes[at] = (byte) b;
|
||||
sum += b;
|
||||
hashcode += sum;
|
||||
at += 1;
|
||||
}
|
||||
}
|
||||
hashcode += sum << 16;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes needed to contain the character in Kim format.
|
||||
*
|
||||
* @param character a Unicode character between 0 and 0x10FFFF.
|
||||
* @return 1, 2, or 3
|
||||
* @throws JSONException if the character is not representable in a kim.
|
||||
*/
|
||||
public static int characterSize(final int character) throws JSONException {
|
||||
if ((character < 0) || (character > 0x10FFFF)) {
|
||||
throw new JSONException("Bad character " + character);
|
||||
}
|
||||
return character <= 0x7F ? 1 : character <= 0x3FFF ? 2 : 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the character at the specified index. The index refers to byte values and ranges from 0 to length - 1.
|
||||
* The index of the next character is at index + Kim.characterSize(kim.characterAt(index)).
|
||||
*
|
||||
* @param at the index of the char value. The first character is at 0.
|
||||
* @return a Unicode character between 0 and 0x10FFFF.
|
||||
* @throws JSONException if at does not point to a valid character.
|
||||
*/
|
||||
public int characterAt(final int at) throws JSONException {
|
||||
final int c = get(at);
|
||||
if ((c & 0x80) == 0) {
|
||||
return c;
|
||||
}
|
||||
int character;
|
||||
final int c1 = get(at + 1);
|
||||
if ((c1 & 0x80) == 0) {
|
||||
character = ((c & 0x7F) << 7) | c1;
|
||||
if (character > 0x7F) {
|
||||
return character;
|
||||
}
|
||||
} else {
|
||||
final int c2 = get(at + 2);
|
||||
character = ((c & 0x7F) << 14) | ((c1 & 0x7F) << 7) | c2;
|
||||
if (((c2 & 0x80) == 0) && (character > 0x3FFF) && (character <= 0x10FFFF) && (
|
||||
(character < 0xD800) || (character > 0xDFFF))) {
|
||||
return character;
|
||||
}
|
||||
}
|
||||
throw new JSONException("Bad character at " + at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of this kim to a byte array.
|
||||
*
|
||||
* @param bytes A byte array of sufficient size.
|
||||
* @param at The position within the byte array to take the byes.
|
||||
* @return The position immediately after the copy.
|
||||
*/
|
||||
public int copy(final byte[] bytes, final int at) {
|
||||
System.arraycopy(this.bytes, 0, bytes, at, length);
|
||||
return at + length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Two kim objects containing exactly the same bytes in the same order are equal to each other.
|
||||
*
|
||||
* @param obj the other kim with which to compare.
|
||||
* @return true if this and obj are both kim objects containing identical byte sequences.
|
||||
*/
|
||||
@Override public boolean equals(final Object obj) {
|
||||
if (!(obj instanceof Kim)) {
|
||||
return false;
|
||||
}
|
||||
final Kim that = (Kim) obj;
|
||||
if (this == that) {
|
||||
return true;
|
||||
}
|
||||
if (hashcode != that.hashcode) {
|
||||
return false;
|
||||
}
|
||||
return java.util.Arrays.equals(bytes, that.bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a byte from a kim.
|
||||
*
|
||||
* @param at The position of the byte. The first byte is at 0.
|
||||
* @return The byte.
|
||||
* @throws JSONException if there is no byte at that position.
|
||||
*/
|
||||
public int get(final int at) throws JSONException {
|
||||
if ((at < 0) || (at > length)) {
|
||||
throw new JSONException("Bad character at " + at);
|
||||
}
|
||||
return (bytes[at]) & 0xFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code value for the kim.
|
||||
*/
|
||||
@Override public int hashCode() {
|
||||
return hashcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a UTF-16 String from this kim. The number of codepoints in the string will not be greater than the number
|
||||
* of bytes in the kim, although it could be less.
|
||||
*
|
||||
* @return The string. A kim memoizes its string representation.
|
||||
* @throws JSONException if the kim is not valid.
|
||||
*/
|
||||
@Override public String toString() throws JSONException {
|
||||
if (string == null) {
|
||||
int c;
|
||||
int length = 0;
|
||||
final char chars[] = new char[this.length];
|
||||
for (int at = 0; at < this.length; at += characterSize(c)) {
|
||||
c = characterAt(at);
|
||||
if (c < 0x10000) {
|
||||
chars[length] = (char) c;
|
||||
length += 1;
|
||||
} else {
|
||||
chars[length] = (char) (0xD800 | ((c - 0x10000) >>> 10));
|
||||
length += 1;
|
||||
chars[length] = (char) (0xDC00 | (c & 0x03FF));
|
||||
length += 1;
|
||||
}
|
||||
}
|
||||
string = new String(chars, 0, length);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user