Revision: 20761 http://sourceforge.net/p/jmol/code/20761 Author: hansonr Date: 2015-09-09 03:46:44 +0000 (Wed, 09 Sep 2015) Log Message: ----------- Jmol.___JmolVersion="14.3.16_2015.09.08"
code: Efficient JSON parser javajs.util.JSONParser Modified Paths: -------------- trunk/Jmol/src/org/jmol/adapter/smarter/SmarterJmolAdapter.java trunk/Jmol/src/org/jmol/modelsetbio/BioModel.java trunk/Jmol/src/org/jmol/viewer/Jmol.properties trunk/Jmol/src/org/jmol/viewer/Viewer.java Added Paths: ----------- trunk/Jmol/src/javajs/util/JSJSONParser.java trunk/Jmol/src/javajs/util/JSONException.java Added: trunk/Jmol/src/javajs/util/JSJSONParser.java =================================================================== --- trunk/Jmol/src/javajs/util/JSJSONParser.java (rev 0) +++ trunk/Jmol/src/javajs/util/JSJSONParser.java 2015-09-09 03:46:44 UTC (rev 20761) @@ -0,0 +1,316 @@ +package javajs.util; + +import java.util.HashMap; +import java.util.Map; + + + +/** + * a very simple JSON parser for JSON objects that are compatible with JavaScript + * A gross simplification of https://github.com/douglascrockford/JSON-java + * + * A SUBSET of JSON with similarly to window.JSON.parse(): + * + * -- requires quoted strings for keys and values + * + * -- does not allow /xxx/ objects + * + * + */ +public class JSJSONParser { + + private String str; + private int index; + private int len; + + public JSJSONParser () { + // for reflection + } + + /** + * requires { "key":"value", "key":"value",....} + * + * @param str + * + * @return Map or null + */ + @SuppressWarnings("unchecked") + public Map<String, Object> parseMap(String str) { + index = 0; + this.str = str; + len = str.length(); + if (getChar() != '{') + return null; + returnChar(); + return (Map<String, Object>) getValue(false); + } + + /** + * Could return Integer, Double, Boolean, String, Map<String, Object>, Lst<Object>, or null + * + * @param str + * @return a object equivalent to the JSON string str + * + */ + public Object parse(String str) { + index = 0; + this.str = str; + len = str.length(); + return getValue(false); + } + + private char next() { + return (index < len ? str.charAt(index++) : '\0'); + } + + private void returnChar() { + index--; + } + + /** + * Get the next char in the string, skipping whitespace. + * + * @throws JSONException + * @return one character, or 0 if there are no more characters. + */ + private char getChar() throws JSONException { + for (;;) { + char c = next(); + if (c == 0 || c > ' ') { + return c; + } + } + } + + /** + * only allowing the following values: + * + * {...} object + * + * [...] array + * + * Integer + * + * Double + * + * "quoted string" + * + * + * @param isKey if we should allow {...} and [...] + * @return a subclass of Object + * @throws JSONException + */ + private Object getValue(boolean isKey) throws JSONException { + int i = index; + char c = getChar(); + switch (c) { + case '\0': + return null; + case '"': + case '\'': + return getString(c); + case '{': + if (!isKey) + return getObject(); + c = 0; + break; + case '[': + if (!isKey) + return getArray(); + c = 0; + break; + default: + // standard syntax is assumed; not checking all possible invalid keys + // for example, "-" is not allowed in JavaScript, which is what this is for + returnChar(); + while (c >= ' ' && "[,]{:}'\"".indexOf(c) < 0) + c = next(); + returnChar(); + if (isKey && c != ':') + c = 0; + break; + } + if (isKey && c == 0) + throw new JSONException("invalid key"); + + String string = str.substring(i, index); + + // check for the only valid simple words: true, false, null (lower case) + // and in this case, only for + + if (!isKey) { + if (string.equals("true")) { + return Boolean.TRUE; + } + if (string.equals("false")) { + return Boolean.FALSE; + } + if (string.equals("null")) { + return null; + } + } + // only numbers from here on: + + c = string.charAt(0); + if (c >= '0' && c <= '9' || c == '-') + try { + if (string.indexOf('.') < 0 && string.indexOf('e') < 0 + && string.indexOf('E') < 0) + return new Integer(string); + // not allowing infinity or NaN + Double d = Double.valueOf(string); + if (!d.isInfinite() && !d.isNaN()) + return d; + } catch (Exception e) { + } + // not a valid number + throw new JSONException("invalid value"); + } + + private String getString(char quote) throws JSONException { + char c; + SB sb = null; + int i0 = index; + for (;;) { + int i1 = index; + switch (c = next()) { + case '\0': + case '\n': + case '\r': + throw syntaxError("Unterminated string"); + case '\\': + switch (c = next()) { + case '"': + case '\'': + case '\\': + case '/': + break; + case 'b': + c = '\b'; + break; + case 't': + c = '\t'; + break; + case 'n': + c = '\n'; + break; + case 'f': + c = '\f'; + break; + case 'r': + c = '\r'; + break; + case 'u': + int i = index; + index += 4; + try { + c = (char) Integer.parseInt(str.substring(i, index), 16); + } catch (Exception e) { + throw syntaxError("Substring bounds error"); + } + break; + default: + throw syntaxError("Illegal escape."); + } + break; + default: + if (c == quote) + return (sb == null ? str.substring(i0, i1) : sb.toString()); + break; + } + if (index > i1 + 1) { + if (sb == null) { + sb = new SB(); + sb.append(str.substring(i0, i1)); + } + } + if (sb != null) + sb.appendC(c); + } + } + + private Object getObject() { + Map<String, Object> map = new HashMap<String, Object>(); + String key = null; + switch (getChar()) { + case '}': + return map; + case 0: + throw new JSONException("invalid object"); + } + returnChar(); + boolean isKey = false; + for (;;) { + if ((isKey = !isKey) == true) + key = getValue(true).toString(); + else + map.put(key, getValue(false)); + switch (getChar()) { + case '}': + return map; + case ':': + if (isKey) + continue; + isKey = true; + //$FALL-THROUGH$ + case ',': + if (!isKey) + continue; + //$FALL-THROUGH$ + default: + throw syntaxError("Expected ',' or ':' or '}'"); + } + } + } + + private Object getArray() { + Lst<Object> l = new Lst<Object>(); + switch (getChar()) { + case ']': + return l; + case 0: + throw new JSONException("invalid array"); + } + returnChar(); + boolean isNull = false; + for (;;) { + if (isNull) { + l.addLast(null); + isNull = false; + } else { + l.addLast(getValue(false)); + } + switch (getChar()) { + case ',': + switch (getChar()) { + case ']': + // terminal , + return l; + case ',': + // empty value + isNull = true; + //$FALL-THROUGH$ + default: + returnChar(); + } + continue; + case ']': + return l; + default: + throw syntaxError("Expected ',' or ']'"); + } + } + } + + /** + * Make a JSONException to signal a syntax error. + * + * @param message + * The error message. + * @return A JSONException object, suitable for throwing + */ + public JSONException syntaxError(String message) { + return new JSONException(message + " for " + str.substring(0, Math.min(index, len))); + } + +} Property changes on: trunk/Jmol/src/javajs/util/JSJSONParser.java ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: trunk/Jmol/src/javajs/util/JSONException.java =================================================================== --- trunk/Jmol/src/javajs/util/JSONException.java (rev 0) +++ trunk/Jmol/src/javajs/util/JSONException.java 2015-09-09 03:46:44 UTC (rev 20761) @@ -0,0 +1,8 @@ +package javajs.util; + +public class JSONException extends RuntimeException { + public JSONException(String message) { + super(message); + } + +} Property changes on: trunk/Jmol/src/javajs/util/JSONException.java ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Modified: trunk/Jmol/src/org/jmol/adapter/smarter/SmarterJmolAdapter.java =================================================================== --- trunk/Jmol/src/org/jmol/adapter/smarter/SmarterJmolAdapter.java 2015-09-08 06:25:42 UTC (rev 20760) +++ trunk/Jmol/src/org/jmol/adapter/smarter/SmarterJmolAdapter.java 2015-09-09 03:46:44 UTC (rev 20761) @@ -31,10 +31,13 @@ import org.jmol.api.JmolFilesReaderInterface; import javajs.api.GenericBinaryDocument; +import javajs.api.Interface; import javajs.util.Lst; import org.jmol.script.SV; import org.jmol.util.Logger; + +import javajs.util.JSJSONParser; import javajs.util.P3; import javajs.util.PT; import javajs.util.Rdr; @@ -46,7 +49,6 @@ import java.util.Map; - public class SmarterJmolAdapter extends JmolAdapter { /************************************************************** @@ -207,7 +209,7 @@ // hack to determine type: String type = (f.contains("version\":\"DSSR") ? "dssr" : f .contains("/outliers/") ? "validation" : "domains"); - SV x = vwr.evaluateExpressionAsVariable(f); + SV x = vwr.parseJSON(f); if (x != null && x.getMap() != null) htParams.put(type, x); continue; Modified: trunk/Jmol/src/org/jmol/modelsetbio/BioModel.java =================================================================== --- trunk/Jmol/src/org/jmol/modelsetbio/BioModel.java 2015-09-08 06:25:42 UTC (rev 20760) +++ trunk/Jmol/src/org/jmol/modelsetbio/BioModel.java 2015-09-09 03:46:44 UTC (rev 20761) @@ -1324,7 +1324,7 @@ Object annotv = cache.get(key); if (annotv == null && ann != null) { annotv = (ann instanceof SV || ann instanceof Hashtable ? ann - : vwr.evaluateExpressionAsVariable(ann)); + : vwr.parseJSON((String) ann)); cache.put(key, annotv); } return (annotv instanceof SV || annotv instanceof Hashtable ? annotv : null); Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties =================================================================== --- trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2015-09-08 06:25:42 UTC (rev 20760) +++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2015-09-09 03:46:44 UTC (rev 20761) @@ -58,8 +58,12 @@ TODO: image off stops JSmol -Jmol.___JmolVersion="14.3.16_2015.09.06" +Jmol.___JmolVersion="14.3.16_2015.09.08" +code: Efficient JSON parser javajs.util.JSONParser + +JmolVersion="14.3.16_2015.09.06" + new feature: 3DNA DSSR JSON mode -- http://x3dna.bio.columbia.edu/dssr/report.php?id=1ehz&opts=--more%20--json=ebi-no-str-id -- uses unit ids Modified: trunk/Jmol/src/org/jmol/viewer/Viewer.java =================================================================== --- trunk/Jmol/src/org/jmol/viewer/Viewer.java 2015-09-08 06:25:42 UTC (rev 20760) +++ trunk/Jmol/src/org/jmol/viewer/Viewer.java 2015-09-09 03:46:44 UTC (rev 20761) @@ -45,6 +45,7 @@ import javajs.awt.Font; import javajs.util.CU; import javajs.util.DF; +import javajs.util.JSJSONParser; import javajs.util.Lst; import javajs.util.M3; import javajs.util.M4; @@ -9345,7 +9346,7 @@ jmolpopup.jpiUpdateComputedMenus(); } - JmolChimeMessenger jcm; + private JmolChimeMessenger jcm; public JmolChimeMessenger getChimeMessenger() { return (jcm == null ? jcm = ((JmolChimeMessenger) Interface.getInterface( @@ -9357,4 +9358,11 @@ false)); } + private JSJSONParser jsonParser; + + public SV parseJSON(String ann) { + if (jsonParser == null) + jsonParser = ((JSJSONParser) Interface.getInterface("javajs.util.JSJSONParser", this, "script")); + return SV.getVariable(jsonParser.parseMap(ann)); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Monitor Your Dynamic Infrastructure at Any Scale With Datadog! Get real-time metrics from all of your servers, apps and tools in one place. SourceForge users - Click here to start your Free Trial of Datadog now! http://pubads.g.doubleclick.net/gampad/clk?id=241902991&iu=/4140 _______________________________________________ Jmol-commits mailing list Jmol-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jmol-commits